class Type: def __eq__(self, other): return False class BotType: def __eq__(self, other): return isinstance(other, BotType) class PrimitiveType(Type): name: str def __init__(self, name: str): 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]): 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 class ClassType(Type): name: str parents: list['ClassType'] methods: dict[str, tuple[list[Type], Type, set[str]]] fields: dict[str, Type] def __init__(self, name: str): self.name = name self.parents = [] self.methods = {} self.fields = {} def __str__(self): return self.name def __eq__(self, other): return isinstance(other, ClassType) and self.name == other.name class VirtualClassType(Type): base: ClassType def __init__(self, base: ClassType): 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] def __init__(self, params: list[Type]): self.params = params 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 class ListType(ParametricType): def __init__(self, param: Type): super().__init__([param]) def __str__(self): return f"list[{self.params[0]}]" class TupleType(ParametricType): def __init__(self, params: list[Type]): super().__init__(params) def __str__(self): return f"tuple[{', '.join([str(v) for v in self.params])}]"