From 099a0dde736270a6d801cd28c032f77ce9ebb14d Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Thu, 15 Jan 2026 02:07:53 -0300 Subject: [PATCH] refactor: Split plotnik-lib into bytecode, vm, compiler crates --- Cargo.lock | 57 +- Cargo.toml | 13 +- crates/plotnik-bytecode/Cargo.toml | 18 + .../src/bytecode/aligned_vec.rs | 0 .../src/bytecode/aligned_vec_tests.rs | 0 .../src/bytecode/constants.rs | 0 .../src/bytecode/dump.rs | 19 +- .../src/bytecode/effects.rs | 11 +- .../src/bytecode/effects_tests.rs | 10 +- .../src/bytecode/entrypoint.rs | 8 +- .../src/bytecode/entrypoint_tests.rs | 0 .../src/bytecode/format.rs | 0 .../src/bytecode/format_tests.rs | 0 .../src/bytecode/header.rs | 4 +- .../src/bytecode/header_tests.rs | 0 .../src/bytecode/ids.rs | 0 .../src/bytecode/instructions.rs | 18 +- .../src/bytecode/instructions_tests.rs | 80 ++ .../src/bytecode/mod.rs | 11 +- .../src/bytecode/module.rs | 2 +- .../src/bytecode/module_tests.rs | 42 ++ .../src/bytecode/nav.rs | 0 .../src/bytecode/nav_tests.rs | 0 .../src/bytecode/node_type_ir.rs | 78 ++ .../src/bytecode/node_type_ir_tests.rs | 73 ++ .../src/bytecode/sections.rs | 28 +- .../src/bytecode/sections_tests.rs | 0 .../src/bytecode/type_meta.rs | 22 +- .../src/bytecode/type_meta_tests.rs | 0 crates/plotnik-bytecode/src/dfa.rs | 17 + crates/plotnik-bytecode/src/lib.rs | 28 + crates/plotnik-bytecode/src/predicate_op.rs | 112 +++ .../src/type_system/arity.rs | 0 .../src/type_system/arity_tests.rs | 0 .../src/type_system/kind.rs | 0 .../src/type_system/kind_tests.rs | 0 .../src/type_system/mod.rs | 0 .../src/type_system/primitives.rs | 0 .../src/type_system/primitives_tests.rs | 0 .../src/type_system/quantifier.rs | 0 .../src/type_system/quantifier_tests.rs | 0 crates/plotnik-cli/src/commands/run_common.rs | 2 +- crates/plotnik-compiler/Cargo.toml | 35 + .../src/analyze/dependencies.rs | 0 .../src/analyze/dependencies_tests.rs | 0 .../src/analyze/invariants.rs | 0 .../src/analyze/link.rs | 0 .../src/analyze/link_tests.rs | 0 .../src/analyze/mod.rs | 0 .../src/analyze/recursion.rs | 0 .../src/analyze/refs.rs | 0 .../src/analyze/refs_tests.rs | 0 .../src/analyze/symbol_table.rs | 0 .../src/analyze/symbol_table_tests.rs | 0 .../src/analyze/type_check/context.rs | 0 .../src/analyze/type_check/context_tests.rs | 0 .../src/analyze/type_check/infer.rs | 0 .../src/analyze/type_check/mod.rs | 0 .../src/analyze/type_check/symbol.rs | 0 .../src/analyze/type_check/symbol_tests.rs | 0 .../analyze/type_check/type_check_tests.rs | 0 .../src/analyze/type_check/types.rs | 4 +- .../src/analyze/type_check/unify.rs | 0 .../src/analyze/type_check/unify_tests.rs | 0 .../src/analyze/utils.rs | 0 .../src/analyze/validation/alt_kinds.rs | 0 .../src/analyze/validation/alt_kinds_tests.rs | 0 .../src/analyze/validation/anchors.rs | 0 .../src/analyze/validation/anchors_tests.rs | 0 .../analyze/validation/empty_constructs.rs | 0 .../validation/empty_constructs_tests.rs | 0 .../src/analyze/validation/mod.rs | 0 .../src/analyze/validation/predicates.rs | 0 .../analyze/validation/predicates_tests.rs | 0 .../src/analyze/visitor.rs | 0 .../src/bytecode/ir.rs | 20 +- .../src/bytecode/ir_tests.rs | 3 +- crates/plotnik-compiler/src/bytecode/mod.rs | 8 + .../src/compile/capture.rs | 2 +- .../src/compile/capture_tests.rs | 3 +- .../src/compile/compile_tests.rs | 0 .../src/compile/compiler.rs | 2 +- .../src/compile/error.rs | 0 .../src/compile/expressions.rs | 4 +- .../src/compile/mod.rs | 0 .../src/compile/navigation.rs | 2 +- .../src/compile/quantifier.rs | 2 +- .../src/compile/scope.rs | 8 +- .../src/compile/sequences.rs | 2 +- .../src/diagnostics/diagnostics_tests.rs | 0 .../src/diagnostics/message.rs | 0 .../src/diagnostics/mod.rs | 0 .../src/diagnostics/printer.rs | 0 .../src/emit/emit_tests.rs | 0 .../src/emit/emitter.rs | 10 +- .../src/emit/error.rs | 0 .../src/emit/layout.rs | 0 .../src/emit/layout_tests.rs | 2 +- .../src/emit/mod.rs | 0 .../src/emit/regex_table.rs | 2 +- .../src/emit/regex_table_tests.rs | 2 +- ...it__emit_tests__alternations_captured.snap | 39 + ...t_tests__alternations_captured_tagged.snap | 51 ++ ...mit_tests__alternations_in_quantifier.snap | 75 ++ ...mit__emit_tests__alternations_labeled.snap | 52 ++ ...ts__alternations_no_internal_captures.snap | 41 + ...it_tests__alternations_null_injection.snap | 48 ++ ...ternations_tagged_in_field_constraint.snap | 53 ++ ...ternations_tagged_with_definition_ref.snap | 66 ++ ...t__emit_tests__alternations_unlabeled.snap | 48 ++ ..._emit_tests__anchors_between_siblings.snap | 37 + ...emit__emit_tests__anchors_first_child.snap | 35 + ..._emit__emit_tests__anchors_last_child.snap | 38 + ...__emit__emit_tests__anchors_no_anchor.snap | 37 + ...t__emit_tests__anchors_with_anonymous.snap | 37 + ...ler__emit__emit_tests__captures_basic.snap | 36 + ...t__emit_tests__captures_deeply_nested.snap | 58 ++ ...s__captures_enum_with_type_annotation.snap | 53 ++ ...__emit__emit_tests__captures_multiple.snap | 46 ++ ...mit__emit_tests__captures_nested_flat.snap | 50 ++ ...sts__captures_optional_wrapper_struct.snap | 57 ++ ...it__emit_tests__captures_struct_scope.snap | 49 ++ ..._captures_struct_with_type_annotation.snap | 43 ++ ...emit_tests__captures_with_type_custom.snap | 39 + ...emit_tests__captures_with_type_string.snap | 36 + ...__emit_tests__captures_wrapper_struct.snap | 69 ++ ...tests__comprehensive_multi_definition.snap | 88 +++ ...mit__emit_tests__definitions_multiple.snap | 49 ++ ...mit_tests__definitions_nested_capture.snap | 77 ++ ...it__emit_tests__definitions_reference.snap | 58 ++ ..._emit__emit_tests__definitions_single.snap | 36 + ..._emit__emit_tests__fields_alternation.snap | 51 ++ ...er__emit__emit_tests__fields_multiple.snap | 46 ++ ...ler__emit__emit_tests__fields_negated.snap | 40 + ...iler__emit__emit_tests__fields_single.snap | 38 + ...er__emit__emit_tests__nodes_anonymous.snap | 38 + ...mpiler__emit__emit_tests__nodes_error.snap | 35 + ...iler__emit__emit_tests__nodes_missing.snap | 35 + ...mpiler__emit__emit_tests__nodes_named.snap | 36 + ..._emit__emit_tests__nodes_wildcard_any.snap | 37 + ...mit__emit_tests__nodes_wildcard_named.snap | 37 + ...mit__emit_tests__optional_first_child.snap | 57 ++ ...__emit_tests__optional_null_injection.snap | 47 ++ ..._tests__quantifiers_first_child_array.snap | 62 ++ ...mit__emit_tests__quantifiers_optional.snap | 47 ++ ...tests__quantifiers_optional_nongreedy.snap | 47 ++ ...r__emit__emit_tests__quantifiers_plus.snap | 47 ++ ...mit_tests__quantifiers_plus_nongreedy.snap | 47 ++ ..._tests__quantifiers_repeat_navigation.snap | 53 ++ ...s__quantifiers_sequence_in_called_def.snap | 83 ++ ...r__emit__emit_tests__quantifiers_star.snap | 49 ++ ...mit_tests__quantifiers_star_nongreedy.snap | 49 ++ ..._emit_tests__quantifiers_struct_array.snap | 68 ++ ...r__emit__emit_tests__recursion_simple.snap | 67 ++ ...sts__recursion_with_structured_result.snap | 82 ++ ...er__emit__emit_tests__sequences_basic.snap | 37 + ...__emit_tests__sequences_in_quantifier.snap | 56 ++ ...r__emit__emit_tests__sequences_nested.snap | 41 + ...__emit_tests__sequences_with_captures.snap | 46 ++ ...it__emit_tests__alternations_captured.snap | 0 ...t_tests__alternations_captured_tagged.snap | 0 ...mit_tests__alternations_in_quantifier.snap | 0 ...mit__emit_tests__alternations_labeled.snap | 0 ...ts__alternations_no_internal_captures.snap | 0 ...it_tests__alternations_null_injection.snap | 0 ...ternations_tagged_in_field_constraint.snap | 0 ...ternations_tagged_with_definition_ref.snap | 0 ...t__emit_tests__alternations_unlabeled.snap | 0 ..._emit_tests__anchors_between_siblings.snap | 0 ...emit__emit_tests__anchors_first_child.snap | 0 ..._emit__emit_tests__anchors_last_child.snap | 0 ...__emit__emit_tests__anchors_no_anchor.snap | 0 ...t__emit_tests__anchors_with_anonymous.snap | 0 ...lib__emit__emit_tests__captures_basic.snap | 0 ...t__emit_tests__captures_deeply_nested.snap | 0 ...s__captures_enum_with_type_annotation.snap | 0 ...__emit__emit_tests__captures_multiple.snap | 0 ...mit__emit_tests__captures_nested_flat.snap | 0 ...sts__captures_optional_wrapper_struct.snap | 0 ...it__emit_tests__captures_struct_scope.snap | 0 ..._captures_struct_with_type_annotation.snap | 0 ...emit_tests__captures_with_type_custom.snap | 0 ...emit_tests__captures_with_type_string.snap | 0 ...__emit_tests__captures_wrapper_struct.snap | 0 ...tests__comprehensive_multi_definition.snap | 0 ...mit__emit_tests__definitions_multiple.snap | 0 ...mit_tests__definitions_nested_capture.snap | 0 ...it__emit_tests__definitions_reference.snap | 0 ..._emit__emit_tests__definitions_single.snap | 0 ..._emit__emit_tests__fields_alternation.snap | 0 ...ib__emit__emit_tests__fields_multiple.snap | 0 ...lib__emit__emit_tests__fields_negated.snap | 0 ..._lib__emit__emit_tests__fields_single.snap | 0 ...ib__emit__emit_tests__nodes_anonymous.snap | 0 ...ik_lib__emit__emit_tests__nodes_error.snap | 0 ..._lib__emit__emit_tests__nodes_missing.snap | 0 ...ik_lib__emit__emit_tests__nodes_named.snap | 0 ..._emit__emit_tests__nodes_wildcard_any.snap | 0 ...mit__emit_tests__nodes_wildcard_named.snap | 0 ...mit__emit_tests__optional_first_child.snap | 0 ...__emit_tests__optional_null_injection.snap | 0 ..._tests__quantifiers_first_child_array.snap | 0 ...mit__emit_tests__quantifiers_optional.snap | 0 ...tests__quantifiers_optional_nongreedy.snap | 0 ...b__emit__emit_tests__quantifiers_plus.snap | 0 ...mit_tests__quantifiers_plus_nongreedy.snap | 0 ..._tests__quantifiers_repeat_navigation.snap | 0 ...s__quantifiers_sequence_in_called_def.snap | 0 ...b__emit__emit_tests__quantifiers_star.snap | 0 ...mit_tests__quantifiers_star_nongreedy.snap | 0 ..._emit_tests__quantifiers_struct_array.snap | 0 ...b__emit__emit_tests__recursion_simple.snap | 0 ...sts__recursion_with_structured_result.snap | 0 ...ib__emit__emit_tests__sequences_basic.snap | 0 ...__emit_tests__sequences_in_quantifier.snap | 0 ...b__emit__emit_tests__sequences_nested.snap | 0 ...__emit_tests__sequences_with_captures.snap | 0 .../src/emit/string_table.rs | 2 +- .../src/emit/string_table_tests.rs | 0 .../src/emit/type_table.rs | 5 +- .../src/emit/type_table_tests.rs | 0 crates/plotnik-compiler/src/lib.rs | 52 ++ .../src/parser/ast.rs | 93 +-- .../src/parser/ast_tests.rs | 0 .../src/parser/core.rs | 0 .../src/parser/cst.rs | 0 .../src/parser/cst_tests.rs | 0 .../src/parser/grammar/atoms.rs | 0 .../src/parser/grammar/expressions.rs | 0 .../src/parser/grammar/fields.rs | 0 .../src/parser/grammar/items.rs | 0 .../src/parser/grammar/mod.rs | 0 .../src/parser/grammar/structures.rs | 0 .../src/parser/grammar/utils.rs | 0 .../src/parser/grammar/validation.rs | 0 .../src/parser/invariants.rs | 0 .../src/parser/lexer.rs | 0 .../src/parser/lexer_tests.rs | 0 .../src/parser/mod.rs | 0 .../tests/grammar/alternations_tests.rs | 0 .../src/parser/tests/grammar/anchors_tests.rs | 0 .../parser/tests/grammar/captures_tests.rs | 0 .../parser/tests/grammar/definitions_tests.rs | 0 .../src/parser/tests/grammar/fields_tests.rs | 0 .../src/parser/tests/grammar/mod.rs | 0 .../src/parser/tests/grammar/nodes_tests.rs | 0 .../parser/tests/grammar/quantifiers_tests.rs | 0 .../parser/tests/grammar/sequences_tests.rs | 0 .../src/parser/tests/grammar/special_tests.rs | 0 .../src/parser/tests/grammar/trivia_tests.rs | 0 .../src/parser/tests/mod.rs | 0 .../parser/tests/recovery/coverage_tests.rs | 0 .../parser/tests/recovery/incomplete_tests.rs | 0 .../src/parser/tests/recovery/mod.rs | 0 .../parser/tests/recovery/unclosed_tests.rs | 0 .../parser/tests/recovery/unexpected_tests.rs | 0 .../parser/tests/recovery/validation_tests.rs | 0 .../src/query/dump.rs | 0 .../src/query/mod.rs | 0 .../src/query/printer.rs | 0 .../src/query/printer_tests.rs | 0 .../src/query/query_tests.rs | 6 +- .../src/query/source_map.rs | 0 .../src/query/source_map_tests.rs | 0 .../src/query/stages.rs | 0 .../src/typegen/mod.rs | 0 .../src/typegen/typescript/analysis.rs | 12 +- .../src/typegen/typescript/config.rs | 2 +- .../src/typegen/typescript/convert.rs | 12 +- .../src/typegen/typescript/emitter.rs | 4 +- .../src/typegen/typescript/mod.rs | 2 +- .../src/typegen/typescript/naming.rs | 12 +- .../src/typegen/typescript/render.rs | 18 +- .../src/colors.rs | 0 crates/plotnik-core/src/lib.rs | 2 + crates/plotnik-lib/Cargo.toml | 16 +- .../src/bytecode/instructions_tests.rs | 175 ----- .../plotnik-lib/src/bytecode/module_tests.rs | 229 ------ ...ecode__dump_tests__dump_comprehensive.snap | 79 -- crates/plotnik-lib/src/engine/engine_tests.rs | 714 ------------------ crates/plotnik-lib/src/engine/verify_tests.rs | 208 ----- crates/plotnik-lib/src/lib.rs | 64 +- crates/plotnik-vm/Cargo.toml | 21 + .../src/engine/checkpoint.rs | 0 .../src/engine/cursor.rs | 2 +- .../src/engine/effect.rs | 0 crates/plotnik-vm/src/engine/engine_tests.rs | 5 + .../src/engine/error.rs | 2 +- .../src/engine/frame.rs | 0 .../src/engine/materializer.rs | 6 +- .../src/engine/mod.rs | 2 + ...engine_tests__alternation_merge_ident.snap | 0 ...__engine_tests__alternation_merge_num.snap | 0 ...ation_tagged_definition_ref_backtrack.snap | 0 ...ngine_tests__alternation_tagged_ident.snap | 0 ..._engine_tests__alternation_tagged_num.snap | 0 ...ngine__engine_tests__anchor_adjacency.snap | 0 ...ine__engine_tests__anchor_first_child.snap | 0 ...gine__engine_tests__anchor_last_child.snap | 0 ...e_tests__anchor_last_child_multi_item.snap | 0 ...ngine_tests__anchor_last_child_single.snap | 0 ..._tests__anchor_last_child_with_trivia.snap | 0 ...ngine__engine_tests__capture_multiple.snap | 0 ..._engine__engine_tests__capture_single.snap | 0 ...gine_tests__capture_string_annotation.snap | 0 ...e__engine_tests__field_negated_absent.snap | 0 ...gine_tests__quantifier_nongreedy_star.snap | 0 ...ine_tests__quantifier_optional_absent.snap | 0 ...ne_tests__quantifier_optional_present.snap | 0 ...engine__engine_tests__quantifier_plus.snap | 0 ...uantifier_plus_with_string_annotation.snap | 0 ...engine__engine_tests__quantifier_star.snap | 0 ...uantifier_star_with_string_annotation.snap | 0 ...engine_tests__quantifier_struct_array.snap | 0 ..._engine_tests__recursion_member_chain.snap | 0 ..._engine_tests__recursion_nested_calls.snap | 0 ...gression_call_searches_among_siblings.snap | 0 ...on_call_searches_for_field_constraint.snap | 0 ...on_childless_node_with_inner_optional.snap | 0 ...ession_childless_node_with_inner_star.snap | 0 ...s__regression_empty_captured_sequence.snap | 0 ...ression_enum_tag_with_definition_refs.snap | 0 ...on_enum_variant_array_capture_payload.snap | 0 ..._nested_quantifiers_empty_inner_array.snap | 0 ...ted_quantifiers_struct_captures_mixed.snap | 0 ..._node_capture_on_parent_with_children.snap | 0 ...sion_optional_empty_captured_sequence.snap | 0 ...ecursive_alternation_uncaptured_array.snap | 0 ...sion_recursive_captures_nest_properly.snap | 0 ...egression_scalar_array_captures_nodes.snap | 0 ...ssion_tagged_alternation_materializes.snap | 0 ...beled_alternation_5_branches_captures.snap | 0 ...beled_alternation_8_branches_captures.snap | 0 ...e__engine_tests__search_skip_siblings.snap | 0 ..._tests__suppressive_capture_anonymous.snap | 0 ...gine_tests__suppressive_capture_named.snap | 0 ..._suppressive_capture_suppresses_inner.snap | 0 ...pressive_capture_with_regular_sibling.snap | 0 ..._tests__suppressive_capture_with_wrap.snap | 0 ...ests__wildcard_bare_matches_anonymous.snap | 0 ...tests__wildcard_named_skips_anonymous.snap | 0 .../src/engine/trace.rs | 9 +- .../src/engine/value.rs | 2 +- .../src/engine/verify.rs | 32 +- crates/plotnik-vm/src/engine/verify_tests.rs | 4 + .../src/engine/vm.rs | 7 +- crates/plotnik-vm/src/lib.rs | 14 + 347 files changed, 3717 insertions(+), 1739 deletions(-) create mode 100644 crates/plotnik-bytecode/Cargo.toml rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/aligned_vec.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/aligned_vec_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/constants.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/dump.rs (97%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/effects.rs (89%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/effects_tests.rs (75%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/entrypoint.rs (90%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/entrypoint_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/format.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/format_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/header.rs (98%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/header_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/ids.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/instructions.rs (98%) create mode 100644 crates/plotnik-bytecode/src/bytecode/instructions_tests.rs rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/mod.rs (89%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/module.rs (99%) create mode 100644 crates/plotnik-bytecode/src/bytecode/module_tests.rs rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/nav.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/nav_tests.rs (100%) create mode 100644 crates/plotnik-bytecode/src/bytecode/node_type_ir.rs create mode 100644 crates/plotnik-bytecode/src/bytecode/node_type_ir_tests.rs rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/sections.rs (77%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/sections_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/type_meta.rs (94%) rename crates/{plotnik-lib => plotnik-bytecode}/src/bytecode/type_meta_tests.rs (100%) create mode 100644 crates/plotnik-bytecode/src/dfa.rs create mode 100644 crates/plotnik-bytecode/src/lib.rs create mode 100644 crates/plotnik-bytecode/src/predicate_op.rs rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/arity.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/arity_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/kind.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/kind_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/mod.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/primitives.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/primitives_tests.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/quantifier.rs (100%) rename crates/{plotnik-lib => plotnik-bytecode}/src/type_system/quantifier_tests.rs (100%) create mode 100644 crates/plotnik-compiler/Cargo.toml rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/dependencies.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/dependencies_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/invariants.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/link.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/link_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/recursion.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/refs.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/refs_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/symbol_table.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/symbol_table_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/context.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/context_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/infer.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/symbol.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/symbol_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/type_check_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/types.rs (96%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/unify.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/type_check/unify_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/utils.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/alt_kinds.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/alt_kinds_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/anchors.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/anchors_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/empty_constructs.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/empty_constructs_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/predicates.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/validation/predicates_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/analyze/visitor.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/bytecode/ir.rs (97%) rename crates/{plotnik-lib => plotnik-compiler}/src/bytecode/ir_tests.rs (98%) create mode 100644 crates/plotnik-compiler/src/bytecode/mod.rs rename crates/{plotnik-lib => plotnik-compiler}/src/compile/capture.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/capture_tests.rs (96%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/compile_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/compiler.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/error.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/expressions.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/navigation.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/quantifier.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/scope.rs (98%) rename crates/{plotnik-lib => plotnik-compiler}/src/compile/sequences.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/diagnostics/diagnostics_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/diagnostics/message.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/diagnostics/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/diagnostics/printer.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/emit_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/emitter.rs (96%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/error.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/layout.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/layout_tests.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/regex_table.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/regex_table_tests.rs (98%) create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_captured.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_captured_tagged.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_in_quantifier.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_labeled.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_no_internal_captures.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_null_injection.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_tagged_in_field_constraint.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_tagged_with_definition_ref.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__alternations_unlabeled.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__anchors_between_siblings.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__anchors_first_child.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__anchors_last_child.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__anchors_no_anchor.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__anchors_with_anonymous.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_basic.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_deeply_nested.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_enum_with_type_annotation.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_multiple.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_nested_flat.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_optional_wrapper_struct.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_struct_scope.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_struct_with_type_annotation.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_with_type_custom.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_with_type_string.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__captures_wrapper_struct.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__comprehensive_multi_definition.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__definitions_multiple.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__definitions_nested_capture.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__definitions_reference.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__definitions_single.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__fields_alternation.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__fields_multiple.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__fields_negated.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__fields_single.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__nodes_anonymous.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__nodes_error.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__nodes_missing.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__nodes_named.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__nodes_wildcard_any.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__nodes_wildcard_named.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__optional_first_child.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__optional_null_injection.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_first_child_array.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_optional.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_optional_nongreedy.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_plus.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_plus_nongreedy.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_repeat_navigation.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_sequence_in_called_def.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_star.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_star_nongreedy.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__quantifiers_struct_array.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__recursion_simple.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__recursion_with_structured_result.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__sequences_basic.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__sequences_in_quantifier.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__sequences_nested.snap create mode 100644 crates/plotnik-compiler/src/emit/snapshots/plotnik_compiler__emit__emit_tests__sequences_with_captures.snap rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_captured.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_captured_tagged.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_in_quantifier.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_labeled.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_no_internal_captures.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_null_injection.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_tagged_in_field_constraint.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_tagged_with_definition_ref.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__alternations_unlabeled.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__anchors_between_siblings.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__anchors_first_child.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__anchors_last_child.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__anchors_no_anchor.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__anchors_with_anonymous.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_basic.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_deeply_nested.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_enum_with_type_annotation.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_multiple.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_nested_flat.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_optional_wrapper_struct.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_struct_scope.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_struct_with_type_annotation.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_with_type_custom.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_with_type_string.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__captures_wrapper_struct.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__comprehensive_multi_definition.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__definitions_multiple.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__definitions_nested_capture.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__definitions_reference.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__definitions_single.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__fields_alternation.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__fields_multiple.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__fields_negated.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__fields_single.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__nodes_anonymous.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__nodes_error.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__nodes_missing.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__nodes_named.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__nodes_wildcard_any.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__nodes_wildcard_named.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__optional_first_child.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__optional_null_injection.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_first_child_array.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_optional.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_optional_nongreedy.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_plus.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_plus_nongreedy.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_repeat_navigation.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_sequence_in_called_def.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_star.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_star_nongreedy.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__quantifiers_struct_array.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__recursion_simple.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__recursion_with_structured_result.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__sequences_basic.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__sequences_in_quantifier.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__sequences_nested.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/snapshots/plotnik_lib__emit__emit_tests__sequences_with_captures.snap (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/string_table.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/string_table_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/type_table.rs (99%) rename crates/{plotnik-lib => plotnik-compiler}/src/emit/type_table_tests.rs (100%) create mode 100644 crates/plotnik-compiler/src/lib.rs rename crates/{plotnik-lib => plotnik-compiler}/src/parser/ast.rs (87%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/ast_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/core.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/cst.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/cst_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/atoms.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/expressions.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/fields.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/items.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/structures.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/utils.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/grammar/validation.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/invariants.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/lexer.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/lexer_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/alternations_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/anchors_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/captures_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/definitions_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/fields_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/nodes_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/quantifiers_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/sequences_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/special_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/grammar/trivia_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/recovery/coverage_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/recovery/incomplete_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/recovery/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/recovery/unclosed_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/recovery/unexpected_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/parser/tests/recovery/validation_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/dump.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/printer.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/printer_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/query_tests.rs (98%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/source_map.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/source_map_tests.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/query/stages.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/mod.rs (100%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/analysis.rs (96%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/config.rs (98%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/convert.rs (95%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/emitter.rs (97%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/mod.rs (95%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/naming.rs (93%) rename crates/{plotnik-lib => plotnik-compiler}/src/typegen/typescript/render.rs (94%) rename crates/{plotnik-lib => plotnik-core}/src/colors.rs (100%) delete mode 100644 crates/plotnik-lib/src/bytecode/instructions_tests.rs delete mode 100644 crates/plotnik-lib/src/bytecode/module_tests.rs delete mode 100644 crates/plotnik-lib/src/bytecode/snapshots/plotnik_lib__bytecode__dump_tests__dump_comprehensive.snap delete mode 100644 crates/plotnik-lib/src/engine/engine_tests.rs delete mode 100644 crates/plotnik-lib/src/engine/verify_tests.rs create mode 100644 crates/plotnik-vm/Cargo.toml rename crates/{plotnik-lib => plotnik-vm}/src/engine/checkpoint.rs (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/cursor.rs (99%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/effect.rs (100%) create mode 100644 crates/plotnik-vm/src/engine/engine_tests.rs rename crates/{plotnik-lib => plotnik-vm}/src/engine/error.rs (95%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/frame.rs (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/materializer.rs (98%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/mod.rs (95%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__alternation_merge_ident.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__alternation_merge_num.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__alternation_tagged_definition_ref_backtrack.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__alternation_tagged_ident.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__alternation_tagged_num.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__anchor_adjacency.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__anchor_first_child.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__anchor_last_child.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__anchor_last_child_multi_item.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__anchor_last_child_single.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__anchor_last_child_with_trivia.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__capture_multiple.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__capture_single.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__capture_string_annotation.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__field_negated_absent.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_nongreedy_star.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_optional_absent.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_optional_present.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_plus.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_plus_with_string_annotation.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_star.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_star_with_string_annotation.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__quantifier_struct_array.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__recursion_member_chain.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__recursion_nested_calls.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_call_searches_among_siblings.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_call_searches_for_field_constraint.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_childless_node_with_inner_optional.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_childless_node_with_inner_star.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_empty_captured_sequence.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_enum_tag_with_definition_refs.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_enum_variant_array_capture_payload.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_nested_quantifiers_empty_inner_array.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_nested_quantifiers_struct_captures_mixed.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_node_capture_on_parent_with_children.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_optional_empty_captured_sequence.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_recursive_alternation_uncaptured_array.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_recursive_captures_nest_properly.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_scalar_array_captures_nodes.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_tagged_alternation_materializes.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_unlabeled_alternation_5_branches_captures.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__regression_unlabeled_alternation_8_branches_captures.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__search_skip_siblings.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__suppressive_capture_anonymous.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__suppressive_capture_named.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__suppressive_capture_suppresses_inner.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__suppressive_capture_with_regular_sibling.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__suppressive_capture_with_wrap.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__wildcard_bare_matches_anonymous.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/snapshots/plotnik_lib__engine__engine_tests__wildcard_named_skips_anonymous.snap (100%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/trace.rs (99%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/value.rs (99%) rename crates/{plotnik-lib => plotnik-vm}/src/engine/verify.rs (93%) create mode 100644 crates/plotnik-vm/src/engine/verify_tests.rs rename crates/{plotnik-lib => plotnik-vm}/src/engine/vm.rs (99%) create mode 100644 crates/plotnik-vm/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 329ce936..c6a75730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1656,6 +1656,40 @@ dependencies = [ "thiserror", ] +[[package]] +name = "plotnik-bytecode" +version = "0.2.2" +dependencies = [ + "insta", + "plotnik-core", + "regex-automata", + "thiserror", +] + +[[package]] +name = "plotnik-compiler" +version = "0.2.2" +dependencies = [ + "annotate-snippets", + "arborium-tree-sitter", + "crc32fast", + "indexmap", + "indoc", + "insta", + "logos", + "memmap2", + "plotnik-bytecode", + "plotnik-core", + "plotnik-langs", + "regex-automata", + "regex-syntax", + "rowan", + "serde", + "serde_json", + "tempfile", + "thiserror", +] + [[package]] name = "plotnik-core" version = "0.2.2" @@ -1784,22 +1818,29 @@ dependencies = [ name = "plotnik-lib" version = "0.2.2" dependencies = [ - "annotate-snippets", "arborium-tree-sitter", - "crc32fast", - "indexmap", "indoc", "insta", - "logos", - "memmap2", + "plotnik-bytecode", + "plotnik-compiler", "plotnik-core", "plotnik-langs", - "regex-automata", - "regex-syntax", - "rowan", + "plotnik-vm", "serde", "serde_json", "tempfile", +] + +[[package]] +name = "plotnik-vm" +version = "0.2.2" +dependencies = [ + "arborium-tree-sitter", + "insta", + "plotnik-bytecode", + "plotnik-core", + "regex-automata", + "serde", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 73eec191..a384225e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,14 @@ [workspace] resolver = "2" -members = ["crates/plotnik-cli", "crates/plotnik-lib", "crates/plotnik-langs", "crates/plotnik-core"] +members = [ + "crates/plotnik-bytecode", + "crates/plotnik-cli", + "crates/plotnik-compiler", + "crates/plotnik-core", + "crates/plotnik-langs", + "crates/plotnik-lib", + "crates/plotnik-vm", +] [workspace.package] version = "0.2.2" @@ -9,6 +17,9 @@ repository = "https://github.com/plotnik-lang/plotnik" edition = "2024" [workspace.dependencies] +plotnik-bytecode = { path = "crates/plotnik-bytecode", version = "0.2.2" } +plotnik-compiler = { path = "crates/plotnik-compiler", version = "0.2.2" } plotnik-core = { path = "crates/plotnik-core", version = "0.2.2" } plotnik-langs = { path = "crates/plotnik-langs", version = "0.2.2" } plotnik-lib = { path = "crates/plotnik-lib", version = "0.2.2" } +plotnik-vm = { path = "crates/plotnik-vm", version = "0.2.2" } diff --git a/crates/plotnik-bytecode/Cargo.toml b/crates/plotnik-bytecode/Cargo.toml new file mode 100644 index 00000000..471bdf7a --- /dev/null +++ b/crates/plotnik-bytecode/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "plotnik-bytecode" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +description = "Bytecode format and runtime types for Plotnik" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } + +[dependencies] +plotnik-core.workspace = true +regex-automata = { version = "0.4", features = ["dfa-search"] } +thiserror = "2.0.17" + +[dev-dependencies] +insta = { version = "=1.46.0", features = ["yaml"] } diff --git a/crates/plotnik-lib/src/bytecode/aligned_vec.rs b/crates/plotnik-bytecode/src/bytecode/aligned_vec.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/aligned_vec.rs rename to crates/plotnik-bytecode/src/bytecode/aligned_vec.rs diff --git a/crates/plotnik-lib/src/bytecode/aligned_vec_tests.rs b/crates/plotnik-bytecode/src/bytecode/aligned_vec_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/aligned_vec_tests.rs rename to crates/plotnik-bytecode/src/bytecode/aligned_vec_tests.rs diff --git a/crates/plotnik-lib/src/bytecode/constants.rs b/crates/plotnik-bytecode/src/bytecode/constants.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/constants.rs rename to crates/plotnik-bytecode/src/bytecode/constants.rs diff --git a/crates/plotnik-lib/src/bytecode/dump.rs b/crates/plotnik-bytecode/src/bytecode/dump.rs similarity index 97% rename from crates/plotnik-lib/src/bytecode/dump.rs rename to crates/plotnik-bytecode/src/bytecode/dump.rs index 7487a2b1..c14b671f 100644 --- a/crates/plotnik-lib/src/bytecode/dump.rs +++ b/crates/plotnik-bytecode/src/bytecode/dump.rs @@ -5,15 +5,14 @@ use std::collections::BTreeMap; use std::fmt::Write as _; -use crate::colors::Colors; - -use crate::parser::PredicateOp; +use plotnik_core::Colors; +use crate::predicate_op::PredicateOp; use super::format::{LineBuilder, Symbol, format_effect, nav_symbol, width_for_count}; use super::ids::TypeId; use super::instructions::StepId; -use super::ir::NodeTypeIR; use super::module::{Instruction, Module}; +use super::node_type_ir::NodeTypeIR; use super::nav::Nav; use super::type_meta::{TypeData, TypeKind}; use super::{Call, Match, Return, Trampoline}; @@ -78,13 +77,13 @@ impl DumpContext { let mut node_type_names = BTreeMap::new(); for i in 0..node_types.len() { let t = node_types.get(i); - node_type_names.insert(t.id(), strings.get(t.name()).to_string()); + node_type_names.insert(t.id, strings.get(t.name).to_string()); } let mut node_field_names = BTreeMap::new(); for i in 0..node_fields.len() { let f = node_fields.get(i); - node_field_names.insert(f.id(), strings.get(f.name()).to_string()); + node_field_names.insert(f.id, strings.get(f.name).to_string()); } // Collect all strings for unlinked mode lookups @@ -210,14 +209,14 @@ fn dump_types_defs(out: &mut String, module: &Module, ctx: &DumpContext) { TypeKind::Struct => { let fields: Vec<_> = types .members_of(&def) - .map(|m| strings.get(m.name()).to_string()) + .map(|m| strings.get(m.name).to_string()) .collect(); format!("{} ; {{ {} }}{}", c.dim, fields.join(", "), c.reset) } TypeKind::Enum => { let variants: Vec<_> = types .members_of(&def) - .map(|m| strings.get(m.name()).to_string()) + .map(|m| strings.get(m.name).to_string()) .collect(); format!("{} ; {}{}", c.dim, variants.join(" | "), c.reset) } @@ -293,8 +292,8 @@ fn format_type_name(type_id: TypeId, module: &Module, ctx: &DumpContext) -> Stri // Try to find a name in types.names for i in 0..types.names_count() { let entry = types.get_name(i); - if entry.type_id() == type_id { - return strings.get(entry.name()).to_string(); + if entry.type_id == type_id { + return strings.get(entry.name).to_string(); } } diff --git a/crates/plotnik-lib/src/bytecode/effects.rs b/crates/plotnik-bytecode/src/bytecode/effects.rs similarity index 89% rename from crates/plotnik-lib/src/bytecode/effects.rs rename to crates/plotnik-bytecode/src/bytecode/effects.rs index c4adad9c..a9400169 100644 --- a/crates/plotnik-lib/src/bytecode/effects.rs +++ b/crates/plotnik-bytecode/src/bytecode/effects.rs @@ -43,8 +43,8 @@ impl EffectOpcode { #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct EffectOp { - pub(crate) opcode: EffectOpcode, - pub(crate) payload: usize, + pub opcode: EffectOpcode, + pub payload: usize, } impl EffectOp { @@ -69,11 +69,4 @@ impl EffectOp { let raw = ((self.opcode as u16) << 10) | ((self.payload as u16) & 0x3FF); raw.to_le_bytes() } - - pub fn opcode(&self) -> EffectOpcode { - self.opcode - } - pub fn payload(&self) -> usize { - self.payload - } } diff --git a/crates/plotnik-lib/src/bytecode/effects_tests.rs b/crates/plotnik-bytecode/src/bytecode/effects_tests.rs similarity index 75% rename from crates/plotnik-lib/src/bytecode/effects_tests.rs rename to crates/plotnik-bytecode/src/bytecode/effects_tests.rs index dac1b114..10ea56ce 100644 --- a/crates/plotnik-lib/src/bytecode/effects_tests.rs +++ b/crates/plotnik-bytecode/src/bytecode/effects_tests.rs @@ -5,8 +5,8 @@ fn roundtrip_with_payload() { let op = EffectOp::new(EffectOpcode::Set, 42); let bytes = op.to_bytes(); let decoded = EffectOp::from_bytes(bytes); - assert_eq!(decoded.opcode(), EffectOpcode::Set); - assert_eq!(decoded.payload(), 42); + assert_eq!(decoded.opcode, EffectOpcode::Set); + assert_eq!(decoded.payload, 42); } #[test] @@ -14,8 +14,8 @@ fn roundtrip_no_payload() { let op = EffectOp::new(EffectOpcode::Node, 0); let bytes = op.to_bytes(); let decoded = EffectOp::from_bytes(bytes); - assert_eq!(decoded.opcode(), EffectOpcode::Node); - assert_eq!(decoded.payload(), 0); + assert_eq!(decoded.opcode, EffectOpcode::Node); + assert_eq!(decoded.payload, 0); } #[test] @@ -23,7 +23,7 @@ fn max_payload() { let op = EffectOp::new(EffectOpcode::Enum, 1023); let bytes = op.to_bytes(); let decoded = EffectOp::from_bytes(bytes); - assert_eq!(decoded.payload(), 1023); + assert_eq!(decoded.payload, 1023); } #[test] diff --git a/crates/plotnik-lib/src/bytecode/entrypoint.rs b/crates/plotnik-bytecode/src/bytecode/entrypoint.rs similarity index 90% rename from crates/plotnik-lib/src/bytecode/entrypoint.rs rename to crates/plotnik-bytecode/src/bytecode/entrypoint.rs index 0536de5d..a15b4315 100644 --- a/crates/plotnik-lib/src/bytecode/entrypoint.rs +++ b/crates/plotnik-bytecode/src/bytecode/entrypoint.rs @@ -8,12 +8,12 @@ use super::{StringId, TypeId}; #[repr(C)] pub struct Entrypoint { /// Definition name. - pub(crate) name: StringId, + pub name: StringId, /// Starting instruction address. - pub(crate) target: StepAddr, + pub target: StepAddr, /// Result type. - pub(crate) result_type: TypeId, - pub(crate) _pad: u16, + pub result_type: TypeId, + _pad: u16, } const _: () = assert!(std::mem::size_of::() == 8); diff --git a/crates/plotnik-lib/src/bytecode/entrypoint_tests.rs b/crates/plotnik-bytecode/src/bytecode/entrypoint_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/entrypoint_tests.rs rename to crates/plotnik-bytecode/src/bytecode/entrypoint_tests.rs diff --git a/crates/plotnik-lib/src/bytecode/format.rs b/crates/plotnik-bytecode/src/bytecode/format.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/format.rs rename to crates/plotnik-bytecode/src/bytecode/format.rs diff --git a/crates/plotnik-lib/src/bytecode/format_tests.rs b/crates/plotnik-bytecode/src/bytecode/format_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/format_tests.rs rename to crates/plotnik-bytecode/src/bytecode/format_tests.rs diff --git a/crates/plotnik-lib/src/bytecode/header.rs b/crates/plotnik-bytecode/src/bytecode/header.rs similarity index 98% rename from crates/plotnik-lib/src/bytecode/header.rs rename to crates/plotnik-bytecode/src/bytecode/header.rs index cbdf277e..139611bf 100644 --- a/crates/plotnik-lib/src/bytecode/header.rs +++ b/crates/plotnik-bytecode/src/bytecode/header.rs @@ -42,8 +42,8 @@ pub struct Header { pub entrypoints_count: u16, pub transitions_count: u16, - // Bytes 44-63: Reserved - pub(crate) _reserved: [u8; 20], + // Bytes 44-63: Reserved (public for cross-crate struct initialization) + pub _reserved: [u8; 20], } const _: () = assert!(std::mem::size_of::
() == 64); diff --git a/crates/plotnik-lib/src/bytecode/header_tests.rs b/crates/plotnik-bytecode/src/bytecode/header_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/header_tests.rs rename to crates/plotnik-bytecode/src/bytecode/header_tests.rs diff --git a/crates/plotnik-lib/src/bytecode/ids.rs b/crates/plotnik-bytecode/src/bytecode/ids.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/ids.rs rename to crates/plotnik-bytecode/src/bytecode/ids.rs diff --git a/crates/plotnik-lib/src/bytecode/instructions.rs b/crates/plotnik-bytecode/src/bytecode/instructions.rs similarity index 98% rename from crates/plotnik-lib/src/bytecode/instructions.rs rename to crates/plotnik-bytecode/src/bytecode/instructions.rs index 6545258f..009f058f 100644 --- a/crates/plotnik-lib/src/bytecode/instructions.rs +++ b/crates/plotnik-bytecode/src/bytecode/instructions.rs @@ -7,8 +7,8 @@ use std::num::NonZeroU16; use super::constants::{SECTION_ALIGN, STEP_SIZE}; use super::effects::EffectOp; -use super::ir::NodeTypeIR; use super::nav::Nav; +use super::node_type_ir::NodeTypeIR; /// Step address in bytecode (raw u16). /// @@ -338,15 +338,15 @@ impl<'a> Match<'a> { #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Call { /// Segment index (0-3). - pub(crate) segment: u8, + pub segment: u8, /// Navigation to apply before jumping to target. - pub(crate) nav: Nav, + pub nav: Nav, /// Field constraint (None = no constraint). - pub(crate) node_field: Option, + pub node_field: Option, /// Return address (current segment). - pub(crate) next: StepId, + pub next: StepId, /// Callee entry point (target segment from type_id). - pub(crate) target: StepId, + pub target: StepId, } impl Call { @@ -416,7 +416,7 @@ impl Call { #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Return { /// Segment index (0-3). - pub(crate) segment: u8, + pub segment: u8, } impl Return { @@ -468,9 +468,9 @@ impl Default for Return { #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Trampoline { /// Segment index (0-3). - pub(crate) segment: u8, + pub segment: u8, /// Return address (where to continue after entrypoint returns). - pub(crate) next: StepId, + pub next: StepId, } impl Trampoline { diff --git a/crates/plotnik-bytecode/src/bytecode/instructions_tests.rs b/crates/plotnik-bytecode/src/bytecode/instructions_tests.rs new file mode 100644 index 00000000..c0a70ef7 --- /dev/null +++ b/crates/plotnik-bytecode/src/bytecode/instructions_tests.rs @@ -0,0 +1,80 @@ +//! Tests for bytecode instructions. + +use std::num::NonZeroU16; + +use super::instructions::{Call, Opcode, Return, StepId, align_to_section, select_match_opcode}; +use super::nav::Nav; + +#[test] +fn opcode_sizes() { + assert_eq!(Opcode::Match8.size(), 8); + assert_eq!(Opcode::Match16.size(), 16); + assert_eq!(Opcode::Match24.size(), 24); + assert_eq!(Opcode::Match32.size(), 32); + assert_eq!(Opcode::Match48.size(), 48); + assert_eq!(Opcode::Match64.size(), 64); + assert_eq!(Opcode::Call.size(), 8); + assert_eq!(Opcode::Return.size(), 8); +} + +#[test] +fn opcode_step_counts() { + assert_eq!(Opcode::Match8.step_count(), 1); + assert_eq!(Opcode::Match16.step_count(), 2); + assert_eq!(Opcode::Match32.step_count(), 4); + assert_eq!(Opcode::Match64.step_count(), 8); +} + +#[test] +fn opcode_payload_slots() { + assert_eq!(Opcode::Match8.payload_slots(), 0); + assert_eq!(Opcode::Match16.payload_slots(), 4); + assert_eq!(Opcode::Match24.payload_slots(), 8); + assert_eq!(Opcode::Match32.payload_slots(), 12); + assert_eq!(Opcode::Match48.payload_slots(), 20); + assert_eq!(Opcode::Match64.payload_slots(), 28); +} + +#[test] +fn select_match_opcode_picks_smallest() { + assert_eq!(select_match_opcode(0), Some(Opcode::Match8)); + assert_eq!(select_match_opcode(1), Some(Opcode::Match16)); + assert_eq!(select_match_opcode(4), Some(Opcode::Match16)); + assert_eq!(select_match_opcode(5), Some(Opcode::Match24)); + assert_eq!(select_match_opcode(12), Some(Opcode::Match32)); + assert_eq!(select_match_opcode(20), Some(Opcode::Match48)); + assert_eq!(select_match_opcode(28), Some(Opcode::Match64)); + assert_eq!(select_match_opcode(29), None); +} + +#[test] +fn align_to_section_works() { + assert_eq!(align_to_section(0), 0); + assert_eq!(align_to_section(1), 64); + assert_eq!(align_to_section(64), 64); + assert_eq!(align_to_section(65), 128); + assert_eq!(align_to_section(100), 128); +} + +#[test] +fn call_roundtrip() { + let c = Call::new( + Nav::Down, + NonZeroU16::new(42), + StepId::new(100), + StepId::new(500), + ); + + let bytes = c.to_bytes(); + let decoded = Call::from_bytes(bytes); + assert_eq!(decoded, c); +} + +#[test] +fn return_roundtrip() { + let r = Return::new(); + + let bytes = r.to_bytes(); + let decoded = Return::from_bytes(bytes); + assert_eq!(decoded, r); +} diff --git a/crates/plotnik-lib/src/bytecode/mod.rs b/crates/plotnik-bytecode/src/bytecode/mod.rs similarity index 89% rename from crates/plotnik-lib/src/bytecode/mod.rs rename to crates/plotnik-bytecode/src/bytecode/mod.rs index 430714c9..1f972dd9 100644 --- a/crates/plotnik-lib/src/bytecode/mod.rs +++ b/crates/plotnik-bytecode/src/bytecode/mod.rs @@ -11,9 +11,9 @@ mod format; mod header; mod ids; mod instructions; -mod ir; mod module; mod nav; +mod node_type_ir; mod sections; mod type_meta; @@ -54,10 +54,7 @@ pub use format::{ width_for_count, }; -pub use ir::{ - CallIR, EffectIR, InstructionIR, Label, LayoutResult, MatchIR, MemberRef, NodeTypeIR, - PredicateIR, PredicateValueIR, ReturnIR, TrampolineIR, -}; +pub use node_type_ir::NodeTypeIR; #[cfg(test)] mod aligned_vec_tests; @@ -72,12 +69,12 @@ mod header_tests; #[cfg(test)] mod instructions_tests; #[cfg(test)] -mod ir_tests; -#[cfg(test)] mod module_tests; #[cfg(test)] mod nav_tests; #[cfg(test)] +mod node_type_ir_tests; +#[cfg(test)] mod sections_tests; #[cfg(test)] mod type_meta_tests; diff --git a/crates/plotnik-lib/src/bytecode/module.rs b/crates/plotnik-bytecode/src/bytecode/module.rs similarity index 99% rename from crates/plotnik-lib/src/bytecode/module.rs rename to crates/plotnik-bytecode/src/bytecode/module.rs index 5ebea12b..554fb8db 100644 --- a/crates/plotnik-lib/src/bytecode/module.rs +++ b/crates/plotnik-bytecode/src/bytecode/module.rs @@ -448,7 +448,7 @@ impl<'a> TriviaView<'a> { /// Check if a node type is trivia. pub fn contains(&self, node_type: u16) -> bool { - (0..self.count).any(|i| self.get(i).node_type() == node_type) + (0..self.count).any(|i| self.get(i).node_type == node_type) } } diff --git a/crates/plotnik-bytecode/src/bytecode/module_tests.rs b/crates/plotnik-bytecode/src/bytecode/module_tests.rs new file mode 100644 index 00000000..84b31009 --- /dev/null +++ b/crates/plotnik-bytecode/src/bytecode/module_tests.rs @@ -0,0 +1,42 @@ +//! Tests for the bytecode module. + +use super::module::{ByteStorage, ModuleError}; +use super::AlignedVec; + +#[test] +fn byte_storage_copy_from_slice() { + let data = [1u8, 2, 3, 4, 5]; + let storage = ByteStorage::copy_from_slice(&data); + + assert_eq!(&*storage, &data[..]); + assert_eq!(storage.len(), 5); + assert_eq!(storage[2], 3); +} + +#[test] +fn byte_storage_from_aligned() { + let vec = AlignedVec::copy_from_slice(&[1, 2, 3, 4, 5]); + let storage = ByteStorage::from_aligned(vec); + + assert_eq!(&*storage, &[1, 2, 3, 4, 5]); + assert_eq!(storage.len(), 5); +} + +#[test] +fn module_error_display() { + let err = ModuleError::InvalidMagic; + assert_eq!(err.to_string(), "invalid magic: expected PTKQ"); + + let err = ModuleError::UnsupportedVersion(99); + assert!(err.to_string().contains("99")); + + let err = ModuleError::FileTooSmall(32); + assert!(err.to_string().contains("32")); + + let err = ModuleError::SizeMismatch { + header: 100, + actual: 50, + }; + assert!(err.to_string().contains("100")); + assert!(err.to_string().contains("50")); +} diff --git a/crates/plotnik-lib/src/bytecode/nav.rs b/crates/plotnik-bytecode/src/bytecode/nav.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/nav.rs rename to crates/plotnik-bytecode/src/bytecode/nav.rs diff --git a/crates/plotnik-lib/src/bytecode/nav_tests.rs b/crates/plotnik-bytecode/src/bytecode/nav_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/nav_tests.rs rename to crates/plotnik-bytecode/src/bytecode/nav_tests.rs diff --git a/crates/plotnik-bytecode/src/bytecode/node_type_ir.rs b/crates/plotnik-bytecode/src/bytecode/node_type_ir.rs new file mode 100644 index 00000000..306048d6 --- /dev/null +++ b/crates/plotnik-bytecode/src/bytecode/node_type_ir.rs @@ -0,0 +1,78 @@ +//! Node type constraint for Match instructions. +//! +//! Extracted from ir.rs for use by runtime instruction decoding. + +use std::num::NonZeroU16; + +/// Node type constraint for Match instructions. +/// +/// Distinguishes between named nodes (`(identifier)`), anonymous nodes (`"text"`), +/// and wildcards (`_`, `(_)`). Encoded in bytecode header byte bits 5-4. +/// +/// | `node_kind` | Value | Meaning | `node_type=0` | `node_type>0` | +/// | ----------- | ----- | ------------ | ------------------- | ----------------- | +/// | `00` | Any | `_` pattern | No check | (invalid) | +/// | `01` | Named | `(_)`/`(t)` | Check `is_named()` | Check `kind_id()` | +/// | `10` | Anon | `"text"` | Check `!is_named()` | Check `kind_id()` | +/// | `11` | - | Reserved | Error | Error | +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] +pub enum NodeTypeIR { + /// Any node (`_` pattern) - no type check performed. + #[default] + Any, + /// Named node constraint (`(_)` or `(identifier)`). + /// - `None` = any named node (check `is_named()`) + /// - `Some(id)` = specific named type (check `kind_id()`) + Named(Option), + /// Anonymous node constraint (`"text"` literals). + /// - `None` = any anonymous node (check `!is_named()`) + /// - `Some(id)` = specific anonymous type (check `kind_id()`) + Anonymous(Option), +} + +impl NodeTypeIR { + /// Encode to bytecode: returns (node_kind bits, node_type value). + /// + /// `node_kind` is 2 bits for header byte bits 5-4. + /// `node_type` is u16 for bytes 2-3. + pub fn to_bytes(self) -> (u8, u16) { + match self { + Self::Any => (0b00, 0), + Self::Named(opt) => (0b01, opt.map(|n| n.get()).unwrap_or(0)), + Self::Anonymous(opt) => (0b10, opt.map(|n| n.get()).unwrap_or(0)), + } + } + + /// Decode from bytecode: node_kind bits (2 bits) and node_type value (u16). + pub fn from_bytes(node_kind: u8, node_type: u16) -> Self { + match node_kind { + 0b00 => Self::Any, + 0b01 => Self::Named(NonZeroU16::new(node_type)), + 0b10 => Self::Anonymous(NonZeroU16::new(node_type)), + _ => panic!("invalid node_kind: {node_kind}"), + } + } + + /// Check if this represents a specific type ID (not a wildcard). + pub fn type_id(&self) -> Option { + match self { + Self::Any => None, + Self::Named(opt) | Self::Anonymous(opt) => *opt, + } + } + + /// Check if this is the Any wildcard. + pub fn is_any(&self) -> bool { + matches!(self, Self::Any) + } + + /// Check if this is a Named constraint (wildcard or specific). + pub fn is_named(&self) -> bool { + matches!(self, Self::Named(_)) + } + + /// Check if this is an Anonymous constraint (wildcard or specific). + pub fn is_anonymous(&self) -> bool { + matches!(self, Self::Anonymous(_)) + } +} diff --git a/crates/plotnik-bytecode/src/bytecode/node_type_ir_tests.rs b/crates/plotnik-bytecode/src/bytecode/node_type_ir_tests.rs new file mode 100644 index 00000000..c281c4e3 --- /dev/null +++ b/crates/plotnik-bytecode/src/bytecode/node_type_ir_tests.rs @@ -0,0 +1,73 @@ +use std::num::NonZeroU16; + +use super::node_type_ir::NodeTypeIR; + +#[test] +fn roundtrip_any() { + let orig = NodeTypeIR::Any; + let (kind, type_val) = orig.to_bytes(); + let decoded = NodeTypeIR::from_bytes(kind, type_val); + assert_eq!(decoded, orig); +} + +#[test] +fn roundtrip_named_wildcard() { + let orig = NodeTypeIR::Named(None); + let (kind, type_val) = orig.to_bytes(); + let decoded = NodeTypeIR::from_bytes(kind, type_val); + assert_eq!(decoded, orig); +} + +#[test] +fn roundtrip_named_specific() { + let orig = NodeTypeIR::Named(NonZeroU16::new(42)); + let (kind, type_val) = orig.to_bytes(); + let decoded = NodeTypeIR::from_bytes(kind, type_val); + assert_eq!(decoded, orig); +} + +#[test] +fn roundtrip_anonymous_wildcard() { + let orig = NodeTypeIR::Anonymous(None); + let (kind, type_val) = orig.to_bytes(); + let decoded = NodeTypeIR::from_bytes(kind, type_val); + assert_eq!(decoded, orig); +} + +#[test] +fn roundtrip_anonymous_specific() { + let orig = NodeTypeIR::Anonymous(NonZeroU16::new(100)); + let (kind, type_val) = orig.to_bytes(); + let decoded = NodeTypeIR::from_bytes(kind, type_val); + assert_eq!(decoded, orig); +} + +#[test] +fn type_id_extraction() { + assert_eq!(NodeTypeIR::Any.type_id(), None); + assert_eq!(NodeTypeIR::Named(None).type_id(), None); + assert_eq!( + NodeTypeIR::Named(NonZeroU16::new(5)).type_id(), + NonZeroU16::new(5) + ); + assert_eq!(NodeTypeIR::Anonymous(None).type_id(), None); + assert_eq!( + NodeTypeIR::Anonymous(NonZeroU16::new(7)).type_id(), + NonZeroU16::new(7) + ); +} + +#[test] +fn kind_checks() { + assert!(NodeTypeIR::Any.is_any()); + assert!(!NodeTypeIR::Any.is_named()); + assert!(!NodeTypeIR::Any.is_anonymous()); + + assert!(!NodeTypeIR::Named(None).is_any()); + assert!(NodeTypeIR::Named(None).is_named()); + assert!(!NodeTypeIR::Named(None).is_anonymous()); + + assert!(!NodeTypeIR::Anonymous(None).is_any()); + assert!(!NodeTypeIR::Anonymous(None).is_named()); + assert!(NodeTypeIR::Anonymous(None).is_anonymous()); +} diff --git a/crates/plotnik-lib/src/bytecode/sections.rs b/crates/plotnik-bytecode/src/bytecode/sections.rs similarity index 77% rename from crates/plotnik-lib/src/bytecode/sections.rs rename to crates/plotnik-bytecode/src/bytecode/sections.rs index 0d950e9e..be9187f8 100644 --- a/crates/plotnik-lib/src/bytecode/sections.rs +++ b/crates/plotnik-bytecode/src/bytecode/sections.rs @@ -27,9 +27,9 @@ impl Slice { #[repr(C)] pub struct NodeSymbol { /// Tree-sitter node type ID - pub(crate) id: u16, + pub id: u16, /// StringId for the node kind name - pub(crate) name: StringId, + pub name: StringId, } impl NodeSymbol { @@ -37,13 +37,6 @@ impl NodeSymbol { pub fn new(id: u16, name: StringId) -> Self { Self { id, name } } - - pub fn id(&self) -> u16 { - self.id - } - pub fn name(&self) -> StringId { - self.name - } } /// Maps tree-sitter NodeFieldId to its string name. @@ -51,9 +44,9 @@ impl NodeSymbol { #[repr(C)] pub struct FieldSymbol { /// Tree-sitter field ID - pub(crate) id: u16, + pub id: u16, /// StringId for the field name - pub(crate) name: StringId, + pub name: StringId, } impl FieldSymbol { @@ -61,20 +54,13 @@ impl FieldSymbol { pub fn new(id: u16, name: StringId) -> Self { Self { id, name } } - - pub fn id(&self) -> u16 { - self.id - } - pub fn name(&self) -> StringId { - self.name - } } /// A node type ID that counts as trivia (whitespace, comments). #[derive(Clone, Copy, Debug)] #[repr(C)] pub struct TriviaEntry { - pub(crate) node_type: u16, + pub node_type: u16, } impl TriviaEntry { @@ -82,8 +68,4 @@ impl TriviaEntry { pub fn new(node_type: u16) -> Self { Self { node_type } } - - pub fn node_type(&self) -> u16 { - self.node_type - } } diff --git a/crates/plotnik-lib/src/bytecode/sections_tests.rs b/crates/plotnik-bytecode/src/bytecode/sections_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/sections_tests.rs rename to crates/plotnik-bytecode/src/bytecode/sections_tests.rs diff --git a/crates/plotnik-lib/src/bytecode/type_meta.rs b/crates/plotnik-bytecode/src/bytecode/type_meta.rs similarity index 94% rename from crates/plotnik-lib/src/bytecode/type_meta.rs rename to crates/plotnik-bytecode/src/bytecode/type_meta.rs index 81aa893f..4ca82de0 100644 --- a/crates/plotnik-lib/src/bytecode/type_meta.rs +++ b/crates/plotnik-bytecode/src/bytecode/type_meta.rs @@ -166,9 +166,9 @@ impl TypeDef { #[repr(C)] pub struct TypeName { /// StringId of the type name. - pub(crate) name: StringId, + pub name: StringId, /// TypeId this name refers to. - pub(crate) type_id: TypeId, + pub type_id: TypeId, } const _: () = assert!(std::mem::size_of::() == 4); @@ -186,13 +186,6 @@ impl TypeName { bytes[2..4].copy_from_slice(&self.type_id.0.to_le_bytes()); bytes } - - pub fn name(&self) -> StringId { - self.name - } - pub fn type_id(&self) -> TypeId { - self.type_id - } } /// Field or variant entry (4 bytes). @@ -200,9 +193,9 @@ impl TypeName { #[repr(C)] pub struct TypeMember { /// Field/variant name. - pub(crate) name: StringId, + pub name: StringId, /// Type of this field/variant. - pub(crate) type_id: TypeId, + pub type_id: TypeId, } const _: () = assert!(std::mem::size_of::() == 4); @@ -220,11 +213,4 @@ impl TypeMember { bytes[2..4].copy_from_slice(&self.type_id.0.to_le_bytes()); bytes } - - pub fn name(&self) -> StringId { - self.name - } - pub fn type_id(&self) -> TypeId { - self.type_id - } } diff --git a/crates/plotnik-lib/src/bytecode/type_meta_tests.rs b/crates/plotnik-bytecode/src/bytecode/type_meta_tests.rs similarity index 100% rename from crates/plotnik-lib/src/bytecode/type_meta_tests.rs rename to crates/plotnik-bytecode/src/bytecode/type_meta_tests.rs diff --git a/crates/plotnik-bytecode/src/dfa.rs b/crates/plotnik-bytecode/src/dfa.rs new file mode 100644 index 00000000..146f153c --- /dev/null +++ b/crates/plotnik-bytecode/src/dfa.rs @@ -0,0 +1,17 @@ +//! DFA deserialization for regex predicates. +//! +//! Extracted from emit for use by the runtime. + +use regex_automata::dfa::sparse::DFA; + +/// Deserialize a sparse DFA from bytecode. +/// +/// # Safety +/// The bytes must have been produced by `DFA::to_bytes_little_endian()`. +pub fn deserialize_dfa(bytes: &[u8]) -> Result, String> { + // SAFETY: We only serialize DFAs we built, and the format is stable + // within the same regex-automata version. + DFA::from_bytes(bytes) + .map(|(dfa, _)| dfa) + .map_err(|e| e.to_string()) +} diff --git a/crates/plotnik-bytecode/src/lib.rs b/crates/plotnik-bytecode/src/lib.rs new file mode 100644 index 00000000..116a85ba --- /dev/null +++ b/crates/plotnik-bytecode/src/lib.rs @@ -0,0 +1,28 @@ +//! Bytecode format and runtime types for Plotnik. +//! +//! This crate contains: +//! - Bytecode format definitions (Module, Header, instructions) +//! - Type system primitives (TypeKind, Arity, QuantifierKind) +//! - Runtime helpers (Colors, PredicateOp, DFA deserialization) + +#![allow(clippy::comparison_chain)] + +pub mod bytecode; +pub mod dfa; +pub mod predicate_op; +pub mod type_system; + +// Re-export commonly used items at crate root +pub use bytecode::{ + AlignedVec, ByteStorage, Call, EffectOp, EffectOpcode, Entrypoint, EntrypointsView, + FieldSymbol, Header, Instruction, LineBuilder, MAGIC, MAX_MATCH_PAYLOAD_SLOTS, + MAX_PRE_EFFECTS, Match, Module, ModuleError, Nav, NodeSymbol, NodeTypeIR, Opcode, RegexView, + Return, SECTION_ALIGN, STEP_SIZE, SectionOffsets, Slice, StepAddr, StepId, StringId, + StringsView, Symbol, SymbolsView, Trampoline, TriviaEntry, TriviaView, TypeData, TypeDef, + TypeId, TypeKind, TypeMember, TypeName, TypesView, VERSION, align_to_section, cols, dump, + format_effect, nav_symbol, select_match_opcode, superscript, trace, truncate_text, + width_for_count, +}; +pub use dfa::deserialize_dfa; +pub use predicate_op::PredicateOp; +pub use type_system::{Arity, PrimitiveType, QuantifierKind}; diff --git a/crates/plotnik-bytecode/src/predicate_op.rs b/crates/plotnik-bytecode/src/predicate_op.rs new file mode 100644 index 00000000..0853daa5 --- /dev/null +++ b/crates/plotnik-bytecode/src/predicate_op.rs @@ -0,0 +1,112 @@ +//! Predicate operators for bytecode. +//! +//! Extracted from parser for use by both compiler and runtime. +//! The runtime needs to decode predicate operators from bytecode. + +/// Predicate operator for node text filtering. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum PredicateOp { + /// `==` - equals + Eq, + /// `!=` - not equals + Ne, + /// `^=` - starts with + StartsWith, + /// `$=` - ends with + EndsWith, + /// `*=` - contains + Contains, + /// `=~` - regex match + RegexMatch, + /// `!~` - regex no match + RegexNoMatch, +} + +impl PredicateOp { + /// Decode from bytecode representation. + pub fn from_byte(b: u8) -> Self { + match b { + 0 => Self::Eq, + 1 => Self::Ne, + 2 => Self::StartsWith, + 3 => Self::EndsWith, + 4 => Self::Contains, + 5 => Self::RegexMatch, + 6 => Self::RegexNoMatch, + _ => panic!("invalid predicate op byte: {b}"), + } + } + + /// Encode for bytecode. + pub fn to_byte(self) -> u8 { + match self { + Self::Eq => 0, + Self::Ne => 1, + Self::StartsWith => 2, + Self::EndsWith => 3, + Self::Contains => 4, + Self::RegexMatch => 5, + Self::RegexNoMatch => 6, + } + } + + /// Operator as display string. + pub fn as_str(self) -> &'static str { + match self { + Self::Eq => "==", + Self::Ne => "!=", + Self::StartsWith => "^=", + Self::EndsWith => "$=", + Self::Contains => "*=", + Self::RegexMatch => "=~", + Self::RegexNoMatch => "!~", + } + } + + /// Check if this is a regex operator. + pub fn is_regex_op(&self) -> bool { + matches!(self, Self::RegexMatch | Self::RegexNoMatch) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn byte_roundtrip() { + for op in [ + PredicateOp::Eq, + PredicateOp::Ne, + PredicateOp::StartsWith, + PredicateOp::EndsWith, + PredicateOp::Contains, + PredicateOp::RegexMatch, + PredicateOp::RegexNoMatch, + ] { + assert_eq!(PredicateOp::from_byte(op.to_byte()), op); + } + } + + #[test] + fn as_str() { + assert_eq!(PredicateOp::Eq.as_str(), "=="); + assert_eq!(PredicateOp::Ne.as_str(), "!="); + assert_eq!(PredicateOp::StartsWith.as_str(), "^="); + assert_eq!(PredicateOp::EndsWith.as_str(), "$="); + assert_eq!(PredicateOp::Contains.as_str(), "*="); + assert_eq!(PredicateOp::RegexMatch.as_str(), "=~"); + assert_eq!(PredicateOp::RegexNoMatch.as_str(), "!~"); + } + + #[test] + fn is_regex_op() { + assert!(!PredicateOp::Eq.is_regex_op()); + assert!(!PredicateOp::Ne.is_regex_op()); + assert!(!PredicateOp::StartsWith.is_regex_op()); + assert!(!PredicateOp::EndsWith.is_regex_op()); + assert!(!PredicateOp::Contains.is_regex_op()); + assert!(PredicateOp::RegexMatch.is_regex_op()); + assert!(PredicateOp::RegexNoMatch.is_regex_op()); + } +} diff --git a/crates/plotnik-lib/src/type_system/arity.rs b/crates/plotnik-bytecode/src/type_system/arity.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/arity.rs rename to crates/plotnik-bytecode/src/type_system/arity.rs diff --git a/crates/plotnik-lib/src/type_system/arity_tests.rs b/crates/plotnik-bytecode/src/type_system/arity_tests.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/arity_tests.rs rename to crates/plotnik-bytecode/src/type_system/arity_tests.rs diff --git a/crates/plotnik-lib/src/type_system/kind.rs b/crates/plotnik-bytecode/src/type_system/kind.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/kind.rs rename to crates/plotnik-bytecode/src/type_system/kind.rs diff --git a/crates/plotnik-lib/src/type_system/kind_tests.rs b/crates/plotnik-bytecode/src/type_system/kind_tests.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/kind_tests.rs rename to crates/plotnik-bytecode/src/type_system/kind_tests.rs diff --git a/crates/plotnik-lib/src/type_system/mod.rs b/crates/plotnik-bytecode/src/type_system/mod.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/mod.rs rename to crates/plotnik-bytecode/src/type_system/mod.rs diff --git a/crates/plotnik-lib/src/type_system/primitives.rs b/crates/plotnik-bytecode/src/type_system/primitives.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/primitives.rs rename to crates/plotnik-bytecode/src/type_system/primitives.rs diff --git a/crates/plotnik-lib/src/type_system/primitives_tests.rs b/crates/plotnik-bytecode/src/type_system/primitives_tests.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/primitives_tests.rs rename to crates/plotnik-bytecode/src/type_system/primitives_tests.rs diff --git a/crates/plotnik-lib/src/type_system/quantifier.rs b/crates/plotnik-bytecode/src/type_system/quantifier.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/quantifier.rs rename to crates/plotnik-bytecode/src/type_system/quantifier.rs diff --git a/crates/plotnik-lib/src/type_system/quantifier_tests.rs b/crates/plotnik-bytecode/src/type_system/quantifier_tests.rs similarity index 100% rename from crates/plotnik-lib/src/type_system/quantifier_tests.rs rename to crates/plotnik-bytecode/src/type_system/quantifier_tests.rs diff --git a/crates/plotnik-cli/src/commands/run_common.rs b/crates/plotnik-cli/src/commands/run_common.rs index ee386321..50b7ae03 100644 --- a/crates/plotnik-cli/src/commands/run_common.rs +++ b/crates/plotnik-cli/src/commands/run_common.rs @@ -122,7 +122,7 @@ pub fn validate( pub fn build_trivia_types(module: &Module) -> Vec { let trivia_view = module.trivia(); (0..trivia_view.len()) - .map(|i| trivia_view.get(i).node_type()) + .map(|i| trivia_view.get(i).node_type) .collect() } diff --git a/crates/plotnik-compiler/Cargo.toml b/crates/plotnik-compiler/Cargo.toml new file mode 100644 index 00000000..7d771eae --- /dev/null +++ b/crates/plotnik-compiler/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "plotnik-compiler" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +description = "Compiler for Plotnik query language (parser, analyzer, bytecode emitter)" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } + +[dependencies] +plotnik-bytecode.workspace = true +plotnik-core.workspace = true +plotnik-langs = { workspace = true, optional = true } +annotate-snippets = "0.12.9" +logos = "0.16.0" +indexmap = "2" +rowan = "0.16.1" +serde = { version = "1.0", features = ["derive"] } +thiserror = "2.0.17" +arborium-tree-sitter = "2.10.0" +crc32fast = "1.4" +memmap2 = "0.9" +regex-automata = { version = "0.4", features = ["dfa-build", "dfa-search"] } +regex-syntax = "0.8" + +[features] +default = ["plotnik-langs"] + +[dev-dependencies] +insta = { version = "=1.46.0", features = ["yaml"] } +indoc = "=2.0.7" +serde_json = "=1.0.149" +tempfile = "=3.24.0" diff --git a/crates/plotnik-lib/src/analyze/dependencies.rs b/crates/plotnik-compiler/src/analyze/dependencies.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/dependencies.rs rename to crates/plotnik-compiler/src/analyze/dependencies.rs diff --git a/crates/plotnik-lib/src/analyze/dependencies_tests.rs b/crates/plotnik-compiler/src/analyze/dependencies_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/dependencies_tests.rs rename to crates/plotnik-compiler/src/analyze/dependencies_tests.rs diff --git a/crates/plotnik-lib/src/analyze/invariants.rs b/crates/plotnik-compiler/src/analyze/invariants.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/invariants.rs rename to crates/plotnik-compiler/src/analyze/invariants.rs diff --git a/crates/plotnik-lib/src/analyze/link.rs b/crates/plotnik-compiler/src/analyze/link.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/link.rs rename to crates/plotnik-compiler/src/analyze/link.rs diff --git a/crates/plotnik-lib/src/analyze/link_tests.rs b/crates/plotnik-compiler/src/analyze/link_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/link_tests.rs rename to crates/plotnik-compiler/src/analyze/link_tests.rs diff --git a/crates/plotnik-lib/src/analyze/mod.rs b/crates/plotnik-compiler/src/analyze/mod.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/mod.rs rename to crates/plotnik-compiler/src/analyze/mod.rs diff --git a/crates/plotnik-lib/src/analyze/recursion.rs b/crates/plotnik-compiler/src/analyze/recursion.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/recursion.rs rename to crates/plotnik-compiler/src/analyze/recursion.rs diff --git a/crates/plotnik-lib/src/analyze/refs.rs b/crates/plotnik-compiler/src/analyze/refs.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/refs.rs rename to crates/plotnik-compiler/src/analyze/refs.rs diff --git a/crates/plotnik-lib/src/analyze/refs_tests.rs b/crates/plotnik-compiler/src/analyze/refs_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/refs_tests.rs rename to crates/plotnik-compiler/src/analyze/refs_tests.rs diff --git a/crates/plotnik-lib/src/analyze/symbol_table.rs b/crates/plotnik-compiler/src/analyze/symbol_table.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/symbol_table.rs rename to crates/plotnik-compiler/src/analyze/symbol_table.rs diff --git a/crates/plotnik-lib/src/analyze/symbol_table_tests.rs b/crates/plotnik-compiler/src/analyze/symbol_table_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/symbol_table_tests.rs rename to crates/plotnik-compiler/src/analyze/symbol_table_tests.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/context.rs b/crates/plotnik-compiler/src/analyze/type_check/context.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/context.rs rename to crates/plotnik-compiler/src/analyze/type_check/context.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/context_tests.rs b/crates/plotnik-compiler/src/analyze/type_check/context_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/context_tests.rs rename to crates/plotnik-compiler/src/analyze/type_check/context_tests.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/infer.rs b/crates/plotnik-compiler/src/analyze/type_check/infer.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/infer.rs rename to crates/plotnik-compiler/src/analyze/type_check/infer.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/mod.rs b/crates/plotnik-compiler/src/analyze/type_check/mod.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/mod.rs rename to crates/plotnik-compiler/src/analyze/type_check/mod.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/symbol.rs b/crates/plotnik-compiler/src/analyze/type_check/symbol.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/symbol.rs rename to crates/plotnik-compiler/src/analyze/type_check/symbol.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/symbol_tests.rs b/crates/plotnik-compiler/src/analyze/type_check/symbol_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/symbol_tests.rs rename to crates/plotnik-compiler/src/analyze/type_check/symbol_tests.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/type_check_tests.rs b/crates/plotnik-compiler/src/analyze/type_check/type_check_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/type_check_tests.rs rename to crates/plotnik-compiler/src/analyze/type_check/type_check_tests.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/types.rs b/crates/plotnik-compiler/src/analyze/type_check/types.rs similarity index 96% rename from crates/plotnik-lib/src/analyze/type_check/types.rs rename to crates/plotnik-compiler/src/analyze/type_check/types.rs index 45938248..5a6b30b6 100644 --- a/crates/plotnik-lib/src/analyze/type_check/types.rs +++ b/crates/plotnik-compiler/src/analyze/type_check/types.rs @@ -9,8 +9,8 @@ use std::collections::BTreeMap; use super::symbol::{DefId, Symbol}; // Re-export shared type system components -pub use crate::type_system::{Arity, QuantifierKind}; -use crate::type_system::{PrimitiveType, TYPE_STRING as PRIM_TYPE_STRING}; +pub use plotnik_bytecode::type_system::{Arity, QuantifierKind}; +use plotnik_bytecode::type_system::{PrimitiveType, TYPE_STRING as PRIM_TYPE_STRING}; /// Interned type identifier. /// diff --git a/crates/plotnik-lib/src/analyze/type_check/unify.rs b/crates/plotnik-compiler/src/analyze/type_check/unify.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/unify.rs rename to crates/plotnik-compiler/src/analyze/type_check/unify.rs diff --git a/crates/plotnik-lib/src/analyze/type_check/unify_tests.rs b/crates/plotnik-compiler/src/analyze/type_check/unify_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/type_check/unify_tests.rs rename to crates/plotnik-compiler/src/analyze/type_check/unify_tests.rs diff --git a/crates/plotnik-lib/src/analyze/utils.rs b/crates/plotnik-compiler/src/analyze/utils.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/utils.rs rename to crates/plotnik-compiler/src/analyze/utils.rs diff --git a/crates/plotnik-lib/src/analyze/validation/alt_kinds.rs b/crates/plotnik-compiler/src/analyze/validation/alt_kinds.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/alt_kinds.rs rename to crates/plotnik-compiler/src/analyze/validation/alt_kinds.rs diff --git a/crates/plotnik-lib/src/analyze/validation/alt_kinds_tests.rs b/crates/plotnik-compiler/src/analyze/validation/alt_kinds_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/alt_kinds_tests.rs rename to crates/plotnik-compiler/src/analyze/validation/alt_kinds_tests.rs diff --git a/crates/plotnik-lib/src/analyze/validation/anchors.rs b/crates/plotnik-compiler/src/analyze/validation/anchors.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/anchors.rs rename to crates/plotnik-compiler/src/analyze/validation/anchors.rs diff --git a/crates/plotnik-lib/src/analyze/validation/anchors_tests.rs b/crates/plotnik-compiler/src/analyze/validation/anchors_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/anchors_tests.rs rename to crates/plotnik-compiler/src/analyze/validation/anchors_tests.rs diff --git a/crates/plotnik-lib/src/analyze/validation/empty_constructs.rs b/crates/plotnik-compiler/src/analyze/validation/empty_constructs.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/empty_constructs.rs rename to crates/plotnik-compiler/src/analyze/validation/empty_constructs.rs diff --git a/crates/plotnik-lib/src/analyze/validation/empty_constructs_tests.rs b/crates/plotnik-compiler/src/analyze/validation/empty_constructs_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/empty_constructs_tests.rs rename to crates/plotnik-compiler/src/analyze/validation/empty_constructs_tests.rs diff --git a/crates/plotnik-lib/src/analyze/validation/mod.rs b/crates/plotnik-compiler/src/analyze/validation/mod.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/mod.rs rename to crates/plotnik-compiler/src/analyze/validation/mod.rs diff --git a/crates/plotnik-lib/src/analyze/validation/predicates.rs b/crates/plotnik-compiler/src/analyze/validation/predicates.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/predicates.rs rename to crates/plotnik-compiler/src/analyze/validation/predicates.rs diff --git a/crates/plotnik-lib/src/analyze/validation/predicates_tests.rs b/crates/plotnik-compiler/src/analyze/validation/predicates_tests.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/validation/predicates_tests.rs rename to crates/plotnik-compiler/src/analyze/validation/predicates_tests.rs diff --git a/crates/plotnik-lib/src/analyze/visitor.rs b/crates/plotnik-compiler/src/analyze/visitor.rs similarity index 100% rename from crates/plotnik-lib/src/analyze/visitor.rs rename to crates/plotnik-compiler/src/analyze/visitor.rs diff --git a/crates/plotnik-lib/src/bytecode/ir.rs b/crates/plotnik-compiler/src/bytecode/ir.rs similarity index 97% rename from crates/plotnik-lib/src/bytecode/ir.rs rename to crates/plotnik-compiler/src/bytecode/ir.rs index 035a3061..aedae9ce 100644 --- a/crates/plotnik-lib/src/bytecode/ir.rs +++ b/crates/plotnik-compiler/src/bytecode/ir.rs @@ -7,13 +7,11 @@ use std::collections::BTreeMap; use std::num::NonZeroU16; -use super::effects::{EffectOp, EffectOpcode}; -use super::instructions::{ - Call, Opcode, Return, StepAddr, StepId, Trampoline, select_match_opcode, +use plotnik_bytecode::{ + Call, EffectOp, EffectOpcode, Nav, Opcode, PredicateOp, Return, StepAddr, StepId, Trampoline, + select_match_opcode, }; -use super::nav::Nav; use crate::analyze::type_check::TypeId; -use crate::parser::PredicateOp; /// Node type constraint for Match instructions. /// @@ -295,9 +293,9 @@ impl EffectIR { #[derive(Clone, Debug)] pub enum PredicateValueIR { /// String comparison value. - String(crate::bytecode::StringId), + String(plotnik_bytecode::StringId), /// Regex pattern (StringId for pattern, compiled to DFA during emit). - Regex(crate::bytecode::StringId), + Regex(plotnik_bytecode::StringId), } /// Predicate IR for node text filtering. @@ -312,7 +310,7 @@ pub struct PredicateIR { impl PredicateIR { /// Create a string predicate (==, !=, ^=, $=, *=). - pub fn string(op: PredicateOp, value: crate::bytecode::StringId) -> Self { + pub fn string(op: PredicateOp, value: plotnik_bytecode::StringId) -> Self { Self { op, value: PredicateValueIR::String(value), @@ -320,7 +318,7 @@ impl PredicateIR { } /// Create a regex predicate (=~, !~). - pub fn regex(op: PredicateOp, pattern_id: crate::bytecode::StringId) -> Self { + pub fn regex(op: PredicateOp, pattern_id: plotnik_bytecode::StringId) -> Self { Self { op, value: PredicateValueIR::Regex(pattern_id), @@ -387,7 +385,7 @@ impl InstructionIR { where F: Fn(plotnik_core::Symbol, TypeId) -> Option, G: Fn(TypeId) -> Option, - R: Fn(crate::bytecode::StringId) -> Option, + R: Fn(plotnik_bytecode::StringId) -> Option, { match self { Self::Match(m) => m.resolve(map, lookup_member, get_member_base, lookup_regex), @@ -559,7 +557,7 @@ impl MatchIR { where F: Fn(plotnik_core::Symbol, TypeId) -> Option, G: Fn(TypeId) -> Option, - R: Fn(crate::bytecode::StringId) -> Option, + R: Fn(plotnik_bytecode::StringId) -> Option, { let can_use_match8 = self.pre_effects.is_empty() && self.neg_fields.is_empty() diff --git a/crates/plotnik-lib/src/bytecode/ir_tests.rs b/crates/plotnik-compiler/src/bytecode/ir_tests.rs similarity index 98% rename from crates/plotnik-lib/src/bytecode/ir_tests.rs rename to crates/plotnik-compiler/src/bytecode/ir_tests.rs index 6a65b7ac..3bddc9d5 100644 --- a/crates/plotnik-lib/src/bytecode/ir_tests.rs +++ b/crates/plotnik-compiler/src/bytecode/ir_tests.rs @@ -1,11 +1,10 @@ use std::collections::BTreeMap; use std::num::NonZeroU16; +use plotnik_bytecode::{EffectOpcode, Nav}; use plotnik_core::Symbol; -use super::effects::EffectOpcode; use super::ir::{CallIR, EffectIR, InstructionIR, Label, MatchIR, MemberRef, NodeTypeIR, ReturnIR}; -use super::nav::Nav; use crate::analyze::type_check::TypeId; #[test] diff --git a/crates/plotnik-compiler/src/bytecode/mod.rs b/crates/plotnik-compiler/src/bytecode/mod.rs new file mode 100644 index 00000000..bdfa4025 --- /dev/null +++ b/crates/plotnik-compiler/src/bytecode/mod.rs @@ -0,0 +1,8 @@ +//! Compile-time IR for bytecode emission. + +mod ir; + +#[cfg(test)] +mod ir_tests; + +pub use ir::*; diff --git a/crates/plotnik-lib/src/compile/capture.rs b/crates/plotnik-compiler/src/compile/capture.rs similarity index 99% rename from crates/plotnik-lib/src/compile/capture.rs rename to crates/plotnik-compiler/src/compile/capture.rs index 35dbf1ed..8c399e1b 100644 --- a/crates/plotnik-lib/src/compile/capture.rs +++ b/crates/plotnik-compiler/src/compile/capture.rs @@ -7,7 +7,7 @@ use std::collections::HashSet; use crate::analyze::type_check::{TypeContext, TypeId, TypeShape}; use crate::bytecode::EffectIR; -use crate::bytecode::EffectOpcode; +use plotnik_bytecode::EffectOpcode; use crate::parser::ast::{self, Expr}; use super::Compiler; diff --git a/crates/plotnik-lib/src/compile/capture_tests.rs b/crates/plotnik-compiler/src/compile/capture_tests.rs similarity index 96% rename from crates/plotnik-lib/src/compile/capture_tests.rs rename to crates/plotnik-compiler/src/compile/capture_tests.rs index b2e3ac31..b6e50510 100644 --- a/crates/plotnik-lib/src/compile/capture_tests.rs +++ b/crates/plotnik-compiler/src/compile/capture_tests.rs @@ -1,5 +1,6 @@ use super::capture::CaptureEffects; -use crate::bytecode::{EffectIR, EffectOpcode, MemberRef}; +use plotnik_bytecode::EffectOpcode; +use crate::bytecode::{EffectIR, MemberRef}; #[test] fn nest_scope_preserves_outer_and_nests_inner() { diff --git a/crates/plotnik-lib/src/compile/compile_tests.rs b/crates/plotnik-compiler/src/compile/compile_tests.rs similarity index 100% rename from crates/plotnik-lib/src/compile/compile_tests.rs rename to crates/plotnik-compiler/src/compile/compile_tests.rs diff --git a/crates/plotnik-lib/src/compile/compiler.rs b/crates/plotnik-compiler/src/compile/compiler.rs similarity index 99% rename from crates/plotnik-lib/src/compile/compiler.rs rename to crates/plotnik-compiler/src/compile/compiler.rs index 33ce415b..93a465a3 100644 --- a/crates/plotnik-lib/src/compile/compiler.rs +++ b/crates/plotnik-compiler/src/compile/compiler.rs @@ -5,7 +5,7 @@ use plotnik_core::{Interner, NodeFieldId, NodeTypeId, Symbol}; use crate::analyze::symbol_table::SymbolTable; use crate::analyze::type_check::{DefId, TypeContext}; -use crate::bytecode::Nav; +use plotnik_bytecode::Nav; use crate::bytecode::{InstructionIR, Label, ReturnIR, TrampolineIR}; use crate::emit::StringTableBuilder; use crate::parser::Expr; diff --git a/crates/plotnik-lib/src/compile/error.rs b/crates/plotnik-compiler/src/compile/error.rs similarity index 100% rename from crates/plotnik-lib/src/compile/error.rs rename to crates/plotnik-compiler/src/compile/error.rs diff --git a/crates/plotnik-lib/src/compile/expressions.rs b/crates/plotnik-compiler/src/compile/expressions.rs similarity index 99% rename from crates/plotnik-lib/src/compile/expressions.rs rename to crates/plotnik-compiler/src/compile/expressions.rs index 891a4715..92fc0d0e 100644 --- a/crates/plotnik-lib/src/compile/expressions.rs +++ b/crates/plotnik-compiler/src/compile/expressions.rs @@ -10,7 +10,7 @@ use std::num::NonZeroU16; use crate::analyze::type_check::TypeShape; -use crate::bytecode::Nav; +use plotnik_bytecode::Nav; use crate::bytecode::{EffectIR, InstructionIR, Label, MatchIR, NodeTypeIR, PredicateIR}; use crate::parser::ast::{self, Expr}; @@ -79,7 +79,7 @@ impl Compiler<'_> { // right after match), other effects go on final_exit (after children processing). // Node/Text capture effects use matched_node which is only valid immediately after the match, // before descending into children (which may clobber matched_node via backtracking). - use crate::bytecode::EffectOpcode; + use plotnik_bytecode::EffectOpcode; // Find Node/Text effects and their following Set effects (they come in pairs: Node Set) let mut entry_effects = Vec::new(); diff --git a/crates/plotnik-lib/src/compile/mod.rs b/crates/plotnik-compiler/src/compile/mod.rs similarity index 100% rename from crates/plotnik-lib/src/compile/mod.rs rename to crates/plotnik-compiler/src/compile/mod.rs diff --git a/crates/plotnik-lib/src/compile/navigation.rs b/crates/plotnik-compiler/src/compile/navigation.rs similarity index 99% rename from crates/plotnik-lib/src/compile/navigation.rs rename to crates/plotnik-compiler/src/compile/navigation.rs index 864d1b67..19d45cb9 100644 --- a/crates/plotnik-lib/src/compile/navigation.rs +++ b/crates/plotnik-compiler/src/compile/navigation.rs @@ -3,7 +3,7 @@ //! Handles anchor-based navigation modes and navigation transformations //! for quantifier repeat iterations. -use crate::bytecode::Nav; +use plotnik_bytecode::Nav; use crate::parser::{Expr, SeqItem}; // Re-export from parser for compile module consumers diff --git a/crates/plotnik-lib/src/compile/quantifier.rs b/crates/plotnik-compiler/src/compile/quantifier.rs similarity index 99% rename from crates/plotnik-lib/src/compile/quantifier.rs rename to crates/plotnik-compiler/src/compile/quantifier.rs index 8548f3c0..a2fc8438 100644 --- a/crates/plotnik-lib/src/compile/quantifier.rs +++ b/crates/plotnik-compiler/src/compile/quantifier.rs @@ -7,7 +7,7 @@ //! - Whether skip/match need separate exits use crate::analyze::type_check::TypeId; -use crate::bytecode::Nav; +use plotnik_bytecode::Nav; use crate::bytecode::{EffectIR, Label}; use crate::parser::SyntaxKind; use crate::parser::ast::{self, Expr}; diff --git a/crates/plotnik-lib/src/compile/scope.rs b/crates/plotnik-compiler/src/compile/scope.rs similarity index 98% rename from crates/plotnik-lib/src/compile/scope.rs rename to crates/plotnik-compiler/src/compile/scope.rs index 073ebc94..67484b56 100644 --- a/crates/plotnik-lib/src/compile/scope.rs +++ b/crates/plotnik-compiler/src/compile/scope.rs @@ -6,7 +6,7 @@ use std::num::NonZeroU16; use crate::analyze::type_check::TypeId; use crate::bytecode::{CallIR, EffectIR, Label, MatchIR, MemberRef}; -use crate::bytecode::{EffectOpcode, Nav}; +use plotnik_bytecode::{EffectOpcode, Nav}; use crate::parser::Expr; use super::Compiler; @@ -397,7 +397,7 @@ impl Compiler<'_> { /// If there are more successors than fit in a single Match instruction, /// this creates a cascade of epsilon transitions to preserve NFA semantics. pub(super) fn emit_epsilon(&mut self, label: Label, successors: Vec