Expand description
Fact-table lookup (FACT_TABLE.md, Stages A–C): the generic enumerator for a
predicate compiled to a .rodata table instead of one function per clause.
Same observable behavior as the per-clause facts — solution order = program
order, choice-point backtracking — mirroring between/3’s shape.
A table cell is one word. Immediate columns (atom / i61-int) are stored
inline and unified directly. Non-immediate columns (compound, list, float,
big-int — Stage C) are stored as a blob reference: a STR/LST/FLT/
BIG word whose payload indexes a per-predicate .rodata serialized blob
(the copyterm/TermBuf format). fact_scan restores such a cell onto the
heap via restore_cells before unifying — so the cell tag (atom/int vs the
pointer tags) tells the two cases apart with no extra metadata.
Stage B’s first-argument index applies only when column 0 is all-immediate; otherwise (or for an unbound/non-immediate query arg) the scan covers all rows. Either way matching rows are visited in program order.
Delivery to the continuation is a musttail in the GENERATED entry/retry
functions, not here: these helpers only find/bind a row and push the
choice point, then RETURN. That return pops their frame before the
generated code tail-calls the continuation, so recursion through a fact
predicate (e.g. edge in a recursive path/2) keeps a constant C stack.
Functions§
- plg_
rt_ ⚠fact_ first - Compiled entry: snapshot the args + continuation into a control frame, pick the row range to scan (binary search on the index when the first arg is a bound atom/int, else all rows), then find the first matching row. Returns 1 if a solution was set up (the generated entry then musttails the continuation), 0 if no row matches.
- plg_
rt_ ⚠fact_ next - Choice-point retry: restore the saved continuation (the driver may have
overwritten
m.k_fn), then resume the scan from the frame’s cursor.