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
;/
|