-
Notifications
You must be signed in to change notification settings - Fork 38
/
interp_Ldyn.py
166 lines (147 loc) · 5.54 KB
/
interp_Ldyn.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
from ast import *
from interp_Lfun import Function
from interp_Llambda import InterpLlambda
from utils import *
from dataclasses import dataclass
@dataclass(eq=True)
class Tagged(Value):
value : Value
tag : str
__match_args__ = ("value", "tag")
def __str__(self):
return str(self.value)
# todo: refactor the primitive operations
class InterpLdyn(InterpLlambda):
def tag(self, v):
if v is True or v is False:
return Tagged(v, 'bool')
elif isinstance(v, int):
return Tagged(v, 'int')
elif isinstance(v, Function):
return Tagged(v, 'function')
elif isinstance(v, list):
return Tagged(v, 'tuple')
elif isinstance(v, type(None)):
return Tagged(v, 'none')
else:
raise Exception('tag: unexpected ' + repr(v))
def untag(self, v, expected_tag, ast):
match v:
case Tagged(val, tag):
if tag != expected_tag:
raise TrappedError('expected tag ' + expected_tag \
+ ', not ' + ' ' + repr(v))
return val
case _:
raise Exception('expected Tagged value with ' + expected_tag \
+ ', not ' + ' ' + repr(v))
def apply_fun(self, fun, args, e):
f = self.untag(fun, 'function', e)
return super().apply_fun(f, args, e)
def interp_exp(self, e, env):
match e:
# Tag the values
case Constant(n):
return self.tag(super().interp_exp(e, env))
case Tuple(es, Load()):
return self.tag(super().interp_exp(e, env))
case ast.List(es, Load()):
return self.tag(super().interp_exp(e, env))
case Lambda(params, body):
return self.tag(super().interp_exp(e, env))
case Call(Name('input_int'), []):
return self.tag(super().interp_exp(e, env))
# Lint operations
case BinOp(left, Add(), right):
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
return self.tag(self.untag(l, 'int', e) + self.untag(r, 'int', e))
case BinOp(left, Sub(), right):
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
return self.tag(self.untag(l, 'int', e) - self.untag(r, 'int', e))
case UnaryOp(USub(), e1):
v = self.interp_exp(e1, env)
return self.tag(- self.untag(v, 'int', e))
# Lif operations
case IfExp(test, body, orelse):
v = self.interp_exp(test, env)
match self.untag(v, 'bool', e):
case True:
return self.interp_exp(body, env)
case False:
return self.interp_exp(orelse, env)
case UnaryOp(Not(), e1):
v = self.interp_exp(e1, env)
return self.tag(not self.untag(v, 'bool', e))
case BoolOp(And(), values):
left = values[0]; right = values[1]
l = self.interp_exp(left, env)
match self.untag(l, 'bool', e):
case True:
return self.interp_exp(right, env)
case False:
return self.tag(False)
case BoolOp(Or(), values):
left = values[0]; right = values[1]
l = self.interp_exp(left, env)
match self.untag(l, 'bool', e):
case True:
return True
case False:
return self.interp_exp(right, env)
case Compare(left, [cmp], [right]):
l = self.interp_exp(left, env)
r = self.interp_exp(right, env)
if l.tag == r.tag:
return self.tag(self.interp_cmp(cmp)(l.value, r.value))
else:
raise Exception('interp Compare unexpected ' \
+ repr(l) + ' ' + repr(r))
# Ltup operations
case Subscript(tup, index, Load()):
t = self.interp_exp(tup, env)
n = self.interp_exp(index, env)
return self.untag(t, 'tuple', e)[self.untag(n, 'int', e)]
case Call(Name('len'), [tup]):
t = self.interp_exp(tup, env)
return self.tag(len(self.untag(t, 'tuple', e)))
# Larray operations
case BinOp(left, Mult(), right):
l = self.interp_exp(left, env); r = self.interp_exp(right, env)
return self.tag(self.untag(l, 'int', e) * self.untag(r, 'int', e))
case _:
return super().interp_exp(e, env)
def interp_stmt(self, s, env, cont):
match s:
# Lif statements
case If(test, body, orelse):
v = self.interp_exp(test, env)
match self.untag(v, 'bool', s):
case True:
return self.interp_stmts(body + cont, env)
case False:
return self.interp_stmts(orelse + cont, env)
# Lwhile statements
case While(test, body, []):
v = self.interp_exp(test, env)
if self.untag(v, 'bool', test):
self.interp_stmts(body + [s] + cont, env)
else:
return self.interp_stmts(cont, env)
# Ltup statements
case Assign([Subscript(tup, index)], value):
tup = self.interp_exp(tup, env)
index = self.interp_exp(index, env)
tup_v = self.untag(tup, 'tuple', s)
index_v = self.untag(index, 'int', s)
tup_v[index_v] = self.interp_exp(value, env)
return self.interp_stmts(cont, env)
# override to tag the function
case FunctionDef(name, params, bod, dl, returns, comment):
if isinstance(params, ast.arguments):
ps = [p.arg for p in params.args]
else:
ps = [x for (x,t) in params]
env[name] = self.tag(Function(name, ps, bod, env))
return self.interp_stmts(cont, env)
case _:
return super().interp_stmt(s, env, cont)