From 9fe0f77ab10f7ff9f67142c9833a6cc819606931 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Thu, 1 Jan 2026 14:32:20 -0300 Subject: [PATCH] refactor: reorganize bytecode tests with file-based snapshots --- crates/plotnik-lib/src/bytecode/dump.rs | 23 +- crates/plotnik-lib/src/bytecode/dump_tests.rs | 1025 ----------------- crates/plotnik-lib/src/bytecode/mod.rs | 2 - crates/plotnik-lib/src/emit/codegen_tests.rs | 899 ++++++--------- ..._codegen_tests__alternations_captured.snap | 39 + ...n_tests__alternations_captured_tagged.snap | 54 + ...gen_tests__alternations_in_quantifier.snap | 77 ++ ...__codegen_tests__alternations_labeled.snap | 54 + ...ts__alternations_no_internal_captures.snap | 42 + ...en_tests__alternations_null_injection.snap | 44 + ...codegen_tests__alternations_unlabeled.snap | 44 + ...degen_tests__anchors_between_siblings.snap | 39 + ...t__codegen_tests__anchors_first_child.snap | 37 + ...it__codegen_tests__anchors_last_child.snap | 37 + ...mit__codegen_tests__anchors_no_anchor.snap | 39 + ...codegen_tests__anchors_with_anonymous.snap | 39 + ...__emit__codegen_tests__captures_basic.snap | 36 + ...codegen_tests__captures_deeply_nested.snap | 47 + ...mit__codegen_tests__captures_multiple.snap | 43 + ...__codegen_tests__captures_nested_flat.snap | 43 + ...sts__captures_optional_wrapper_struct.snap | 50 + ..._codegen_tests__captures_struct_scope.snap | 43 + ...egen_tests__captures_with_type_custom.snap | 39 + ...egen_tests__captures_with_type_string.snap | 36 + ...odegen_tests__captures_wrapper_struct.snap | 61 + ...tests__comprehensive_multi_definition.snap | 87 ++ ...__codegen_tests__definitions_multiple.snap | 49 + ..._codegen_tests__definitions_reference.snap | 58 + ...it__codegen_tests__definitions_single.snap | 36 + ..._emit__codegen_tests__fields_multiple.snap | 43 + ...__emit__codegen_tests__fields_negated.snap | 40 + ...b__emit__codegen_tests__fields_single.snap | 39 + ..._emit__codegen_tests__nodes_anonymous.snap | 39 + ...lib__emit__codegen_tests__nodes_error.snap | 36 + ...b__emit__codegen_tests__nodes_missing.snap | 36 + ...lib__emit__codegen_tests__nodes_named.snap | 36 + ...it__codegen_tests__nodes_wildcard_any.snap | 38 + ...__codegen_tests__nodes_wildcard_named.snap | 38 + ...__codegen_tests__optional_first_child.snap | 47 + ...odegen_tests__optional_null_injection.snap | 42 + ..._tests__quantifiers_first_child_array.snap | 51 + ...__codegen_tests__quantifiers_optional.snap | 42 + ...tests__quantifiers_optional_nongreedy.snap | 42 + ...emit__codegen_tests__quantifiers_plus.snap | 41 + ...gen_tests__quantifiers_plus_nongreedy.snap | 41 + ..._tests__quantifiers_repeat_navigation.snap | 46 + ...emit__codegen_tests__quantifiers_star.snap | 42 + ...gen_tests__quantifiers_star_nongreedy.snap | 42 + ...degen_tests__quantifiers_struct_array.snap | 58 + ...emit__codegen_tests__recursion_simple.snap | 63 + ...sts__recursion_with_structured_result.snap | 80 ++ ..._emit__codegen_tests__sequences_basic.snap | 39 + ...odegen_tests__sequences_in_quantifier.snap | 49 + ...emit__codegen_tests__sequences_nested.snap | 43 + ...odegen_tests__sequences_with_captures.snap | 41 + docs/binary-format/07-dump-format.md | 88 +- 56 files changed, 2730 insertions(+), 1634 deletions(-) delete mode 100644 crates/plotnik-lib/src/bytecode/dump_tests.rs create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured_tagged.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_in_quantifier.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_labeled.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_no_internal_captures.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_null_injection.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_unlabeled.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_between_siblings.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_first_child.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_last_child.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_no_anchor.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_with_anonymous.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_basic.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_deeply_nested.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_multiple.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_nested_flat.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_optional_wrapper_struct.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_struct_scope.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_custom.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_string.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_wrapper_struct.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__comprehensive_multi_definition.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_multiple.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_reference.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_single.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_multiple.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_negated.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_single.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_anonymous.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_error.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_missing.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_named.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_any.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_named.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_first_child.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_null_injection.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_first_child_array.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional_nongreedy.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus_nongreedy.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_repeat_navigation.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star_nongreedy.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_struct_array.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_simple.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_with_structured_result.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_basic.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_in_quantifier.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_nested.snap create mode 100644 crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_with_captures.snap diff --git a/crates/plotnik-lib/src/bytecode/dump.rs b/crates/plotnik-lib/src/bytecode/dump.rs index 7d3dc0d0..a2c623be 100644 --- a/crates/plotnik-lib/src/bytecode/dump.rs +++ b/crates/plotnik-lib/src/bytecode/dump.rs @@ -30,7 +30,7 @@ pub fn dump(module: &Module) -> String { fn dump_header(out: &mut String, module: &Module) { let header = module.header(); - out.push_str("[header]\n"); + out.push_str("[flags]\n"); writeln!(out, "linked = {}", header.is_linked()).unwrap(); out.push('\n'); } @@ -139,7 +139,7 @@ fn dump_types_defs(out: &mut String, module: &Module, ctx: &DumpContext) { let types = module.types(); let strings = module.strings(); - out.push_str("[types.defs]\n"); + out.push_str("[type_defs]\n"); // Builtins (T00-T02) out.push_str("T00 = void\n"); @@ -153,8 +153,8 @@ fn dump_types_defs(out: &mut String, module: &Module, ctx: &DumpContext) { let kind = def.type_kind().expect("valid type kind"); let formatted = match kind { - TypeKind::Struct => format!("Struct(M{}, {})", def.data, def.count), - TypeKind::Enum => format!("Enum(M{}, {})", def.data, def.count), + TypeKind::Struct => format!("Struct M{}[{}]", def.data, def.count), + TypeKind::Enum => format!("Enum M{}[{}]", def.data, def.count), TypeKind::Optional => format!("Optional(T{:02})", def.data), TypeKind::ArrayZeroOrMore => format!("ArrayStar(T{:02})", def.data), TypeKind::ArrayOneOrMore => format!("ArrayPlus(T{:02})", def.data), @@ -201,14 +201,14 @@ fn dump_types_members(out: &mut String, module: &Module, ctx: &DumpContext) { let types = module.types(); let strings = module.strings(); - out.push_str("[types.members]\n"); + out.push_str("[type_members]\n"); for i in 0..types.members_count() { let member = types.get_member(i); let name = strings.get(member.name); let type_name = format_type_name(member.type_id, module, ctx); writeln!( out, - "M{i} = (S{:02}, T{:02}) ; {name}: {type_name}", + "M{i}: S{:02} โ†’ T{:02} ; {name}: {type_name}", member.name.0, member.type_id.0 ) .unwrap(); @@ -220,13 +220,13 @@ fn dump_types_names(out: &mut String, module: &Module, _ctx: &DumpContext) { let types = module.types(); let strings = module.strings(); - out.push_str("[types.names]\n"); + out.push_str("[type_names]\n"); for i in 0..types.names_count() { let entry = types.get_name(i); let name = strings.get(entry.name); writeln!( out, - "N{i} = (S{:02}, T{:02}) ; {name}", + "N{i}: S{:02} โ†’ T{:02} ; {name}", entry.name.0, entry.type_id.0 ) .unwrap(); @@ -264,7 +264,7 @@ fn dump_entrypoints(out: &mut String, module: &Module, _ctx: &DumpContext) { let strings = module.strings(); let entrypoints = module.entrypoints(); - out.push_str("[entry]\n"); + out.push_str("[entrypoints]\n"); // Collect and sort by name for display let mut entries: Vec<_> = (0..entrypoints.len()) @@ -302,7 +302,7 @@ fn dump_code(out: &mut String, module: &Module, ctx: &DumpContext) { ((transitions_count as f64).log10().floor() as usize + 1).max(2) }; - out.push_str("[code]\n"); + out.push_str("[transitions]\n"); let mut step = 0u16; while (step as usize) < transitions_count { @@ -323,8 +323,9 @@ fn dump_code(out: &mut String, module: &Module, ctx: &DumpContext) { } /// Pad a base string to a target column width, then append a suffix. +/// Ensures at least 2 spaces between base and suffix. fn pad_to_column(base: String, col: usize, suffix: &str) -> String { - let padding = col.saturating_sub(base.chars().count()); + let padding = col.saturating_sub(base.chars().count()).max(2); format!("{base}{:padding$}{suffix}", "") } diff --git a/crates/plotnik-lib/src/bytecode/dump_tests.rs b/crates/plotnik-lib/src/bytecode/dump_tests.rs deleted file mode 100644 index 4069196a..00000000 --- a/crates/plotnik-lib/src/bytecode/dump_tests.rs +++ /dev/null @@ -1,1025 +0,0 @@ -//! Tests for bytecode dump functionality. - -use crate::Query; -use indoc::indoc; - -#[test] -fn dump_minimal() { - let input = "Test = (identifier) @id"; - - let res = Query::expect_valid_linked_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "id" - S02 "Test" - S03 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { id } - - [types.members] - M0 = (S01, T01) ; id: Node - - [types.names] - N0 = (S02, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 (identifier) [Node Set(M0)] 04 - 04 โ–ถ - "#); -} - -#[test] -fn dump_multiple_entrypoints() { - let input = indoc! {r#" - Expression = [(identifier) @name (number) @value] - Root = (function_declaration name: (identifier) @name) - "#}; - - let res = Query::expect_valid_linked_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "name" - S02 "value" - S03 "Expression" - S04 "Root" - S05 "identifier" - S06 "number" - S07 "function_declaration" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { name, value } - T04 = Struct(M2, 1) ; { name } - T05 = Optional(T01) ; Node? - - [types.members] - M0 = (S01, T05) ; name: T05 - M1 = (S02, T05) ; value: T05 - M2 = (S01, T01) ; name: Node - - [types.names] - N0 = (S03, T03) ; Expression - N1 = (S04, T04) ; Root - - [entry] - Expression = 01 :: T03 - Root = 04 :: T04 - - [code] - 00 ๐œ€ โ—ผ - - Expression: - 01 ๐œ€ 02 - 02 ๐œ€ 13, 17 - - Root: - 04 ๐œ€ 05 - 05 (function_declaration) 06 - 06 โ†“* name: (identifier) [Node Set(M2)]08 - 08 *โ†‘ยน 09 - 09 โ–ถ - 10 โ–ถ - 11 (identifier) [Node Set(M0)] 10 - 13 ๐œ€ [Null Set(M1)] 11 - 15 (number) [Node Set(M1)] 10 - 17 ๐œ€ [Null Set(M0)] 15 - "#); -} - -#[test] -fn dump_with_field_constraints() { - let input = indoc! {r#" - Test = (binary_expression - left: (_) @left - right: (_) @right) - "#}; - - let res = Query::expect_valid_linked_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "left" - S02 "right" - S03 "Test" - S04 "binary_expression" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { left, right } - - [types.members] - M0 = (S01, T01) ; left: Node - M1 = (S02, T01) ; right: Node - - [types.names] - N0 = (S03, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 (binary_expression) 03 - 03 โ†“* left: _ [Node Set(M0)] 05 - 05 * right: _ [Node Set(M1)] 07 - 07 *โ†‘ยน 08 - 08 โ–ถ - "#); -} - -#[test] -fn dump_with_quantifier() { - let input = "Test = (identifier)* @items"; - - let res = Query::expect_valid_linked_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "items" - S02 "Test" - S03 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = ArrayStar(T01) ; Node* - T04 = Struct(M0, 1) ; { items } - - [types.members] - M0 = (S01, T03) ; items: T03 - - [types.names] - N0 = (S02, T04) ; Test - - [entry] - Test = 01 :: T04 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 ๐œ€ [Arr] 04 - 04 ๐œ€ 09, 07 - 06 โ–ถ - 07 ๐œ€ [EndArr Set(M0)] 06 - 09 (identifier) [Push] 13 - 11 (identifier) [Push] 13 - 13 ๐œ€ 11, 07 - "#); -} - -#[test] -fn dump_with_alternation() { - let input = "Test = [(identifier) @id (string) @str]"; - - let res = Query::expect_valid_linked_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "id" - S02 "str" - S03 "Test" - S04 "identifier" - S05 "string" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { id, str } - T04 = Optional(T01) ; Node? - - [types.members] - M0 = (S01, T04) ; id: T04 - M1 = (S02, T04) ; str: T04 - - [types.names] - N0 = (S03, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 ๐œ€ 07, 11 - 04 โ–ถ - 05 (identifier) [Node Set(M0)] 04 - 07 ๐œ€ [Null Set(M1)] 05 - 09 (string) [Node Set(M1)] 04 - 11 ๐œ€ [Null Set(M0)] 09 - "#); -} - -#[test] -fn dump_comprehensive() { - // A query that exercises most features: - // - Multiple definitions (entrypoints) - // - Field constraints (node_fields) - // - Multiple node types (node_types) - // - Captures with types (type_defs, type_members) - // - Alternation (branching in code) - let input = indoc! {r#" - Ident = (identifier) @name :: string - Expression = [ - Literal: (number) @value - Variable: (identifier) @name - ] - Assignment = (assignment_expression - left: (identifier) @target - right: (Expression) @value) - "#}; - - let res = Query::expect_valid_linked_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "name" - S02 "value" - S03 "Literal" - S04 "Variable" - S05 "target" - S06 "Ident" - S07 "Expression" - S08 "Assignment" - S09 "identifier" - S10 "number" - S11 "assignment_expression" - S12 "left" - S13 "right" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { name } - T04 = Struct(M1, 1) ; { value } - T05 = Struct(M2, 1) ; { name } - T06 = Enum(M3, 2) ; Literal | Variable - T07 = Struct(M5, 2) ; { value, target } - - [types.members] - M0 = (S01, T02) ; name: str - M1 = (S02, T01) ; value: Node - M2 = (S01, T01) ; name: Node - M3 = (S03, T04) ; Literal: T04 - M4 = (S04, T05) ; Variable: T05 - M5 = (S02, T06) ; value: Expression - M6 = (S05, T01) ; target: Node - - [types.names] - N0 = (S06, T03) ; Ident - N1 = (S07, T06) ; Expression - N2 = (S08, T07) ; Assignment - - [entry] - Assignment = 08 :: T07 - Expression = 05 :: T06 - Ident = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Ident: - 01 ๐œ€ 02 - 02 (identifier) [Text Set(M0)] 04 - 04 โ–ถ - - Expression: - 05 ๐œ€ 06 - 06 ๐œ€ 22, 28 - - Assignment: - 08 ๐œ€ 09 - 09 (assignment_expression) 10 - 10 โ†“* left: (identifier) [Node Set(M6)]12 - 12 * โ–ถ right: (Expression) 13 - 13 ๐œ€ [Set(M5)] 15 - 15 *โ†‘ยน 16 - 16 โ–ถ - 17 โ–ถ - 18 ๐œ€ [EndEnum] 17 - 20 (number) [Node Set(M1)] 18 - 22 ๐œ€ [Enum(M3)] 20 - 24 ๐œ€ [EndEnum] 17 - 26 (identifier) [Node Set(M2)] 24 - 28 ๐œ€ [Enum(M4)] 26 - "#); -} - -/// Regression test for nested bubble captures. -/// -/// Previously, deeply nested bubble captures (3+ levels) produced incorrect -/// member indices. The innermost captures were offset incorrectly because -/// each bubble capture pushed an intermediate type as the scope, but those -/// types weren't emitted to bytecode. The fix ensures bubble captures don't -/// push new scopes, so all member lookups reference the root struct. -#[test] -fn dump_nested_bubble_captures_three_levels() { - // 3 levels of nested bubble captures: @a wraps @b wraps @c - let input = "Test = (a (b (c) @c) @b) @a"; - - let res = Query::expect_valid_bytecode(input); - - // Verify member indices: @c should use M2, @b should use M1, @a should use M0 - // Previously this would incorrectly produce: @cโ†’M1, @bโ†’M0, @aโ†’M0 - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "a" - S02 "b" - S03 "c" - S04 "Test" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 3) ; { a, b, c } - - [types.members] - M0 = (S01, T01) ; a: Node - M1 = (S02, T01) ; b: Node - M2 = (S03, T01) ; c: Node - - [types.names] - N0 = (S04, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 (a) [Node Set(M0)] 04 - 04 โ†“* (b) [Node Set(M1)] 06 - 06 โ†“* (c) [Node Set(M2)] 08 - 08 *โ†‘ยน 09 - 09 *โ†‘ยน 10 - 10 โ–ถ - "#); -} - -#[test] -fn dump_nested_bubble_captures_four_levels() { - // 4 levels of nested bubble captures - let input = "Test = (a (b (c (d) @d) @c) @b) @a"; - - let res = Query::expect_valid_bytecode(input); - - // Verify all member indices are correct - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "a" - S02 "b" - S03 "c" - S04 "d" - S05 "Test" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 4) ; { a, b, c, d } - - [types.members] - M0 = (S01, T01) ; a: Node - M1 = (S02, T01) ; b: Node - M2 = (S03, T01) ; c: Node - M3 = (S04, T01) ; d: Node - - [types.names] - N0 = (S05, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 (a) [Node Set(M0)] 04 - 04 โ†“* (b) [Node Set(M1)] 06 - 06 โ†“* (c) [Node Set(M2)] 08 - 08 โ†“* (d) [Node Set(M3)] 10 - 10 *โ†‘ยน 11 - 11 *โ†‘ยน 12 - 12 *โ†‘ยน 13 - 13 โ–ถ - "#); -} - -/// Regression test for quantifier repeat navigation. -/// -/// Previously, repeat iterations in */+ quantifiers used None for navigation, -/// defaulting to Stay. This caused infinite loops because the VM would match -/// the same node forever instead of advancing to the next sibling. -#[test] -fn dump_quantifier_repeat_navigation() { - let input = "Test = (function_declaration (decorator)* @decs)"; - - let res = Query::expect_valid_linked_bytecode(input); - - // The first iteration should use Down (โ†“*), repeat should use Next (*) - // Previously, the repeat iteration had no navigation (stayed on same node) - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "decs" - S02 "Test" - S03 "function_declaration" - S04 "decorator" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = ArrayStar(T01) ; Node* - T04 = Struct(M0, 1) ; { decs } - - [types.members] - M0 = (S01, T03) ; decs: T03 - - [types.names] - N0 = (S02, T04) ; Test - - [entry] - Test = 01 :: T04 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 (function_declaration) 03 - 03 ๐œ€ [Arr] 05 - 05 ๐œ€ 13, 11 - 07 ๐œ€ [EndArr Set(M0)] 09 - 09 *โ†‘ยน 10 - 10 โ–ถ - 11 ๐œ€ [EndArr Set(M0)] 10 - 13 โ†“* (decorator) [Push] 17 - 15 * (decorator) [Push] 17 - 17 ๐œ€ 15, 07 - "#); -} - -/// Regression test for Null effect emission in alternations. -/// -/// When a capture appears in some alternation branches but not others, -/// the compiler must inject Null Set(member) for the missing fields. -/// This ensures the output object always has all fields defined. -#[test] -fn dump_alternation_null_injection() { - let input = "Test = [(identifier) @x (number) @y]"; - - let res = Query::expect_valid_linked_bytecode(input); - - // Branch 1 (identifier @x) should inject Null Set(M1) for missing @y - // Branch 2 (number @y) should inject Null Set(M0) for missing @x - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "x" - S02 "y" - S03 "Test" - S04 "identifier" - S05 "number" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { x, y } - T04 = Optional(T01) ; Node? - - [types.members] - M0 = (S01, T04) ; x: T04 - M1 = (S02, T04) ; y: T04 - - [types.names] - N0 = (S03, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 ๐œ€ 07, 11 - 04 โ–ถ - 05 (identifier) [Node Set(M0)] 04 - 07 ๐œ€ [Null Set(M1)] 05 - 09 (number) [Node Set(M1)] 04 - 11 ๐œ€ [Null Set(M0)] 09 - "#); -} - -/// Regression test for captured tagged alternation effect placement. -/// -/// When a tagged alternation has an outer capture like `[A: (x) @a] @item`, -/// the outer capture's Set effect must go on the EndEnum step, not on the -/// branch body. Otherwise the field receives a Node instead of the enum. -#[test] -fn dump_captured_tagged_alternation() { - let input = "Q = [A: (identifier) @a B: (number) @b] @item"; - - let res = Query::expect_valid_linked_bytecode(input); - - // The Set(M3) for @item should be on the EndEnum step, not with Node Set(M0/M1) - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "a" - S02 "b" - S03 "A" - S04 "B" - S05 "item" - S06 "Q" - S07 "identifier" - S08 "number" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { a } - T04 = Struct(M1, 1) ; { b } - T05 = Enum(M2, 2) ; A | B - T06 = Struct(M4, 1) ; { item } - - [types.members] - M0 = (S01, T01) ; a: Node - M1 = (S02, T01) ; b: Node - M2 = (S03, T03) ; A: T03 - M3 = (S04, T04) ; B: T04 - M4 = (S05, T05) ; item: T05 - - [types.names] - N0 = (S06, T06) ; Q - - [entry] - Q = 01 :: T06 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 ๐œ€ 09, 15 - 04 โ–ถ - 05 ๐œ€ [EndEnum Set(M4)] 04 - 07 (identifier) [Node Set(M0)] 05 - 09 ๐œ€ [Enum(M2)] 07 - 11 ๐œ€ [EndEnum Set(M4)] 04 - 13 (number) [Node Set(M1)] 11 - 15 ๐œ€ [Enum(M3)] 13 - "#); -} - -/// Regression test for captured tagged alternation inside quantifier. -/// -/// Same issue as above, but the outer capture is inside a row quantifier. -/// The Set effect for @item must be on EndEnum, not on the branch body. -#[test] -fn dump_captured_tagged_alternation_in_quantifier() { - let input = - "Q = (object { [A: (pair) @a B: (shorthand_property_identifier) @b] @item }* @items)"; - - let res = Query::expect_valid_linked_bytecode(input); - - // The Set(M4) for @item should be on the EndEnum step - insta::assert_snapshot!(res, @r#" - [header] - linked = true - - [strings] - S00 "Beauty will save the world" - S01 "a" - S02 "b" - S03 "A" - S04 "B" - S05 "item" - S06 "items" - S07 "Q" - S08 "object" - S09 "pair" - S10 "shorthand_property_identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { a } - T04 = Struct(M1, 1) ; { b } - T05 = Enum(M2, 2) ; A | B - T06 = Struct(M4, 1) ; { item } - T07 = ArrayStar(T06) ; T06* - T08 = Struct(M5, 1) ; { items } - - [types.members] - M0 = (S01, T01) ; a: Node - M1 = (S02, T01) ; b: Node - M2 = (S03, T03) ; A: T03 - M3 = (S04, T04) ; B: T04 - M4 = (S05, T05) ; item: T05 - M5 = (S06, T07) ; items: T07 - - [types.names] - N0 = (S07, T08) ; Q - - [entry] - Q = 01 :: T08 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 (object) 03 - 03 ๐œ€ [Arr] 05 - 05 ๐œ€ 29, 11 - 07 ๐œ€ [EndArr Set(M5)] 09 - 09 *โ†‘ยน 10 - 10 โ–ถ - 11 ๐œ€ [EndArr Set(M5)] 10 - 13 ๐œ€ [EndObj Push] 49 - 15 ๐œ€ [EndEnum Set(M4)] 13 - 17 โ†“* (pair) [Node Set(M0)] 15 - 19 ๐œ€ [Enum(M2)] 17 - 21 ๐œ€ [EndEnum Set(M4)] 13 - 23 โ†“* (shorthand_property_identifier) [Node Set(M1)]21 - 25 ๐œ€ [Enum(M3)] 23 - 27 ๐œ€ 19, 25 - 29 ๐œ€ [Obj] 27 - 31 ๐œ€ [EndObj Push] 49 - 33 ๐œ€ [EndEnum Set(M4)] 31 - 35 * (pair) [Node Set(M0)] 33 - 37 ๐œ€ [Enum(M2)] 35 - 39 ๐œ€ [EndEnum Set(M4)] 31 - 41 * (shorthand_property_identifier) [Node Set(M1)]39 - 43 ๐œ€ [Enum(M3)] 41 - 45 ๐œ€ 37, 43 - 47 ๐œ€ [Obj] 45 - 49 ๐œ€ 47, 07 - "#); -} - -/// Regression test: alternation capture without internal captures needs Node effect. -/// -/// Bug: `[(identifier) (number)] @x` was missing the Node effect, producing -/// just `[Set(M0)]` instead of `[Node Set(M0)]`. The alternation doesn't have -/// internal captures, so it produces a Node value, not a Struct. -#[test] -fn regression_alternation_capture_node_effect() { - let input = "Q = (program [(identifier) (number)] @x)"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "x" - S02 "Q" - S03 "program" - S04 "identifier" - S05 "number" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { x } - - [types.members] - M0 = (S01, T01) ; x: Node - - [types.names] - N0 = (S02, T03) ; Q - - [entry] - Q = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 (program) 03 - 03 ๐œ€ 06, 08 - 05 โ–ถ - 06 โ†“* (identifier) [Node Set(M0)] 10 - 08 โ†“* (number) [Node Set(M0)] 10 - 10 *โ†‘ยน 05 - "#); -} - -/// Regression test: optional first-child skip path needs Down navigation. -/// -/// Bug: When `(parent (child)? @a (sibling) @b)` skips the optional, the sibling -/// was compiled with Next navigation, but we never descended into parent's children. -/// The skip path must use Down navigation for the first non-skipped child. -#[test] -fn regression_optional_first_child_skip_navigation() { - let input = "Q = (program (identifier)? @id (number) @n)"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "id" - S02 "n" - S03 "Q" - S04 "program" - S05 "number" - S06 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { id, n } - T04 = Optional(T01) ; Node? - - [types.members] - M0 = (S01, T04) ; id: T04 - M1 = (S02, T01) ; n: Node - - [types.names] - N0 = (S03, T03) ; Q - - [entry] - Q = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 (program) 03 - 03 ๐œ€ 12, 10 - 05 โ–ถ - 06 โ†“* (number) [Node Set(M1)] 14 - 08 * (number) [Node Set(M1)] 14 - 10 ๐œ€ [Null Set(M0)] 06 - 12 โ†“* (identifier) [Node Set(M0)] 08 - 14 *โ†‘ยน 05 - "#); -} - -/// Regression test: optional skip path needs Null injection for captures. -/// -/// Bug: When `(parent (child)? @a)` skips the optional, the field @a was never -/// set to null. Alternations correctly inject `[Null Set(Mx)]` for missing -/// captures, but optionals didn't. -#[test] -fn regression_optional_skip_null_injection() { - let input = "Q = (function_declaration (decorator)? @dec)"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "dec" - S02 "Q" - S03 "function_declaration" - S04 "decorator" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { dec } - T04 = Optional(T01) ; Node? - - [types.members] - M0 = (S01, T04) ; dec: T04 - - [types.names] - N0 = (S02, T03) ; Q - - [entry] - Q = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 (function_declaration) 03 - 03 ๐œ€ 05, 09 - 05 โ†“* (decorator) [Node Set(M0)] 07 - 07 *โ†‘ยน 08 - 08 โ–ถ - 09 ๐œ€ [Null Set(M0)] 08 - "#); -} - -/// Regression test: star first-child with array capture preserves Arr/EndArr. -/// -/// Bug: When compiling `(parent (child)* @arr (sibling) @s)` as first-child, -/// the array scope (Arr/EndArr) was being stripped. The fix must preserve -/// array semantics while also handling skip navigation. -#[test] -fn regression_star_first_child_array_capture() { - let input = "Q = (array (identifier)* @ids (number) @n)"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "ids" - S02 "n" - S03 "Q" - S04 "array" - S05 "number" - S06 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = ArrayStar(T01) ; Node* - T04 = Struct(M0, 2) ; { ids, n } - - [types.members] - M0 = (S01, T03) ; ids: T03 - M1 = (S02, T01) ; n: Node - - [types.names] - N0 = (S03, T04) ; Q - - [entry] - Q = 01 :: T04 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 (array) 03 - 03 ๐œ€ [Arr] 05 - 05 ๐œ€ 16, 14 - 07 โ–ถ - 08 โ†“* (number) [Node Set(M1)] 22 - 10 * (number) [Node Set(M1)] 22 - 12 ๐œ€ [EndArr Set(M0)] 10 - 14 ๐œ€ [EndArr Set(M0)] 08 - 16 โ†“* (identifier) [Push] 20 - 18 * (identifier) [Push] 20 - 20 ๐œ€ 18, 12 - 22 *โ†‘ยน 07 - "#); -} - -/// Regression test: struct array with internal captures needs Obj/EndObj. -/// -/// Bug: When `{(a) @a (b) @b}* @items` is compiled, the struct boundaries -/// (Obj/EndObj) and Set effects are missing. Each iteration should produce: -/// Obj โ†’ Node Set(M0) โ†’ Node Set(M1) โ†’ EndObj Push -#[test] -fn regression_struct_array_internal_captures() { - let input = "Q = (array {(identifier) @a (number) @b}* @items)"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "a" - S02 "b" - S03 "items" - S04 "Q" - S05 "array" - S06 "number" - S07 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { a, b } - T04 = ArrayStar(T03) ; T03* - T05 = Struct(M2, 1) ; { items } - - [types.members] - M0 = (S01, T01) ; a: Node - M1 = (S02, T01) ; b: Node - M2 = (S03, T04) ; items: T04 - - [types.names] - N0 = (S04, T05) ; Q - - [entry] - Q = 01 :: T05 - - [code] - 00 ๐œ€ โ—ผ - - Q: - 01 ๐œ€ 02 - 02 (array) 03 - 03 ๐œ€ [Arr] 05 - 05 ๐œ€ 19, 11 - 07 ๐œ€ [EndArr Set(M2)] 09 - 09 *โ†‘ยน 10 - 10 โ–ถ - 11 ๐œ€ [EndArr Set(M2)] 10 - 13 ๐œ€ [EndObj Push] 29 - 15 * (number) [Node Set(M1)] 13 - 17 โ†“* (identifier) [Node Set(M0)] 15 - 19 ๐œ€ [Obj] 17 - 21 ๐œ€ [EndObj Push] 29 - 23 * (number) [Node Set(M1)] 21 - 25 * (identifier) [Node Set(M0)] 23 - 27 ๐œ€ [Obj] 25 - 29 ๐œ€ 27, 07 - "#); -} diff --git a/crates/plotnik-lib/src/bytecode/mod.rs b/crates/plotnik-lib/src/bytecode/mod.rs index daa8979e..ebe040de 100644 --- a/crates/plotnik-lib/src/bytecode/mod.rs +++ b/crates/plotnik-lib/src/bytecode/mod.rs @@ -45,8 +45,6 @@ pub use module::{ pub use dump::dump; -#[cfg(test)] -mod dump_tests; #[cfg(test)] mod instructions_tests; #[cfg(test)] diff --git a/crates/plotnik-lib/src/emit/codegen_tests.rs b/crates/plotnik-lib/src/emit/codegen_tests.rs index f1845428..28492180 100644 --- a/crates/plotnik-lib/src/emit/codegen_tests.rs +++ b/crates/plotnik-lib/src/emit/codegen_tests.rs @@ -1,647 +1,442 @@ -//! Tests for bytecode emission. - -use indoc::indoc; +//! Comprehensive bytecode emission tests. +//! +//! Tests are organized by language feature and use file-based snapshots. +//! Each test verifies the bytecode output for a specific language construct. use crate::Query; -use crate::bytecode::{Header, MAGIC, Module, QTypeId, VERSION}; -use super::{StringTableBuilder, TypeTableBuilder}; - -#[test] -fn emit_minimal_query() { - let input = "Test = (identifier) @id"; - - let bytes = Query::expect_valid_linked_bytes(input); - - // Verify header - assert!(bytes.len() >= 64); - let header = Header::from_bytes(&bytes); - assert_eq!(header.magic, MAGIC); - assert_eq!(header.version, VERSION); - assert_eq!(header.total_size as usize, bytes.len()); +use indoc::indoc; - // Should have 1 entrypoint - assert_eq!(header.entrypoints_count, 1); +macro_rules! snap { + ($query:expr) => {{ + let query = $query.trim(); + let bytecode = Query::expect_valid_bytecode(query); + insta::with_settings!({ + omit_expression => true + }, { + insta::assert_snapshot!(format!("{query}\n---\n{bytecode}")); + }); + }}; +} - // Should have at least one string (the definition name "Test") - assert!(header.str_table_count >= 1); +// ============================================================================ +// 1. NODES +// ============================================================================ - // Should have at least one node type ("identifier") - assert!(header.node_types_count >= 1); +#[test] +fn nodes_named() { + snap!(indoc! {r#" + Test = (identifier) @id + "#}); } #[test] -fn emit_roundtrip_via_module() { - let input = "Test = (identifier) @id"; - - let bytes = Query::expect_valid_linked_bytes(input); - let module = Module::from_bytes(bytes).expect("load module"); - - // Verify we can read back the strings - assert!(module.header().str_table_count >= 1); - - // Verify we can read back entrypoints - let entrypoints = module.entrypoints(); - assert_eq!(entrypoints.len(), 1); - - // Verify we can read the entrypoint name - let ep = entrypoints.get(0); - let name = module.strings().get(ep.name); - assert_eq!(name, "Test"); +fn nodes_anonymous() { + snap!(indoc! {r#" + Test = (binary_expression "+" @op) + "#}); } #[test] -fn emit_multiple_definitions() { - let input = indoc! {r#" - Foo = (identifier) @id - Bar = (string) @str - "#}; - - let bytes = Query::expect_valid_linked_bytes(input); - let header = Header::from_bytes(&bytes); - - // Should have 2 entrypoints - assert_eq!(header.entrypoints_count, 2); - - // Entrypoints preserve definition order - let module = Module::from_bytes(bytes).expect("load module"); - let entrypoints = module.entrypoints(); - - let ep0 = entrypoints.get(0); - let ep1 = entrypoints.get(1); - - let name0 = module.strings().get(ep0.name); - let name1 = module.strings().get(ep1.name); - - assert_eq!(name0, "Foo"); // Foo defined first - assert_eq!(name1, "Bar"); +fn nodes_wildcard_any() { + snap!(indoc! {r#" + Test = (pair key: _ @key) + "#}); } #[test] -fn emit_with_field_constraint() { - let input = "Test = (function_declaration name: (identifier) @name)"; - - let bytes = Query::expect_valid_linked_bytes(input); - let header = Header::from_bytes(&bytes); - - // Should have at least one field ("name") - assert!(header.node_fields_count >= 1); - - let module = Module::from_bytes(bytes).expect("load module"); - let fields = module.node_fields(); - - // Find the "name" field - let has_name_field = (0..fields.len()).any(|i| { - let f = fields.get(i); - module.strings().get(f.name) == "name" - }); - assert!(has_name_field, "should have 'name' field"); +fn nodes_wildcard_named() { + snap!(indoc! {r#" + Test = (pair key: (_) @key) + "#}); } #[test] -fn emit_with_struct_type() { - let input = indoc! {r#" - Test = (function_declaration - name: (identifier) @name - body: (_) @body) - "#}; - - let bytes = Query::expect_valid_linked_bytes(input); - let module = Module::from_bytes(bytes).expect("load module"); - let types = module.types(); - - // Should have type definitions for the struct - // The struct has 2 fields, so we expect type members - assert!(types.defs_count() >= 1 || types.members_count() >= 2); +fn nodes_error() { + snap!(indoc! {r#" + Test = (ERROR) @err + "#}); } #[test] -fn emit_checksum_is_valid() { - let input = "Test = (identifier) @id"; +fn nodes_missing() { + snap!(indoc! {r#" + Test = (MISSING) @m + "#}); +} - let bytes = Query::expect_valid_linked_bytes(input); - let header = Header::from_bytes(&bytes); +// ============================================================================ +// 2. CAPTURES +// ============================================================================ - // Verify checksum - let computed = crc32fast::hash(&bytes[64..]); - assert_eq!(header.checksum, computed, "checksum mismatch"); +#[test] +fn captures_basic() { + snap!(indoc! {r#" + Test = (identifier) @name + "#}); } #[test] -fn emit_sections_are_aligned() { - let input = "Test = (identifier) @id"; - - let bytes = Query::expect_valid_linked_bytes(input); - let header = Header::from_bytes(&bytes); - - // All section offsets should be 64-byte aligned - assert_eq!(header.str_blob_offset % 64, 0, "str_blob not aligned"); - assert_eq!(header.str_table_offset % 64, 0, "str_table not aligned"); - assert_eq!(header.node_types_offset % 64, 0, "node_types not aligned"); - assert_eq!(header.node_fields_offset % 64, 0, "node_fields not aligned"); - assert_eq!(header.trivia_offset % 64, 0, "trivia not aligned"); - assert_eq!(header.type_meta_offset % 64, 0, "type_meta not aligned"); - assert_eq!(header.entrypoints_offset % 64, 0, "entrypoints not aligned"); - assert_eq!(header.transitions_offset % 64, 0, "transitions not aligned"); +fn captures_multiple() { + snap!(indoc! {r#" + Test = (binary_expression (identifier) @a (number) @b) + "#}); } -// Builder API tests - these test internal APIs directly - #[test] -fn string_table_builder_deduplicates() { - use plotnik_core::Interner; - - let mut interner = Interner::new(); - let sym1 = interner.intern("foo"); - let sym2 = interner.intern("bar"); - let sym3 = interner.intern("foo"); // Same as sym1 - - let mut builder = StringTableBuilder::new(); - let id1 = builder.get_or_intern(sym1, &interner).expect("id1"); - let id2 = builder.get_or_intern(sym2, &interner).expect("id2"); - let id3 = builder.get_or_intern(sym3, &interner).expect("id3"); - - assert_eq!(id1, id3); // Same symbol -> same StringId - assert_ne!(id1, id2); // Different symbols -> different StringIds - // 3 strings: easter egg at index 0, plus 2 unique user strings - assert_eq!(builder.len(), 3); +fn captures_nested_flat() { + snap!(indoc! {r#" + Test = (a (b (c) @c) @b) @a + "#}); } #[test] -fn string_table_builder_intern_str() { - let mut builder = StringTableBuilder::new(); - - let id1 = builder.intern_str("hello"); - let id2 = builder.intern_str("world"); - let id3 = builder.intern_str("hello"); // Duplicate - - assert_eq!(id1, id3); - assert_ne!(id1, id2); - // 3 strings: easter egg at index 0, plus 2 unique user strings - assert_eq!(builder.len(), 3); +fn captures_deeply_nested() { + snap!(indoc! {r#" + Test = (a (b (c (d) @d) @c) @b) @a + "#}); } #[test] -fn type_table_builder_builtins() { - use crate::analyze::type_check::{TYPE_NODE, TYPE_STRING, TYPE_VOID}; +fn captures_with_type_string() { + snap!(indoc! {r#" + Test = (identifier) @name :: string + "#}); +} - let mut builder = TypeTableBuilder::new(); +#[test] +fn captures_with_type_custom() { + snap!(indoc! {r#" + Test = (identifier) @name :: Identifier + "#}); +} - // Build with empty context - let type_ctx = crate::analyze::type_check::TypeContext::new(); - let interner = plotnik_core::Interner::new(); - let mut strings = StringTableBuilder::new(); +#[test] +fn captures_struct_scope() { + snap!(indoc! {r#" + Test = {(a) @a (b) @b} @item + "#}); +} - builder - .build(&type_ctx, &interner, &mut strings) - .expect("build"); +#[test] +fn captures_wrapper_struct() { + snap!(indoc! {r#" + Test = {{(identifier) @id (number) @num} @row}* @rows + "#}); +} - // Builtins should be mapped - assert_eq!(builder.get(TYPE_VOID), Some(QTypeId::VOID)); - assert_eq!(builder.get(TYPE_NODE), Some(QTypeId::NODE)); - assert_eq!(builder.get(TYPE_STRING), Some(QTypeId::STRING)); +#[test] +fn captures_optional_wrapper_struct() { + snap!(indoc! {r#" + Test = {{(identifier) @id} @inner}? @outer + "#}); } -// Anchor bytecode emission tests +// ============================================================================ +// 3. FIELDS +// ============================================================================ #[test] -fn emit_anchor_between_siblings() { - // Anchor between two named nodes should generate NextSkip - let input = "Test = (parent (a) . (b))"; +fn fields_single() { + snap!(indoc! {r#" + Test = (function_declaration name: (identifier) @name) + "#}); +} - let res = Query::expect_valid_bytecode(input); +#[test] +fn fields_multiple() { + snap!(indoc! {r#" + Test = (binary_expression + left: (_) @left + right: (_) @right) + "#}); +} - insta::assert_snapshot!(res, @r#" - [header] - linked = false +#[test] +fn fields_negated() { + snap!(indoc! {r#" + Test = (function_declaration name: (identifier) @name !type_parameters) + "#}); +} - [strings] - S00 "Beauty will save the world" - S01 "Test" - S02 "parent" - S03 "b" - S04 "a" +// ============================================================================ +// 4. QUANTIFIERS +// ============================================================================ - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 0) ; { } +#[test] +fn quantifiers_optional() { + snap!(indoc! {r#" + Test = (function_declaration (decorator)? @dec) + "#}); +} - [types.members] +#[test] +fn quantifiers_star() { + snap!(indoc! {r#" + Test = (identifier)* @items + "#}); +} - [types.names] - N0 = (S01, T03) ; Test +#[test] +fn quantifiers_plus() { + snap!(indoc! {r#" + Test = (identifier)+ @items + "#}); +} - [entry] - Test = 01 :: T03 +#[test] +fn quantifiers_optional_nongreedy() { + snap!(indoc! {r#" + Test = (function_declaration (decorator)?? @dec) + "#}); +} - [code] - 00 ๐œ€ โ—ผ +#[test] +fn quantifiers_star_nongreedy() { + snap!(indoc! {r#" + Test = (identifier)*? @items + "#}); +} - Test: - 01 ๐œ€ 02 - 02 (parent) 03 - 03 โ†“* (a) 04 - 04 ~ (b) 05 - 05 *โ†‘ยน 06 - 06 โ–ถ - "#); +#[test] +fn quantifiers_plus_nongreedy() { + snap!(indoc! {r#" + Test = (identifier)+? @items + "#}); } #[test] -fn emit_anchor_first_child() { - // Leading anchor should generate DownSkip - let input = "Test = (parent . (first))"; +fn quantifiers_struct_array() { + snap!(indoc! {r#" + Test = (array {(identifier) @a (number) @b}* @items) + "#}); +} - let res = Query::expect_valid_bytecode(input); +#[test] +fn quantifiers_first_child_array() { + snap!(indoc! {r#" + Test = (array (identifier)* @ids (number) @n) + "#}); +} - insta::assert_snapshot!(res, @r#" - [header] - linked = false +#[test] +fn quantifiers_repeat_navigation() { + snap!(indoc! {r#" + Test = (function_declaration (decorator)* @decs) + "#}); +} - [strings] - S00 "Beauty will save the world" - S01 "Test" - S02 "parent" - S03 "first" +// ============================================================================ +// 5. SEQUENCES +// ============================================================================ - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 0) ; { } +#[test] +fn sequences_basic() { + snap!(indoc! {r#" + Test = (parent {(a) (b)}) + "#}); +} - [types.members] +#[test] +fn sequences_with_captures() { + snap!(indoc! {r#" + Test = (parent {(a) @a (b) @b}) + "#}); +} - [types.names] - N0 = (S01, T03) ; Test +#[test] +fn sequences_nested() { + snap!(indoc! {r#" + Test = (parent {(a) {(b) (c)} (d)}) + "#}); +} - [entry] - Test = 01 :: T03 +#[test] +fn sequences_in_quantifier() { + snap!(indoc! {r#" + Test = (parent {(a) (b)}* @items) + "#}); +} - [code] - 00 ๐œ€ โ—ผ +// ============================================================================ +// 6. ALTERNATIONS +// ============================================================================ - Test: - 01 ๐œ€ 02 - 02 (parent) 03 - 03 โ†“~ (first) 04 - 04 *โ†‘ยน 05 - 05 โ–ถ - "#); +#[test] +fn alternations_unlabeled() { + snap!(indoc! {r#" + Test = [(identifier) @id (string) @str] + "#}); } #[test] -fn emit_anchor_last_child() { - // Trailing anchor should generate UpSkipTrivia - let input = "Test = (parent (last) .)"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false +fn alternations_labeled() { + snap!(indoc! {r#" + Test = [ + A: (identifier) @a + B: (number) @b + ] + "#}); +} - [strings] - S00 "Beauty will save the world" - S01 "Test" - S02 "parent" - S03 "last" +#[test] +fn alternations_null_injection() { + snap!(indoc! {r#" + Test = [(identifier) @x (number) @y] + "#}); +} - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 0) ; { } +#[test] +fn alternations_captured() { + snap!(indoc! {r#" + Test = [(identifier) (number)] @value + "#}); +} - [types.members] +#[test] +fn alternations_captured_tagged() { + snap!(indoc! {r#" + Test = [A: (identifier) @a B: (number) @b] @item + "#}); +} - [types.names] - N0 = (S01, T03) ; Test +#[test] +fn alternations_in_quantifier() { + snap!(indoc! {r#" + Test = (object { [A: (pair) @a B: (shorthand_property_identifier) @b] @item }* @items) + "#}); +} - [entry] - Test = 01 :: T03 +#[test] +fn alternations_no_internal_captures() { + snap!(indoc! {r#" + Test = (program [(identifier) (number)] @x) + "#}); +} - [code] - 00 ๐œ€ โ—ผ +// ============================================================================ +// 7. ANCHORS +// ============================================================================ - Test: - 01 ๐œ€ 02 - 02 (parent) 03 - 03 โ†“* (last) 04 - 04 ~โ†‘ยน 05 - 05 โ–ถ - "#); +#[test] +fn anchors_between_siblings() { + snap!(indoc! {r#" + Test = (parent (a) . (b)) + "#}); } #[test] -fn emit_anchor_with_anonymous_node() { - // Anchor with anonymous node should generate NextExact - let input = r#"Test = (parent "+" . (next))"#; +fn anchors_first_child() { + snap!(indoc! {r#" + Test = (parent . (first)) + "#}); +} - let res = Query::expect_valid_bytecode(input); +#[test] +fn anchors_last_child() { + snap!(indoc! {r#" + Test = (parent (last) .) + "#}); +} - insta::assert_snapshot!(res, @r#" - [header] - linked = false +#[test] +fn anchors_with_anonymous() { + snap!(indoc! {r#" + Test = (parent "+" . (next)) + "#}); +} - [strings] - S00 "Beauty will save the world" - S01 "Test" - S02 "parent" - S03 "next" - S04 "+" +#[test] +fn anchors_no_anchor() { + snap!(indoc! {r#" + Test = (parent (a) (b)) + "#}); +} - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 0) ; { } +// ============================================================================ +// 8. NAMED EXPRESSIONS +// ============================================================================ - [types.members] +#[test] +fn definitions_single() { + snap!(indoc! {r#" + Foo = (identifier) @id + "#}); +} - [types.names] - N0 = (S01, T03) ; Test +#[test] +fn definitions_multiple() { + snap!(indoc! {r#" + Foo = (identifier) @id + Bar = (string) @str + "#}); +} - [entry] - Test = 01 :: T03 +#[test] +fn definitions_reference() { + snap!(indoc! {r#" + Expression = [(identifier) @name (number) @value] + Root = (function_declaration name: (identifier) @name) + "#}); +} - [code] - 00 ๐œ€ โ—ผ +// ============================================================================ +// 9. RECURSION +// ============================================================================ - Test: - 01 ๐œ€ 02 - 02 (parent) 03 - 03 โ†“* (+) 04 - 04 . (next) 05 - 05 *โ†‘ยน 06 - 06 โ–ถ - "#); +#[test] +fn recursion_simple() { + snap!(indoc! {r#" + Expr = [ + Lit: (number) @value :: string + Rec: (call_expression function: (identifier) @fn arguments: (Expr) @inner) + ] + "#}); } #[test] -fn emit_no_anchor_uses_next() { - // No anchor between siblings uses Next - let input = "Test = (parent (a) (b))"; - - let res = Query::expect_valid_bytecode(input); - - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "Test" - S02 "parent" - S03 "b" - S04 "a" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 0) ; { } - - [types.members] - - [types.names] - N0 = (S01, T03) ; Test - - [entry] - Test = 01 :: T03 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 (parent) 03 - 03 โ†“* (a) 04 - 04 * (b) 05 - 05 *โ†‘ยน 06 - 06 โ–ถ - "#); -} - -// Tests for wrapper struct Set() emission (Issue 1 fix) - -#[test] -fn emit_wrapper_struct_set() { - // Wrapper struct captures should emit Set() for the wrapper field. - // Pattern: {{inner captures} @wrapper}* @outer - // The @wrapper capture should Set into the array element type. - let input = "Test = {{(identifier) @id (number) @num} @row}* @rows"; - - let res = Query::expect_valid_bytecode(input); - - // Verify Set(M2) is emitted for the @row wrapper field - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "id" - S02 "num" - S03 "row" - S04 "rows" - S05 "Test" - S06 "number" - S07 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 2) ; { id, num } - T04 = Struct(M2, 1) ; { row } - T05 = ArrayStar(T04) ; T04* - T06 = Struct(M3, 1) ; { rows } - - [types.members] - M0 = (S01, T01) ; id: Node - M1 = (S02, T01) ; num: Node - M2 = (S03, T03) ; row: T03 - M3 = (S04, T05) ; rows: T05 - - [types.names] - N0 = (S05, T06) ; Test - - [entry] - Test = 01 :: T06 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 ๐œ€ [Arr] 04 - 04 ๐œ€ 19, 07 - 06 โ–ถ - 07 ๐œ€ [EndArr Set(M3)] 06 - 09 ๐œ€ [EndObj Push] 33 - 11 ๐œ€ [EndObj Set(M2)] 09 - 13 * (number) [Node Set(M1)] 11 - 15 (identifier) [Node Set(M0)] 13 - 17 ๐œ€ [Obj] 15 - 19 ๐œ€ [Obj] 17 - 21 ๐œ€ [EndObj Push] 33 - 23 ๐œ€ [EndObj Set(M2)] 21 - 25 * (number) [Node Set(M1)] 23 - 27 (identifier) [Node Set(M0)] 25 - 29 ๐œ€ [Obj] 27 - 31 ๐œ€ [Obj] 29 - 33 ๐œ€ 31, 07 - "#); -} - -#[test] -fn emit_optional_wrapper_struct_set() { - // Optional wrapper struct captures should also emit Set() for the wrapper field. - let input = "Test = {{(identifier) @id} @inner}? @outer"; - - let res = Query::expect_valid_bytecode(input); - - // Verify Set(M1) is emitted for the @inner wrapper field - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "id" - S02 "inner" - S03 "outer" - S04 "Test" - S05 "identifier" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { id } - T04 = Struct(M1, 1) ; { inner } - T05 = Struct(M2, 1) ; { outer } - T06 = Optional(T03) ; T03? - T07 = Optional(T04) ; T04? - - [types.members] - M0 = (S01, T01) ; id: Node - M1 = (S02, T06) ; inner: T06 - M2 = (S03, T07) ; outer: T07 - - [types.names] - N0 = (S04, T05) ; Test - - [entry] - Test = 01 :: T05 - - [code] - 00 ๐œ€ โ—ผ - - Test: - 01 ๐œ€ 02 - 02 ๐œ€ [Obj] 04 - 04 ๐œ€ 13, 15 - 06 โ–ถ - 07 ๐œ€ [EndObj Set(M2)] 06 - 09 ๐œ€ [EndObj Set(M1)] 07 - 11 (identifier) [Node Set(M0)] 09 - 13 ๐œ€ [Obj] 11 - 15 ๐œ€ [Null Set(M1)] 07 - "#); -} - -// Tests for recursive ref structured result (Issue 2 fix) - -#[test] -fn emit_recursive_ref_structured_result() { - // Recursive refs returning structured types should not emit Node before Set. - // The Call leaves the structured result pending, which Set directly consumes. - let input = indoc! {r#" +fn recursion_with_structured_result() { + snap!(indoc! {r#" Expr = [ Lit: (number) @value :: string Nested: (call_expression function: (identifier) @fn arguments: (Expr) @inner) ] Test = (program (Expr) @expr) - "#}; - - let res = Query::expect_valid_bytecode(input); - - // Verify [Set(M5)] without Node for @expr capture of recursive ref - // Verify [Set(M2)] without Node for @inner capture of recursive ref - insta::assert_snapshot!(res, @r#" - [header] - linked = false - - [strings] - S00 "Beauty will save the world" - S01 "value" - S02 "fn" - S03 "inner" - S04 "Lit" - S05 "Nested" - S06 "expr" - S07 "Expr" - S08 "Test" - S09 "number" - S10 "call_expression" - S11 "arguments" - S12 "function" - S13 "identifier" - S14 "program" - - [types.defs] - T00 = void - T01 = Node - T02 = str - T03 = Struct(M0, 1) ; { value } - T04 = Struct(M1, 2) ; { fn, inner } - T05 = Enum(M3, 2) ; Lit | Nested - T06 = Struct(M5, 1) ; { expr } - - [types.members] - M0 = (S01, T02) ; value: str - M1 = (S02, T01) ; fn: Node - M2 = (S03, T05) ; inner: Expr - M3 = (S04, T03) ; Lit: T03 - M4 = (S05, T04) ; Nested: T04 - M5 = (S06, T05) ; expr: Expr - - [types.names] - N0 = (S07, T05) ; Expr - N1 = (S08, T06) ; Test - - [entry] - Expr = 01 :: T05 - Test = 04 :: T06 - - [code] - 00 ๐œ€ โ—ผ - - Expr: - 01 ๐œ€ 02 - 02 ๐œ€ 19, 27 - - Test: - 04 ๐œ€ 05 - 05 (program) 06 - 06 โ†“* โ–ถ (Expr) 07 - 07 ๐œ€ [Set(M5)] 09 - 09 *โ†‘ยน 10 - 10 โ–ถ - 11 ๐œ€ [Set(M2)] 13 - 13 *โ†‘ยน 21 - 14 โ–ถ - 15 ๐œ€ [EndEnum] 14 - 17 (number) [Text Set(M0)] 15 - 19 ๐œ€ [Enum(M3)] 17 - 21 ๐œ€ [EndEnum] 14 - 23 * โ–ถ arguments: (Expr) 11 - 24 โ†“* function: (identifier) [Node Set(M1)]23 - 26 (call_expression) 24 - 27 ๐œ€ [Enum(M4)] 26 - "#); + "#}); +} + +// ============================================================================ +// 10. OPTIONALS +// ============================================================================ + +#[test] +fn optional_first_child() { + snap!(indoc! {r#" + Test = (program (identifier)? @id (number) @n) + "#}); +} + +#[test] +fn optional_null_injection() { + snap!(indoc! {r#" + Test = (function_declaration (decorator)? @dec) + "#}); +} + +// ============================================================================ +// 11. COMPREHENSIVE +// ============================================================================ + +#[test] +fn comprehensive_multi_definition() { + snap!(indoc! {r#" + Ident = (identifier) @name :: string + Expression = [ + Literal: (number) @value + Variable: (identifier) @name + ] + Assignment = (assignment_expression + left: (identifier) @target + right: (Expression) @value) + "#}); } diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured.snap new file mode 100644 index 00000000..1ceca613 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = [(identifier) (number)] @value +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "value" +S02 "Test" +S03 "identifier" +S04 "number" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { value } + +[type_members] +M0: S01 โ†’ T01 ; value: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ 05, 07 + 04 โ–ถ + 05 (identifier) [Node Set(M0)] 04 + 07 (number) [Node Set(M0)] 04 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured_tagged.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured_tagged.snap new file mode 100644 index 00000000..5ef36198 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_captured_tagged.snap @@ -0,0 +1,54 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = [A: (identifier) @a B: (number) @b] @item +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "A" +S04 "B" +S05 "item" +S06 "Test" +S07 "identifier" +S08 "number" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { a } +T04 = Struct M1[1] ; { b } +T05 = Enum M2[2] ; A | B +T06 = Struct M4[1] ; { item } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T03 ; A: T03 +M3: S04 โ†’ T04 ; B: T04 +M4: S05 โ†’ T05 ; item: T05 + +[type_names] +N0: S06 โ†’ T06 ; Test + +[entrypoints] +Test = 01 :: T06 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ 09, 15 + 04 โ–ถ + 05 ๐œ€ [EndEnum Set(M4)] 04 + 07 (identifier) [Node Set(M0)] 05 + 09 ๐œ€ [Enum(M2)] 07 + 11 ๐œ€ [EndEnum Set(M4)] 04 + 13 (number) [Node Set(M1)] 11 + 15 ๐œ€ [Enum(M3)] 13 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_in_quantifier.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_in_quantifier.snap new file mode 100644 index 00000000..8e67a1cd --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_in_quantifier.snap @@ -0,0 +1,77 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (object { [A: (pair) @a B: (shorthand_property_identifier) @b] @item }* @items) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "A" +S04 "B" +S05 "item" +S06 "items" +S07 "Test" +S08 "object" +S09 "pair" +S10 "shorthand_property_identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { a } +T04 = Struct M1[1] ; { b } +T05 = Enum M2[2] ; A | B +T06 = Struct M4[1] ; { item } +T07 = ArrayStar(T06) ; T06* +T08 = Struct M5[1] ; { items } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T03 ; A: T03 +M3: S04 โ†’ T04 ; B: T04 +M4: S05 โ†’ T05 ; item: T05 +M5: S06 โ†’ T07 ; items: T07 + +[type_names] +N0: S07 โ†’ T08 ; Test + +[entrypoints] +Test = 01 :: T08 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (object) 03 + 03 ๐œ€ [Arr] 05 + 05 ๐œ€ 29, 11 + 07 ๐œ€ [EndArr Set(M5)] 09 + 09 *โ†‘ยน 10 + 10 โ–ถ + 11 ๐œ€ [EndArr Set(M5)] 10 + 13 ๐œ€ [EndObj Push] 49 + 15 ๐œ€ [EndEnum Set(M4)] 13 + 17 โ†“* (pair) [Node Set(M0)] 15 + 19 ๐œ€ [Enum(M2)] 17 + 21 ๐œ€ [EndEnum Set(M4)] 13 + 23 โ†“* (shorthand_property_identifier) [Node Set(M1)] 21 + 25 ๐œ€ [Enum(M3)] 23 + 27 ๐œ€ 19, 25 + 29 ๐œ€ [Obj] 27 + 31 ๐œ€ [EndObj Push] 49 + 33 ๐œ€ [EndEnum Set(M4)] 31 + 35 * (pair) [Node Set(M0)] 33 + 37 ๐œ€ [Enum(M2)] 35 + 39 ๐œ€ [EndEnum Set(M4)] 31 + 41 * (shorthand_property_identifier) [Node Set(M1)] 39 + 43 ๐œ€ [Enum(M3)] 41 + 45 ๐œ€ 37, 43 + 47 ๐œ€ [Obj] 45 + 49 ๐œ€ 47, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_labeled.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_labeled.snap new file mode 100644 index 00000000..bbc929fc --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_labeled.snap @@ -0,0 +1,54 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = [ + A: (identifier) @a + B: (number) @b +] +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "A" +S04 "B" +S05 "Test" +S06 "identifier" +S07 "number" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { a } +T04 = Struct M1[1] ; { b } +T05 = Enum M2[2] ; A | B + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T03 ; A: T03 +M3: S04 โ†’ T04 ; B: T04 + +[type_names] +N0: S05 โ†’ T05 ; Test + +[entrypoints] +Test = 01 :: T05 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ 09, 15 + 04 โ–ถ + 05 ๐œ€ [EndEnum] 04 + 07 (identifier) [Node Set(M0)] 05 + 09 ๐œ€ [Enum(M2)] 07 + 11 ๐œ€ [EndEnum] 04 + 13 (number) [Node Set(M1)] 11 + 15 ๐œ€ [Enum(M3)] 13 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_no_internal_captures.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_no_internal_captures.snap new file mode 100644 index 00000000..14ae4649 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_no_internal_captures.snap @@ -0,0 +1,42 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (program [(identifier) (number)] @x) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "x" +S02 "Test" +S03 "program" +S04 "identifier" +S05 "number" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { x } + +[type_members] +M0: S01 โ†’ T01 ; x: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (program) 03 + 03 ๐œ€ 06, 08 + 05 โ–ถ + 06 โ†“* (identifier) [Node Set(M0)] 10 + 08 โ†“* (number) [Node Set(M0)] 10 + 10 *โ†‘ยน 05 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_null_injection.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_null_injection.snap new file mode 100644 index 00000000..f1dca580 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_null_injection.snap @@ -0,0 +1,44 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = [(identifier) @x (number) @y] +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "x" +S02 "y" +S03 "Test" +S04 "identifier" +S05 "number" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { x, y } +T04 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T04 ; x: T04 +M1: S02 โ†’ T04 ; y: T04 + +[type_names] +N0: S03 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ 07, 11 + 04 โ–ถ + 05 (identifier) [Node Set(M0)] 04 + 07 ๐œ€ [Null Set(M1)] 05 + 09 (number) [Node Set(M1)] 04 + 11 ๐œ€ [Null Set(M0)] 09 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_unlabeled.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_unlabeled.snap new file mode 100644 index 00000000..af764e5e --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__alternations_unlabeled.snap @@ -0,0 +1,44 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = [(identifier) @id (string) @str] +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "str" +S03 "Test" +S04 "identifier" +S05 "string" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { id, str } +T04 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T04 ; id: T04 +M1: S02 โ†’ T04 ; str: T04 + +[type_names] +N0: S03 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ 07, 11 + 04 โ–ถ + 05 (identifier) [Node Set(M0)] 04 + 07 ๐œ€ [Null Set(M1)] 05 + 09 (string) [Node Set(M1)] 04 + 11 ๐œ€ [Null Set(M0)] 09 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_between_siblings.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_between_siblings.snap new file mode 100644 index 00000000..b87a9317 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_between_siblings.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent (a) . (b)) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "b" +S04 "a" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (a) 04 + 04 ~ (b) 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_first_child.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_first_child.snap new file mode 100644 index 00000000..e213e6a5 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_first_child.snap @@ -0,0 +1,37 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent . (first)) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "first" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“~ (first) 04 + 04 *โ†‘ยน 05 + 05 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_last_child.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_last_child.snap new file mode 100644 index 00000000..943c5272 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_last_child.snap @@ -0,0 +1,37 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent (last) .) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "last" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (last) 04 + 04 ~โ†‘ยน 05 + 05 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_no_anchor.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_no_anchor.snap new file mode 100644 index 00000000..17238464 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_no_anchor.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent (a) (b)) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "b" +S04 "a" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (a) 04 + 04 * (b) 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_with_anonymous.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_with_anonymous.snap new file mode 100644 index 00000000..b9c79e31 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__anchors_with_anonymous.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent "+" . (next)) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "next" +S04 "+" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (+) 04 + 04 . (next) 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_basic.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_basic.snap new file mode 100644 index 00000000..437191cd --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_basic.snap @@ -0,0 +1,36 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier) @name +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "name" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { name } + +[type_members] +M0: S01 โ†’ T01 ; name: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (identifier) [Node Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_deeply_nested.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_deeply_nested.snap new file mode 100644 index 00000000..5d27debd --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_deeply_nested.snap @@ -0,0 +1,47 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (a (b (c (d) @d) @c) @b) @a +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "c" +S04 "d" +S05 "Test" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[4] ; { a, b, c, d } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T01 ; c: Node +M3: S04 โ†’ T01 ; d: Node + +[type_names] +N0: S05 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (a) [Node Set(M0)] 04 + 04 โ†“* (b) [Node Set(M1)] 06 + 06 โ†“* (c) [Node Set(M2)] 08 + 08 โ†“* (d) [Node Set(M3)] 10 + 10 *โ†‘ยน 11 + 11 *โ†‘ยน 12 + 12 *โ†‘ยน 13 + 13 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_multiple.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_multiple.snap new file mode 100644 index 00000000..3dea748e --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_multiple.snap @@ -0,0 +1,43 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (binary_expression (identifier) @a (number) @b) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "Test" +S04 "binary_expression" +S05 "number" +S06 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { a, b } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node + +[type_names] +N0: S03 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (binary_expression) 03 + 03 โ†“* (identifier) [Node Set(M0)] 05 + 05 * (number) [Node Set(M1)] 07 + 07 *โ†‘ยน 08 + 08 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_nested_flat.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_nested_flat.snap new file mode 100644 index 00000000..e5d2a2d2 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_nested_flat.snap @@ -0,0 +1,43 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (a (b (c) @c) @b) @a +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "c" +S04 "Test" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[3] ; { a, b, c } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T01 ; c: Node + +[type_names] +N0: S04 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (a) [Node Set(M0)] 04 + 04 โ†“* (b) [Node Set(M1)] 06 + 06 โ†“* (c) [Node Set(M2)] 08 + 08 *โ†‘ยน 09 + 09 *โ†‘ยน 10 + 10 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_optional_wrapper_struct.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_optional_wrapper_struct.snap new file mode 100644 index 00000000..ddab4285 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_optional_wrapper_struct.snap @@ -0,0 +1,50 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = {{(identifier) @id} @inner}? @outer +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "inner" +S03 "outer" +S04 "Test" +S05 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { id } +T04 = Struct M1[1] ; { inner } +T05 = Struct M2[1] ; { outer } +T06 = Optional(T03) ; T03? +T07 = Optional(T04) ; T04? + +[type_members] +M0: S01 โ†’ T01 ; id: Node +M1: S02 โ†’ T06 ; inner: T06 +M2: S03 โ†’ T07 ; outer: T07 + +[type_names] +N0: S04 โ†’ T05 ; Test + +[entrypoints] +Test = 01 :: T05 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Obj] 04 + 04 ๐œ€ 13, 15 + 06 โ–ถ + 07 ๐œ€ [EndObj Set(M2)] 06 + 09 ๐œ€ [EndObj Set(M1)] 07 + 11 (identifier) [Node Set(M0)] 09 + 13 ๐œ€ [Obj] 11 + 15 ๐œ€ [Null Set(M1)] 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_struct_scope.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_struct_scope.snap new file mode 100644 index 00000000..48072979 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_struct_scope.snap @@ -0,0 +1,43 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = {(a) @a (b) @b} @item +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "item" +S04 "Test" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { a, b } +T04 = Struct M2[1] ; { item } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T03 ; item: T03 + +[type_names] +N0: S04 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Obj] 04 + 04 (a) [Node Set(M0)] 06 + 06 * (b) [Node Set(M1)] 08 + 08 ๐œ€ [EndObj Set(M2)] 10 + 10 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_custom.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_custom.snap new file mode 100644 index 00000000..3271d995 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_custom.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier) @name :: Identifier +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Identifier" +S02 "name" +S03 "Test" +S04 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Alias(T01) +T04 = Struct M0[1] ; { name } + +[type_members] +M0: S02 โ†’ T03 ; name: Identifier + +[type_names] +N0: S01 โ†’ T03 ; Identifier +N1: S03 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (identifier) [Node Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_string.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_string.snap new file mode 100644 index 00000000..86bb399c --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_with_type_string.snap @@ -0,0 +1,36 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier) @name :: string +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "name" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { name } + +[type_members] +M0: S01 โ†’ T02 ; name: str + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (identifier) [Text Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_wrapper_struct.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_wrapper_struct.snap new file mode 100644 index 00000000..c14db635 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__captures_wrapper_struct.snap @@ -0,0 +1,61 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = {{(identifier) @id (number) @num} @row}* @rows +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "num" +S03 "row" +S04 "rows" +S05 "Test" +S06 "number" +S07 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { id, num } +T04 = Struct M2[1] ; { row } +T05 = ArrayStar(T04) ; T04* +T06 = Struct M3[1] ; { rows } + +[type_members] +M0: S01 โ†’ T01 ; id: Node +M1: S02 โ†’ T01 ; num: Node +M2: S03 โ†’ T03 ; row: T03 +M3: S04 โ†’ T05 ; rows: T05 + +[type_names] +N0: S05 โ†’ T06 ; Test + +[entrypoints] +Test = 01 :: T06 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Arr] 04 + 04 ๐œ€ 19, 07 + 06 โ–ถ + 07 ๐œ€ [EndArr Set(M3)] 06 + 09 ๐œ€ [EndObj Push] 33 + 11 ๐œ€ [EndObj Set(M2)] 09 + 13 * (number) [Node Set(M1)] 11 + 15 (identifier) [Node Set(M0)] 13 + 17 ๐œ€ [Obj] 15 + 19 ๐œ€ [Obj] 17 + 21 ๐œ€ [EndObj Push] 33 + 23 ๐œ€ [EndObj Set(M2)] 21 + 25 * (number) [Node Set(M1)] 23 + 27 (identifier) [Node Set(M0)] 25 + 29 ๐œ€ [Obj] 27 + 31 ๐œ€ [Obj] 29 + 33 ๐œ€ 31, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__comprehensive_multi_definition.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__comprehensive_multi_definition.snap new file mode 100644 index 00000000..7d1dfd15 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__comprehensive_multi_definition.snap @@ -0,0 +1,87 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Ident = (identifier) @name :: string +Expression = [ + Literal: (number) @value + Variable: (identifier) @name +] +Assignment = (assignment_expression + left: (identifier) @target + right: (Expression) @value) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "name" +S02 "value" +S03 "Literal" +S04 "Variable" +S05 "target" +S06 "Ident" +S07 "Expression" +S08 "Assignment" +S09 "identifier" +S10 "number" +S11 "assignment_expression" +S12 "right" +S13 "left" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { name } +T04 = Struct M1[1] ; { value } +T05 = Struct M2[1] ; { name } +T06 = Enum M3[2] ; Literal | Variable +T07 = Struct M5[2] ; { value, target } + +[type_members] +M0: S01 โ†’ T02 ; name: str +M1: S02 โ†’ T01 ; value: Node +M2: S01 โ†’ T01 ; name: Node +M3: S03 โ†’ T04 ; Literal: T04 +M4: S04 โ†’ T05 ; Variable: T05 +M5: S02 โ†’ T06 ; value: Expression +M6: S05 โ†’ T01 ; target: Node + +[type_names] +N0: S06 โ†’ T03 ; Ident +N1: S07 โ†’ T06 ; Expression +N2: S08 โ†’ T07 ; Assignment + +[entrypoints] +Assignment = 08 :: T07 +Expression = 05 :: T06 +Ident = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Ident: + 01 ๐œ€ 02 + 02 (identifier) [Text Set(M0)] 04 + 04 โ–ถ + +Expression: + 05 ๐œ€ 06 + 06 ๐œ€ 22, 28 + +Assignment: + 08 ๐œ€ 09 + 09 (assignment_expression) 10 + 10 โ†“* left: (identifier) [Node Set(M6)] 12 + 12 * โ–ถ right: (Expression) 13 + 13 ๐œ€ [Set(M5)] 15 + 15 *โ†‘ยน 16 + 16 โ–ถ + 17 โ–ถ + 18 ๐œ€ [EndEnum] 17 + 20 (number) [Node Set(M1)] 18 + 22 ๐œ€ [Enum(M3)] 20 + 24 ๐œ€ [EndEnum] 17 + 26 (identifier) [Node Set(M2)] 24 + 28 ๐œ€ [Enum(M4)] 26 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_multiple.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_multiple.snap new file mode 100644 index 00000000..36850c4d --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_multiple.snap @@ -0,0 +1,49 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Foo = (identifier) @id +Bar = (string) @str +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "str" +S03 "Foo" +S04 "Bar" +S05 "identifier" +S06 "string" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { id } +T04 = Struct M1[1] ; { str } + +[type_members] +M0: S01 โ†’ T01 ; id: Node +M1: S02 โ†’ T01 ; str: Node + +[type_names] +N0: S03 โ†’ T03 ; Foo +N1: S04 โ†’ T04 ; Bar + +[entrypoints] +Bar = 05 :: T04 +Foo = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Foo: + 01 ๐œ€ 02 + 02 (identifier) [Node Set(M0)] 04 + 04 โ–ถ + +Bar: + 05 ๐œ€ 06 + 06 (string) [Node Set(M1)] 08 + 08 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_reference.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_reference.snap new file mode 100644 index 00000000..5f9de4f9 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_reference.snap @@ -0,0 +1,58 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Expression = [(identifier) @name (number) @value] +Root = (function_declaration name: (identifier) @name) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "name" +S02 "value" +S03 "Expression" +S04 "Root" +S05 "identifier" +S06 "number" +S07 "function_declaration" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { name, value } +T04 = Struct M2[1] ; { name } +T05 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T05 ; name: T05 +M1: S02 โ†’ T05 ; value: T05 +M2: S01 โ†’ T01 ; name: Node + +[type_names] +N0: S03 โ†’ T03 ; Expression +N1: S04 โ†’ T04 ; Root + +[entrypoints] +Expression = 01 :: T03 +Root = 04 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Expression: + 01 ๐œ€ 02 + 02 ๐œ€ 13, 17 + +Root: + 04 ๐œ€ 05 + 05 (function_declaration) 06 + 06 โ†“* name: (identifier) [Node Set(M2)] 08 + 08 *โ†‘ยน 09 + 09 โ–ถ + 10 โ–ถ + 11 (identifier) [Node Set(M0)] 10 + 13 ๐œ€ [Null Set(M1)] 11 + 15 (number) [Node Set(M1)] 10 + 17 ๐œ€ [Null Set(M0)] 15 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_single.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_single.snap new file mode 100644 index 00000000..231eed50 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_single.snap @@ -0,0 +1,36 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Foo = (identifier) @id +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "Foo" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { id } + +[type_members] +M0: S01 โ†’ T01 ; id: Node + +[type_names] +N0: S02 โ†’ T03 ; Foo + +[entrypoints] +Foo = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Foo: + 01 ๐œ€ 02 + 02 (identifier) [Node Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_multiple.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_multiple.snap new file mode 100644 index 00000000..b788c862 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_multiple.snap @@ -0,0 +1,43 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (binary_expression + left: (_) @left + right: (_) @right) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "left" +S02 "right" +S03 "Test" +S04 "binary_expression" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { left, right } + +[type_members] +M0: S01 โ†’ T01 ; left: Node +M1: S02 โ†’ T01 ; right: Node + +[type_names] +N0: S03 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (binary_expression) 03 + 03 โ†“* left: _ [Node Set(M0)] 05 + 05 * right: _ [Node Set(M1)] 07 + 07 *โ†‘ยน 08 + 08 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_negated.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_negated.snap new file mode 100644 index 00000000..5cd5f19c --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_negated.snap @@ -0,0 +1,40 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (function_declaration name: (identifier) @name !type_parameters) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "name" +S02 "Test" +S03 "function_declaration" +S04 "type_parameters" +S05 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { name } + +[type_members] +M0: S01 โ†’ T01 ; name: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 !type_parameters (function_declaration) 04 + 04 โ†“* name: (identifier) [Node Set(M0)] 06 + 06 *โ†‘ยน 07 + 07 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_single.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_single.snap new file mode 100644 index 00000000..c6667e3b --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__fields_single.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (function_declaration name: (identifier) @name) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "name" +S02 "Test" +S03 "function_declaration" +S04 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { name } + +[type_members] +M0: S01 โ†’ T01 ; name: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (function_declaration) 03 + 03 โ†“* name: (identifier) [Node Set(M0)] 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_anonymous.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_anonymous.snap new file mode 100644 index 00000000..c1a7b7b5 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_anonymous.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (binary_expression "+" @op) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "op" +S02 "Test" +S03 "binary_expression" +S04 "+" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { op } + +[type_members] +M0: S01 โ†’ T01 ; op: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (binary_expression) 03 + 03 โ†“* (+) [Node Set(M0)] 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_error.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_error.snap new file mode 100644 index 00000000..9b9dab79 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_error.snap @@ -0,0 +1,36 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (ERROR) @err +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "err" +S02 "Test" +S03 "ERROR" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { err } + +[type_members] +M0: S01 โ†’ T01 ; err: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (ERROR) [Node Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_missing.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_missing.snap new file mode 100644 index 00000000..2632782f --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_missing.snap @@ -0,0 +1,36 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (MISSING) @m +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "m" +S02 "Test" +S03 "MISSING" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { m } + +[type_members] +M0: S01 โ†’ T01 ; m: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (MISSING) [Node Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_named.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_named.snap new file mode 100644 index 00000000..3942767b --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_named.snap @@ -0,0 +1,36 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier) @id +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { id } + +[type_members] +M0: S01 โ†’ T01 ; id: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (identifier) [Node Set(M0)] 04 + 04 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_any.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_any.snap new file mode 100644 index 00000000..1f180366 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_any.snap @@ -0,0 +1,38 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (pair key: _ @key) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "key" +S02 "Test" +S03 "pair" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { key } + +[type_members] +M0: S01 โ†’ T01 ; key: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (pair) 03 + 03 โ†“* key: _ [Node Set(M0)] 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_named.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_named.snap new file mode 100644 index 00000000..5cbb9c1c --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__nodes_wildcard_named.snap @@ -0,0 +1,38 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (pair key: (_) @key) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "key" +S02 "Test" +S03 "pair" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { key } + +[type_members] +M0: S01 โ†’ T01 ; key: Node + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (pair) 03 + 03 โ†“* key: _ [Node Set(M0)] 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_first_child.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_first_child.snap new file mode 100644 index 00000000..cfede84c --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_first_child.snap @@ -0,0 +1,47 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (program (identifier)? @id (number) @n) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "id" +S02 "n" +S03 "Test" +S04 "program" +S05 "number" +S06 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { id, n } +T04 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T04 ; id: T04 +M1: S02 โ†’ T01 ; n: Node + +[type_names] +N0: S03 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (program) 03 + 03 ๐œ€ 12, 10 + 05 โ–ถ + 06 โ†“* (number) [Node Set(M1)] 14 + 08 * (number) [Node Set(M1)] 14 + 10 ๐œ€ [Null Set(M0)] 06 + 12 โ†“* (identifier) [Node Set(M0)] 08 + 14 *โ†‘ยน 05 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_null_injection.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_null_injection.snap new file mode 100644 index 00000000..0b2e79ee --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__optional_null_injection.snap @@ -0,0 +1,42 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (function_declaration (decorator)? @dec) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "dec" +S02 "Test" +S03 "function_declaration" +S04 "decorator" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { dec } +T04 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T04 ; dec: T04 + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (function_declaration) 03 + 03 ๐œ€ 05, 09 + 05 โ†“* (decorator) [Node Set(M0)] 07 + 07 *โ†‘ยน 08 + 08 โ–ถ + 09 ๐œ€ [Null Set(M0)] 08 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_first_child_array.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_first_child_array.snap new file mode 100644 index 00000000..5fc683ba --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_first_child_array.snap @@ -0,0 +1,51 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (array (identifier)* @ids (number) @n) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "ids" +S02 "n" +S03 "Test" +S04 "array" +S05 "number" +S06 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayStar(T01) ; Node* +T04 = Struct M0[2] ; { ids, n } + +[type_members] +M0: S01 โ†’ T03 ; ids: T03 +M1: S02 โ†’ T01 ; n: Node + +[type_names] +N0: S03 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (array) 03 + 03 ๐œ€ [Arr] 05 + 05 ๐œ€ 16, 14 + 07 โ–ถ + 08 โ†“* (number) [Node Set(M1)] 22 + 10 * (number) [Node Set(M1)] 22 + 12 ๐œ€ [EndArr Set(M0)] 10 + 14 ๐œ€ [EndArr Set(M0)] 08 + 16 โ†“* (identifier) [Push] 20 + 18 * (identifier) [Push] 20 + 20 ๐œ€ 18, 12 + 22 *โ†‘ยน 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional.snap new file mode 100644 index 00000000..0b2e79ee --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional.snap @@ -0,0 +1,42 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (function_declaration (decorator)? @dec) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "dec" +S02 "Test" +S03 "function_declaration" +S04 "decorator" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { dec } +T04 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T04 ; dec: T04 + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (function_declaration) 03 + 03 ๐œ€ 05, 09 + 05 โ†“* (decorator) [Node Set(M0)] 07 + 07 *โ†‘ยน 08 + 08 โ–ถ + 09 ๐œ€ [Null Set(M0)] 08 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional_nongreedy.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional_nongreedy.snap new file mode 100644 index 00000000..6c955cd8 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_optional_nongreedy.snap @@ -0,0 +1,42 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (function_declaration (decorator)?? @dec) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "dec" +S02 "Test" +S03 "function_declaration" +S04 "decorator" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { dec } +T04 = Optional(T01) ; Node? + +[type_members] +M0: S01 โ†’ T04 ; dec: T04 + +[type_names] +N0: S02 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (function_declaration) 03 + 03 ๐œ€ 09, 05 + 05 โ†“* (decorator) [Node Set(M0)] 07 + 07 *โ†‘ยน 08 + 08 โ–ถ + 09 ๐œ€ [Null Set(M0)] 08 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus.snap new file mode 100644 index 00000000..453c2a65 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus.snap @@ -0,0 +1,41 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier)+ @items +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "items" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayPlus(T01) ; Node+ +T04 = Struct M0[1] ; { items } + +[type_members] +M0: S01 โ†’ T03 ; items: T03 + +[type_names] +N0: S02 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Arr] 04 + 04 (identifier) [Push] 11 + 06 โ–ถ + 07 ๐œ€ [EndArr Set(M0)] 06 + 09 (identifier) [Push] 11 + 11 ๐œ€ 09, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus_nongreedy.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus_nongreedy.snap new file mode 100644 index 00000000..ef0e077a --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_plus_nongreedy.snap @@ -0,0 +1,41 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier)+? @items +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "items" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayPlus(T01) ; Node+ +T04 = Struct M0[1] ; { items } + +[type_members] +M0: S01 โ†’ T03 ; items: T03 + +[type_names] +N0: S02 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Arr] 04 + 04 (identifier) [Push] 11 + 06 โ–ถ + 07 ๐œ€ [EndArr Set(M0)] 06 + 09 (identifier) [Push] 11 + 11 ๐œ€ 07, 09 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_repeat_navigation.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_repeat_navigation.snap new file mode 100644 index 00000000..e5533632 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_repeat_navigation.snap @@ -0,0 +1,46 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (function_declaration (decorator)* @decs) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "decs" +S02 "Test" +S03 "function_declaration" +S04 "decorator" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayStar(T01) ; Node* +T04 = Struct M0[1] ; { decs } + +[type_members] +M0: S01 โ†’ T03 ; decs: T03 + +[type_names] +N0: S02 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (function_declaration) 03 + 03 ๐œ€ [Arr] 05 + 05 ๐œ€ 13, 11 + 07 ๐œ€ [EndArr Set(M0)] 09 + 09 *โ†‘ยน 10 + 10 โ–ถ + 11 ๐œ€ [EndArr Set(M0)] 10 + 13 โ†“* (decorator) [Push] 17 + 15 * (decorator) [Push] 17 + 17 ๐œ€ 15, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star.snap new file mode 100644 index 00000000..c3cadd2f --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star.snap @@ -0,0 +1,42 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier)* @items +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "items" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayStar(T01) ; Node* +T04 = Struct M0[1] ; { items } + +[type_members] +M0: S01 โ†’ T03 ; items: T03 + +[type_names] +N0: S02 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Arr] 04 + 04 ๐œ€ 09, 07 + 06 โ–ถ + 07 ๐œ€ [EndArr Set(M0)] 06 + 09 (identifier) [Push] 13 + 11 (identifier) [Push] 13 + 13 ๐œ€ 11, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star_nongreedy.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star_nongreedy.snap new file mode 100644 index 00000000..a9a68235 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_star_nongreedy.snap @@ -0,0 +1,42 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (identifier)*? @items +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "items" +S02 "Test" +S03 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayStar(T01) ; Node* +T04 = Struct M0[1] ; { items } + +[type_members] +M0: S01 โ†’ T03 ; items: T03 + +[type_names] +N0: S02 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 ๐œ€ [Arr] 04 + 04 ๐œ€ 07, 09 + 06 โ–ถ + 07 ๐œ€ [EndArr Set(M0)] 06 + 09 (identifier) [Push] 13 + 11 (identifier) [Push] 13 + 13 ๐œ€ 07, 11 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_struct_array.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_struct_array.snap new file mode 100644 index 00000000..b9efef7e --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_struct_array.snap @@ -0,0 +1,58 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (array {(identifier) @a (number) @b}* @items) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "items" +S04 "Test" +S05 "array" +S06 "number" +S07 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { a, b } +T04 = ArrayStar(T03) ; T03* +T05 = Struct M2[1] ; { items } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node +M2: S03 โ†’ T04 ; items: T04 + +[type_names] +N0: S04 โ†’ T05 ; Test + +[entrypoints] +Test = 01 :: T05 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (array) 03 + 03 ๐œ€ [Arr] 05 + 05 ๐œ€ 19, 11 + 07 ๐œ€ [EndArr Set(M2)] 09 + 09 *โ†‘ยน 10 + 10 โ–ถ + 11 ๐œ€ [EndArr Set(M2)] 10 + 13 ๐œ€ [EndObj Push] 29 + 15 * (number) [Node Set(M1)] 13 + 17 โ†“* (identifier) [Node Set(M0)] 15 + 19 ๐œ€ [Obj] 17 + 21 ๐œ€ [EndObj Push] 29 + 23 * (number) [Node Set(M1)] 21 + 25 * (identifier) [Node Set(M0)] 23 + 27 ๐œ€ [Obj] 25 + 29 ๐œ€ 27, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_simple.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_simple.snap new file mode 100644 index 00000000..f44f905c --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_simple.snap @@ -0,0 +1,63 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Expr = [ + Lit: (number) @value :: string + Rec: (call_expression function: (identifier) @fn arguments: (Expr) @inner) +] +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "value" +S02 "fn" +S03 "inner" +S04 "Lit" +S05 "Rec" +S06 "Expr" +S07 "number" +S08 "call_expression" +S09 "arguments" +S10 "function" +S11 "identifier" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { value } +T04 = Struct M1[2] ; { fn, inner } +T05 = Enum M3[2] ; Lit | Rec + +[type_members] +M0: S01 โ†’ T02 ; value: str +M1: S02 โ†’ T01 ; fn: Node +M2: S03 โ†’ T05 ; inner: Expr +M3: S04 โ†’ T03 ; Lit: T03 +M4: S05 โ†’ T04 ; Rec: T04 + +[type_names] +N0: S06 โ†’ T05 ; Expr + +[entrypoints] +Expr = 01 :: T05 + +[transitions] + 00 ๐œ€ โ—ผ + +Expr: + 01 ๐œ€ 02 + 02 ๐œ€ 12, 20 + 04 ๐œ€ [Set(M2)] 06 + 06 *โ†‘ยน 14 + 07 โ–ถ + 08 ๐œ€ [EndEnum] 07 + 10 (number) [Text Set(M0)] 08 + 12 ๐œ€ [Enum(M3)] 10 + 14 ๐œ€ [EndEnum] 07 + 16 * โ–ถ arguments: (Expr) 04 + 17 โ†“* function: (identifier) [Node Set(M1)] 16 + 19 (call_expression) 17 + 20 ๐œ€ [Enum(M4)] 19 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_with_structured_result.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_with_structured_result.snap new file mode 100644 index 00000000..0d5cba63 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__recursion_with_structured_result.snap @@ -0,0 +1,80 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Expr = [ + Lit: (number) @value :: string + Nested: (call_expression function: (identifier) @fn arguments: (Expr) @inner) +] + +Test = (program (Expr) @expr) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "value" +S02 "fn" +S03 "inner" +S04 "Lit" +S05 "Nested" +S06 "expr" +S07 "Expr" +S08 "Test" +S09 "number" +S10 "call_expression" +S11 "arguments" +S12 "function" +S13 "identifier" +S14 "program" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[1] ; { value } +T04 = Struct M1[2] ; { fn, inner } +T05 = Enum M3[2] ; Lit | Nested +T06 = Struct M5[1] ; { expr } + +[type_members] +M0: S01 โ†’ T02 ; value: str +M1: S02 โ†’ T01 ; fn: Node +M2: S03 โ†’ T05 ; inner: Expr +M3: S04 โ†’ T03 ; Lit: T03 +M4: S05 โ†’ T04 ; Nested: T04 +M5: S06 โ†’ T05 ; expr: Expr + +[type_names] +N0: S07 โ†’ T05 ; Expr +N1: S08 โ†’ T06 ; Test + +[entrypoints] +Expr = 01 :: T05 +Test = 04 :: T06 + +[transitions] + 00 ๐œ€ โ—ผ + +Expr: + 01 ๐œ€ 02 + 02 ๐œ€ 19, 27 + +Test: + 04 ๐œ€ 05 + 05 (program) 06 + 06 โ†“* โ–ถ (Expr) 07 + 07 ๐œ€ [Set(M5)] 09 + 09 *โ†‘ยน 10 + 10 โ–ถ + 11 ๐œ€ [Set(M2)] 13 + 13 *โ†‘ยน 21 + 14 โ–ถ + 15 ๐œ€ [EndEnum] 14 + 17 (number) [Text Set(M0)] 15 + 19 ๐œ€ [Enum(M3)] 17 + 21 ๐œ€ [EndEnum] 14 + 23 * โ–ถ arguments: (Expr) 11 + 24 โ†“* function: (identifier) [Node Set(M1)] 23 + 26 (call_expression) 24 + 27 ๐œ€ [Enum(M4)] 26 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_basic.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_basic.snap new file mode 100644 index 00000000..2df0c5e6 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_basic.snap @@ -0,0 +1,39 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent {(a) (b)}) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "b" +S04 "a" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (a) 04 + 04 * (b) 05 + 05 *โ†‘ยน 06 + 06 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_in_quantifier.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_in_quantifier.snap new file mode 100644 index 00000000..416d54a0 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_in_quantifier.snap @@ -0,0 +1,49 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent {(a) (b)}* @items) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "items" +S02 "Test" +S03 "parent" +S04 "b" +S05 "a" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = ArrayStar(T01) ; Node* +T04 = Struct M0[1] ; { items } + +[type_members] +M0: S01 โ†’ T03 ; items: T03 + +[type_names] +N0: S02 โ†’ T04 ; Test + +[entrypoints] +Test = 01 :: T04 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 ๐œ€ [Arr] 05 + 05 ๐œ€ 15, 11 + 07 ๐œ€ [EndArr Set(M0)] 09 + 09 *โ†‘ยน 10 + 10 โ–ถ + 11 ๐œ€ [EndArr Set(M0)] 10 + 13 * (b) [Push] 19 + 15 โ†“* (a) 13 + 16 * (b) [Push] 19 + 18 * (a) 16 + 19 ๐œ€ 18, 07 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_nested.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_nested.snap new file mode 100644 index 00000000..79a11859 --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_nested.snap @@ -0,0 +1,43 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent {(a) {(b) (c)} (d)}) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "Test" +S02 "parent" +S03 "d" +S04 "c" +S05 "b" +S06 "a" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[0] ; { } + +[type_members] + +[type_names] +N0: S01 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (a) 04 + 04 * (b) 05 + 05 * (c) 06 + 06 * (d) 07 + 07 *โ†‘ยน 08 + 08 โ–ถ diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_with_captures.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_with_captures.snap new file mode 100644 index 00000000..ca85e1aa --- /dev/null +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__sequences_with_captures.snap @@ -0,0 +1,41 @@ +--- +source: crates/plotnik-lib/src/emit/codegen_tests.rs +--- +Test = (parent {(a) @a (b) @b}) +--- +[flags] +linked = false + +[strings] +S00 "Beauty will save the world" +S01 "a" +S02 "b" +S03 "Test" +S04 "parent" + +[type_defs] +T00 = void +T01 = Node +T02 = str +T03 = Struct M0[2] ; { a, b } + +[type_members] +M0: S01 โ†’ T01 ; a: Node +M1: S02 โ†’ T01 ; b: Node + +[type_names] +N0: S03 โ†’ T03 ; Test + +[entrypoints] +Test = 01 :: T03 + +[transitions] + 00 ๐œ€ โ—ผ + +Test: + 01 ๐œ€ 02 + 02 (parent) 03 + 03 โ†“* (a) [Node Set(M0)] 05 + 05 * (b) [Node Set(M1)] 07 + 07 *โ†‘ยน 08 + 08 โ–ถ diff --git a/docs/binary-format/07-dump-format.md b/docs/binary-format/07-dump-format.md index 50767642..f7d4b97e 100644 --- a/docs/binary-format/07-dump-format.md +++ b/docs/binary-format/07-dump-format.md @@ -29,7 +29,7 @@ placed directly on match instructions rather than in separate epsilon steps. Str effects (`Obj`, `EndObj`, `Arr`, `EndArr`, `Enum`, `EndEnum`) remain in epsilons. ``` -[header] +[flags] linked = true [strings] @@ -48,36 +48,36 @@ S11 "assignment_expression" S12 "left" S13 "right" -[types.defs] +[type_defs] T00 = void T01 = Node T02 = str -T03 = Struct(M0, 1) ; { name } -T04 = Struct(M1, 1) ; { value } -T05 = Struct(M2, 1) ; { name } -T06 = Enum(M3, 2) ; Literal | Variable -T07 = Struct(M5, 2) ; { value, target } - -[types.members] -M0 = (S01, T02) ; name: str -M1 = (S02, T01) ; value: Node -M2 = (S01, T01) ; name: Node -M3 = (S03, T04) ; Literal: T04 -M4 = (S04, T05) ; Variable: T05 -M5 = (S02, T06) ; value: Expression -M6 = (S05, T01) ; target: Node - -[types.names] -N0 = (S06, T03) ; Ident -N1 = (S07, T06) ; Expression -N2 = (S08, T07) ; Assignment - -[entry] +T03 = Struct M0[1] ; { name } +T04 = Struct M1[1] ; { value } +T05 = Struct M2[1] ; { name } +T06 = Enum M3[2] ; Literal | Variable +T07 = Struct M5[2] ; { value, target } + +[type_members] +M0: S01 โ†’ T02 ; name: str +M1: S02 โ†’ T01 ; value: Node +M2: S01 โ†’ T01 ; name: Node +M3: S03 โ†’ T04 ; Literal: T04 +M4: S04 โ†’ T05 ; Variable: T05 +M5: S02 โ†’ T06 ; value: Expression +M6: S05 โ†’ T01 ; target: Node + +[type_names] +N0: S06 โ†’ T03 ; Ident +N1: S07 โ†’ T06 ; Expression +N2: S08 โ†’ T07 ; Assignment + +[entrypoints] Assignment = 08 :: T07 Expression = 05 :: T06 Ident = 01 :: T03 -[code] +[transitions] 00 ๐œ€ โ—ผ Ident: @@ -92,7 +92,7 @@ Expression: Assignment: 08 ๐œ€ 09 09 (assignment_expression) 10 - 10 โ†“* left: (identifier) [Node Set(M6)]12 + 10 โ†“* left: (identifier) [Node Set(M6)] 12 12 * โ–ถ right: (Expression) 13 13 ๐œ€ [Set(M5)] 15 15 *โ†‘ยน 16 @@ -187,30 +187,30 @@ Effects in `[pre]` execute before match attempt; effects in `[post]` execute aft | Prefix | Section | Description | | ------ | ------------- | ----------- | | S## | strings | StringId | -| T## | types.defs | TypeId | -| M## | types.members | MemberIndex | -| N## | types.names | NameIndex | +| T## | type_defs | TypeId | +| M## | type_members | MemberIndex | +| N## | type_names | NameIndex | ## Type Format -### types.defs +### type_defs -| Kind | Format | Example | -| -------- | -------------------- | ---------------------- | -| void | `void` | `T00 = void` | -| Node | `Node` | `T01 = Node` | -| str | `str` | `T02 = str` | -| Struct | `Struct(Mxx, count)` | `T03 = Struct(M0, 1)` | -| Enum | `Enum(Mxx, count)` | `T05 = Enum(M2, 2)` | -| Optional | `Optional(Txx)` | `T07 = Optional(T05)` | -| Array\* | `ArrayStar(Txx)` | `ArrayStar(T09)` | -| Array+ | `ArrayPlus(Txx)` | `T10 = ArrayPlus(T09)` | -| Alias | `Alias(Txx)` | `T03 = Alias(T01)` | +| Kind | Format | Example | +| -------- | ------------------- | ------------------------ | +| void | `void` | `T00 = void` | +| Node | `Node` | `T01 = Node` | +| str | `str` | `T02 = str` | +| Struct | `Struct Mxx[n]` | `T03 = Struct M0[1]` | +| Enum | `Enum Mxx[n]` | `T06 = Enum M3[2]` | +| Optional | `Optional(Txx)` | `T07 = Optional(T05)` | +| Array\* | `ArrayStar(Txx)` | `T03 = ArrayStar(T01)` | +| Array+ | `ArrayPlus(Txx)` | `T10 = ArrayPlus(T09)` | +| Alias | `Alias(Txx)` | `T03 = Alias(T01)` | -### types.members +### type_members -Format: `Mx = (Sxx, Txx) ; comment` +Format: `Mx: Sxx โ†’ Txx ; comment` -### types.names +### type_names -Format: `Nx = (Sxx, Txx) ; comment` +Format: `Nx: Sxx โ†’ Txx ; comment`