Skip to content

Commit c36b369

Browse files
committed
adding UncheckedCast
1 parent d7df743 commit c36b369

File tree

9 files changed

+117
-17
lines changed

9 files changed

+117
-17
lines changed

interp_Clambda.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ def interp_exp(self, e, env):
2525
case AllocateClosure(length, typ, arity):
2626
array = [None] * length
2727
return ClosureTuple(array, arity)
28+
case UncheckedCast(exp, ty):
29+
return self.interp_exp(exp, env)
2830
case _:
2931
return super().interp_exp(e, env)

interp_Lany.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ def interp_exp(self, e, env):
5050
match e:
5151
case Inject(value, typ):
5252
v = self.interp_exp(value, env)
53+
if isinstance(value, Tagged):
54+
raise Exception('cannot inject a value that is already tagged')
5355
return Tagged(v, self.type_to_tag(typ))
5456
case Project(value, typ):
5557
v = self.interp_exp(value, env)
@@ -58,7 +60,7 @@ def interp_exp(self, e, env):
5860
return val
5961
case _:
6062
raise Exception('interp project to ' + repr(typ) \
61-
+ ' unexpected ' + repr(v))
63+
+ ' unexpected ' + repr(v) + '\nin\n' + str(e))
6264
case Call(Name(atl), [tup, index]) \
6365
if atl == 'any_load' or atl == 'any_load_unsafe':
6466
tv = self.interp_exp(tup, env)
@@ -93,6 +95,8 @@ def interp_exp(self, e, env):
9395
case Call(Name('make_any'), [value, tag]):
9496
v = self.interp_exp(value, env)
9597
t = self.interp_exp(tag, env)
98+
if isinstance(v, Tagged):
99+
raise Exception('cannot inject a value that is already tagged')
96100
return Tagged(v, t)
97101
case Call(Name('arity'), [fun]):
98102
f = self.interp_exp(fun, env)

interp_Llambda.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ def interp_exp(self, e, env):
3939
return env[id]
4040
case Lambda(params, body):
4141
return Function('lambda', params, [Return(body)], env)
42+
case UncheckedCast(exp, ty):
43+
return self.interp_exp(exp, env)
4244
case Closure(arity, args):
4345
return ClosureTuple([self.interp_exp(arg, env) for arg in args], arity)
4446
case AllocateClosure(length, typ, arity):

type_check_Cif.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ def type_check(self, p):
116116
self.type_check_tail(ss[-1], env)
117117
if env == old_env:
118118
break
119-
undefs = [x for x,t in env.items() if t == Bottom()]
120-
if undefs:
121-
raise Exception('error: undefined type for ' + str(undefs))
119+
# because of explicate_control there can be undefined vars -Jeremy
120+
# undefs = [x for x,t in env.items() if t == Bottom()]
121+
# if undefs:
122+
# raise Exception('error: undefined type for ' + str(undefs))
122123
p.var_types = env
123124
case _:
124125
raise Exception('error in type_check, unexpected ' + repr(p))

type_check_Clambda.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from utils import AllocateClosure, Uninitialized
1+
from utils import AllocateClosure, Uninitialized, UncheckedCast
22
from type_check_Cfun import TypeCheckCfun
33

44
class TypeCheckClambda(TypeCheckCfun):
@@ -9,6 +9,9 @@ def type_check_exp(self, e, env):
99
return ty
1010
case AllocateClosure(length, typ, arity):
1111
return typ
12+
case UncheckedCast(exp, ty):
13+
self.type_check_exp(exp, env)
14+
return ty
1215
case _:
1316
return super().type_check_exp(e, env)
1417

type_check_Larray.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def type_check_exp(self, e, env):
8585
case Bottom():
8686
return VoidType()
8787
case _:
88-
raise Exception('type_check_stmts: unexpected ' + repr(tup_t))
88+
raise Exception('type_check_exp: unexpected ' + repr(tup_t))
8989
case BinOp(left, Mult(), right):
9090
l = self.type_check_exp(left, env)
9191
self.check_type_equal(l, IntType(), left)
@@ -111,7 +111,11 @@ def type_check_stmts(self, ss, env):
111111
case TupleType(ts):
112112
match index:
113113
case Constant(i):
114-
self.check_type_equal(ts[i], value_t, ss[0])
114+
if 0 <= i and i < len(ts):
115+
self.check_type_equal(ts[i], value_t, ss[0])
116+
else:
117+
raise Exception('subscript ' + str(i) + ' not in range of '
118+
+ str(tup_t) + ' in\n' + str(ss[0]))
115119
case _:
116120
raise Exception('subscript required constant integer index')
117121
case ListType(ty):

type_check_Lgrad.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,45 @@ def type_check_exp(self, e, env):
171171
e.has_type = ListType(elt_ty)
172172
return e.has_type
173173

174+
case Call(Name('array_len'), [tup]):
175+
tup_t = self.type_check_exp(tup, env)
176+
tup.has_type = tup_t
177+
match tup_t:
178+
case ListType(ty):
179+
return IntType()
180+
case Bottom():
181+
return Bottom()
182+
case AnyType():
183+
return IntType()
184+
case _:
185+
raise Exception('array_len: unexpected ' + repr(tup_t))
186+
case Call(Name('array_load'), [lst, index]):
187+
lst_ty = self.type_check_exp(lst, env)
188+
index_ty = self.type_check_exp(index, env)
189+
self.check_consistent(index_ty, IntType(), index)
190+
match lst_ty:
191+
case ListType(ty):
192+
return ty
193+
case AnyType():
194+
return AnyType()
195+
case _:
196+
raise Exception('array_load: unexpected ' + repr(lst_ty))
197+
case Call(Name('array_store'), [tup, index, value]):
198+
tup_t = self.type_check_exp(tup, env)
199+
value_t = self.type_check_exp(value, env)
200+
index_ty = self.type_check_exp(index, env)
201+
self.check_consistent(index_ty, IntType(), index)
202+
match tup_t:
203+
case ListType(ty):
204+
self.check_consistent(ty, value_t, e)
205+
return VoidType()
206+
case Bottom():
207+
return VoidType()
208+
case AnyType():
209+
return VoidType()
210+
case _:
211+
raise Exception('type_check_exp: unexpected ' + repr(tup_t))
212+
174213
# Cases for Llambda
175214
case Lambda(params, body):
176215
self.check_exp(e, AnyType(), env)
@@ -185,18 +224,35 @@ def type_check_exp(self, e, env):
185224
case _:
186225
raise Exception('type_check_exp: in arity, unexpected ' + \
187226
repr(func_t))
227+
228+
# primitives introduced by the resolve pass
229+
case Call(Name('any_load'), [tup, index]):
230+
self.check_exp(tup, AnyType(), env)
231+
self.check_exp(index, IntType(), env)
232+
return AnyType()
233+
case Call(Name('any_store'), [tup, index, value]):
234+
self.check_exp(tup, AnyType(), env)
235+
self.type_check_exp(value, env)
236+
self.check_exp(index, IntType(), env)
237+
return VoidType()
238+
case Call(Name('any_len'), [tup]):
239+
self.check_exp(tup, AnyType(), env)
240+
return IntType()
241+
188242
# Cases for Lfun (last because the below Call pattern is general)
189243
case FunRef(id, arity):
190244
return env[id]
191245
case Call(func, args):
192246
func_t = self.type_check_exp(func, env)
193-
args_t = [self.type_check_exp(arg, env) for arg in args]
194247
match func_t:
195248
case FunctionType(params_t, return_t):
196-
for (arg_t, param_t) in zip(args_t, params_t):
197-
self.check_consistent(param_t, arg_t, e)
249+
for (arg, param_t) in zip(args, params_t):
250+
self.check_exp(arg, param_t, env)
251+
# for (arg_t, param_t) in zip(args_t, params_t):
252+
# self.check_consistent(param_t, arg_t, e)
198253
return return_t
199254
case AnyType():
255+
args_t = [self.type_check_exp(arg, env) for arg in args]
200256
anys = [AnyType() for _ in args_t]
201257
fun_ty = FunctionType(anys, AnyType())
202258
return AnyType()
@@ -209,6 +265,7 @@ def type_check_exp(self, e, env):
209265
def check_exp(self, e, ty, env):
210266
match e:
211267
case Lambda(params, body):
268+
trace('check_exp: ' + str(e) + '\nexpected type: ' + str(ty))
212269
if isinstance(params, ast.arguments):
213270
new_params = [a.arg for a in params.args]
214271
e.args = new_params

type_check_Llambda.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,36 @@
99

1010
class TypeCheckLlambda(TypeCheckLfun):
1111

12+
# Example:
13+
# given: Callable[[tuple[bottom,tuple[int]], int], int]
14+
# output: tuple[Callable[[tuple[],int], int]]:
15+
def closure_type(self, fun_ty):
16+
match fun_ty:
17+
case FunctionType(params, rt):
18+
return TupleType([FunctionType([TupleType([])] + params[1:], rt)])
19+
case _:
20+
raise Exception('erase_closure_type expected function type, not '
21+
+ str(fun_ty))
22+
1223
def type_check_exp(self, e, env):
1324
match e:
1425
case Name(id):
1526
e.has_type = env[id]
1627
return env[id]
1728
case FunRef(id, arity):
18-
return env[id]
29+
e.has_type = env[id]
30+
return e.has_type
31+
case UncheckedCast(exp, ty):
32+
self.type_check_exp(exp, env)
33+
return ty
1934
case Closure(arity, es):
2035
ts = [self.type_check_exp(e, env) for e in es]
36+
# closure values with different shapes must be given compatible types
37+
# e.has_type and e.erased_type is used in expose_allocation
2138
e.has_type = TupleType(ts)
22-
return e.has_type # this is just wrong: closure values with different shapes must be given compatible types
39+
function_type = ts[0]
40+
e.erased_type = self.closure_type(function_type)
41+
return e.erased_type
2342
case Lambda(params, body):
2443
raise Exception('cannot synthesize a type for lambda: ' + str(e))
2544
case AllocateClosure(length, typ, arity):
@@ -42,11 +61,10 @@ def type_check_exp(self, e, env):
4261
case FunctionType(params_t, return_t):
4362
for (arg, param_t) in zip(args, params_t):
4463
self.check_exp(arg, param_t, env)
45-
# self.check_type_equal(return_t, ty, e)
4664
return return_t
4765
case _:
48-
raise Exception('type_check_exp: in call, unexpected ' + \
49-
repr(func_t))
66+
raise Exception('type_check_exp: unexpected ' + \
67+
repr(func_t) + '\nin call\n' + str(e))
5068
case Uninitialized(ty):
5169
return ty
5270
case _:

utils.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,11 @@ def __str__(self):
747747
return 'alloc_clos(' + str(self.length) + ',' + str(self.ty) \
748748
+ ',' + str(self.arity) + ')'
749749

750+
@dataclass
751+
class UncheckedCast(expr):
752+
exp: expr
753+
ty: Type
754+
__match_args__ = ("exp","ty")
750755

751756
@dataclass
752757
class Collect(stmt):
@@ -766,7 +771,7 @@ class Begin(expr):
766771
def __str__(self):
767772
indent()
768773
stmts = ''.join([str(s) for s in self.body])
769-
end = indent_stmt() + + 'produce ' + str(self.result)
774+
end = indent_stmt() + 'produce ' + str(self.result)
770775
dedent()
771776
return '{\n' + stmts + end + '}'
772777

@@ -877,7 +882,11 @@ class Closure(expr):
877882
__match_args__ = ("arity", "args")
878883

879884
def __str__(self):
880-
return 'closure{' + repr(self.arity) + '}(' + ', '.join([str(e) for e in self.args]) + ')'
885+
if hasattr(self, 'has_type'):
886+
typ = ':' + str(self.has_type)
887+
else:
888+
typ = ''
889+
return 'closure{' + repr(self.arity) + '}(' + ', '.join([str(e) for e in self.args]) + ')' + typ
881890

882891

883892
@dataclass

0 commit comments

Comments
 (0)