feat(wam-c): T9 fact-table inline (backtrackable, default in-range, capped) - #3300
Open
s243a wants to merge 1 commit into
Open
feat(wam-c): T9 fact-table inline (backtrackable, default in-range, capped)#3300s243a wants to merge 1 commit into
s243a wants to merge 1 commit into
Conversation
…apped) Brings the Rust/F# T9 fact-table work to the C WAM target. The C target already emitted a static row table + first-arg bucket index, but its scan was deterministic (returned only the first matching row). T9 makes the in-window fact lowering backtrackable so every matching row is enumerated, and adds the t9 window / opt-out / oversized semantics around it. Policy (mirrors Rust/F#): an all-ground-facts predicate (arity >= 1) whose row count is in [t9_min_rows, t9_max_rows] (defaults 64..256) lowers to the backtrackable fact-table handler by default. Opt out with fact_table_inline(false); below t9_min_rows keeps the cheap deterministic scanner; above t9_max_rows declines + warns (steer to an external fact source). Mechanism (mirrors the runtime's disjunction side-stack CP): - Runtime (wam_runtime.h): WAM_FACT_TABLE_RETRY sentinel; WamFactTableFrame side-stack (flattened row table ptr + candidate indices + pos + arity + return_pc) saved/restored/pruned alongside disj_top in the ChoicePoint; a shared static-inline wam_fact_table_scan that, on a match, leaves a choice point for the remaining candidates before binding, so backtracking yields the next row. wam_run dispatches WAM_FACT_TABLE_RETRY to wam_resume_fact_table. - Emitter (wam_c_target.pl): wam_c_fact_table_classify + thresholds + wam_c_maybe_warn_oversized_facts; a fact_table(Rows) plan gated ahead of the deterministic fact_only branch in plan_wam_c_lowered_helper (Options now threaded through); wam_c_fact_table_helper_for_predicate emits the row table + bucket index (reused) and a handler that derefs the first arg, picks the bucket (or full scan) and drives wam_fact_table_scan. Registered as a foreign predicate, so it is reachable as a query and from another predicate unchanged. Tests: test_wam_c_fact_table_exec.pl (gcc-gated; query-mode matrix (+,-)/(-,+)/(-,-)/(+,+)/absent-key enumerated by forcing backtracking -> ALL 6 PASS) and test_wam_c_fact_table_emit.pl (planner gating, opt-out, below-min, above-cap+warning, value literals, emitted scan). Existing C target suite stays green. Matrix: add a `c` row, T9 ✓ capped. https://claude.ai/code/session_013gLfigNMgCkxybbp7m6fXw
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.
What
Brings T9 fact-table inline to the C WAM target (after Rust and F#).
Key difference from the other targets: C already had a static row table + first-arg bucket index + a per-row unify scan — but the scan was deterministic (returned only the first matching row, so
edge(a,X)over multipleafacts yielded just one solution). T9 makes the in-window fact lowering backtrackable so every matching row is enumerated, and adds the t9 window / opt-out / oversized policy around it.Policy (mirrors Rust/F#)
An all-ground-facts predicate (arity ≥ 1) whose row count is in
[t9_min_rows, t9_max_rows](defaults 64..256) lowers to the backtrackable fact-table handler by default. Opt out withfact_table_inline(false); belowt9_min_rowskeeps the cheap deterministic scanner; abovet9_max_rowsdeclines + warns (steer to an external fact source).Mechanism (mirrors the runtime's disjunction side-stack choice point)
wam_runtime.h): aWAM_FACT_TABLE_RETRYsentinel; aWamFactTableFrameside-stack (flattened row-table pointer + candidate index array + position + arity + return PC) saved/restored/pruned alongsidedisj_topin theChoicePoint; a sharedstatic inline wam_fact_table_scanthat, on a match, leaves a choice point for the remaining candidates before binding so backtracking yields the next row.wam_rundispatchesWAM_FACT_TABLE_RETRY→wam_resume_fact_table. (Made the scan a headerstatic inlineso both the generated handlers and the resume function can call it across translation units.)wam_c_target.pl):wam_c_fact_table_classify+ thresholds +wam_c_maybe_warn_oversized_facts; afact_table(Rows)plan gated ahead of the deterministicfact_onlybranch inplan_wam_c_lowered_helper(Options now threaded through the planner);wam_c_fact_table_helper_for_predicatereuses the existing row table + bucket index and emits a handler that derefs the first arg, picks the bucket (or full scan) and driveswam_fact_table_scan. Registered through the same foreign-predicate path as today's facts, so it's reachable as a query and from another predicate with zero dispatch changes.Tests
tests/test_wam_c_fact_table_exec.pl(gcc-gated): builds a project and a C driver that enumerates all solutions per arg mode by forcing backtracking (acollect/2foreign that records bindings and fails). Verifies(+,-)index lookup →[1,2,4]in source order,(-,+)value-bound scan →[b],(-,-)→ all 6,(+,+)membership, and absent-key → 0. ALL 6 PASS (exit-code assertions).tests/test_wam_c_fact_table_emit.pl(fast): planner gating (default→fact_table, opt-out/below-min/above-cap→fact_only), oversized warning, classifier, emitted scan + row table + bucket switch, value literals.Matrix: adds a
crow (the matrix previously had none), T9 = ✓ capped.🤖 Generated with Claude Code
https://claude.ai/code/session_013gLfigNMgCkxybbp7m6fXw
Generated by Claude Code