]>
Commit | Line | Data |
---|---|---|
1 | variables = {} | |
2 | functions = {} | |
3 | ||
4 | ||
5 | ||
6 | function evaluate(expr, varlevel) | |
7 | assert(varlevel) | |
8 | if expr.type == "function" then | |
9 | local retval,nvarlevel = evaluate(expr.body, varlevel) | |
10 | assert((type(retval) == "nil" and expr.returntype == "void") or | |
11 | (type(retval) == "number" and expr.returntype == "int"), "incorrect return type "..type(retval).." for function returning "..expr.returntype) | |
12 | return retval,varlevel | |
13 | elseif expr.type == "stmtlist" then | |
14 | for k,v in pairs(expr.body) do | |
15 | local retval | |
16 | retval,varlevel = evaluate(v, varlevel) | |
17 | if not varlevel then -- we've taken a 'return' | |
18 | return retval,nil | |
19 | end | |
20 | end | |
21 | return nil,varlevel | |
22 | elseif expr.type == "variable" then | |
23 | varlevel = varlevel + 1 | |
24 | variables[varlevel] = { name = expr.name, type = expr.vtype, value = expr.initializer } | |
25 | return nil,varlevel | |
26 | elseif expr.type == "expression" then | |
27 | return evaluate(expr.value, varlevel), varlevel | |
28 | elseif expr.type == "while" then | |
29 | while evaluate(expr.expression, varlevel) ~= 0 do | |
30 | local retval,donevarlevel = evaluate(expr.chunk, varlevel) | |
31 | if donevarlevel == nil then | |
32 | return retval, nil | |
33 | end | |
34 | end | |
35 | return nil,varlevel | |
36 | elseif expr.type == "if" then | |
37 | if evaluate(expr.expression, varlevel) ~= 0 then | |
38 | local retval,donevarlevel = evaluate(expr.chunk, varlevel) | |
39 | if donevarlevel == nil then | |
40 | return retval, nil | |
41 | end | |
42 | end | |
43 | return nil,varlevel | |
44 | elseif expr.type == "operator" then | |
45 | local lhs = evaluate(expr.left, varlevel) | |
46 | local rhs = evaluate(expr.right, varlevel) | |
47 | if not (expr.value == "=" and lhs == nil) then -- This case is OK. | |
48 | assert(type(lhs) == type(rhs), "operator "..expr.value.." on two different types: "..type(lhs).." and "..type(rhs)) | |
49 | end | |
50 | if expr.value == "+" then | |
51 | return lhs + rhs | |
52 | elseif expr.value == "-" then | |
53 | return lhs - rhs | |
54 | elseif expr.value == "*" then | |
55 | return lhs * rhs | |
56 | elseif expr.value == "/" then | |
57 | return lhs / rhs | |
58 | elseif expr.value == ">" then | |
59 | return lhs > rhs and 1 or 0 | |
60 | elseif expr.value == "<" then | |
61 | return lhs < rhs and 1 or 0 | |
62 | elseif expr.value == "==" then | |
63 | return lhs == rhs and 1 or 0 | |
64 | elseif expr.value == "=" then | |
65 | -- blah | |
66 | assert(expr.left.type == "identifier", "lvalue of operator '=' must be an identifier") | |
67 | for k=varlevel,1,-1 do | |
68 | if variables[k].name == expr.left.value then | |
69 | assert(variables[k].type == "int") | |
70 | variables[k].value = rhs | |
71 | return rhs | |
72 | end | |
73 | end | |
74 | error("unknown identifier "..expr.left.value.." in varlevel "..varlevel) | |
75 | else | |
76 | error("unknown operator "..expr.value.." in evaluate") | |
77 | end | |
78 | elseif expr.type == "number" then | |
79 | return expr.value | |
80 | elseif expr.type == "identifier" then | |
81 | for k=varlevel,1,-1 do | |
82 | if variables[k].name == expr.value then | |
83 | return variables[k].value | |
84 | end | |
85 | end | |
86 | error("unknown identifier "..expr.value) | |
87 | elseif expr.type == "funccall" then | |
88 | if not functions[expr.name] then | |
89 | error("unknown function "..expr.name) | |
90 | end | |
91 | assert(table.getn(expr.args) == table.getn(functions[expr.name].args), "wrong number of args for function "..expr.name) | |
92 | ||
93 | local orig_varlevel = varlevel | |
94 | local vars_to_move = {} | |
95 | for k,v in pairs(expr.args) do | |
96 | assert(functions[expr.name].args[k].type == "int", "wrong type for argument #"..k.." to function "..expr.name) | |
97 | varlevel = varlevel + 1 | |
98 | vars_to_move[varlevel] = { type = v.type, name = functions[expr.name].args[k].name } | |
99 | vars_to_move[varlevel].value = evaluate(v.value, orig_varlevel) | |
100 | end | |
101 | for k,v in pairs(vars_to_move) do | |
102 | variables[k] = vars_to_move[k] | |
103 | end | |
104 | ||
105 | if functions[expr.name].native then | |
106 | return functions[expr.name].native(expr, varlevel), orig_varlevel | |
107 | else | |
108 | local retval, varlevel = evaluate(functions[expr.name].body, varlevel) | |
109 | assert(not varlevel) | |
110 | return retval, orig_varlevel | |
111 | end | |
112 | elseif expr.type == "return" then | |
113 | local retval = nil | |
114 | if expr.expression then | |
115 | retval = evaluate(expr.expression, varlevel) | |
116 | end | |
117 | return retval,nil | |
118 | else | |
119 | error("unknown type "..expr.type.." in evaluate") | |
120 | end | |
121 | error("fell through? type was "..expr.type) | |
122 | end | |
123 | ||
124 | functions["printint"] = { returns = "void", args = { { type = "int", name = "toprint" } }, | |
125 | native = function(expr, varlevel) | |
126 | print("NATIVE CALL: printint("..variables[varlevel].value..")") | |
127 | end } | |
128 | ||
129 | function backend(parsetree, outfn) | |
130 | for k,v in pairs(parsetree) do | |
131 | if v.type == "variable" then | |
132 | table.insert(variables, { name = v.name, type = v.vtype, value = v.initializer }) | |
133 | elseif v.type == "function" then | |
134 | functions[v.name] = v | |
135 | else | |
136 | error("invalid type in global deparse") | |
137 | end | |
138 | end | |
139 | ||
140 | local retval,varlevel = evaluate(functions["main"], table.getn(variables)) | |
141 | print("main returned "..retval) | |
142 | end |