enum Type { Int, Str, Bool, Void, Type, Tuple(Type[]), List(Type), Array(Type, int), Function(Type[], Type), Union(Type[]), Object, Return(Type), Enum(str, dict[str, Type[]], Type[]), EnumStruct(Type, str), Struct(str, dict[str, Type], Type[]), Variable(str) } func type_represent(type_: Type) -> str { match type_ in { case Int return "int"; case Str return "str"; case Bool return "bool"; case Void return "void"; case Type return "type"; case Function(arguments, return_type) return "(%s) -> %s" % (join_by(", ", [type_represent(type_) for type_ in arguments]), type_represent(return_type)); case Enum(name, _, generics) do { assert len(generics) == 0; return name; } case Variable(name) return name + "?"; case Struct(name, _, generics) do { assert len(generics) == 0; return name; } case List(type_) return type_represent(type_) + "[]"; case Tuple(types) return "(" + join_by(", ", [type_represent(type_) for type_ in types]) + ")"; case _ do { debug_print(type_); assert false, "type_represent unimplemented"; } } } func type_eq(a_type: Type, b_type: Type) -> bool return type_is_subtype_of(a_type, b_type) && type_is_subtype_of(b_type, a_type); func type_is_subtype_of(type_a: Type, type_b: Type) -> bool { match type_a in { case Type match type_b in { case Type return true; case _ return false; } case Function(a_arguments, a_return_type) match type_b in { case Function(b_arguments, b_return_type) do { assert len(a_arguments) == len(b_arguments); for i in range(0, len(a_arguments)) if !type_is_subtype_of(b_arguments[i], a_arguments[i]) return false; return type_is_subtype_of(a_return_type, b_return_type); } case _ assert false; } case Str match type_b in { case Str return true; case _ return false; } case Enum(a_name, _, a_generics) match type_b in { case Enum(b_name, _, b_generics) do { assert len(a_generics) == 0; assert len(b_generics) == 0; return a_name == b_name; } } case Struct(a_name, a_members, a_generics) match type_b in { case Struct(b_name, b_members, b_generics) do { assert len(a_generics) == 0; assert len(b_generics) == 0; return a_name == b_name; } } case Bool match type_b in { case Bool return true; case _ return false; } case List(a_type) match type_b in { case List(b_type) do { match a_type in { case Variable(_) return true; } match b_type in { case Variable(_) return true; } return type_eq(a_type, b_type); } } case Tuple(a_types) match type_b in { case Tuple(b_types) do { if len(a_types) != len(b_types) return false; for i in range(0, len(a_types)) if !type_is_subtype_of(a_types[i], b_types[i]) return false; return true; } case _ return false; } case _ assert false, "Unimplemented type_is_subtype_of %s, %s" % (type_represent(type_a), type_represent(type_b)); } } func type_fill(type_: Type, types: dict[str, Type], stack: int[]) -> Type { type_id: int = id(type_); new_stack: int[] = stack+[type_id]; match type_ in { case Int return Type.Int; case Str return Type.Str; case Bool return Type.Bool; case Enum(name, members, generics) do { for id_ in stack if id_ == type_id return type_; assert len(generics) == 0, "Unimplemented type_fill enum generics"; for member in members members[member] = [type_fill(element, types, new_stack) for element in members[member]]; for i in range(0, len(generics)) generics[i] = type_fill(generics[i], types, new_stack); return type_; } case Variable(name) do { for type_name in types if type_name == name return types[name]; return type_; } case Struct(name, members, generics) do { assert len(generics) == 0; for field in members members[field] = type_fill(members[field], types, new_stack); return type_; } case List(type_) return Type.List(type_fill(type_, types, new_stack)); case Tuple(types_) return Type.Tuple([type_fill(type_, types, new_stack) for type_ in types_]); case _ assert false, "Unimplemented type_fill %s" % type_represent(type_); } }