From fc1aa888e0e54ad7498538a1a2e0ce91d18a988e Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 18 May 2026 16:04:42 +0100 Subject: [PATCH 1/2] feat(parser)!: `#{` record-literal sigil; `{` is always a block [#218] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Structurally removes the block-vs-record-literal ambiguity (#215 families C+D) with no lookahead heuristic, per the owner-approved Rust-like model: - `{` in expression position is ALWAYS a block. - record/struct literals use `#{ … }` (anonymous `#{ x: 1 }` and typed `Foo #{ x: 1 }`). - record *patterns* unchanged (pattern position has no block alternative — no ambiguity there). Changes: HASH_LBRACE token (token.ml), `#{` lexer rule (lexer.ml; `#` was previously unused so longest-match is collision-free), both ExprRecord productions rerouted LBRACE -> HASH_LBRACE (parser.mly). Menhir conflicts on origin/main (a45b021): 72 S/R + 10 R/R after: 68 S/R + 7 R/R (-4 / -3) Build clean. BREAKING: legacy `{ … }` record syntax no longer parses; the codemod-migrated repo `.affine` files land in the same PR so the 253/257 gate stays green. Refs #218 #215 Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/lexer.ml | 3 +++ lib/parse_driver.ml | 1 + lib/parser.mly | 23 ++++++++++++++--------- lib/token.ml | 2 ++ 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/lexer.ml b/lib/lexer.ml index cc4f120..2833e43 100644 --- a/lib/lexer.ml +++ b/lib/lexer.ml @@ -183,6 +183,9 @@ let rec token state buf = | "-=" -> MINUSEQ | "*=" -> STAREQ | "/=" -> SLASHEQ + (* `#{` opens a record/struct literal (#218); longest-match, and `#` has + no other lexer rule, so this never shadows a single-char token. *) + | "#{" -> HASH_LBRACE (* Single-char tokens *) | '(' -> LPAREN diff --git a/lib/parse_driver.ml b/lib/parse_driver.ml index 806d35b..7cad124 100644 --- a/lib/parse_driver.ml +++ b/lib/parse_driver.ml @@ -76,6 +76,7 @@ let to_menhir_token (tok : Token.t) : Parser.token = | Token.LPAREN -> Parser.LPAREN | Token.RPAREN -> Parser.RPAREN | Token.LBRACE -> Parser.LBRACE + | Token.HASH_LBRACE -> Parser.HASH_LBRACE | Token.RBRACE -> Parser.RBRACE | Token.LBRACKET -> Parser.LBRACKET | Token.RBRACKET -> Parser.RBRACKET diff --git a/lib/parser.mly b/lib/parser.mly index f020126..5175154 100644 --- a/lib/parser.mly +++ b/lib/parser.mly @@ -66,6 +66,10 @@ let rec effect_union_of_list = function /* Punctuation */ %token LPAREN RPAREN LBRACE RBRACE LBRACKET RBRACKET +/* `#{` opens a record/struct literal (#218). `{` is ALWAYS a block in + expression position — this structurally removes the block-vs-record + ambiguity (#215 families C+D) with no lookahead heuristic. */ +%token HASH_LBRACE %token COMMA SEMICOLON COLON COLONCOLON DOT DOTDOT %token ARROW FAT_ARROW PIPE AT UNDERSCORE BACKSLASH QUESTION @@ -768,10 +772,10 @@ expr_primary: ordinary parameter binding named "self". */ | SELF_KW { ExprVar (mk_ident "self" $startpos $endpos) } | name = lower_ident { ExprVar (mk_ident name $startpos $endpos) } - /* Struct literal: `Point { x: v, y: w }`. Must come before the plain - upper_ident production so Menhir shifts LBRACE rather than reducing - upper_ident to ExprVar when the next token is LBRACE. */ - | _ty = upper_ident LBRACE b = expr_record_body RBRACE + /* Struct literal: `Point #{ x: v, y: w }` (#218). The `#{` sigil makes + this unambiguous against the plain `upper_ident` production and against + a following block, so no LBRACE-shift heuristic is needed any more. */ + | _ty = upper_ident HASH_LBRACE b = expr_record_body RBRACE { ExprRecord { er_fields = fst b; er_spread = snd b } } | name = upper_ident { ExprVar (mk_ident name $startpos $endpos) } | ty = upper_ident COLONCOLON variant = upper_ident @@ -787,11 +791,12 @@ expr_primary: /* Arrays */ | LBRACKET es = separated_list(COMMA, expr) RBRACKET { ExprArray es } - /* Records — use a recursive rule (expr_record_body / expr_record_rest) to - avoid the LALR(1) greedy-separator conflict that arises when a ROW_VAR - spread like `..record` follows a COMMA that `separated_list` has already - consumed expecting another record_field. */ - | LBRACE b = expr_record_body RBRACE + /* Anonymous record `#{ f: v, ..spread }` (#218). Uses a recursive rule + (expr_record_body / expr_record_rest) to avoid the LALR(1) greedy- + separator conflict that arises when a ROW_VAR spread like `..record` + follows a COMMA that `separated_list` has already consumed expecting + another record_field. */ + | HASH_LBRACE b = expr_record_body RBRACE { ExprRecord { er_fields = fst b; er_spread = snd b } } /* Block */ diff --git a/lib/token.ml b/lib/token.ml index 993e69b..61c6637 100644 --- a/lib/token.ml +++ b/lib/token.ml @@ -72,6 +72,7 @@ type t = | LPAREN | RPAREN | LBRACE + | HASH_LBRACE | RBRACE | LBRACKET | RBRACKET @@ -186,6 +187,7 @@ let to_string = function | LPAREN -> "(" | RPAREN -> ")" | LBRACE -> "{" + | HASH_LBRACE -> "#{" | RBRACE -> "}" | LBRACKET -> "[" | RBRACKET -> "]" From d41315d9f517f6ef723f995faef9681c2acab366 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 18 May 2026 16:43:11 +0100 Subject: [PATCH 2/2] refactor(stdlib,tests,examples)!: migrate record literals to `#{` [#218] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mechanical companion to the `#{` grammar change — 45 in-repo `.affine` files (stdlib, tests, golden oracles, e2e fixtures, examples) rewritten from legacy `{ … }` record literals to `#{ … }`. Method: a sound, convergent codemod that depends ONLY on the new, unambiguous grammar (never the old ambiguous parser): parse with the new grammar, and at each parse error insert `#` before the innermost enclosing record `{`, iterating to a fixed point. Codepoint-correct (handles non-ASCII). The codemod tooling is intentionally not committed. Result: `dune runtest` = 257/257 green (the #218 gate), identical to the pre-change baseline — no regression; `#{` is now the record syntax across the full test suite. Out of scope (tracked, per the #218 plan steps 3–4): - estate-wide `.affine` sweep in other repos; - ~24 non-gating files the convergent codemod did not auto-migrate (LR error reported past the record's `}`): conformance/valid/*, docs/guides/warmup/*, codegen-deno/*, some tests/types/* — plus the intentional conformance/invalid/* error fixtures and face-syntax examples which must stay as-is. None are in the 257 gate. Refs #218 #215 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../example/codegen_regression_test.affine | 2 +- conformance/valid/011_rows.affine | 2 +- examples/comprehensive_test.affine | 4 ++-- examples/rows.affine | 2 +- examples/typecheck_complete_test.affine | 4 ++-- stdlib/testing.affine | 2 +- test/e2e/fixtures/counter.affine | 2 +- test/e2e/fixtures/full_pipeline.affine | 4 ++-- test/e2e/fixtures/row_polymorphism.affine | 2 +- test/e2e/fixtures/titlescreen.affine | 12 ++++++------ test/e2e/fixtures/type_decls.affine | 4 ++-- test/golden/rows.affine | 2 +- tests/borrow/test_move.affine | 12 ++++++------ tests/codegen/test_pattern_record.affine | 2 +- tests/codegen/test_record_multi_field.affine | 2 +- tests/codegen/test_record_multiple.affine | 4 ++-- tests/codegen/test_record_simple.affine | 2 +- tests/codegen/test_tuple_record_array.affine | 2 +- tests/conformance/arithmetic/add.affine | 12 ++++++------ tests/conformance/arithmetic/divide.affine | 14 +++++++------- tests/conformance/arithmetic/modulo.affine | 12 ++++++------ tests/conformance/arithmetic/multiply.affine | 14 +++++++------- tests/conformance/arithmetic/subtract.affine | 14 +++++++------- tests/conformance/collection/contains.affine | 14 +++++++------- tests/conformance/collection/filter.affine | 12 ++++++------ tests/conformance/collection/fold.affine | 14 +++++++------- tests/conformance/collection/map.affine | 12 ++++++------ tests/conformance/comparison/equal.affine | 16 ++++++++-------- .../conformance/comparison/greater_equal.affine | 12 ++++++------ tests/conformance/comparison/greater_than.affine | 12 ++++++------ tests/conformance/comparison/less_equal.affine | 12 ++++++------ tests/conformance/comparison/less_than.affine | 12 ++++++------ tests/conformance/comparison/not_equal.affine | 12 ++++++------ .../conformance/conditional/if_then_else.affine | 14 +++++++------- tests/conformance/logical/and.affine | 10 +++++----- tests/conformance/logical/not.affine | 6 +++--- tests/conformance/logical/or.affine | 10 +++++----- tests/conformance/string/concat.affine | 12 ++++++------ tests/conformance/string/length.affine | 12 ++++++------ tests/conformance/string/substring.affine | 12 ++++++------ tests/scratch/test_spread.affine | 2 +- tests/scratch/test_spread2.affine | 2 +- tests/types/test_kind_checking.affine | 4 ++-- tests/types/test_row_polymorphism.affine | 6 +++--- tests/types/test_row_simple.affine | 2 +- 45 files changed, 176 insertions(+), 176 deletions(-) diff --git a/affinescript-deno-test/example/codegen_regression_test.affine b/affinescript-deno-test/example/codegen_regression_test.affine index 493b9c4..ca65a57 100644 --- a/affinescript-deno-test/example/codegen_regression_test.affine +++ b/affinescript-deno-test/example/codegen_regression_test.affine @@ -40,7 +40,7 @@ fn advance(s: Lifecycle) -> Lifecycle { } fn make_counters() -> Counters { - { tag: 1, profile_id: 42, activity_count: 7 } + #{ tag: 1, profile_id: 42, activity_count: 7 } } fn read_profile_id(c: Counters) -> Int { diff --git a/conformance/valid/011_rows.affine b/conformance/valid/011_rows.affine index e4904db..322af7d 100644 --- a/conformance/valid/011_rows.affine +++ b/conformance/valid/011_rows.affine @@ -9,7 +9,7 @@ fn get_name[..r](entity: {name: String, ..r}) -> String { } fn with_id[..r](record: {..r}, id: Int) -> {id: Int, ..r} { - { id: id, ..record } + #{ id: id, ..record } } type HasPosition[..r] = {x: Int, y: Int, ..r} diff --git a/examples/comprehensive_test.affine b/examples/comprehensive_test.affine index 99556c8..80448d0 100644 --- a/examples/comprehensive_test.affine +++ b/examples/comprehensive_test.affine @@ -12,7 +12,7 @@ enum Shape { } fn vec2_add(a: Vec2, b: Vec2) -> Vec2 { - { x: a.x + b.x, y: a.y + b.y } + #{ x: a.x + b.x, y: a.y + b.y } } fn area(s: Shape) -> Int { @@ -30,7 +30,7 @@ fn larger_area(s1: Shape, s2: Shape) -> Int = max(area(s1), area(s2)); fn main() -> () { let circle = Circle(5); - let rect = Rect({ x: 3, y: 4 }); + let rect = Rect(#{ x: 3, y: 4 }); let result = larger_area(circle, rect); (); } diff --git a/examples/rows.affine b/examples/rows.affine index 54ac370..2f76f3d 100644 --- a/examples/rows.affine +++ b/examples/rows.affine @@ -15,5 +15,5 @@ struct Point3D { fn getX(p: Point2D) -> Int = p.x; fn mk_point(x: Int, y: Int) -> Point2D { - { x: x, y: y } + #{ x: x, y: y } } diff --git a/examples/typecheck_complete_test.affine b/examples/typecheck_complete_test.affine index 2b16316..7e14109 100644 --- a/examples/typecheck_complete_test.affine +++ b/examples/typecheck_complete_test.affine @@ -15,11 +15,11 @@ enum Color { } fn make_point(x: Int, y: Int) -> Point { - { x: x, y: y } + #{ x: x, y: y } } fn origin() -> Point { - { x: 0, y: 0 } + #{ x: 0, y: 0 } } fn mutate_counter() -> Int { diff --git a/stdlib/testing.affine b/stdlib/testing.affine index 30b8b5e..4621cb9 100644 --- a/stdlib/testing.affine +++ b/stdlib/testing.affine @@ -303,7 +303,7 @@ fn bench(f: () -> (), iterations: Int) -> BenchResult { } let tot = time_now() - start; - { + #{ iterations: iterations, total_time: tot, avg_time: tot / float(iterations) diff --git a/test/e2e/fixtures/counter.affine b/test/e2e/fixtures/counter.affine index e6f7219..26a3160 100644 --- a/test/e2e/fixtures/counter.affine +++ b/test/e2e/fixtures/counter.affine @@ -68,7 +68,7 @@ fn counter_subs(model: Int) -> String { // Wire up the TEA runtime and hand off to the interpreter loop. fn main() -> () { - tea_run({ + tea_run(#{ init: counter_init, update: counter_update, view: counter_view, diff --git a/test/e2e/fixtures/full_pipeline.affine b/test/e2e/fixtures/full_pipeline.affine index 118608b..592772a 100644 --- a/test/e2e/fixtures/full_pipeline.affine +++ b/test/e2e/fixtures/full_pipeline.affine @@ -13,7 +13,7 @@ enum Shape { } fn vec2_add(a: Vec2, b: Vec2) -> Vec2 { - { x: a.x + b.x, y: a.y + b.y } + #{ x: a.x + b.x, y: a.y + b.y } } fn area(s: Shape) -> Int { @@ -31,7 +31,7 @@ fn larger_area(s1: Shape, s2: Shape) -> Int = max(area(s1), area(s2)); fn main() -> () { let circle = Circle(5); - let rect = Rect({ x: 3, y: 4 }); + let rect = Rect(#{ x: 3, y: 4 }); let result = larger_area(circle, rect); (); } diff --git a/test/e2e/fixtures/row_polymorphism.affine b/test/e2e/fixtures/row_polymorphism.affine index 6a2b2bf..c84209e 100644 --- a/test/e2e/fixtures/row_polymorphism.affine +++ b/test/e2e/fixtures/row_polymorphism.affine @@ -16,5 +16,5 @@ struct Point3D { fn getX(p: Point2D) -> Int = p.x; fn mk_point(x: Int, y: Int) -> Point2D { - { x: x, y: y } + #{ x: x, y: y } } diff --git a/test/e2e/fixtures/titlescreen.affine b/test/e2e/fixtures/titlescreen.affine index 66483fc..873a6e3 100644 --- a/test/e2e/fixtures/titlescreen.affine +++ b/test/e2e/fixtures/titlescreen.affine @@ -44,7 +44,7 @@ struct TitleModel { // ── init ───────────────────────────────────────────────────────────────────── fn title_init() -> TitleModel { - { + #{ screen_w: 1280, screen_h: 720, bgm_playing: 0, @@ -58,10 +58,10 @@ fn title_init() -> TitleModel { fn title_update(msg: TitleMsg, model: TitleModel) -> TitleModel { match msg { - NewGame => { screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "new_game" }, - LoadGame => { screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "load_game" }, - Settings => { screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "settings" }, - Credits => { screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "credits" } + NewGame => #{ screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "new_game" }, + LoadGame => #{ screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "load_game" }, + Settings => #{ screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "settings" }, + Credits => #{ screen_w: model.screen_w, screen_h: model.screen_h, bgm_playing: model.bgm_playing, selected: "credits" } } } @@ -84,7 +84,7 @@ fn title_subs(model: TitleModel) -> String { // ── main ────────────────────────────────────────────────────────────────────── fn main() -> () { - tea_run({ + tea_run(#{ init: title_init, update: title_update, view: title_view, diff --git a/test/e2e/fixtures/type_decls.affine b/test/e2e/fixtures/type_decls.affine index 4f65ed9..6c8e1a9 100644 --- a/test/e2e/fixtures/type_decls.affine +++ b/test/e2e/fixtures/type_decls.affine @@ -27,9 +27,9 @@ enum Result[T, E] { } fn make_point(x: Int, y: Int) -> Point { - { x: x, y: y } + #{ x: x, y: y } } fn origin() -> Point { - { x: 0, y: 0 } + #{ x: 0, y: 0 } } diff --git a/test/golden/rows.affine b/test/golden/rows.affine index bacbcab..f22574f 100644 --- a/test/golden/rows.affine +++ b/test/golden/rows.affine @@ -4,5 +4,5 @@ fn getX[..r](p: {x: Int, ..r}) -> Int { } fn addY[..r](p: {..r}) -> {y: Int, ..r} { - {y: 0, ..p} + #{y: 0, ..p} } diff --git a/tests/borrow/test_move.affine b/tests/borrow/test_move.affine index ffded4f..26a998a 100644 --- a/tests/borrow/test_move.affine +++ b/tests/borrow/test_move.affine @@ -43,14 +43,14 @@ fn test_add_two_negatives() -> TestResult { /// Run all add conformance tests fn test_alib_arithmetic_add() -> TestResult { - let suite = { + let suite = #{ name: "aLib arithmetic/add conformance", tests: [ - { name: "add_positive", test: test_add_positive }, - { name: "add_negative", test: test_add_negative }, - { name: "add_zeros", test: test_add_zeros }, - { name: "add_decimal", test: test_add_decimal }, - { name: "add_two_negatives", test: test_add_two_negatives } + #{ name: "add_positive", test: test_add_positive }, + #{ name: "add_negative", test: test_add_negative }, + #{ name: "add_zeros", test: test_add_zeros }, + #{ name: "add_decimal", test: test_add_decimal }, + #{ name: "add_two_negatives", test: test_add_two_negatives } ] }; diff --git a/tests/codegen/test_pattern_record.affine b/tests/codegen/test_pattern_record.affine index 8d95219..f023191 100644 --- a/tests/codegen/test_pattern_record.affine +++ b/tests/codegen/test_pattern_record.affine @@ -1,7 +1,7 @@ // Test record pattern matching fn main() -> Int { - let r = {x: 10, y: 20}; + let r = #{x: 10, y: 20}; let result = match r { {x: a, y: b} => a + b diff --git a/tests/codegen/test_record_multi_field.affine b/tests/codegen/test_record_multi_field.affine index ce45104..400f7d3 100644 --- a/tests/codegen/test_record_multi_field.affine +++ b/tests/codegen/test_record_multi_field.affine @@ -1,6 +1,6 @@ // Test record with multiple fields fn main() -> Int { - let r = {x: 10, y: 20, z: 30}; + let r = #{x: 10, y: 20, z: 30}; return r.x + r.y + r.z; // Should return 60 } diff --git a/tests/codegen/test_record_multiple.affine b/tests/codegen/test_record_multiple.affine index 4b9ec5e..0a950d0 100644 --- a/tests/codegen/test_record_multiple.affine +++ b/tests/codegen/test_record_multiple.affine @@ -1,8 +1,8 @@ // Test multiple distinct records fn main() -> Int { - let r1 = {a: 5, b: 10}; - let r2 = {x: 20, y: 30, z: 40}; + let r1 = #{a: 5, b: 10}; + let r2 = #{x: 20, y: 30, z: 40}; return r1.a + r1.b + r2.x + r2.y + r2.z; // 5 + 10 + 20 + 30 + 40 = 105 } diff --git a/tests/codegen/test_record_simple.affine b/tests/codegen/test_record_simple.affine index 072353f..afd0f28 100644 --- a/tests/codegen/test_record_simple.affine +++ b/tests/codegen/test_record_simple.affine @@ -1,6 +1,6 @@ // Test simple record construction and field access fn main() -> Int { - let r = {x: 42}; + let r = #{x: 42}; return r.x; // Should return 42 } diff --git a/tests/codegen/test_tuple_record_array.affine b/tests/codegen/test_tuple_record_array.affine index d0f597d..6efecc8 100644 --- a/tests/codegen/test_tuple_record_array.affine +++ b/tests/codegen/test_tuple_record_array.affine @@ -3,7 +3,7 @@ type Point = { x: Int, y: Int, z: Int }; fn main() -> Int { - let p = { x: 10, y: 20, z: 30 }; + let p = #{ x: 10, y: 20, z: 30 }; let t = (1, 2, 3, 4); let a = [5, 6]; return p.x + p.y + p.z + t.0 + t.1 + t.2 + t.3 + a[0] + a[1]; diff --git a/tests/conformance/arithmetic/add.affine b/tests/conformance/arithmetic/add.affine index ffded4f..26a998a 100644 --- a/tests/conformance/arithmetic/add.affine +++ b/tests/conformance/arithmetic/add.affine @@ -43,14 +43,14 @@ fn test_add_two_negatives() -> TestResult { /// Run all add conformance tests fn test_alib_arithmetic_add() -> TestResult { - let suite = { + let suite = #{ name: "aLib arithmetic/add conformance", tests: [ - { name: "add_positive", test: test_add_positive }, - { name: "add_negative", test: test_add_negative }, - { name: "add_zeros", test: test_add_zeros }, - { name: "add_decimal", test: test_add_decimal }, - { name: "add_two_negatives", test: test_add_two_negatives } + #{ name: "add_positive", test: test_add_positive }, + #{ name: "add_negative", test: test_add_negative }, + #{ name: "add_zeros", test: test_add_zeros }, + #{ name: "add_decimal", test: test_add_decimal }, + #{ name: "add_two_negatives", test: test_add_two_negatives } ] }; diff --git a/tests/conformance/arithmetic/divide.affine b/tests/conformance/arithmetic/divide.affine index 9711923..473d34b 100644 --- a/tests/conformance/arithmetic/divide.affine +++ b/tests/conformance/arithmetic/divide.affine @@ -50,15 +50,15 @@ fn test_divide_two_negatives() -> TestResult { /// Run all divide conformance tests fn test_alib_arithmetic_divide() -> TestResult { - let suite = { + let suite = #{ name: "aLib arithmetic/divide conformance", tests: [ - { name: "divide_exact", test: test_divide_exact }, - { name: "divide_fractional", test: test_divide_fractional }, - { name: "divide_zero", test: test_divide_zero }, - { name: "divide_negative_dividend", test: test_divide_negative_dividend }, - { name: "divide_negative_divisor", test: test_divide_negative_divisor }, - { name: "divide_two_negatives", test: test_divide_two_negatives } + #{ name: "divide_exact", test: test_divide_exact }, + #{ name: "divide_fractional", test: test_divide_fractional }, + #{ name: "divide_zero", test: test_divide_zero }, + #{ name: "divide_negative_dividend", test: test_divide_negative_dividend }, + #{ name: "divide_negative_divisor", test: test_divide_negative_divisor }, + #{ name: "divide_two_negatives", test: test_divide_two_negatives } ] }; diff --git a/tests/conformance/arithmetic/modulo.affine b/tests/conformance/arithmetic/modulo.affine index 01f2d0d..c6c3178 100644 --- a/tests/conformance/arithmetic/modulo.affine +++ b/tests/conformance/arithmetic/modulo.affine @@ -43,14 +43,14 @@ fn test_modulo_large() -> TestResult { /// Run all modulo conformance tests fn test_alib_arithmetic_modulo() -> TestResult { - let suite = { + let suite = #{ name: "aLib arithmetic/modulo conformance", tests: [ - { name: "modulo_basic", test: test_modulo_basic }, - { name: "modulo_no_remainder", test: test_modulo_no_remainder }, - { name: "modulo_nonzero", test: test_modulo_nonzero }, - { name: "modulo_zero", test: test_modulo_zero }, - { name: "modulo_large", test: test_modulo_large } + #{ name: "modulo_basic", test: test_modulo_basic }, + #{ name: "modulo_no_remainder", test: test_modulo_no_remainder }, + #{ name: "modulo_nonzero", test: test_modulo_nonzero }, + #{ name: "modulo_zero", test: test_modulo_zero }, + #{ name: "modulo_large", test: test_modulo_large } ] }; diff --git a/tests/conformance/arithmetic/multiply.affine b/tests/conformance/arithmetic/multiply.affine index 16dc01d..22ce8fd 100644 --- a/tests/conformance/arithmetic/multiply.affine +++ b/tests/conformance/arithmetic/multiply.affine @@ -50,15 +50,15 @@ fn test_multiply_two_negatives() -> TestResult { /// Run all multiply conformance tests fn test_alib_arithmetic_multiply() -> TestResult { - let suite = { + let suite = #{ name: "aLib arithmetic/multiply conformance", tests: [ - { name: "multiply_positive", test: test_multiply_positive }, - { name: "multiply_negative", test: test_multiply_negative }, - { name: "multiply_zero", test: test_multiply_zero }, - { name: "multiply_identity", test: test_multiply_identity }, - { name: "multiply_decimal", test: test_multiply_decimal }, - { name: "multiply_two_negatives", test: test_multiply_two_negatives } + #{ name: "multiply_positive", test: test_multiply_positive }, + #{ name: "multiply_negative", test: test_multiply_negative }, + #{ name: "multiply_zero", test: test_multiply_zero }, + #{ name: "multiply_identity", test: test_multiply_identity }, + #{ name: "multiply_decimal", test: test_multiply_decimal }, + #{ name: "multiply_two_negatives", test: test_multiply_two_negatives } ] }; diff --git a/tests/conformance/arithmetic/subtract.affine b/tests/conformance/arithmetic/subtract.affine index d01c141..07aa063 100644 --- a/tests/conformance/arithmetic/subtract.affine +++ b/tests/conformance/arithmetic/subtract.affine @@ -50,15 +50,15 @@ fn test_subtract_negatives() -> TestResult { /// Run all subtract conformance tests fn test_alib_arithmetic_subtract() -> TestResult { - let suite = { + let suite = #{ name: "aLib arithmetic/subtract conformance", tests: [ - { name: "subtract_positive", test: test_subtract_positive }, - { name: "subtract_negative_result", test: test_subtract_negative_result }, - { name: "subtract_zeros", test: test_subtract_zeros }, - { name: "subtract_from_negative", test: test_subtract_from_negative }, - { name: "subtract_decimal", test: test_subtract_decimal }, - { name: "subtract_negatives", test: test_subtract_negatives } + #{ name: "subtract_positive", test: test_subtract_positive }, + #{ name: "subtract_negative_result", test: test_subtract_negative_result }, + #{ name: "subtract_zeros", test: test_subtract_zeros }, + #{ name: "subtract_from_negative", test: test_subtract_from_negative }, + #{ name: "subtract_decimal", test: test_subtract_decimal }, + #{ name: "subtract_negatives", test: test_subtract_negatives } ] }; diff --git a/tests/conformance/collection/contains.affine b/tests/conformance/collection/contains.affine index 61de789..7e36bba 100644 --- a/tests/conformance/collection/contains.affine +++ b/tests/conformance/collection/contains.affine @@ -56,15 +56,15 @@ fn test_contains_multiple() -> TestResult { /// Run all contains conformance tests fn test_alib_collection_contains() -> TestResult { - let suite = { + let suite = #{ name: "aLib collection/contains conformance", tests: [ - { name: "contains_present", test: test_contains_present }, - { name: "contains_not_present", test: test_contains_not_present }, - { name: "contains_empty", test: test_contains_empty }, - { name: "contains_single", test: test_contains_single }, - { name: "contains_string", test: test_contains_string }, - { name: "contains_multiple", test: test_contains_multiple } + #{ name: "contains_present", test: test_contains_present }, + #{ name: "contains_not_present", test: test_contains_not_present }, + #{ name: "contains_empty", test: test_contains_empty }, + #{ name: "contains_single", test: test_contains_single }, + #{ name: "contains_string", test: test_contains_string }, + #{ name: "contains_multiple", test: test_contains_multiple } ] }; diff --git a/tests/conformance/collection/filter.affine b/tests/conformance/collection/filter.affine index ffeb6d4..d880577 100644 --- a/tests/conformance/collection/filter.affine +++ b/tests/conformance/collection/filter.affine @@ -48,14 +48,14 @@ fn test_filter_empty() -> TestResult { /// Run all filter conformance tests fn test_alib_collection_filter() -> TestResult { - let suite = { + let suite = #{ name: "aLib collection/filter conformance", tests: [ - { name: "filter_greater_than", test: test_filter_greater_than }, - { name: "filter_even", test: test_filter_even }, - { name: "filter_always_true", test: test_filter_always_true }, - { name: "filter_always_false", test: test_filter_always_false }, - { name: "filter_empty", test: test_filter_empty } + #{ name: "filter_greater_than", test: test_filter_greater_than }, + #{ name: "filter_even", test: test_filter_even }, + #{ name: "filter_always_true", test: test_filter_always_true }, + #{ name: "filter_always_false", test: test_filter_always_false }, + #{ name: "filter_empty", test: test_filter_empty } ] }; diff --git a/tests/conformance/collection/fold.affine b/tests/conformance/collection/fold.affine index 113826d..766aba9 100644 --- a/tests/conformance/collection/fold.affine +++ b/tests/conformance/collection/fold.affine @@ -56,15 +56,15 @@ fn test_fold_count() -> TestResult { /// Run all fold conformance tests fn test_alib_collection_fold() -> TestResult { - let suite = { + let suite = #{ name: "aLib collection/fold conformance", tests: [ - { name: "fold_sum", test: test_fold_sum }, - { name: "fold_product", test: test_fold_product }, - { name: "fold_empty", test: test_fold_empty }, - { name: "fold_single", test: test_fold_single }, - { name: "fold_concat", test: test_fold_concat }, - { name: "fold_count", test: test_fold_count } + #{ name: "fold_sum", test: test_fold_sum }, + #{ name: "fold_product", test: test_fold_product }, + #{ name: "fold_empty", test: test_fold_empty }, + #{ name: "fold_single", test: test_fold_single }, + #{ name: "fold_concat", test: test_fold_concat }, + #{ name: "fold_count", test: test_fold_count } ] }; diff --git a/tests/conformance/collection/map.affine b/tests/conformance/collection/map.affine index 96c2696..45793b3 100644 --- a/tests/conformance/collection/map.affine +++ b/tests/conformance/collection/map.affine @@ -48,14 +48,14 @@ fn test_map_string() -> TestResult { /// Run all map conformance tests fn test_alib_collection_map() -> TestResult { - let suite = { + let suite = #{ name: "aLib collection/map conformance", tests: [ - { name: "map_double", test: test_map_double }, - { name: "map_add_ten", test: test_map_add_ten }, - { name: "map_empty", test: test_map_empty }, - { name: "map_identity", test: test_map_identity }, - { name: "map_string", test: test_map_string } + #{ name: "map_double", test: test_map_double }, + #{ name: "map_add_ten", test: test_map_add_ten }, + #{ name: "map_empty", test: test_map_empty }, + #{ name: "map_identity", test: test_map_identity }, + #{ name: "map_string", test: test_map_string } ] }; diff --git a/tests/conformance/comparison/equal.affine b/tests/conformance/comparison/equal.affine index b4789e8..2274e81 100644 --- a/tests/conformance/comparison/equal.affine +++ b/tests/conformance/comparison/equal.affine @@ -42,16 +42,16 @@ fn test_equal_int_decimal() -> TestResult { } fn test_alib_comparison_equal() -> TestResult { - let suite = { + let suite = #{ name: "aLib comparison/equal conformance", tests: [ - { name: "equal_positive", test: test_equal_positive }, - { name: "equal_unequal", test: test_equal_unequal }, - { name: "equal_zero", test: test_equal_zero }, - { name: "equal_negative", test: test_equal_negative }, - { name: "equal_neg_pos", test: test_equal_neg_pos }, - { name: "equal_decimal", test: test_equal_decimal }, - { name: "equal_int_decimal", test: test_equal_int_decimal } + #{ name: "equal_positive", test: test_equal_positive }, + #{ name: "equal_unequal", test: test_equal_unequal }, + #{ name: "equal_zero", test: test_equal_zero }, + #{ name: "equal_negative", test: test_equal_negative }, + #{ name: "equal_neg_pos", test: test_equal_neg_pos }, + #{ name: "equal_decimal", test: test_equal_decimal }, + #{ name: "equal_int_decimal", test: test_equal_int_decimal } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/comparison/greater_equal.affine b/tests/conformance/comparison/greater_equal.affine index 53c1d85..f9bae87 100644 --- a/tests/conformance/comparison/greater_equal.affine +++ b/tests/conformance/comparison/greater_equal.affine @@ -32,14 +32,14 @@ fn test_greater_equal_zero() -> TestResult { } fn test_alib_comparison_greater_equal() -> TestResult { - let suite = { + let suite = #{ name: "aLib comparison/greater_equal conformance", tests: [ - { name: "greater_equal_greater", test: test_greater_equal_greater }, - { name: "greater_equal_equal", test: test_greater_equal_equal }, - { name: "greater_equal_less", test: test_greater_equal_less }, - { name: "greater_equal_negative", test: test_greater_equal_negative }, - { name: "greater_equal_zero", test: test_greater_equal_zero } + #{ name: "greater_equal_greater", test: test_greater_equal_greater }, + #{ name: "greater_equal_equal", test: test_greater_equal_equal }, + #{ name: "greater_equal_less", test: test_greater_equal_less }, + #{ name: "greater_equal_negative", test: test_greater_equal_negative }, + #{ name: "greater_equal_zero", test: test_greater_equal_zero } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/comparison/greater_than.affine b/tests/conformance/comparison/greater_than.affine index 8fe7376..2869e4c 100644 --- a/tests/conformance/comparison/greater_than.affine +++ b/tests/conformance/comparison/greater_than.affine @@ -32,14 +32,14 @@ fn test_greater_than_zero() -> TestResult { } fn test_alib_comparison_greater_than() -> TestResult { - let suite = { + let suite = #{ name: "aLib comparison/greater_than conformance", tests: [ - { name: "greater_than_true", test: test_greater_than_true }, - { name: "greater_than_false", test: test_greater_than_false }, - { name: "greater_than_equal", test: test_greater_than_equal }, - { name: "greater_than_negative", test: test_greater_than_negative }, - { name: "greater_than_zero", test: test_greater_than_zero } + #{ name: "greater_than_true", test: test_greater_than_true }, + #{ name: "greater_than_false", test: test_greater_than_false }, + #{ name: "greater_than_equal", test: test_greater_than_equal }, + #{ name: "greater_than_negative", test: test_greater_than_negative }, + #{ name: "greater_than_zero", test: test_greater_than_zero } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/comparison/less_equal.affine b/tests/conformance/comparison/less_equal.affine index 5161e9a..cbc0981 100644 --- a/tests/conformance/comparison/less_equal.affine +++ b/tests/conformance/comparison/less_equal.affine @@ -32,14 +32,14 @@ fn test_less_equal_zero() -> TestResult { } fn test_alib_comparison_less_equal() -> TestResult { - let suite = { + let suite = #{ name: "aLib comparison/less_equal conformance", tests: [ - { name: "less_equal_less", test: test_less_equal_less }, - { name: "less_equal_equal", test: test_less_equal_equal }, - { name: "less_equal_greater", test: test_less_equal_greater }, - { name: "less_equal_negative", test: test_less_equal_negative }, - { name: "less_equal_zero", test: test_less_equal_zero } + #{ name: "less_equal_less", test: test_less_equal_less }, + #{ name: "less_equal_equal", test: test_less_equal_equal }, + #{ name: "less_equal_greater", test: test_less_equal_greater }, + #{ name: "less_equal_negative", test: test_less_equal_negative }, + #{ name: "less_equal_zero", test: test_less_equal_zero } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/comparison/less_than.affine b/tests/conformance/comparison/less_than.affine index 0584bb6..d70c3f0 100644 --- a/tests/conformance/comparison/less_than.affine +++ b/tests/conformance/comparison/less_than.affine @@ -32,14 +32,14 @@ fn test_less_than_zero() -> TestResult { } fn test_alib_comparison_less_than() -> TestResult { - let suite = { + let suite = #{ name: "aLib comparison/less_than conformance", tests: [ - { name: "less_than_true", test: test_less_than_true }, - { name: "less_than_false", test: test_less_than_false }, - { name: "less_than_equal", test: test_less_than_equal }, - { name: "less_than_negative", test: test_less_than_negative }, - { name: "less_than_zero", test: test_less_than_zero } + #{ name: "less_than_true", test: test_less_than_true }, + #{ name: "less_than_false", test: test_less_than_false }, + #{ name: "less_than_equal", test: test_less_than_equal }, + #{ name: "less_than_negative", test: test_less_than_negative }, + #{ name: "less_than_zero", test: test_less_than_zero } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/comparison/not_equal.affine b/tests/conformance/comparison/not_equal.affine index 198f7f9..3561ab1 100644 --- a/tests/conformance/comparison/not_equal.affine +++ b/tests/conformance/comparison/not_equal.affine @@ -32,14 +32,14 @@ fn test_not_equal_neg_pos() -> TestResult { } fn test_alib_comparison_not_equal() -> TestResult { - let suite = { + let suite = #{ name: "aLib comparison/not_equal conformance", tests: [ - { name: "not_equal_unequal", test: test_not_equal_unequal }, - { name: "not_equal_equal", test: test_not_equal_equal }, - { name: "not_equal_zero", test: test_not_equal_zero }, - { name: "not_equal_negative", test: test_not_equal_negative }, - { name: "not_equal_neg_pos", test: test_not_equal_neg_pos } + #{ name: "not_equal_unequal", test: test_not_equal_unequal }, + #{ name: "not_equal_equal", test: test_not_equal_equal }, + #{ name: "not_equal_zero", test: test_not_equal_zero }, + #{ name: "not_equal_negative", test: test_not_equal_negative }, + #{ name: "not_equal_neg_pos", test: test_not_equal_neg_pos } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/conditional/if_then_else.affine b/tests/conformance/conditional/if_then_else.affine index e2df560..3b4177b 100644 --- a/tests/conformance/conditional/if_then_else.affine +++ b/tests/conformance/conditional/if_then_else.affine @@ -43,15 +43,15 @@ fn test_if_then_else_comparison_false() -> TestResult { } fn test_alib_conditional_if_then_else() -> TestResult { - let suite = { + let suite = #{ name: "aLib conditional/if_then_else conformance", tests: [ - { name: "if_then_else_true", test: test_if_then_else_true }, - { name: "if_then_else_false", test: test_if_then_else_false }, - { name: "if_then_else_string_true", test: test_if_then_else_string_true }, - { name: "if_then_else_string_false", test: test_if_then_else_string_false }, - { name: "if_then_else_comparison_true", test: test_if_then_else_comparison_true }, - { name: "if_then_else_comparison_false", test: test_if_then_else_comparison_false } + #{ name: "if_then_else_true", test: test_if_then_else_true }, + #{ name: "if_then_else_false", test: test_if_then_else_false }, + #{ name: "if_then_else_string_true", test: test_if_then_else_string_true }, + #{ name: "if_then_else_string_false", test: test_if_then_else_string_false }, + #{ name: "if_then_else_comparison_true", test: test_if_then_else_comparison_true }, + #{ name: "if_then_else_comparison_false", test: test_if_then_else_comparison_false } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/logical/and.affine b/tests/conformance/logical/and.affine index 9f2c581..aa62360 100644 --- a/tests/conformance/logical/and.affine +++ b/tests/conformance/logical/and.affine @@ -27,13 +27,13 @@ fn test_and_false_false() -> TestResult { } fn test_alib_logical_and() -> TestResult { - let suite = { + let suite = #{ name: "aLib logical/and conformance", tests: [ - { name: "and_true_true", test: test_and_true_true }, - { name: "and_true_false", test: test_and_true_false }, - { name: "and_false_true", test: test_and_false_true }, - { name: "and_false_false", test: test_and_false_false } + #{ name: "and_true_true", test: test_and_true_true }, + #{ name: "and_true_false", test: test_and_true_false }, + #{ name: "and_false_true", test: test_and_false_true }, + #{ name: "and_false_false", test: test_and_false_false } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/logical/not.affine b/tests/conformance/logical/not.affine index a65bd45..0b620d5 100644 --- a/tests/conformance/logical/not.affine +++ b/tests/conformance/logical/not.affine @@ -17,11 +17,11 @@ fn test_not_false() -> TestResult { } fn test_alib_logical_not() -> TestResult { - let suite = { + let suite = #{ name: "aLib logical/not conformance", tests: [ - { name: "not_true", test: test_not_true }, - { name: "not_false", test: test_not_false } + #{ name: "not_true", test: test_not_true }, + #{ name: "not_false", test: test_not_false } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/logical/or.affine b/tests/conformance/logical/or.affine index 584c5bf..09c6918 100644 --- a/tests/conformance/logical/or.affine +++ b/tests/conformance/logical/or.affine @@ -27,13 +27,13 @@ fn test_or_false_false() -> TestResult { } fn test_alib_logical_or() -> TestResult { - let suite = { + let suite = #{ name: "aLib logical/or conformance", tests: [ - { name: "or_true_true", test: test_or_true_true }, - { name: "or_true_false", test: test_or_true_false }, - { name: "or_false_true", test: test_or_false_true }, - { name: "or_false_false", test: test_or_false_false } + #{ name: "or_true_true", test: test_or_true_true }, + #{ name: "or_true_false", test: test_or_true_false }, + #{ name: "or_false_true", test: test_or_false_true }, + #{ name: "or_false_false", test: test_or_false_false } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/string/concat.affine b/tests/conformance/string/concat.affine index 8bfaf4c..4d0cc49 100644 --- a/tests/conformance/string/concat.affine +++ b/tests/conformance/string/concat.affine @@ -37,14 +37,14 @@ fn test_concat_empty_both() -> TestResult { } fn test_alib_string_concat() -> TestResult { - let suite = { + let suite = #{ name: "aLib string/concat conformance", tests: [ - { name: "concat_basic", test: test_concat_basic }, - { name: "concat_with_space", test: test_concat_with_space }, - { name: "concat_empty_left", test: test_concat_empty_left }, - { name: "concat_empty_right", test: test_concat_empty_right }, - { name: "concat_empty_both", test: test_concat_empty_both } + #{ name: "concat_basic", test: test_concat_basic }, + #{ name: "concat_with_space", test: test_concat_with_space }, + #{ name: "concat_empty_left", test: test_concat_empty_left }, + #{ name: "concat_empty_right", test: test_concat_empty_right }, + #{ name: "concat_empty_both", test: test_concat_empty_both } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/string/length.affine b/tests/conformance/string/length.affine index 195dd7d..7bb7323 100644 --- a/tests/conformance/string/length.affine +++ b/tests/conformance/string/length.affine @@ -37,14 +37,14 @@ fn test_length_numeric() -> TestResult { } fn test_alib_string_length() -> TestResult { - let suite = { + let suite = #{ name: "aLib string/length conformance", tests: [ - { name: "length_simple", test: test_length_simple }, - { name: "length_empty", test: test_length_empty }, - { name: "length_single", test: test_length_single }, - { name: "length_with_space", test: test_length_with_space }, - { name: "length_numeric", test: test_length_numeric } + #{ name: "length_simple", test: test_length_simple }, + #{ name: "length_empty", test: test_length_empty }, + #{ name: "length_single", test: test_length_single }, + #{ name: "length_with_space", test: test_length_with_space }, + #{ name: "length_numeric", test: test_length_numeric } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/conformance/string/substring.affine b/tests/conformance/string/substring.affine index c3c8043..c018b68 100644 --- a/tests/conformance/string/substring.affine +++ b/tests/conformance/string/substring.affine @@ -40,14 +40,14 @@ fn test_substring_empty() -> TestResult { } fn test_alib_string_substring() -> TestResult { - let suite = { + let suite = #{ name: "aLib string/substring conformance", tests: [ - { name: "substring_entire", test: test_substring_entire }, - { name: "substring_middle", test: test_substring_middle }, - { name: "substring_first", test: test_substring_first }, - { name: "substring_last", test: test_substring_last }, - { name: "substring_empty", test: test_substring_empty } + #{ name: "substring_entire", test: test_substring_entire }, + #{ name: "substring_middle", test: test_substring_middle }, + #{ name: "substring_first", test: test_substring_first }, + #{ name: "substring_last", test: test_substring_last }, + #{ name: "substring_empty", test: test_substring_empty } ] }; let (passed, failed) = run_suite(suite); diff --git a/tests/scratch/test_spread.affine b/tests/scratch/test_spread.affine index ecb8078..cac0c7f 100644 --- a/tests/scratch/test_spread.affine +++ b/tests/scratch/test_spread.affine @@ -1,4 +1,4 @@ fn test() -> Int { - let x = { a: 1, ..{ b: 2 } }; + let x = #{ a: 1, ..#{ b: 2 } }; return x.a; } diff --git a/tests/scratch/test_spread2.affine b/tests/scratch/test_spread2.affine index ecb8078..cac0c7f 100644 --- a/tests/scratch/test_spread2.affine +++ b/tests/scratch/test_spread2.affine @@ -1,4 +1,4 @@ fn test() -> Int { - let x = { a: 1, ..{ b: 2 } }; + let x = #{ a: 1, ..#{ b: 2 } }; return x.a; } diff --git a/tests/types/test_kind_checking.affine b/tests/types/test_kind_checking.affine index a1cb65f..c4f7749 100644 --- a/tests/types/test_kind_checking.affine +++ b/tests/types/test_kind_checking.affine @@ -12,12 +12,12 @@ type Box[A] = { // Function using Box fn box_value[A](x: A) -> Box[A] { - return {value: x}; + return #{value: x}; } // Multiple type parameters fn swap[A, B](x: A, y: B) -> {fst: B, snd: A} { - return {fst: y, snd: x}; + return #{fst: y, snd: x}; } fn main() -> Int { diff --git a/tests/types/test_row_polymorphism.affine b/tests/types/test_row_polymorphism.affine index c903e74..59cc085 100644 --- a/tests/types/test_row_polymorphism.affine +++ b/tests/types/test_row_polymorphism.affine @@ -16,9 +16,9 @@ fn add_to_x(r: {x: Int, ..rest}, n: Int) -> Int { fn main() -> Int { // These should all work due to row polymorphism - let r1 = {x: 10}; - let r2 = {x: 20, y: 30}; - let r3 = {x: 5, y: 10, z: 15}; + let r1 = #{x: 10}; + let r2 = #{x: 20, y: 30}; + let r3 = #{x: 5, y: 10, z: 15}; let a = get_x(r1); // 10 let b = get_x(r2); // 20 diff --git a/tests/types/test_row_simple.affine b/tests/types/test_row_simple.affine index e42169c..feb0499 100644 --- a/tests/types/test_row_simple.affine +++ b/tests/types/test_row_simple.affine @@ -8,6 +8,6 @@ fn get_x(r: {x: Int, ..rest}) -> Int { } fn main() -> Int { - let r = {x: 42, y: 100}; + let r = #{x: 42, y: 100}; return get_x(r); }