From b98d1a1773e2f79a1a03ee221fc17e66acbb9f08 Mon Sep 17 00:00:00 2001 From: Vic Nightfall Date: Sat, 2 Mar 2024 21:48:11 +0100 Subject: [PATCH] Fix test cases --- src/compiler.pr | 37 ++++++++++++++++++++++++++++++++++++- src/debug.pr | 1 + src/typechecking.pr | 19 +++++++++++++++++++ std/std.pr | 4 ++-- test/runtime/test_vector.pr | 2 +- test/test_compiler.pr | 2 +- test/test_lexer.pr | 4 ++-- test/test_parser.pr | 11 ++++++----- test/test_runtime.pr | 4 ++-- version | 2 +- 10 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/compiler.pr b/src/compiler.pr index e532b56..f1535ad 100644 --- a/src/compiler.pr +++ b/src/compiler.pr @@ -1035,7 +1035,7 @@ def push_scope(node: &parser::Node, state: &State) { if state.current_function.has_yield { state.current_function.current_snapshot.push(map::make(int)) } - + if not toolchain::debug_sym { return } let discope = vector::peek(state.discope) if state.discope.length > 0 else null !&Value @@ -2026,6 +2026,38 @@ def convert_static_array_to_tuple(tpe: &typechecking::Type, value: Value, loc: & return ret } +def convert_anon_to_struct(tpe: &typechecking::Type, value: Value, loc: &Value, state: &State) -> Value { + if tpe.field_types.length != value.tpe.field_types.length { return NO_VALUE } + + var fast_path = true + for var i in 0..tpe.field_types.length { + let tpea = tpe.field_types(i).tpe + let tpeb = value.tpe.field_types(i).tpe + if not typechecking::equals(tpea, tpeb) { + fast_path = false + break + } + } + + if fast_path { return value } + + var res = [ kind = ValueKind::UNDEF, tpe = tpe ] !Value + for var fielda in @value.tpe.fields { + let member = state.extract_value(value.tpe.field_types(fielda.index).tpe, value, [fielda.index !int], loc) + + var index = fielda.index + for var fieldb in @tpe.fields { + if fieldb.name == fielda.name { + index = fieldb.index + break + } + } + res = state.insert_value(tpe, res, member, [index !int], loc) + } + + return res +} + export def convert_to(node: &parser::Node, value: Value, tpe: &typechecking::Type, state: &State) -> Value { let loc = make_location(node, state) return convert_to(loc, value, tpe, state) @@ -2081,6 +2113,9 @@ def convert_to(loc: &Value, value: Value, tpe: &typechecking::Type, state: &Stat return value } } + if tpe.kind == value.tpe.kind and value.tpe.is_anon and typechecking::is_struct(value.tpe) { + return convert_anon_to_struct(tpe, value, loc, state) + } if tpe.kind == typechecking::TypeKind::TUNION { if value.tpe.kind == typechecking::TypeKind::TUNION { return convert_variant_to_variant(tpe, value, loc, state) diff --git a/src/debug.pr b/src/debug.pr index a778ece..07b56f1 100644 --- a/src/debug.pr +++ b/src/debug.pr @@ -838,6 +838,7 @@ export def type_to_str(tpe: &typechecking::Type, full_name: bool = false) -> Str typechecking::TypeKind::STRUCT, typechecking::TypeKind::UNION, typechecking::TypeKind::STRUCTURAL, typechecking::TypeKind::TYPE_CONSTRUCTOR + if tpe.is_anon { return "" } return tpe.type_name if full_name else tpe.name case typechecking::TypeKind::TYPE return "type" diff --git a/src/typechecking.pr b/src/typechecking.pr index 58c1d33..1f7da30 100644 --- a/src/typechecking.pr +++ b/src/typechecking.pr @@ -167,6 +167,8 @@ export type Type = struct { // This gets set if it might also be a type argument, in that case we also consider the overload with a type // As an example, consider [int], this might be an array of types or an array type may_be_type: &Type + // True if this is an anonymous struct. name should be "" + is_anon: bool } export def hash(tpe: &Type) -> uint64 { @@ -1482,6 +1484,22 @@ export def convert_type_score(a: &Type, b: &Type, module: &toolchain::Module, is if equals(a, b) { return 0 } + // Convert anonymous struct to value + if a.kind == b.kind and b.kind == TypeKind::STRUCT and b.is_anon { + if a.fields.size != b.fields.size { return -1 } + for var af in @a.fields { + var found = false + for var bf in @b.fields { + if equals(af.tpe, bf.tpe) and af.name == bf.name { + found = true + break + } + } + if not found { return -1 } + } + return 11 + } + if a.kind == TypeKind::UNDEF or b.kind == TypeKind::UNDEF { return 0 } if (a.kind == TypeKind::REFERENCE or a.kind == TypeKind::WEAK_REF) and @@ -5426,6 +5444,7 @@ def walk_StructLit(node: &parser::Node, state: &State) { } tpe = make_struct_type(fields) + tpe.is_anon = true node.tpe = tpe return diff --git a/std/std.pr b/std/std.pr index 0a19da0..93412ee 100644 --- a/std/std.pr +++ b/std/std.pr @@ -406,7 +406,7 @@ def print_val(file: File, ref: runtime::Ref) -> int { } else if tpe.kind == runtime::TypeKind::STRUCT or tpe.kind == runtime::TypeKind::UNION { let fields = tpe.fields var sum = 0 - sum += cstd::fprintf(file, "{".value) + sum += cstd::fprintf(file, "[".value) for var i in 0..fields.size { let field = fields(i) sum += cstd::fprintf(file, "%s = ".value, field.name.value) @@ -418,7 +418,7 @@ def print_val(file: File, ref: runtime::Ref) -> int { sum += cstd::fprintf(file, ", ".value) } } - sum += cstd::fprintf(file, "} !%s".value, tpe.name.value) + sum += cstd::fprintf(file, "] !%s".value, tpe.name.value) return sum } } diff --git a/test/runtime/test_vector.pr b/test/runtime/test_vector.pr index 65f4630..d68ba97 100644 --- a/test/runtime/test_vector.pr +++ b/test/runtime/test_vector.pr @@ -2,7 +2,7 @@ let INITIAL_SIZE = 8 type Vector = struct { length: size_t - data: (&) + data: [&] } type S = struct { a: int } diff --git a/test/test_compiler.pr b/test/test_compiler.pr index f36b5c5..c21133e 100644 --- a/test/test_compiler.pr +++ b/test/test_compiler.pr @@ -631,7 +631,7 @@ def #test test_struct_lit { return [a = 10] } - let h: A = {10} + let h: A = [a = 10] var i: A i = [a = 10] diff --git a/test/test_lexer.pr b/test/test_lexer.pr index fe67fce..5381cb9 100644 --- a/test/test_lexer.pr +++ b/test/test_lexer.pr @@ -322,7 +322,7 @@ def #test test_complex { { "kind": "WHITESPACE", "line": 7, "column": 20 }, { "kind": "OP_ASSIGN", "line": 7, "column": 21 }, { "kind": "WHITESPACE", "line": 7, "column": 22 }, - { "kind": "O_BRACE", "line": 7, "column": 23 }, + { "kind": "O_SQUARE", "line": 7, "column": 23 }, { "kind": "NEW_LINE", "line": 7, "column": 24 }, { "kind": "WHITESPACE", "line": 8, "column": 0 }, { "kind": "IDENTIFIER", "line": 8, "column": 16, "value": "a" }, @@ -338,7 +338,7 @@ def #test test_complex { { "kind": "WHITESPACE", "line": 8, "column": 26 }, { "kind": "STRING", "line": 8, "column": 27, "value": "Test string" }, { "kind": "WHITESPACE", "line": 8, "column": 40 }, - { "kind": "C_BRACE", "line": 8, "column": 41 }, + { "kind": "C_SQUARE", "line": 8, "column": 41 }, { "kind": "WHITESPACE", "line": 8, "column": 42 }, { "kind": "OP_CAST", "line": 8, "column": 43 }, { "kind": "IDENTIFIER", "line": 8, "column": 44, "value": "T" }, diff --git a/test/test_parser.pr b/test/test_parser.pr index 3c790e7..38cfb77 100644 --- a/test/test_parser.pr +++ b/test/test_parser.pr @@ -44,7 +44,7 @@ def #test test_identifiers { }] }""")) - assert parse("foo::bar::(int, () -> ())") == program(json::parse("""{ + assert parse("foo::bar::(int, [] -> [])") == program(json::parse("""{ "kind": "Identifier", "path": [ "foo", @@ -70,7 +70,7 @@ def #test test_identifiers { ] }""")) - assert parse("foo::bar::(int, () -> ())") == program(json::parse("""{\ + assert parse("foo::bar::(int, [] -> [])") == program(json::parse("""{\ "kind": "Identifier", "path": ["foo", "bar"], "prefixed": false, "args": [{ @@ -4462,8 +4462,8 @@ def #test test_array_literal { "kind": "Program", "body": [ { - "kind": "ArrayLit", - "body": [ + "kind": "StructLit", + "args": [ { "kind": "Integer", "value": 1.00000 @@ -4476,7 +4476,8 @@ def #test test_array_literal { "kind": "Integer", "value": 3.00000 } - ] + ], + "kwargs": [] } ] }""") diff --git a/test/test_runtime.pr b/test/test_runtime.pr index 577b43b..ee89950 100644 --- a/test/test_runtime.pr +++ b/test/test_runtime.pr @@ -464,7 +464,7 @@ def #test test_ucs { def inc(a: int) -> int { return a + 1} def test_ucs { - let s: Struct2 = [a = 10, t = null] + let s = [a = 10, t = null] !Struct2 assert s.function() == 10 assert s.function.inc == 11 @@ -491,7 +491,7 @@ def #test test_anonymous { def test_anonymous { var s: Struct3 - s = [a = 10, b = [c = 20, d = 30]] + s = [a = 10] !Struct3 s.a = 10 s.b = [c = 20, d = 30] s.e = 0x4034800000000000 diff --git a/version b/version index 5fb6fa4..2c25562 100644 --- a/version +++ b/version @@ -1 +1 @@ -VERSION=0.3.10 \ No newline at end of file +VERSION=0.3.11