189 lines
4.4 KiB
Python
189 lines
4.4 KiB
Python
import copy
|
|
|
|
class Type:
|
|
methods: dict[str, tuple[list['Type'], 'Type', set[str]]]
|
|
fields: dict[str, 'Type']
|
|
|
|
def __init__(self):
|
|
self.methods = {}
|
|
self.fields = {}
|
|
|
|
def __eq__(self, other):
|
|
return False
|
|
|
|
def get_vars(self):
|
|
return []
|
|
|
|
def subst(self, subst: dict[str, 'Type']):
|
|
return self
|
|
|
|
def inv_subst(self, subst: list[tuple['Type', 'TypeVariable']]):
|
|
for t, tv in subst:
|
|
if self == t:
|
|
return tv
|
|
return self
|
|
|
|
def get_subst(self):
|
|
return {}
|
|
|
|
|
|
class BotType:
|
|
def __eq__(self, other):
|
|
return isinstance(other, BotType)
|
|
|
|
|
|
class PrimitiveType(Type):
|
|
name: str
|
|
|
|
def __init__(self, name: str):
|
|
super().__init__()
|
|
self.name = name
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def __eq__(self, other):
|
|
return isinstance(other, PrimitiveType) and self.name == other.name
|
|
|
|
|
|
class TypeVariable(Type):
|
|
name: str
|
|
# this may be a list of str, Type may not be determined when type variables
|
|
# are instantiated...
|
|
# and they cannot contain other type variables
|
|
constraints: list[Type]
|
|
|
|
def __init__(self, name: str, constraints: list[Type]):
|
|
super().__init__()
|
|
self.name = name
|
|
self.constraints = constraints
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def __eq__(self, other):
|
|
return isinstance(other, TypeVariable) and self.name == other.name
|
|
|
|
def get_vars(self):
|
|
return [self]
|
|
|
|
def subst(self, subst: dict[str, Type]):
|
|
if self.name in subst:
|
|
return subst[self.name]
|
|
return self
|
|
|
|
|
|
class ClassType(Type):
|
|
name: str
|
|
parents: list['ClassType']
|
|
checking: bool
|
|
checked: bool
|
|
|
|
def __init__(self, name: str):
|
|
super().__init__()
|
|
self.name = name
|
|
self.parents = []
|
|
self.checking = False
|
|
self.checked = False
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def __eq__(self, other):
|
|
return isinstance(other, ClassType) and self.name == other.name
|
|
|
|
|
|
class SelfType(Type):
|
|
def __str__(self):
|
|
return 'self'
|
|
|
|
def __eq__(self, other):
|
|
return type(self) == type(other)
|
|
|
|
|
|
class VirtualClassType(Type):
|
|
base: ClassType
|
|
|
|
def __init__(self, base: ClassType):
|
|
super().__init__()
|
|
self.base = base
|
|
|
|
def __str__(self):
|
|
return f"virtual[{self.base}]"
|
|
|
|
def __eq__(self, other):
|
|
return isinstance(other, VirtualClassType) and self.base== other.base
|
|
|
|
class ParametricType(Type):
|
|
params: list[Type]
|
|
name: str
|
|
|
|
method_table = {}
|
|
|
|
def __init__(self, name, params: list[Type]):
|
|
super().__init__()
|
|
self.params = params
|
|
self.name = name
|
|
if name in ParametricType.method_table:
|
|
self.methods = ParametricType.method_table[name]
|
|
|
|
def __eq__(self, other):
|
|
if type(self) != type(other) or len(self.params) != len(other.params):
|
|
return False
|
|
for x, y in zip(self.params, other.params):
|
|
if x != y:
|
|
return False
|
|
return True
|
|
|
|
def get_vars(self):
|
|
result = []
|
|
for p in self.params:
|
|
vars = p.get_vars()
|
|
for v in vars:
|
|
if v not in result:
|
|
result.append(v)
|
|
return result
|
|
|
|
def subst(self, subst: dict[str, Type]):
|
|
s = copy.copy(self)
|
|
s.params = [v.subst(subst) for v in self.params]
|
|
return s
|
|
|
|
def inv_subst(self, subst: list[tuple['Type', 'TypeVariable']]):
|
|
for t, tv in subst:
|
|
if self == t:
|
|
return tv
|
|
s = copy.copy(self)
|
|
s.params = [v.inv_subst(subst) for v in self.params]
|
|
return s
|
|
|
|
def get_subst(self):
|
|
return {f'T{i + 1}': v for i, v in enumerate(self.params)}
|
|
|
|
class ListType(ParametricType):
|
|
def __init__(self, param: Type):
|
|
super().__init__('list', [param])
|
|
|
|
def __str__(self):
|
|
return f"list[{self.params[0]}]"
|
|
|
|
|
|
class TupleType(ParametricType):
|
|
def __init__(self, params: list[Type]):
|
|
super().__init__('tuple', params)
|
|
|
|
def __str__(self):
|
|
return f"tuple[{', '.join([str(v) for v in self.params])}]"
|
|
|
|
|
|
class Context:
|
|
variables: dict[str, TypeVariable]
|
|
types: dict[str, Type]
|
|
functions: dict[str, tuple[list[Type], Type, set[str]]]
|
|
|
|
def __init__(self, variables, types):
|
|
self.variables = variables
|
|
self.types = types
|
|
self.functions = {}
|
|
|