130 lines
4.0 KiB
Plaintext
130 lines
4.0 KiB
Plaintext
|
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_);
|
||
|
}
|
||
|
}
|