From d288928fa9dbf605c520a31647e651f98ce86f29 Mon Sep 17 00:00:00 2001 From: Vic Nightfall Date: Mon, 27 May 2024 19:58:23 +0200 Subject: [PATCH] Fix embedded types not counting towards getters and setters for interfaces --- src/compiler.pr | 6 +++++- src/debug.pr | 1 + src/typechecking.pr | 33 ++++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/compiler.pr b/src/compiler.pr index be11e42..c4c1879 100644 --- a/src/compiler.pr +++ b/src/compiler.pr @@ -6957,7 +6957,7 @@ def defer_unroll(node: &parser::Node, state: &State) { } export def insert_function(module: &toolchain::Module, function: &Function, overwrite: bool = false) { - if not function.name { return } + if not function or not function.name { return } if module.result.functions.contains(function.name) and not overwrite { return } module.result.functions(function.name) = function @@ -7749,6 +7749,10 @@ export def walk_TypeDecl(node: &parser::Node, state: &State) { let tpe = n.tpe if not tpe { continue } + if n.kind == parser::NodeKind::IDENTIFIER { + tpe.name = parser::identifier_to_str(n) + } + let current_variable = state.current_variable if node.parent.kind == parser::NodeKind::PROGRAM { state.current_variable = n.svalue diff --git a/src/debug.pr b/src/debug.pr index 7b31617..7e6c3ec 100644 --- a/src/debug.pr +++ b/src/debug.pr @@ -833,6 +833,7 @@ def tc_args_to_string(tpe: &typechecking::Type, full_name: bool) -> Str { export def type_to_str(tpe: &typechecking::Type, full_name: bool = false) -> Str { if not tpe { return "(none)" } if tpe.tc_tpe { return tc_args_to_string(tpe, full_name) } + if not full_name and tpe.name { return tpe.name } switch tpe.kind !int { case typechecking::TypeKind::BOX return "Box<" + type_to_str(tpe.wk, full_name) + ">" diff --git a/src/typechecking.pr b/src/typechecking.pr index 1a6386b..0bc70b0 100644 --- a/src/typechecking.pr +++ b/src/typechecking.pr @@ -1293,14 +1293,15 @@ def has_function(entry: &TypeEntry, intf: &Type, mb: StructuralTypeMember, modul tpe = tpe.tpe } - if tpe and tpe.kind == typechecking::TypeKind::STRUCT { + if tpe and tpe.kind == typechecking::TypeKind::STRUCT { + let fields = flatten_fields(tpe) if is_setter(mb) { let name = mb.name.slice(6, mb.name.length() - 2) - for var field in @tpe.fields { + for var field in fields { if field.name == name and equals(mb.parameter_t(0).tpe, field.tpe) { return true } } } else if is_getter(mb) { - for var field in @tpe.fields { + for var field in fields { if field.name == mb.name and equals(mb.return_t(0), field.tpe) { return true } } if tpe.const_fields { @@ -1422,9 +1423,9 @@ export def implements(a: &Type, b: &Type, module: &toolchain::Module, visited: & for var i in 0..vector::length(b.members) { let mb = b.members(i) - if not has_function(type_entry, b, mb, module, visited.copy(), check_embed) { + if not has_function(type_entry, b, mb, module, visited.copy(), check_embed) { type_entry.cached(nameb) = CacheEntry::NOT_CONTAINS - return false + return false } } type_entry.cached(nameb) = CacheEntry::CONTAINS @@ -1600,7 +1601,7 @@ export def convert_type_score(a: &Type, b: &Type, module: &toolchain::Module, is } // Embedded structs - if b.kind == TypeKind::STRUCT or is_ref(b) and b.tpe and b.tpe.kind == TypeKind::STRUCT { + if b.kind == TypeKind::STRUCT or (is_ref(b) and b.tpe and b.tpe.kind == TypeKind::STRUCT) { var nb = b.tpe if is_ref(b) else b for var field in @nb.fields { if field.is_embed { @@ -2758,7 +2759,11 @@ export def do_type_lookup(node: &parser::Node, state: &State, current_type: &Typ else make_union_type(fields.to_array(), const_fields.to_array(), current_type)) tpe.line = node.loc.line - tpe.type_name = make_unique_name("", state) + if current_type and current_type.type_name { + tpe.type_name = current_type.type_name + } else { + tpe.type_name = make_unique_name("", state) + } tpe.name = "" tpe.line = node.loc.line @@ -2882,7 +2887,13 @@ export def do_type_lookup(node: &parser::Node, state: &State, current_type: &Typ } else if node.kind == parser::NodeKind::STRUCTURAL_T { let tpe = make_type_raw(TypeKind::STRUCTURAL) if not current_type else current_type tpe.kind = TypeKind::STRUCTURAL - tpe.type_name = make_unique_name("", state) + + if current_type and current_type.type_name { + tpe.type_name = current_type.type_name + } else { + tpe.type_name = make_unique_name("", state) + } + tpe.name = "" let members = vector::make(StructuralTypeMember) @@ -5796,7 +5807,7 @@ def walk_MemberAccess_aggregate(node: &parser::Node, ucs: bool, state: &State) - } // TODO Make this a generator, doesn't work for some reason -def flatten_fields(tpe: &Type, state: &State, v: &Vector(StructMember) = null) -> &Vector(StructMember) { +def flatten_fields(tpe: &Type, v: &Vector(StructMember) = null) -> &Vector(StructMember) { if not v { v = vector::make(StructMember) } if not tpe { return v } if not is_struct(tpe) { @@ -5807,7 +5818,7 @@ def flatten_fields(tpe: &Type, state: &State, v: &Vector(StructMember) = null) - for var field in @tpe.fields { if field.is_embed { let tpe = field.tpe.tpe if is_box(field.tpe) else field.tpe - flatten_fields(tpe, state, v) + flatten_fields(tpe, v) } else { v.push(field) } @@ -5969,7 +5980,7 @@ def walk_StructLit(node: &parser::Node, state: &State) { let name = last_ident_to_str((@kwarg).value.named_arg.name) var found = false - for var field in flatten_fields(tpe, state) { + for var field in flatten_fields(tpe) { if field.name == name { found = true