Skip to content

Commit 257e4b2

Browse files
committed
update type checkers and interpreters
1 parent e2f850f commit 257e4b2

14 files changed

+332
-119
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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ def interp_exp(self, e, env):
2525
match e:
2626
case Call(Name('input_int'), []):
2727
return super().interp_exp(e, env)
28+
case Call(Name('len'), [tup]):
29+
return super().interp_exp(e, env)
2830
case Call(func, args):
2931
f = self.interp_exp(func, env)
3032
vs = [self.interp_exp(arg, env) for arg in args]

interp_Lfun.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def apply_fun(self, fun, args, e):
2626

2727
def interp_exp(self, e, env):
2828
match e:
29-
case Call(Name('input_int'), []):
29+
case Call(Name(f), args) if (f == 'input_int') or (f == 'len') or (f == 'print'):
3030
return super().interp_exp(e, env)
3131
case Call(func, args):
3232
f = self.interp_exp(func, env)

interp_Ltup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ def interp_cmp(self, cmp):
1414
def interp_exp(self, e, env):
1515
match e:
1616
case Tuple(es, Load()):
17-
return tuple([self.interp_exp(e, env) for e in es])
17+
# use a list for mutability
18+
return [self.interp_exp(e, env) for e in es]
1819
case Subscript(tup, index, Load()):
1920
t = self.interp_exp(tup, env)
2021
n = self.interp_exp(index, env)

type_check_Cfun.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,41 @@
11
from ast import *
22
from utils import *
3-
from type_check_Ctup import check_type_equal, TypeCheckCtup
3+
from type_check_Ctup import TypeCheckCtup
44
import copy
55

66
class TypeCheckCfun(TypeCheckCtup):
7-
8-
# def parse_type_annot(self, annot):
9-
# match annot:
10-
# case Name(id):
11-
# if id == 'int':
12-
# return int
13-
# elif id == 'bool':
14-
# return bool
15-
# else:
16-
# raise Exception('parse_type_annot: unexpected ' + repr(annot))
17-
# case TupleType(ts):
18-
# return TupleType([self.parse_type_annot(t) for t in ts])
19-
# case FunctionType(ps, rt):
20-
# return FunctionType([self.parse_type_annot(t) for t in ps],
21-
# self.parse_type_annot(rt))
22-
# case Subscript(Name('Callable'), Tuple([ps, rt])):
23-
# return FunctionType([self.parse_type_annot(t) for t in ps.elts],
24-
# self.parse_type_annot(rt))
25-
# case Subscript(Name('tuple'), Tuple(ts)):
26-
# return TupleType([self.parse_type_annot(t) for t in ts])
27-
# case _:
28-
# raise Exception('parse_type_annot: unexpected ' + repr(annot))
29-
7+
8+
def check_type_equal(self, t1, t2, e):
9+
if t1 == Bottom() or t2 == Bottom():
10+
return
11+
match t1:
12+
case FunctionType(ps1, rt1):
13+
match t2:
14+
case FunctionType(ps2, rt2):
15+
for (p1,p2) in zip(ps1, ps2):
16+
self.check_type_equal(p1, p2, e)
17+
self.check_type_equal(rt1, rt2, e)
18+
case _:
19+
raise Exception('error: ' + repr(t1) + ' != ' + repr(t2) \
20+
+ ' in ' + repr(e))
21+
case _:
22+
super().check_type_equal(t1, t2, e)
23+
3024
def type_check_exp(self, e, env):
3125
match e:
3226
case FunRef(id):
3327
return env[id]
3428
case Call(Name('input_int'), []):
3529
return super().type_check_exp(e, env)
30+
case Call(Name('len'), [tup]):
31+
return super().type_check_exp(e, env)
3632
case Call(func, args):
3733
func_t = self.type_check_exp(func, env)
3834
args_t = [self.type_check_exp(arg, env) for arg in args]
3935
match func_t:
4036
case FunctionType(params_t, return_t):
4137
for (arg_t, param_t) in zip(args_t, params_t):
42-
check_type_equal(param_t, arg_t, e)
38+
self.check_type_equal(param_t, arg_t, e)
4339
return return_t
4440
case Bottom():
4541
return Bottom()

type_check_Cif.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
from utils import CProgram, Goto, trace, Bottom, Let
33
import copy
44

5-
def check_type_equal(t1, t2, e):
5+
class TypeCheckCif:
6+
7+
def check_type_equal(self, t1, t2, e):
68
if t1 == Bottom() or t2 == Bottom():
7-
pass
9+
pass
810
elif t1 != t2:
9-
raise Exception('error: ' + repr(t1) + ' != ' + repr(t2) \
10-
+ ' in ' + repr(e))
11-
12-
class TypeCheckCif:
11+
raise Exception('error: ' + repr(t1) + ' != ' + repr(t2) \
12+
+ ' in ' + repr(e))
1313

1414
def type_check_atm(self, e, env):
1515
match e:
@@ -30,35 +30,35 @@ def type_check_exp(self, e, env):
3030
return self.type_check_atm(e, env)
3131
case IfExp(test, body, orelse):
3232
test_t = self.type_check_exp(test, env)
33-
check_type_equal(bool, test_t, test)
33+
self.check_type_equal(bool, test_t, test)
3434
body_t = self.type_check_exp(body, env)
3535
orelse_t = self.type_check_exp(orelse, env)
36-
check_type_equal(body_t, orelse_t, e)
36+
self.check_type_equal(body_t, orelse_t, e)
3737
return body_t
3838
case BinOp(left, op, right) if isinstance(op, Add) or isinstance(op, Sub):
3939
l = self.type_check_atm(left, env)
40-
check_type_equal(l, int, e)
40+
self.check_type_equal(l, int, e)
4141
r = self.type_check_atm(right, env)
42-
check_type_equal(r, int, e)
42+
self.check_type_equal(r, int, e)
4343
return int
4444
case UnaryOp(USub(), v):
4545
t = self.type_check_atm(v, env)
46-
check_type_equal(t, int, e)
46+
self.check_type_equal(t, int, e)
4747
return int
4848
case UnaryOp(Not(), v):
4949
t = self.type_check_exp(v, env)
50-
check_type_equal(t, bool, e)
50+
self.check_type_equal(t, bool, e)
5151
return bool
5252
case Compare(left, [cmp], [right]) if isinstance(cmp, Eq) or isinstance(cmp, NotEq):
5353
l = self.type_check_atm(left, env)
5454
r = self.type_check_atm(right, env)
55-
check_type_equal(l, r, e)
55+
self.check_type_equal(l, r, e)
5656
return bool
5757
case Compare(left, [cmp], [right]):
5858
l = self.type_check_atm(left, env)
59-
check_type_equal(l, int, left)
59+
self.check_type_equal(l, int, left)
6060
r = self.type_check_atm(right, env)
61-
check_type_equal(r, int, right)
61+
self.check_type_equal(r, int, right)
6262
return bool
6363
case Call(Name('input_int'), []):
6464
return int
@@ -79,18 +79,18 @@ def type_check_stmt(self, s, env):
7979
case Assign([lhs], value):
8080
t = self.type_check_exp(value, env)
8181
if lhs.id in env:
82-
check_type_equal(env.get(lhs.id, Bottom()), t, s)
82+
self.check_type_equal(env.get(lhs.id, Bottom()), t, s)
8383
else:
8484
env[lhs.id] = t
8585
case Expr(Call(Name('print'), [arg])):
8686
t = self.type_check_exp(arg, env)
87-
check_type_equal(t, int, s)
87+
self.check_type_equal(t, int, s)
8888
case Expr(value):
8989
self.type_check_exp(value, env)
9090
case If(Compare(left, [cmp], [right]), body, orelse):
9191
left_t = self.type_check_atm(left, env)
9292
right_t = self.type_check_atm(right, env)
93-
check_type_equal(left_t, right_t, s) # not quite strict enough
93+
self.check_type_equal(left_t, right_t, s) # not quite strict enough
9494
self.type_check_stmts(body, env)
9595
self.type_check_stmts(orelse, env)
9696
case Goto(label):

type_check_Ctup.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
from ast import *
2-
from type_check_Cif import check_type_equal, Bottom
32
from type_check_Cwhile import TypeCheckCwhile
4-
from utils import Allocate, Begin, GlobalValue, Collect, TupleType
3+
from utils import Allocate, Begin, GlobalValue, Collect, TupleType, Bottom
54

65
class TypeCheckCtup(TypeCheckCwhile):
7-
6+
7+
def check_type_equal(self, t1, t2, e):
8+
match t1:
9+
case TupleType(ts1):
10+
match t2:
11+
case TupleType(ts2):
12+
for (ty1, ty2) in zip(ts1,ts2):
13+
self.check_type_equal(ty1, ty2, e)
14+
case Bottom():
15+
pass
16+
case _:
17+
raise Exception('error: ' + repr(t1) + ' != ' + repr(t2) \
18+
+ ' in ' + repr(e))
19+
case _:
20+
super().check_type_equal(t1, t2, e)
21+
822
def type_check_exp(self, e, env):
923
match e:
1024
case Allocate(length, typ):
@@ -36,16 +50,17 @@ def type_check_stmt(self, s, env):
3650
match s:
3751
case Collect(size):
3852
pass
39-
case Assign([Subscript(tup, Constant(index))], value):
53+
case Assign([Subscript(tup, Constant(index), Store())], value):
4054
tup_t = self.type_check_atm(tup, env)
4155
value_t = self.type_check_atm(value, env)
4256
match tup_t:
4357
case TupleType(ts):
44-
check_type_equal(ts[index], value_t, s)
58+
self.check_type_equal(ts[index], value_t, s)
4559
case Bottom():
4660
pass
4761
case _:
48-
raise Exception('error, expected a tuple, not ' + repr(tup_t))
62+
raise Exception('type_check_stmt: expected a tuple, not ' \
63+
+ repr(tup_t))
4964
case _:
5065
return super().type_check_stmt(s, env)
5166

type_check_Lfun.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
11
import ast
22
from ast import *
3-
from type_check_Lvar import check_type_equal
43
from type_check_Ltup import TypeCheckLtup
54
from utils import *
65
import typing
76

87
class TypeCheckLfun(TypeCheckLtup):
98

9+
def check_type_equal(self, t1, t2, e):
10+
if t1 == Bottom() or t2 == Bottom():
11+
return
12+
match t1:
13+
case FunctionType(ps1, rt1):
14+
match t2:
15+
case FunctionType(ps2, rt2):
16+
for (p1,p2) in zip(ps1, ps2):
17+
self.check_type_equal(p1, p2, e)
18+
self.check_type_equal(rt1, rt2, e)
19+
case _:
20+
raise Exception('error: ' + repr(t1) + ' != ' + repr(t2) \
21+
+ ' in ' + repr(e))
22+
case _:
23+
super().check_type_equal(t1, t2, e)
24+
1025
def parse_type_annot(self, annot):
1126
match annot:
1227
case Name(id):
@@ -26,8 +41,10 @@ def parse_type_annot(self, annot):
2641
self.parse_type_annot(rt))
2742
case Subscript(Name('tuple'), Tuple(ts)):
2843
return TupleType([self.parse_type_annot(t) for t in ts])
29-
case t if t == int or t == bool:
44+
case t if t == int or t == bool or t == type(None):
3045
return annot
46+
case Constant(None):
47+
return type(None)
3148
case _:
3249
raise Exception('parse_type_annot: unexpected ' + repr(annot))
3350

@@ -37,13 +54,15 @@ def type_check_exp(self, e, env):
3754
return env[id]
3855
case Call(Name('input_int'), []):
3956
return super().type_check_exp(e, env)
57+
case Call(Name('len'), [tup]):
58+
return super().type_check_exp(e, env)
4059
case Call(func, args):
4160
func_t = self.type_check_exp(func, env)
4261
args_t = [self.type_check_exp(arg, env) for arg in args]
4362
match func_t:
4463
case FunctionType(params_t, return_t):
4564
for (arg_t, param_t) in zip(args_t, params_t):
46-
check_type_equal(param_t, arg_t, e)
65+
self.check_type_equal(param_t, arg_t, e)
4766
return return_t
4867
case _:
4968
raise Exception('type_check_exp: in call, unexpected ' + \
@@ -68,7 +87,7 @@ def type_check_stmts(self, ss, env):
6887
for (x,t) in new_params:
6988
new_env[x] = t
7089
rt = self.type_check_stmts(body, new_env)
71-
check_type_equal(new_returns, rt, ss[0])
90+
self.check_type_equal(new_returns, rt, ss[0])
7291
return self.type_check_stmts(ss[1:], env)
7392
case Return(value):
7493
return self.type_check_exp(value, env)

0 commit comments

Comments
 (0)