python-plus-plus/ppp/ppp_types.ppp
germax26 66cd54e532
Move .ppp files into ppp/ directory
I plan to make a few changes to my language, and I will then update
these files later. I am moving them because I don't want them
polluting the main directory. I probably should have done this to
begin with, but better late than never.
2024-08-11 11:35:49 +10:00

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_);
}
}