nac3-spec/toy-impl/type_def.py

189 lines
4.4 KiB
Python
Raw Permalink Normal View History

2020-12-18 13:03:36 +08:00
import copy
2020-12-17 14:50:51 +08:00
class Type:
2020-12-18 13:03:36 +08:00
methods: dict[str, tuple[list['Type'], 'Type', set[str]]]
fields: dict[str, 'Type']
def __init__(self):
self.methods = {}
self.fields = {}
2020-12-17 17:00:43 +08:00
def __eq__(self, other):
return False
2020-12-17 14:50:51 +08:00
2020-12-17 17:15:00 +08:00
def get_vars(self):
return []
2020-12-18 13:03:36 +08:00
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 {}
2020-12-17 14:50:51 +08:00
class BotType:
2020-12-17 17:00:43 +08:00
def __eq__(self, other):
return isinstance(other, BotType)
2020-12-17 14:50:51 +08:00
class PrimitiveType(Type):
name: str
def __init__(self, name: str):
2020-12-18 13:03:36 +08:00
super().__init__()
2020-12-17 14:50:51 +08:00
self.name = name
def __str__(self):
return self.name
2020-12-17 17:00:43 +08:00
def __eq__(self, other):
return isinstance(other, PrimitiveType) and self.name == other.name
2020-12-17 14:50:51 +08:00
class TypeVariable(Type):
name: str
2020-12-17 17:00:43 +08:00
# this may be a list of str, Type may not be determined when type variables
# are instantiated...
# and they cannot contain other type variables
2020-12-17 14:50:51 +08:00
constraints: list[Type]
def __init__(self, name: str, constraints: list[Type]):
2020-12-18 13:03:36 +08:00
super().__init__()
2020-12-17 14:50:51 +08:00
self.name = name
self.constraints = constraints
def __str__(self):
return self.name
2020-12-17 17:00:43 +08:00
def __eq__(self, other):
return isinstance(other, TypeVariable) and self.name == other.name
2020-12-17 17:15:00 +08:00
def get_vars(self):
return [self]
2020-12-18 13:03:36 +08:00
def subst(self, subst: dict[str, Type]):
if self.name in subst:
return subst[self.name]
return self
2020-12-17 14:50:51 +08:00
class ClassType(Type):
name: str
parents: list['ClassType']
2020-12-22 16:53:44 +08:00
checking: bool
checked: bool
2020-12-17 14:50:51 +08:00
def __init__(self, name: str):
2020-12-18 13:03:36 +08:00
super().__init__()
2020-12-17 14:50:51 +08:00
self.name = name
self.parents = []
2020-12-22 16:53:44 +08:00
self.checking = False
self.checked = False
2020-12-17 14:50:51 +08:00
def __str__(self):
return self.name
2020-12-17 17:00:43 +08:00
def __eq__(self, other):
return isinstance(other, ClassType) and self.name == other.name
2020-12-17 14:50:51 +08:00
2020-12-18 13:03:36 +08:00
class SelfType(Type):
def __str__(self):
return 'self'
2020-12-23 13:43:34 +08:00
def __eq__(self, other):
return type(self) == type(other)
2020-12-18 13:03:36 +08:00
2020-12-17 14:50:51 +08:00
class VirtualClassType(Type):
base: ClassType
def __init__(self, base: ClassType):
2020-12-18 13:03:36 +08:00
super().__init__()
2020-12-17 14:50:51 +08:00
self.base = base
def __str__(self):
return f"virtual[{self.base}]"
2020-12-17 17:00:43 +08:00
def __eq__(self, other):
return isinstance(other, VirtualClassType) and self.base== other.base
class ParametricType(Type):
params: list[Type]
name: str
2020-12-17 17:00:43 +08:00
method_table = {}
def __init__(self, name, params: list[Type]):
2020-12-18 13:03:36 +08:00
super().__init__()
2020-12-17 17:00:43 +08:00
self.params = params
self.name = name
if name in ParametricType.method_table:
self.methods = ParametricType.method_table[name]
2020-12-17 17:00:43 +08:00
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
2020-12-17 14:50:51 +08:00
2020-12-17 17:15:00 +08:00
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
2020-12-18 13:03:36 +08:00
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)}
2020-12-17 17:00:43 +08:00
class ListType(ParametricType):
def __init__(self, param: Type):
super().__init__('list', [param])
2020-12-17 14:50:51 +08:00
def __str__(self):
2020-12-17 17:00:43 +08:00
return f"list[{self.params[0]}]"
2020-12-17 14:50:51 +08:00
2020-12-17 17:00:43 +08:00
class TupleType(ParametricType):
def __init__(self, params: list[Type]):
super().__init__('tuple', params)
2020-12-17 14:50:51 +08:00
def __str__(self):
2020-12-17 17:00:43 +08:00
return f"tuple[{', '.join([str(v) for v in self.params])}]"
2020-12-17 14:50:51 +08:00
2020-12-18 13:03:36 +08:00
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 = {}