7 | 7 |
init_code = []
|
8 | 8 |
for item in root:
|
9 | 9 |
if item[0] == 'fun':
|
10 | |
function = translate_function(item, glob)
|
|
10 |
function = translate_function(item, glob, funcs)
|
11 | 11 |
funcs[item[2][0][0]] = function
|
12 | 12 |
elif item[0] == 'declare':
|
13 | 13 |
for var, init in item[2]:
|
|
15 | 15 |
glob[name] = (cvmtype, init)
|
16 | 16 |
if init:
|
17 | 17 |
init_code.extend(
|
18 | |
translate_declaration(name, (cvmtype, init), glob))
|
|
18 |
translate_declaration(name, (cvmtype, init), glob, funcs))
|
19 | 19 |
else:
|
20 | 20 |
raise Exception('Only function definitions and declarations'
|
21 | 21 |
'are allowed at top level.')
|
22 | 22 |
|
23 | 23 |
return glob, funcs, init_code
|
24 | 24 |
|
25 | |
def translate_function(ftree, glob):
|
|
25 |
def translate_function(ftree, glob, funcs):
|
26 | 26 |
fname = ftree[2][0][0]
|
27 | 27 |
fargs = list(map(cvmtypes.declarator, ftree[2][1]))
|
28 | |
fcode, flocals = translate_compound(ftree[3], glob)
|
|
28 |
fcode, flocals = translate_compound(ftree[3], glob, funcs)
|
29 | 29 |
fret = cvmtypes.typefor(ftree[1])
|
30 | 30 |
return function(fname, fcode, fargs, fret, flocals)
|
31 | 31 |
|
|
34 | 34 |
cvmtype, name = cvmtypes.declarator((decl[1], var))
|
35 | 35 |
loc[name] = (cvmtype, init)
|
36 | 36 |
|
37 | |
def translate_compound(ftree, glob):
|
|
37 |
def translate_compound(ftree, glob, funcs):
|
38 | 38 |
if not ftree: return [], {}
|
39 | 39 |
|
40 | 40 |
declarations = []
|
|
52 | 52 |
code = []
|
53 | 53 |
for var, data in loc.items():
|
54 | 54 |
if data[1]:
|
55 | |
code.extend(translate_declaration(var, data, glob))
|
|
55 |
code.extend(translate_declaration(var, data, glob, funcs))
|
56 | 56 |
for node in ftree[first_statement:]:
|
57 | |
code.extend(translate_statement(node, glob))
|
|
57 |
code.extend(translate_statement(node, glob, funcs))
|
58 | 58 |
|
59 | 59 |
return code, loc
|
60 | 60 |
|
61 | |
def translate_declaration(var, data, glob):
|
62 | |
return (
|
63 | |
translate_statement(data[1], glob) +
|
|
61 |
def translate_declaration(var, data, glob, funcs):
|
|
62 |
return (
|
|
63 |
translate_statement(data[1], glob, funcs) +
|
64 | 64 |
[('store', (var, 'var'))])
|
65 | 65 |
|
66 | |
def translate_statement(ftree, glob):
|
|
66 |
def translate_statement(ftree, glob, funcs):
|
67 | 67 |
'''
|
68 | 68 |
TODO:
|
69 | 69 |
|
70 | 70 |
BREAK
|
71 | 71 |
CALL
|
72 | 72 |
GOTO
|
73 | |
RETURN
|
74 | 73 |
'''
|
75 | 74 |
# Assignment
|
76 | 75 |
if ftree[0] == '=':
|
77 | |
rhs = translate_statement(ftree[2], glob)
|
|
76 |
rhs = translate_statement(ftree[2], glob, funcs)
|
78 | 77 |
return rhs + [('store', ftree[1])]
|
79 | 78 |
|
80 | 79 |
# Variable access
|
81 | 80 |
if ftree[1] == 'var':
|
82 | 81 |
return [('load', ftree)]
|
83 | 82 |
|
|
83 |
# Call stack-related
|
|
84 |
if ftree[0] == 'call':
|
|
85 |
func = funcs[ftree[1][0]]
|
|
86 |
if len(func.args) != len(ftree[2]):
|
|
87 |
raise Exception('Not enough arguments to function "%s"' % ftree[1][0])
|
|
88 |
|
|
89 |
arg_evals = []
|
|
90 |
for arg in ftree[2]:
|
|
91 |
arg_evals.extend(translate_statement(arg, glob, funcs))
|
|
92 |
return arg_evals + [('call', (ftree[1][0], 'func'))]
|
|
93 |
|
|
94 |
if ftree[0] == 'return':
|
|
95 |
return translate_statement(ftree[1], glob, funcs) + [('return',)]
|
|
96 |
|
84 | 97 |
# Unary operators
|
85 | 98 |
if ftree[0] == '++':
|
86 | |
return translate_unop_expression('incr', ftree, glob)
|
|
99 |
return translate_unop_expression('incr', ftree, glob, funcs)
|
87 | 100 |
if ftree[0] == '--':
|
88 | |
return translate_unop_expression('decr', ftree, glob)
|
|
101 |
return translate_unop_expression('decr', ftree, glob, funcs)
|
89 | 102 |
if ftree[0] == '~':
|
90 | |
return translate_unop_expression('not', ftree, glob)
|
|
103 |
return translate_unop_expression('not', ftree, glob, funcs)
|
91 | 104 |
if ftree[0] == '!':
|
92 | |
return translate_unop_expression('bnot', ftree, glob)
|
|
105 |
return translate_unop_expression('bnot', ftree, glob, funcs)
|
93 | 106 |
|
94 | 107 |
# Binary operators
|
95 | 108 |
if ftree[0] == '*' and len(ftree) == 3:
|
96 | |
return translate_binop_expression('mul', ftree, glob)
|
|
109 |
return translate_binop_expression('mul', ftree, glob, funcs)
|
97 | 110 |
if ftree[0] == '+':
|
98 | |
return translate_binop_expression('add', ftree, glob)
|
|
111 |
return translate_binop_expression('add', ftree, glob, funcs)
|
99 | 112 |
if ftree[0] == '-':
|
100 | |
return translate_binop_expression('sub', ftree, glob)
|
|
113 |
return translate_binop_expression('sub', ftree, glob, funcs)
|
101 | 114 |
if ftree[0] == '/':
|
102 | |
return translate_binop_expression('div', ftree, glob)
|
|
115 |
return translate_binop_expression('div', ftree, glob, funcs)
|
103 | 116 |
if ftree[0] == '%':
|
104 | |
return translate_binop_expression('mod', ftree, glob)
|
|
117 |
return translate_binop_expression('mod', ftree, glob, funcs)
|
105 | 118 |
|
106 | 119 |
if ftree[0] == '&' and len(ftree[0]) == 3:
|
107 | |
return translate_binop_expression('and', ftree, glob)
|
|
120 |
return translate_binop_expression('and', ftree, glob, funcs)
|
108 | 121 |
if ftree[0] == '|':
|
109 | |
return translate_binop_expression('or', ftree, glob)
|
|
122 |
return translate_binop_expression('or', ftree, glob, funcs)
|
110 | 123 |
if ftree[0] == '^':
|
111 | |
return translate_binop_expression('xor', ftree, glob)
|
|
124 |
return translate_binop_expression('xor', ftree, glob, funcs)
|
112 | 125 |
|
113 | 126 |
if ftree[0] == '<<':
|
114 | |
return translate_binop_expression('lsh', ftree, glob)
|
|
127 |
return translate_binop_expression('lsh', ftree, glob, funcs)
|
115 | 128 |
if ftree[0] == '>>':
|
116 | |
return translate_binop_expression('rsh', ftree, glob)
|
|
129 |
return translate_binop_expression('rsh', ftree, glob, funcs)
|
117 | 130 |
|
118 | 131 |
if ftree[0] == '&&':
|
119 | |
return translate_binop_expression('band', ftree, glob)
|
|
132 |
return translate_binop_expression('band', ftree, glob, funcs)
|
120 | 133 |
if ftree[0] == '||':
|
121 | |
return translate_binop_expression('bor', ftree, glob)
|
|
134 |
return translate_binop_expression('bor', ftree, glob, funcs)
|
122 | 135 |
|
123 | 136 |
# Comparison operators
|
124 | 137 |
if ftree[0] == '==':
|
125 | |
return translate_binop_expression('eq', ftree, glob)
|
|
138 |
return translate_binop_expression('eq', ftree, glob, funcs)
|
126 | 139 |
if ftree[0] == '>=':
|
127 | |
return translate_binop_expression('geq', ftree, glob)
|
|
140 |
return translate_binop_expression('geq', ftree, glob, funcs)
|
128 | 141 |
if ftree[0] == '<=':
|
129 | |
return translate_binop_expression('leq', ftree, glob)
|
|
142 |
return translate_binop_expression('leq', ftree, glob, funcs)
|
130 | 143 |
if ftree[0] == '>':
|
131 | |
return translate_binop_expression('gt', ftree, glob)
|
|
144 |
return translate_binop_expression('gt', ftree, glob, funcs)
|
132 | 145 |
if ftree[0] == '<':
|
133 | |
return translate_binop_expression('lt', ftree, glob)
|
|
146 |
return translate_binop_expression('lt', ftree, glob, funcs)
|
134 | 147 |
if ftree[0] == '!=':
|
135 | |
return translate_binop_expression('neq', ftree, glob)
|
|
148 |
return translate_binop_expression('neq', ftree, glob, funcs)
|
136 | 149 |
|
137 | 150 |
# Assignment operators
|
138 | 151 |
if ftree[0] == '+=':
|
139 | |
return translate_assign_expression('add', ftree, glob)
|
|
152 |
return translate_assign_expression('add', ftree, glob, funcs)
|
140 | 153 |
if ftree[0] == '-=':
|
141 | |
return translate_assign_expression('sub', ftree, glob)
|
|
154 |
return translate_assign_expression('sub', ftree, glob, funcs)
|
142 | 155 |
if ftree[0] == '*=':
|
143 | |
return translate_assign_expression('mul', ftree, glob)
|
|
156 |
return translate_assign_expression('mul', ftree, glob, funcs)
|
144 | 157 |
if ftree[0] == '/=':
|
145 | |
return translate_assign_expression('div', ftree, glob)
|
|
158 |
return translate_assign_expression('div', ftree, glob, funcs)
|
146 | 159 |
if ftree[0] == '%=':
|
147 | |
return translate_assign_expression('mod', ftree, glob)
|
|
160 |
return translate_assign_expression('mod', ftree, glob, funcs)
|
148 | 161 |
|
149 | 162 |
if ftree[0] == '&=':
|
150 | |
return translate_assign_expression('and', ftree, glob)
|
|
163 |
return translate_assign_expression('and', ftree, glob, funcs)
|
151 | 164 |
if ftree[0] == '|=':
|
152 | |
return translate_assign_expression('or', ftree, glob)
|
|
165 |
return translate_assign_expression('or', ftree, glob, funcs)
|
153 | 166 |
if ftree[0] == '^=':
|
154 | |
return translate_assign_expression('xor', ftree, glob)
|
|
167 |
return translate_assign_expression('xor', ftree, glob, funcs)
|
155 | 168 |
if ftree[0] == '>>=':
|
156 | |
return translate_assign_expression('rsh', ftree, glob)
|
|
169 |
return translate_assign_expression('rsh', ftree, glob, funcs)
|
157 | 170 |
if ftree[0] == '<<=':
|
158 | |
return translate_assign_expression('lsh', ftree, glob)
|
|
171 |
return translate_assign_expression('lsh', ftree, glob, funcs)
|
159 | 172 |
|
160 | 173 |
# Dereferencing
|
161 | 174 |
if ftree[0] == '->':
|
|
166 | 179 |
return [('addr', ftree[1])]
|
167 | 180 |
if ftree[0] == '*':
|
168 | 181 |
return (
|
169 | |
translate_statement(ftree[1], glob) +
|
|
182 |
translate_statement(ftree[1], glob, funcs) +
|
170 | 183 |
[('load', ('result', 'reg'))])
|
171 | 184 |
|
172 | 185 |
# Conditionals
|
173 | 186 |
if ftree[0] == 'if':
|
174 | |
code_true, ignore = translate_compound(ftree[2], glob)
|
175 | |
code_false, ignore = translate_compound(ftree[3], glob)
|
176 | |
return (
|
177 | |
translate_statement(ftree[1], glob) +
|
|
187 |
code_true, ignore = translate_compound(ftree[2], glob, funcs)
|
|
188 |
code_false, ignore = translate_compound(ftree[3], glob, funcs)
|
|
189 |
return (
|
|
190 |
translate_statement(ftree[1], glob, funcs) +
|
178 | 191 |
# Conditional Offset Zero JuMP --
|
179 | 192 |
# relative jump if result register == 0
|
180 | 193 |
[('ozjmp', len(code_true) + 2)] +
|
|
183 | 196 |
code_false)
|
184 | 197 |
|
185 | 198 |
if ftree[0] == '?':
|
186 | |
code_true = translate_statement(ftree[2], glob)
|
187 | |
code_false = translate_statement(ftree[3], glob)
|
188 | |
return (
|
189 | |
translate_statement(ftree[1], glob) +
|
|
199 |
code_true = translate_statement(ftree[2], glob, funcs)
|
|
200 |
code_false = translate_statement(ftree[3], glob, funcs)
|
|
201 |
return (
|
|
202 |
translate_statement(ftree[1], glob, funcs) +
|
190 | 203 |
# Conditional Offset Zero JuMP --
|
191 | 204 |
# relative jump if result register == 0
|
192 | 205 |
[('ozjmp', len(code_true) + 2)] +
|
|
196 | 209 |
[('nop',)])
|
197 | 210 |
|
198 | 211 |
if ftree[0] == 'while':
|
199 | |
condition = translate_statement(ftree[1], glob)
|
200 | |
code_true, ignore = translate_compound(ftree[2], glob)
|
|
212 |
condition = translate_statement(ftree[1], glob, funcs)
|
|
213 |
code_true, ignore = translate_compound(ftree[2], glob, funcs)
|
201 | 214 |
return (
|
202 | 215 |
condition +
|
203 | 216 |
[('ozjmp', len(code_true) + 2)] +
|
|
205 | 218 |
[('ojmp', -len(code_true) - len(condition) - 1), ('nop',)])
|
206 | 219 |
|
207 | 220 |
if ftree[0] == 'do':
|
208 | |
condition = translate_statement(ftree[1], glob)
|
209 | |
code_true, ignore = translate_compound(ftree[2], glob)
|
|
221 |
condition = translate_statement(ftree[1], glob, funcs)
|
|
222 |
code_true, ignore = translate_compound(ftree[2], glob, funcs)
|
210 | 223 |
return (
|
211 | 224 |
code_true +
|
212 | 225 |
condition +
|
|
215 | 228 |
('nop',)])
|
216 | 229 |
|
217 | 230 |
if ftree[0] == 'for':
|
218 | |
body, ignore = translate_compound(ftree[4], glob)
|
219 | |
condition = translate_statement(ftree[2], glob)
|
|
231 |
body, ignore = translate_compound(ftree[4], glob, funcs)
|
|
232 |
condition = translate_statement(ftree[2], glob, funcs)
|
220 | 233 |
update = []
|
221 | 234 |
if ftree[3]:
|
222 | |
update = translate_statement(ftree[3], glob)
|
223 | |
|
224 | |
return (
|
225 | |
translate_statement(ftree[1], glob) +
|
|
235 |
update = translate_statement(ftree[3], glob, funcs)
|
|
236 |
|
|
237 |
return (
|
|
238 |
translate_statement(ftree[1], glob, funcs) +
|
226 | 239 |
condition +
|
227 | 240 |
[('ozjmp', len(body) + len(update) + 2)] +
|
228 | 241 |
body + update +
|
|
237 | 250 |
print('Warning: statement tree %s could not be translated.' % (ftree,))
|
238 | 251 |
return []
|
239 | 252 |
|
240 | |
def translate_unop_expression(op, ftree, glob):
|
241 | |
return (
|
242 | |
translate_statement(ftree[1], glob) +
|
|
253 |
def translate_unop_expression(op, ftree, glob, funcs):
|
|
254 |
return (
|
|
255 |
translate_statement(ftree[1], glob, funcs) +
|
243 | 256 |
[(op,), ('store', ftree[1])])
|
244 | 257 |
|
245 | |
def translate_binop_expression(op, ftree, glob):
|
246 | |
return (
|
247 | |
translate_statement(ftree[1], glob) +
|
248 | |
translate_statement(ftree[2], glob) +
|
|
258 |
def translate_binop_expression(op, ftree, glob, funcs):
|
|
259 |
return (
|
|
260 |
translate_statement(ftree[1], glob, funcs) +
|
|
261 |
translate_statement(ftree[2], glob, funcs) +
|
249 | 262 |
[(op,)])
|
250 | 263 |
|
251 | |
def translate_assign_expression(op, ftree, glob):
|
252 | |
return (
|
253 | |
translate_binop_expression(op, ftree, glob) +
|
|
264 |
def translate_assign_expression(op, ftree, glob, funcs):
|
|
265 |
return (
|
|
266 |
translate_binop_expression(op, ftree, glob, funcs) +
|
254 | 267 |
[('store', ftree[1])])
|