experiment with methods of parametric type
This commit is contained in:
parent
a46edc8a47
commit
3457e594ec
|
@ -13,6 +13,9 @@ class Vec:
|
||||||
else:
|
else:
|
||||||
return Vec([self.v[i] + other.v[i] for i in range(len(self.v))])
|
return Vec([self.v[i] + other.v[i] for i in range(len(self.v))])
|
||||||
|
|
||||||
|
def get(self, index: int32) -> int32:
|
||||||
|
return self.v.head()
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar('T', int32, list[int32])
|
T = TypeVar('T', int32, list[int32])
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,10 @@ def resolve_call(obj,
|
||||||
# TODO: we may want to return the substitution, for monomorphization...
|
# TODO: we may want to return the substitution, for monomorphization...
|
||||||
f_args = None
|
f_args = None
|
||||||
f_result = None
|
f_result = None
|
||||||
|
subst = {}
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
obj = obj.subst(assumptions)
|
obj = obj.subst(assumptions)
|
||||||
|
subst = obj.get_subst()
|
||||||
if obj is None:
|
if obj is None:
|
||||||
if fn in ctx.functions:
|
if fn in ctx.functions:
|
||||||
f = ctx.functions[fn]
|
f = ctx.functions[fn]
|
||||||
|
@ -107,7 +109,8 @@ def resolve_call(obj,
|
||||||
f_args, f_result = TupleType([]), c
|
f_args, f_result = TupleType([]), c
|
||||||
else:
|
else:
|
||||||
raise CustomError(f"No such function {fn}")
|
raise CustomError(f"No such function {fn}")
|
||||||
elif isinstance(obj, PrimitiveType) or isinstance(obj, ClassType):
|
elif isinstance(obj, PrimitiveType) or isinstance(obj, ClassType) \
|
||||||
|
or isinstance(obj, ParametricType):
|
||||||
if fn in obj.methods:
|
if fn in obj.methods:
|
||||||
f = obj.methods[fn]
|
f = obj.methods[fn]
|
||||||
if len(f[0]) == 0 or (not isinstance(f[0][0], SelfType) and \
|
if len(f[0]) == 0 or (not isinstance(f[0][0], SelfType) and \
|
||||||
|
@ -154,7 +157,7 @@ def resolve_call(obj,
|
||||||
raise CustomError("Divergent type after constraints substitution")
|
raise CustomError("Divergent type after constraints substitution")
|
||||||
|
|
||||||
a = TupleType(args)
|
a = TupleType(args)
|
||||||
subst = find_subst(assumptions, {}, a, f_args)
|
subst = find_subst(assumptions, subst, a, f_args)
|
||||||
if isinstance(subst, str):
|
if isinstance(subst, str):
|
||||||
raise CustomError(f"type check failed: {subst}")
|
raise CustomError(f"type check failed: {subst}")
|
||||||
result = f_result.subst(subst)
|
result = f_result.subst(subst)
|
||||||
|
|
|
@ -66,6 +66,11 @@ i32.methods['__init__'] = ([SelfType(), I], None, {'I'})
|
||||||
i64.methods['__init__'] = ([SelfType(), I], None, {'I'})
|
i64.methods['__init__'] = ([SelfType(), I], None, {'I'})
|
||||||
f32.methods['__init__'] = ([SelfType(), I], None, {'I'})
|
f32.methods['__init__'] = ([SelfType(), I], None, {'I'})
|
||||||
|
|
||||||
|
ParametricType.method_table['list'] = {
|
||||||
|
'get': ([SelfType(), i32], TypeVariable('T1', []), set()),
|
||||||
|
'head': ([SelfType()], TypeVariable('T1', []), set())
|
||||||
|
}
|
||||||
|
|
||||||
simplest_ctx = Context({}, types)
|
simplest_ctx = Context({}, types)
|
||||||
simplest_ctx.functions['len'] = ([ListType(A)], i32, {'A'})
|
simplest_ctx.functions['len'] = ([ListType(A)], i32, {'A'})
|
||||||
simplest_ctx.functions['range'] = ([i32], ListType(i32), set())
|
simplest_ctx.functions['range'] = ([i32], ListType(i32), set())
|
||||||
|
|
|
@ -23,6 +23,9 @@ class Type:
|
||||||
return tv
|
return tv
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def get_subst(self):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class BotType:
|
class BotType:
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
@ -113,10 +116,16 @@ class VirtualClassType(Type):
|
||||||
|
|
||||||
class ParametricType(Type):
|
class ParametricType(Type):
|
||||||
params: list[Type]
|
params: list[Type]
|
||||||
|
name: str
|
||||||
|
|
||||||
def __init__(self, params: list[Type]):
|
method_table = {}
|
||||||
|
|
||||||
|
def __init__(self, name, params: list[Type]):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.params = params
|
self.params = params
|
||||||
|
self.name = name
|
||||||
|
if name in ParametricType.method_table:
|
||||||
|
self.methods = ParametricType.method_table[name]
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if type(self) != type(other) or len(self.params) != len(other.params):
|
if type(self) != type(other) or len(self.params) != len(other.params):
|
||||||
|
@ -148,9 +157,12 @@ class ParametricType(Type):
|
||||||
s.params = [v.inv_subst(subst) for v in self.params]
|
s.params = [v.inv_subst(subst) for v in self.params]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def get_subst(self):
|
||||||
|
return {f'T{i + 1}': v for i, v in enumerate(self.params)}
|
||||||
|
|
||||||
class ListType(ParametricType):
|
class ListType(ParametricType):
|
||||||
def __init__(self, param: Type):
|
def __init__(self, param: Type):
|
||||||
super().__init__([param])
|
super().__init__('list', [param])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"list[{self.params[0]}]"
|
return f"list[{self.params[0]}]"
|
||||||
|
@ -158,7 +170,7 @@ class ListType(ParametricType):
|
||||||
|
|
||||||
class TupleType(ParametricType):
|
class TupleType(ParametricType):
|
||||||
def __init__(self, params: list[Type]):
|
def __init__(self, params: list[Type]):
|
||||||
super().__init__(params)
|
super().__init__('tuple', params)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"tuple[{', '.join([str(v) for v in self.params])}]"
|
return f"tuple[{', '.join([str(v) for v in self.params])}]"
|
||||||
|
|
Loading…
Reference in New Issue