Initial commit
[jwcc.git] / lib / backend / interpreter.lua
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
This page took 0.026718 seconds and 4 git commands to generate.