Skip to content
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
619f801
Port tuple-output functions from egglog#938
oflatt Jul 2, 2026
ed920b5
egglog-experimental: adapt to tuple-output Schema/ResolvedCall
oflatt Jul 7, 2026
25724ad
Tidy tuple-output doc comments
oflatt Jul 7, 2026
e688d4c
Load all output columns in the input command for tuple-output functions
oflatt Jul 7, 2026
fcd5cfa
egglog-bridge: general merge-action MergeFn variants (Seq/TableInsert…
oflatt Jul 2, 2026
8cee351
egglog: native congruence :merge builder for constructor views (inert)
oflatt Jul 2, 2026
063a19d
egglog: resolve term-encoding congruence via native :merge (proof mode)
oflatt Jul 2, 2026
c7c2ce8
egglog: make the proof encoding self-contained via :internal-proof-names
oflatt Jul 3, 2026
5ac8196
core-relations: support self-referential merges (self-write pre-seed)
oflatt Jul 7, 2026
a6f6e9a
egglog-bridge: knot-tying for self-referential merges
oflatt Jul 7, 2026
02b4e59
egglog: single self-referential UF for term (non-proof) encoding
oflatt Jul 7, 2026
58abda4
egglog: single self-referential UF for proof-mode encoding
oflatt Jul 7, 2026
ab88652
Clean up encoding docs and comments for consistency
oflatt Jul 7, 2026
07b7e7e
some cleanup
oflatt Jul 10, 2026
2a18824
Reject extracting tuple-output functions; expand tuple-output tests
oflatt Jul 11, 2026
645310a
Add engine-level tests for merge-action variants and self-referential…
oflatt Jul 13, 2026
49e461e
Add design note: :merge as an action block (retire the MergeFn DSL)
oflatt Jul 13, 2026
9118adb
backend: identity/payload value columns for merges
oflatt Jul 13, 2026
bd2c649
backend: make the identity-column guard subsume-safe
oflatt Jul 13, 2026
9f8489f
backend: make the identity-column guard opt-in via Option
oflatt Jul 13, 2026
599c940
encoding: drop IfEq from merges via identity columns + orientation prims
oflatt Jul 13, 2026
de24e1e
:merge is a value-producing action block, typechecked via the action …
oflatt Jul 13, 2026
4e19453
merge: run the action block directly; drop Seq/TableInsert/Construct
oflatt Jul 13, 2026
c70259e
cargo fmt: normalize bridge examples and merge files
oflatt Jul 13, 2026
e632ce4
Add .egg tests for tuple output and merge action blocks
oflatt Jul 13, 2026
aa03f91
merge actions
oflatt Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions egglog-experimental/src/fresh_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ fn desugar_fresh_rule(
schema: Schema {
input: schema,
output: output_sort,
extra_outputs: vec![],
},
cost: first_opts.cost,
unextractable: first_opts.unextractable,
Expand Down
2 changes: 2 additions & 0 deletions egglog-experimental/src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ fn required_context(egraph: &mut EGraph, expr: &ResolvedExpr) -> Context {
}
}
ResolvedCall::Primitive(_) => Context::Pure,
// `values` builds/destructures a tuple value; it reads or writes no tables.
ResolvedCall::Values(_) => Context::Pure,
ResolvedCall::Func(func) => match func.subtype {
FunctionSubtype::Constructor => Context::Write,
FunctionSubtype::Custom => Context::Read,
Expand Down
21 changes: 21 additions & 0 deletions egglog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

## [Unreleased] - ReleaseDate

- **Single self-referential union-find (proof mode).** The proof term encoding now
represents each sort's union-find as one native-tuple function `@UF : (S) -> (S, Proof)`
(parent + a proof `key = parent`) with a self-referential `:merge`, replacing the former
two-table `@UF_S (S S) -> Proof` relation plus `@UF_Sf` index. Constructor-view congruence
and the UF self-merge both keep the smaller e-class and stage an oriented displaced edge,
so the `single_parent`/`uf_function_index` rules and per-term self-loop seeds are gone. This
mirrors the term (non-proof) encoding's single-table `@UF : (S) -> S`.
- **Tuple-output functions.** A function may declare more than one output sort, e.g.
`(function interval (Math) (i64 i64) :merge (values (max old0 new0) (min old1 new1)))`. Such a
function stores its outputs as separate value columns; the functional dependency is
`keys -> (value0, value1, ...)`. Outputs are destructured in queries with
`(= (values lo hi) (interval x))`, written with `(set (interval x) (values 0 100))`, and merged
with a `(values ...)` clause whose `i`-th element merges column `i` using the bound variables
`old0`, `new0`, `old1`, `new1`, .... Tuple outputs are only allowed for plain functions (not
constructors, relations, or view tables) and are not supported by the term/proof encoding.
- Built-in keywords (most command, action, and schedule heads such as `function`, `set`, `union`,
`rule`, `run`, ..., plus the tuple constructor `values`) are now reserved and may no longer be
used as user identifiers (function/sort/constructor/relation/variant names or variables). Names
starting with `:` are likewise reserved, since that prefix marks option keywords (`:merge`,
`:cost`, ...). The common-word commands `input` and `output` are only partially reserved: they
remain usable as variables, but not as definition names or as the head of a call expression.
- Add typed `EGraph` extension state that clones with `EGraph` and is restored by `push`/`pop`.
- Report full source file paths in egglog span and error messages.
- Fix seminaive matching after nested containers rebuild in place by propagating dirty container ids through parent containers.
Expand Down
11 changes: 10 additions & 1 deletion egglog/core-relations/src/free_join/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,16 @@ impl Database {
while !to_merge.is_empty() {
for table_id in to_merge.iter().copied() {
let mut info = self.tables.unwrap_val(table_id);
let mut es = ExecutionState::new(self.read_only_view(), Default::default());
// Pre-seed the table's OWN buffer so a self-referential merge — one that stages a
// write back into its own table (e.g. the term encoder's `@UF` recursive
// parent-union) — can stage it. The table has been `unwrap_val`'d out of
// `self.tables`, so the lazy `new_buffer()` path (which indexes `self.tables`) would
// fail for the self id. Staged rows land in `pending_state` and are picked up on the
// next fixpoint iteration of this loop. Non-self-referential merges get an empty,
// never-touched buffer. (The strata path in `merge_all` handles this via write-deps.)
let mut bufs = DenseIdMap::default();
bufs.insert(table_id, info.table.new_buffer());
let mut es = ExecutionState::new(self.read_only_view(), bufs);
changed |= info.table.merge(&mut es).added || es.changed;
self.tables.insert(table_id, info);
}
Expand Down
Loading
Loading