summaryrefslogtreecommitdiff
path: root/tnslc/compiler.tnsl
blob: ab43e6bf75e37056727b236f130272dec62e79d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# Actual compilation of the vector of tokens, ported from the "dirty tnsl"
# that was originally written for the interpreter

# CompData represents three vectors:
# hsec - the heading of the output assembly
# dsec - the data tied to the assembly
# csec - the .text section that is the code of the assembly
struct CompData {
    Vector
        hsec,
        dsec,
        csec
}

/; method CompData
    /; start
        self.hsec.start(1)
        self.dsec.start(1)
        self.csec.start(1)
    ;/

    /; add (CompData c)
        self.hsec.add(c.hsec)
        self.dsec.add(c.dsec)
        self.csec.add(c.csec)
    ;/

    /; _del
        self.hsec._del()
        self.dsec._del()
        self.csec._del()
    ;/
;/

# Path represents the actual path of a file
# that we are trying to tokenize
# Assumes that the last item in the path array is a file name
struct Path {
    int 
        path_count,
    ~~uint8
        split_path
}

/; method Path
    /; start (~uint8 path)
        self.split_path = _alloc(8)
        self.split_path{0} = _alloc(1)
        self.path_count = 1
        
        int i = 0
        int j = cstr_len(path)

        /; loop (i < j) [i++]
            /; if (path{i} == '\\' || path{i} == '/')

            ;/
        ;/ 
    ;/

    /; copy [Path]
        Path out
        out.start(self.full_path())
    ;/

    /; sub_folder (~uint8 sub)
        ~uint8 file_name
    ;/
    
    /; relative_file(~uint8 rel_pth) [Path]

    ;/

    /; full_path [~uint8]
        ~uint8 pth = _alloc(1)

        /; loop (pth)

        ;/
    ;/

    /; open_read [~void]
        ~uint8 path = self.full_path()
        ~void out = _open_file(path)
        _delete(path)
        return out
    ;/

    /; open_write [~void]
        ~uint8 path = self.full_path()
        ~void out = _create_file(path)
        _delete(path)
        return out
    ;/

    /; _del
        /; loop (int i = 0; i < self.path_count) [i++]
            _delete(self.split_path{i})
        ;/

        _delete(self.split_path)
    ;/
;/


#
# Actual compiler code -- here be dragons
#

# Types of pointers the compiler may generate or work with
enum PTR_TYPE [uint] {
    POINTER = 0,
    REFERENCE = 1,
    ARRAY = 2
}

# Represents a type of a variable
struct Type {
    int
        s,          # size of type (bytes)
        p_ct,       # ptr_chain count
        m_ct,       # member count
    ~uint8
        name,       # name of the type
    ~uint
        ptr_chain,  # for every pointer augment on the type, give it an extra PTR_TYPE in the chain
    ~Variable
        members,    # member variables (their types and names)
    ~Module
        mod         # the methods (if any) that are associated with this type
}

/; method Type
    /; start

    ;/

    /; size [int]
        /; loop (int i = 0; i < self.p_ct) [i++]
            /; if (self.ptr_chain{i} == PTR_TYPE.REFERENCE)
                return 8
            ;/
        ;/
        return self.s
    ;/

    /; _del
        _delete(self.name)
        _delete(self.ptr_chain)
        _delete(self.members)
        _delete(self.mod)
    ;/
;/

/; NO_TYPE [Type]
    Type t
    t.s = 0
    t.name = 0
    t.ptr_chain = 0
    t.members = 0
    t.mod = 0
    return t
;/

/; is_primitive (~uint8 name)

;/

# Location type represents the type of memory
# that the variable is stored in
enum LOCATION [uint] {
    REGISTER = 0,
    STACK = 1,
    LABEL = 2,
    LITERAL = 3
}

# The Big Kahuna
struct Variable {
    ~uint8
        name,
    Type
        _type,
    uint
        location, # Actual location.  If literal, the literal value. 
                  # If register, corrosponds to a register name.
                  # If stack, represents the offset from the base pointer
                  # Ignore if label.
        loc_type
}

# I hate c-like strings.  Hopefully once I'm done with this
# language I'll have something that doesn't use them


# This part sucks ass
/; method Variable

;/

# Scopes
struct Scope {
    int
        num,
        c,    # Figure it out yourself
        tmp,
    ~Scope
        parent,
    ~uint8
        name
}

/; method Scope

;/

struct Function {
    ~uint8
        name,
    ~Type 
        inputs,
    Type
        output,
    ~Module mod
}

/; method Function

;/

struct Module {
    ~Module
        parent,
    bool
        exp,       # Export functions or not
    ~uint8
        name,
    ~Type
        types,     # Types defined in this module
    ~Variable
        defs,      # Variables defined in this module
    ~Function
        functions, # Functions defined in this module
    ~Module
        sub        # Sub modules
}

/; method Module

;/

#
# Actual compiler functions
#

# Used in the first pass
/; get_type_P1

;/

/; get_type_P2

;/

/; get_artifact [~~uint8]

;/

/; is_call [bool]

;/

/; is_definition

;/