Skip to content

Commit 73a089d

Browse files
committed
updates to interpreters and type checkers
1 parent c6502fa commit 73a089d

17 files changed

+760
-10
lines changed

interp-Rvar.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from utils import input_int
2+
3+
class InterpRVar:
4+
5+
def interp_exp(env, e):
6+
match e:
7+
case Constant(n):
8+
return n
9+
case Call(Name('input_int'), []):
10+
return input_int()
11+
case UnaryOp(USub(), e1):
12+
return - interp_exp(e1)
13+
case BinOp(e1, Add(), e2):
14+
return interp_exp(e1) + interp_exp(e2)
15+
case _:
16+
return False
17+
18+
def interp_Rint(p):
19+
match p:
20+
case Module(e):
21+

interpRvar.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from utils import input_int
2+
3+
class InterpRVar:
4+
5+
def interp_exp(env, e):
6+
match e:
7+
case Constant(n):
8+
return n
9+
case Call(Name('input_int'), []):
10+
return input_int()
11+
case UnaryOp(USub(), e1):
12+
return - interp_exp(e1)
13+
case BinOp(e1, Add(), e2):
14+
return interp_exp(e1) + interp_exp(e2)
15+
case _:
16+
return False
17+
18+
def interp_stmt(s):
19+
match s:
20+
case Call(Name('print'), [e]):
21+
print(interp_exp(e))
22+
case Expr(e):
23+
interp_exp(e)
24+
case _:
25+
return
26+
27+
def interp_Rint(p):
28+
match p:
29+
case Module(body):
30+
for s in body:
31+
interp_stmt(s)
32+
33+
if __name__ == "__main__":
34+
eight = Constant(8)
35+
neg_eight = UnaryOp(USub(), eight)
36+
read = Call(Name('input_int'), [])
37+
ast1_1 = BinOp(read, Add(), neg_eight)
38+
pr = Call(Name('print'), [ast1_1])
39+
p = Module([pr])
40+
interp_Rint(p)

interp_Cfun.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from ast import *
2+
from interp_Ctup import InterpCtup
3+
from utils import *
4+
from interp_Lfun import Function
5+
6+
class InterpCfun(InterpCtup):
7+
8+
def apply_fun(self, fun, args, e):
9+
match fun:
10+
case Function(name, xs, blocks, env):
11+
old_blocks = self.blocks
12+
self.blocks = blocks
13+
# trace('apply_fun ' + name)
14+
# trace(blocks.keys())
15+
new_env = {x: v for (x,v) in env.items()}
16+
for (x,arg) in zip(xs, args):
17+
new_env[x] = arg
18+
ret = self.interp_stmts(blocks[label_name(name + 'start')], new_env)
19+
self.blocks = old_blocks
20+
return ret
21+
case _:
22+
raise Exception('apply_fun: unexpected: ' + repr(fun))
23+
24+
def interp_exp(self, e, env):
25+
match e:
26+
case Call(Name('input_int'), []):
27+
return super().interp_exp(e, env)
28+
case Call(func, args):
29+
f = self.interp_exp(func, env)
30+
vs = [self.interp_exp(arg, env) for arg in args]
31+
return self.apply_fun(f, vs, e)
32+
case FunRef(id):
33+
return env[id]
34+
case _:
35+
return super().interp_exp(e, env)
36+
37+
def interp_stmts(self, ss, env):
38+
if len(ss) == 0:
39+
raise Exception('interp_stmts function ended without return')
40+
match ss[0]:
41+
case Return(value):
42+
return self.interp_exp(value, env)
43+
case _:
44+
return super().interp_stmts(ss, env)
45+
46+
def interp(self, p):
47+
match p:
48+
case CProgramDefs(defs):
49+
env = {}
50+
for d in defs:
51+
match d:
52+
case FunctionDef(name, params, blocks, dl, returns, comment):
53+
env[name] = Function(name, [p.arg for p in params.args],
54+
blocks, env)
55+
self.blocks = {}
56+
self.apply_fun(env['main'], [], None)
57+
case _:
58+
raise Exception('interp: unexpected ' + repr(p))
59+

interp_Cif.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from ast import *
2-
from interp_Pif import InterpPif
2+
from interp_Lif import InterpLif
33
from utils import *
44

5-
class InterpCif(InterpPif):
5+
class InterpCif(InterpLif):
66

77
def interp_stmts(self, ss, env):
88
if len(ss) == 0:
@@ -11,14 +11,14 @@ def interp_stmts(self, ss, env):
1111
case Return(value):
1212
return self.interp_exp(value, env)
1313
case Goto(label):
14-
return self.interp_stmts(self.CFG[label], env)
14+
return self.interp_stmts(self.blocks[label], env)
1515
case _:
1616
return super().interp_stmts(ss, env)
1717

1818
def interp_C(self, p):
1919
match p:
20-
case CProgram(cfg):
20+
case CProgram(blocks):
2121
env = {}
22-
self.CFG = cfg
22+
self.blocks = blocks
2323
self.interp_stmts(cfg[label_name('start')], env)
2424

interp_Lfun.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from ast import *
2+
from interp_Ltup import InterpLtup
3+
from utils import *
4+
5+
class Function:
6+
__match_args__ = ("name", "params", "body", "env")
7+
def __init__(self, name, params, body, env):
8+
self.name = name
9+
self.params = params
10+
self.body = body
11+
self.env = env
12+
def __repr__(self):
13+
return 'Function(' + self.name + ', ...)'
14+
15+
class InterpLfun(InterpLtup):
16+
17+
def apply_fun(self, fun, args, e):
18+
match fun:
19+
case Function(name, xs, body, env):
20+
new_env = {x: v for (x,v) in env.items()}
21+
for (x,arg) in zip(xs, args):
22+
new_env[x] = arg
23+
return self.interp_stmts(body, new_env)
24+
case _:
25+
raise Exception('apply_fun: unexpected: ' + repr(fun))
26+
27+
def interp_exp(self, e, env):
28+
match e:
29+
case Call(Name('input_int'), []):
30+
return super().interp_exp(e, env)
31+
case Call(func, args):
32+
f = self.interp_exp(func, env)
33+
vs = [self.interp_exp(arg, env) for arg in args]
34+
return self.apply_fun(f, vs, e)
35+
case FunRef(id):
36+
return env[id]
37+
case _:
38+
return super().interp_exp(e, env)
39+
40+
def interp_stmts(self, ss, env):
41+
if len(ss) == 0:
42+
return
43+
match ss[0]:
44+
case Return(value):
45+
return self.interp_exp(value, env)
46+
case _:
47+
return super().interp_stmts(ss, env)
48+
49+
def interp(self, p):
50+
match p:
51+
case Module(defs):
52+
env = {}
53+
for d in defs:
54+
match d:
55+
case FunctionDef(name, params, bod, dl, returns, comment):
56+
env[name] = Function(name, [p.arg for p in params.args],
57+
bod, env)
58+
self.apply_fun(env['main'], [], None)
59+
case _:
60+
raise Exception('interp: unexpected ' + repr(p))

interp_Lif.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from ast import *
2+
from interp_Lvar import InterpLvar
3+
from utils import *
4+
5+
class InterpLif(InterpLvar):
6+
7+
def interp_cmp(self, cmp):
8+
match cmp:
9+
case Lt():
10+
return lambda x, y: x < y
11+
case LtE():
12+
return lambda x, y: x <= y
13+
case Gt():
14+
return lambda x, y: x > y
15+
case GtE():
16+
return lambda x, y: x >= y
17+
case Eq():
18+
return lambda x, y: x == y
19+
case NotEq():
20+
return lambda x, y: x != y
21+
22+
def interp_exp(self, e, env):
23+
match e:
24+
case IfExp(test, body, orelse):
25+
match self.interp_exp(test, env):
26+
case True:
27+
return self.interp_exp(body, env)
28+
case False:
29+
return self.interp_exp(orelse, env)
30+
case UnaryOp(Not(), v):
31+
return not self.interp_exp(v, env)
32+
case BoolOp(And(), values):
33+
left = values[0]; right = values[1]
34+
match self.interp_exp(left, env):
35+
case True:
36+
return self.interp_exp(right, env)
37+
case False:
38+
return False
39+
case BoolOp(Or(), values):
40+
left = values[0]; right = values[1]
41+
match self.interp_exp(left, env):
42+
case True:
43+
return True
44+
case False:
45+
return self.interp_exp(right, env)
46+
case Compare(left, [cmp], [right]):
47+
l = self.interp_exp(left, env)
48+
r = self.interp_exp(right, env)
49+
return self.interp_cmp(cmp)(l, r)
50+
case Let(Name(x), rhs, body):
51+
v = self.interp_exp(rhs, env)
52+
new_env = dict(env)
53+
new_env[x] = v
54+
return self.interp_exp(body, new_env)
55+
case _:
56+
return super().interp_exp(e, env)
57+
58+
def interp_stmts(self, ss, env):
59+
if len(ss) == 0:
60+
return
61+
match ss[0]:
62+
case If(test, body, orelse):
63+
match self.interp_exp(test, env):
64+
case True:
65+
return self.interp_stmts(body + ss[1:], env)
66+
case False:
67+
return self.interp_stmts(orelse + ss[1:], env)
68+
case _:
69+
return super().interp_stmts(ss, env)
70+

interp_Lint.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from ast import *
2+
from utils import input_int
3+
4+
def interp_exp(e):
5+
match e:
6+
case BinOp(left, Add(), right):
7+
l = interp_exp(left); r = interp_exp(right)
8+
return l + r
9+
case BinOp(left, Sub(), right):
10+
l = interp_exp(left); r = interp_exp(right)
11+
return l - r
12+
case UnaryOp(USub(), v):
13+
return - interp_exp(v)
14+
case Constant(value):
15+
return value
16+
case Call(Name('input_int'), []):
17+
return int(input())
18+
case _:
19+
raise Exception('error in interp_exp, unexpected ' + repr(e))
20+
21+
def interp_stmt(s):
22+
match s:
23+
case Expr(Call(Name('print'), [arg])):
24+
print(interp_exp(arg))
25+
case Expr(value):
26+
interp_exp(value)
27+
28+
def interp(p):
29+
match p:
30+
case Module(body):
31+
for s in body:
32+
interp_stmt(s)
33+
34+
# This version is for InterpLvar to inherit from
35+
class InterpLint:
36+
def interp_exp(self, e, env):
37+
match e:
38+
case BinOp(left, Add(), right):
39+
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
40+
return l + r
41+
case BinOp(left, Sub(), right):
42+
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
43+
return l - r
44+
case UnaryOp(USub(), v):
45+
return - self.interp_exp(v, env)
46+
case Constant(value):
47+
return value
48+
case Call(Name('input_int'), []):
49+
return int(input())
50+
case _:
51+
raise Exception('error in interp_exp, unexpected ' + repr(e))
52+
53+
def interp_stmts(self, ss, env):
54+
if len(ss) == 0:
55+
return
56+
match ss[0]:
57+
case Expr(Call(Name('print'), [arg])):
58+
print(self.interp_exp(arg, env), end='')
59+
return self.interp_stmts(ss[1:], env)
60+
case Expr(value):
61+
self.interp_exp(value, env)
62+
return self.interp_stmts(ss[1:], env)
63+
case _:
64+
raise Exception('error in interp_stmts, unexpected ' + repr(ss[0]))
65+
66+
def interp(self, p):
67+
match p:
68+
case Module(body):
69+
self.interp_stmts(body, {})
70+
71+
if __name__ == "__main__":
72+
eight = Constant(8)
73+
neg_eight = UnaryOp(USub(), eight)
74+
read = Call(Name('input_int'), [])
75+
ast1_1 = BinOp(read, Add(), neg_eight)
76+
pr = Expr(Call(Name('print'), [ast1_1]))
77+
p = Module([pr])
78+
interp_Lint(p)

0 commit comments

Comments
 (0)