]> Joshua Wise's Git repositories - jwcc.git/blame - lib/backend/interpreter.lua
Initial commit
[jwcc.git] / lib / backend / interpreter.lua
CommitLineData
933e60e3
JW
1variables = {}
2functions = {}
3
4
5
6function 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)
122end
123
124functions["printint"] = { returns = "void", args = { { type = "int", name = "toprint" } },
125 native = function(expr, varlevel)
126 print("NATIVE CALL: printint("..variables[varlevel].value..")")
127 end }
128
129function 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)
142end
This page took 0.035619 seconds and 4 git commands to generate.