Phase -1 / Etch / Tree-walking interpreter#7
Merged
Conversation
…esources Additive S4 ECS surface (S1 comptime path untouched): - registry.zig: ComponentId, FieldKind/FieldDesc/ComponentDesc, register by comptime T or by raw descriptor (Etch bridge path), find field by name. - archetype_dynamic.zig: 16 KiB SoA chunks computed at runtime from component sizes/aligns, spawnDefault memcpy's registry defaults. - resources.zig: HashMap<ComponentId, []u8> + dirty bit. - query_runtime.zig: includes/excludes set test + chunk iterator. - world.zig: additive surface, new DynamicLocation map keyed by EntityId.
- value.zig: Value tagged union (int/float/bool/string_id/entity_id/component_ref), RuntimeError + RuntimeErrorKind, checked int helpers. - ecs_bridge.zig: Bridge owns Etch-name → ComponentId maps for components and resources; read/write component fields and resource fields by name through the registry's FieldDesc offsets. - interp.zig: Interpreter.compile / runFor / stepOnce. Registers components and resources, collects rule include/exclude/filter/resource-deps from the when tree, evaluates rule bodies in source order, single tick = step + tick boundary (resets resource dirty bits). - root.zig: extends the weld_etch public surface with Value, Interpreter, RuntimeReport, runProgram, runWithAst, evalConst. - build.zig: wires weld_core into the weld_etch module.
- diff_runner.zig: generic driver (FieldValue/FieldSpec/ComponentSpec/ EntitySpec/ResourceInit/WorldSpec/ExpectedWorld + runProgram(Runner, ...)). - runner_interp.zig: interpreter Runner (setup/step/finalize). Heap-boxes the AST so the Interpreter's borrowed pointer survives the Runner move. - 20 .etch programs + sidecars under tests/etch_interp/programs/ covering arithmetic, mutation, when single, and/or/not composition, has-with-filter (int/bool/float), resource gate, resource changed dirty/clean, multi-rule ordering. - corpus_facade.zig + corpus_test.zig wired into zig build test through four new modules in build.zig.
- bench/fixtures/demo_5_rules.etch: shared 5-rule fixture covering arithmetic, in-place mutation, field-equality filter, resource gate, and rule ordering. - bench/fixture_facade.zig: tiny module that @embedFiles the fixture so both the bench and demo binary can reach it (their root modules differ). - bench/etch_interp.zig: two sweeps (1 000 × 5 × 1 000 and 10 000 × 5 × 100), per-tick samples, Markdown report under bench/results/. - src/demo_etch_interp.zig: spawns 1 000 entities, runs 60 ticks, prints the mandated summary line. - build.zig: registers fixture_facade module, S4 bench step bench-etch-interp, S4 demo step run-demo-etch-interp.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brief
briefs/S4-etch-tree-walking-interpreter.mdRésumé
S4 validates the tree-walking interpreter hypothesis (cf.
engine-spec.md§22.3 sub-section S4). Tier 0 gains an additive runtime ECS surface — runtime component registry, dynamic SoA archetype, resource store, runtime query — without touching the S1 comptime(Transform, Velocity)path. The Etch interpreter walks the S3 AST directly, compiles each component / resource / rule into runtime descriptors (registry ids, predicate pool, field filter, resource deps), and executes rule bodies tick by tick. A 20-program differential corpus parameterised by aRunnerinterface exercises every supportedwhenform, in-place mutation, resource gating, and multi-rule ordering. The interface is the contract S5's codegen runner will plug into without modifying the harness.Critères d'acceptation
Interpreter,Value,RuntimeReport,runProgram,evalConst).Runner-parameterised driver + interpreter Runner.bench-etch-interp) — two sweeps (1 000 × 5 × 1 000 and 10 000 × 5 × 100). Apple Silicon dev primary, ReleaseSafe: median 0.603 ms / tick at 1 000 (gate 10 ms, target 5 ms — beaten 16× and 8×), median 6.593 ms / tick at 10 000 (gate 100 ms, target 50 ms — beaten 15× and 7.5×). Report archived underbench/results/.run-demo-etch-interp) — producesDemo S4 OK | mode=ReleaseSafe | entities=1000 | rules=5 | ticks=60 | rules_matched=300 | errors=0 | total=37.566ms.std.testing.allocatoron the full test suite.zig build,zig build test(Debug + ReleaseSafe),zig fmt --checkall green locally.run,bench-ecs,bench-etch,bindgen-vk,bindgen-wayland) still pass.Notes de review
Three points to flag explicitly:
(Transform, Velocity)archetype and its bench are untouched.World.init()stays zero-arg —Registry,ResourceStore,DynamicArchetypeare unmanaged perengine-zig-conventions.md§3.orpredicates compile to aPredicateNodepool and the runtime walks every dynamic archetype to evaluate it. Adequate for S4 corpus volume; a bitset short-cut may be needed in Phase 0.5 when archetype counts grow.Interpreterholds a*const Ast. The parser's value-returningparse(gpa, source)would otherwise leave a dangling pointer once the Ast value moves into the Runner struct. The Runner allocates a stable*Ast, hands its address to the Interpreter, and frees infinalize. The "borrowed Ast" API onInterpreter.run(gpa, &ast, world, ticks)is preserved for short-lived callers; the long-lived Runner path is the new convention.See also the Closure notes section of the brief for the full GO verdict, final measurements, and the residual debt list — including three S4-specific debts formalised post-bench (RuntimeQuery unused in hot path,
RuntimeReport.last_errornever assigned,ecs_bridge.writeValueAsBytespanics on type mismatch).Changelog
Code
src/core/ecs/registry.zig,archetype_dynamic.zig,resources.zig,query_runtime.zig— new Tier 0 surface.src/core/ecs/world.zig,src/core/root.zig— additive edits.src/etch/value.zig,ecs_bridge.zig,interp.zig— interpreter pieces.src/etch/root.zig— public surface extension.src/demo_etch_interp.zig— demo binary.bench/etch_interp.zig,bench/fixtures/demo_5_rules.etch,bench/fixture_facade.zig— bench harness + shared fixture.bench/results/s4-etch-interp-20260515-1946.md— initial bench report (Apple Silicon dev primary, ReleaseSafe, verdict GO).tests/etch_interp/diff_runner.zig,runner_interp.zig,corpus_facade.zig,corpus_test.zig— generic Runner-parameterised driver + interpreter Runner + facade + test entry.tests/etch_interp/programs/*.etch× 20 +*.expected.zig× 20 — differential corpus.build.zig— registersbench-etch-interp,run-demo-etch-interp, fixture facade, S4 test modules.Documentation
README.md— bumped status to S4, added bench + demo build steps, mentionedtests/etch_interp/in the project layout. Aligned tags table with actual git state (S2 / S3 are posted, dropped "pending merge"); fixed the bench layout line to point at the "Basic commands" block instead of naming a single bench.CLAUDE.md— flipped current milestone to S4 (CLOSED, PR pending), added S4 row to the Tags table, marked the S4 hypothesis as validated. Aligned tags table with actual git state (S1 → 2026-05-09, S2 → 2026-05-11, S3 → 2026-05-15, "Last released tag" bumped tov0.0.4-S3-etch-parser-subset). Date stamp updated to 2026-05-16.briefs/S4-etch-tree-walking-interpreter.md— milestone brief; copied verbatim at branch creation, ticked Specs read, kept execution journal, filled Closure notes at status → CLOSED. Three S4-specific residual debts formalised in Closure notes (RuntimeQuery unused on hot path,RuntimeReport.last_errornever assigned,ecs_bridge.writeValueAsBytespanics on type mismatch).