Skip to content

Commit 9080d12

Browse files
committed
update interpreters and type checkers
1 parent 506c93a commit 9080d12

18 files changed

+116
-283
lines changed

interp_Carray.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ def interp_exp(self, e, env):
99
case ast.List(es, Load()):
1010
return [self.interp_exp(e, env) for e in es]
1111
case BinOp(left, Mult(), right):
12-
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
12+
l = self.interp_exp(left, env)
13+
r = self.interp_exp(right, env)
1314
return l * r
1415
case AllocateArray(length, typ):
1516
array = [None] * length
@@ -20,11 +21,17 @@ def interp_exp(self, e, env):
2021
case Call(Name('array_load'), [tup, index]):
2122
t = self.interp_exp(tup, env)
2223
n = self.interp_exp(index, env)
23-
return t[n]
24+
if n < len(t):
25+
return t[n]
26+
else:
27+
raise TrappedError('array index out of bounds')
2428
case Call(Name('array_store'), [tup, index, value]):
2529
tup = self.interp_exp(tup, env)
2630
index = self.interp_exp(index, env)
27-
tup[index] = self.interp_exp(value, env)
31+
if index < len(tup):
32+
tup[index] = self.interp_exp(value, env)
33+
else:
34+
raise TrappedError('array index out of bounds')
2835
return None
2936
case _:
3037
return super().interp_exp(e, env)

interp_Cfun.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,12 @@ def interp_exp(self, e, env):
3232
case _:
3333
return super().interp_exp(e, env)
3434

35-
def interp_stmts(self, ss, env):
36-
if len(ss) == 0:
37-
raise Exception('interp_stmts function ended without return')
38-
match ss[0]:
35+
def interp_stmt(self, s, env, cont):
36+
match s:
3937
case TailCall(func, args):
4038
return self.interp_exp(Call(func, args), env)
4139
case _:
42-
return super().interp_stmts(ss, env)
40+
return super().interp_stmt(s, env, cont)
4341

4442
def interp(self, p):
4543
match p:

interp_Cif.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44

55
class InterpCif(InterpLif):
66

7-
def interp_stmts(self, ss, env):
8-
if len(ss) == 0:
9-
return
10-
match ss[0]:
7+
def interp_stmt(self, s, env, cont):
8+
match s:
119
case Return(value):
1210
return self.interp_exp(value, env)
1311
case Goto(label):
1412
return self.interp_stmts(self.blocks[label], env)
1513
case _:
16-
return super().interp_stmts(ss, env)
14+
return super().interp_stmt(s, env, cont)
1715

1816
def interp(self, p):
1917
match p:

interp_Ctup.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,14 @@ def interp_exp(self, e, env):
2626
case _:
2727
return super().interp_exp(e, env)
2828

29-
def interp_stmts(self, ss, env):
30-
if len(ss) == 0:
31-
return
32-
match ss[0]:
29+
def interp_stmt(self, s, env, cont):
30+
match s:
3331
case Collect(size):
34-
return self.interp_stmts(ss[1:], env)
32+
return self.interp_stmts(cont, env)
3533
case Assign([Subscript(tup, index)], value):
3634
tup = self.interp_exp(tup, env)
3735
index = self.interp_exp(index, env)
3836
tup[index] = self.interp_exp(value, env)
39-
return self.interp_stmts(ss[1:], env)
37+
return self.interp_stmts(cont, env)
4038
case _:
41-
return super().interp_stmts(ss, env)
39+
return super().interp_stmt(s, env, cont)

interp_Larray.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ def interp_exp(self, e, env):
1111
case BinOp(left, Mult(), right):
1212
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
1313
return l * r
14+
case Subscript(tup, index, Load()):
15+
t = self.interp_exp(tup, env)
16+
n = self.interp_exp(index, env)
17+
if n < len(t):
18+
return t[n]
19+
else:
20+
raise TrappedError('array index out of bounds')
1421
case AllocateArray(length, typ):
1522
array = [None] * length
1623
return array
@@ -20,23 +27,30 @@ def interp_exp(self, e, env):
2027
case Call(Name('array_load'), [tup, index]):
2128
t = self.interp_exp(tup, env)
2229
n = self.interp_exp(index, env)
23-
return t[n]
30+
if n < len(t):
31+
return t[n]
32+
else:
33+
raise TrappedError('array index out of bounds')
2434
case Call(Name('array_store'), [tup, index, value]):
25-
tup = self.interp_exp(tup, env)
26-
index = self.interp_exp(index, env)
27-
tup[index] = self.interp_exp(value, env)
35+
t = self.interp_exp(tup, env)
36+
n = self.interp_exp(index, env)
37+
if n < len(t):
38+
t[n] = self.interp_exp(value, env)
39+
else:
40+
raise TrappedError('array index out of bounds')
2841
return None
2942
case _:
3043
return super().interp_exp(e, env)
3144

32-
def interp_stmts(self, ss, env):
33-
if len(ss) == 0:
34-
return
35-
match ss[0]:
45+
def interp_stmt(self, s, env, cont):
46+
match s:
3647
case Assign([Subscript(tup, index)], value):
37-
tup = self.interp_exp(tup, env)
38-
index = self.interp_exp(index, env)
39-
tup[index] = self.interp_exp(value, env)
40-
return self.interp_stmts(ss[1:], env)
48+
t = self.interp_exp(tup, env)
49+
n = self.interp_exp(index, env)
50+
if n < len(t):
51+
t[n] = self.interp_exp(value, env)
52+
else:
53+
raise TrappedError('array index out of bounds')
54+
return self.interp_stmts(cont, env)
4155
case _:
42-
return super().interp_stmts(ss, env)
56+
return super().interp_stmt(s, env, cont)

interp_Ldyn.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def untag(self, v, expected_tag, ast):
3434
match v:
3535
case Tagged(val, tag):
3636
if tag != expected_tag:
37-
raise Exception('expected tag ' + expected_tag \
38-
+ ', not ' + ' ' + repr(v))
37+
raise TrappedError('expected tag ' + expected_tag \
38+
+ ', not ' + ' ' + repr(v))
3939
return val
4040
case _:
4141
raise Exception('expected Tagged value with ' + expected_tag \
@@ -123,34 +123,34 @@ def interp_exp(self, e, env):
123123
case _:
124124
return super().interp_exp(e, env)
125125

126-
def interp_stmts(self, ss, env):
127-
if len(ss) == 0:
128-
return
129-
match ss[0]:
126+
def interp_stmt(self, s, env, cont):
127+
match s:
130128

131129
# Lif statements
132130
case If(test, body, orelse):
133131
v = self.interp_exp(test, env)
134-
match self.untag(v, 'bool', ss[0]):
132+
match self.untag(v, 'bool', s):
135133
case True:
136-
return self.interp_stmts(body + ss[1:], env)
134+
return self.interp_stmts(body + cont, env)
137135
case False:
138-
return self.interp_stmts(orelse + ss[1:], env)
136+
return self.interp_stmts(orelse + cont, env)
139137

140138
# Lwhile statements
141139
case While(test, body, []):
142-
while self.untag(self.interp_exp(test, env), 'bool', ss[0]):
143-
self.interp_stmts(body, env)
144-
return self.interp_stmts(ss[1:], env)
140+
v = self.interp_exp(test, env)
141+
if self.untag(v, 'bool', test):
142+
self.interp_stmts(body + [s] + cont, env)
143+
else:
144+
return self.interp_stmts(cont, env)
145145

146146
# Ltup statements
147147
case Assign([Subscript(tup, index)], value):
148148
tup = self.interp_exp(tup, env)
149149
index = self.interp_exp(index, env)
150-
tup_v = self.untag(tup, 'tuple', ss[0])
151-
index_v = self.untag(index, 'int', ss[0])
150+
tup_v = self.untag(tup, 'tuple', s)
151+
index_v = self.untag(index, 'int', s)
152152
tup_v[index_v] = self.interp_exp(value, env)
153-
return self.interp_stmts(ss[1:], env)
153+
return self.interp_stmts(cont, env)
154154

155155
# override to tag the function
156156
case FunctionDef(name, params, bod, dl, returns, comment):
@@ -159,8 +159,8 @@ def interp_stmts(self, ss, env):
159159
else:
160160
ps = [x for (x,t) in params]
161161
env[name] = self.tag(Function(name, ps, bod, env))
162-
return self.interp_stmts(ss[1:], env)
162+
return self.interp_stmts(cont, env)
163163

164164
case _:
165-
return super().interp_stmts(ss, env)
165+
return super().interp_stmt(s, env, cont)
166166

interp_Lfun.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@ def interp_exp(self, e, env):
3737
case _:
3838
return super().interp_exp(e, env)
3939

40-
def interp_stmts(self, ss, env):
41-
if len(ss) == 0:
42-
return
43-
match ss[0]:
40+
def interp_stmt(self, s, env, cont):
41+
match s:
4442
case Return(value):
4543
return self.interp_exp(value, env)
4644
case FunctionDef(name, params, bod, dl, returns, comment):
@@ -49,9 +47,9 @@ def interp_stmts(self, ss, env):
4947
else:
5048
ps = [x for (x,t) in params]
5149
env[name] = Function(name, ps, bod, env)
52-
return self.interp_stmts(ss[1:], env)
50+
return self.interp_stmts(cont, env)
5351
case _:
54-
return super().interp_stmts(ss, env)
52+
return super().interp_stmt(s, env, cont)
5553

5654
def interp(self, p):
5755
match p:

interp_Lif.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,14 @@ def interp_exp(self, e, env):
5858
case _:
5959
return super().interp_exp(e, env)
6060

61-
def interp_stmts(self, ss, env):
62-
if len(ss) == 0:
63-
return
64-
match ss[0]:
61+
def interp_stmt(self, s, env, cont):
62+
match s:
6563
case If(test, body, orelse):
6664
match self.interp_exp(test, env):
6765
case True:
68-
return self.interp_stmts(body + ss[1:], env)
66+
return self.interp_stmts(body + cont, env)
6967
case False:
70-
return self.interp_stmts(orelse + ss[1:], env)
68+
return self.interp_stmts(orelse + cont, env)
7169
case _:
72-
return super().interp_stmts(ss, env)
70+
return super().interp_stmt(s, env, cont)
7371

interp_Lint.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,27 @@ def interp_exp(self, e, env):
5050
case _:
5151
raise Exception('error in interp_exp, unexpected ' + repr(e))
5252

53-
def interp_stmts(self, ss, env):
54-
if len(ss) == 0:
55-
return
56-
match ss[0]:
53+
# The cont parameter is a list of statements that are the
54+
# continuaton of the current statement s.
55+
# We use this continuation-passing approach because
56+
# it enables the handling of Goto in interp_Cif.py.
57+
def interp_stmt(self, s, env, cont):
58+
match s:
5759
case Expr(Call(Name('print'), [arg])):
5860
val = self.interp_exp(arg, env)
5961
print(val, end='')
60-
return self.interp_stmts(ss[1:], env)
62+
return self.interp_stmts(cont, env)
6163
case Expr(value):
6264
self.interp_exp(value, env)
63-
return self.interp_stmts(ss[1:], env)
65+
return self.interp_stmts(cont, env)
6466
case _:
65-
raise Exception('error in interp_stmts, unexpected ' + repr(ss[0]))
67+
raise Exception('error in interp_stmt, unexpected ' + repr(s))
68+
69+
def interp_stmts(self, ss, env):
70+
if len(ss) == 0:
71+
return None
72+
else:
73+
return self.interp_stmt(ss[0], env, ss[1:])
6674

6775
def interp(self, p):
6876
match p:

interp_Llambda.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ def __getitem__(self, item):
1414
return self.args[item]
1515
def __setitem__(self, item, value):
1616
self.args[item] = value
17+
def __len__(self):
18+
return len(self.args)
1719

1820
class InterpLlambda(InterpLfun):
1921

@@ -45,15 +47,13 @@ def interp_exp(self, e, env):
4547
case _:
4648
return super().interp_exp(e, env)
4749

48-
def interp_stmts(self, ss, env):
49-
if len(ss) == 0:
50-
return
51-
match ss[0]:
50+
def interp_stmt(self, s, env, cont):
51+
match s:
5252
case AnnAssign(lhs, typ, value, simple):
5353
env[lhs.id] = self.interp_exp(value, env)
54-
return self.interp_stmts(ss[1:], env)
54+
return self.interp_stmts(cont, env)
5555
case Pass():
56-
return self.interp_stmts(ss[1:], env)
56+
return self.interp_stmts(cont, env)
5757
case _:
58-
return super().interp_stmts(ss, env)
58+
return super().interp_stmt(s, env, cont)
5959

0 commit comments

Comments
 (0)