Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ members = [
"numeric-id",
"union-find",
"src/sort/add_primitive",
"quote-macro",
"static-macro",
"wasm-example"
]

Expand Down Expand Up @@ -39,6 +41,7 @@ rayon = "1.10.0"
mimalloc = "0.1"
quote = "1.0"
syn = "2.0"
proc-macro2 = "1.0"
arc-swap = "1.7.1"
fixedbitset = "0.5"
smallvec = "1.10"
Expand Down Expand Up @@ -77,6 +80,7 @@ egglog-concurrency = { path = "concurrency", version = "2.0.0" }
egglog-numeric-id = { path = "numeric-id", version = "2.0.0" }
egglog-union-find = { path = "union-find", version = "2.0.0" }
egglog-add-primitive = { path = "src/sort/add_primitive", version = "2.0.0" }
egglog-quote = { path = "quote-macro", version = "2.0.0" }
egglog-reports = { path = "egglog-reports", version = "2.0.0" }
egglog = { path = ".", default-features = false, version = "2.0.0" }

Expand Down Expand Up @@ -154,6 +158,7 @@ egglog-ast = { workspace = true }
egglog-bridge = { workspace = true }
egglog-numeric-id = { workspace = true }
egglog-add-primitive = { workspace = true }
egglog-quote = { workspace = true }
egglog-reports = { workspace = true }
serde_json = { workspace = true }

Expand Down
13 changes: 7 additions & 6 deletions benches/rust_api_benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn match_only_rust_rule_setup(case: RustRuleBenchCase) -> RustRuleBenchInput {
"rust_rule_bench",
ruleset,
vars![x: i64],
facts![(R x)],
query![(R x)].unwrap(),
|_ctx, _values| Some(()),
)
.unwrap();
Expand Down Expand Up @@ -136,7 +136,7 @@ fn insert_loop_setup(case: RustRuleInsertLoopBenchCase) -> RustRuleBenchInput {
"rust_rule_insert_loop",
ruleset,
vars![x: i64],
facts![(R x)],
query![(R x)].unwrap(),
// insert f(x) = x + 1, f(x+1) = x + 2, ..., f(x+n_ops-1) = x + n_ops in one rule run
move |mut ctx, _values| {
for i in 0..case.n_ops {
Expand Down Expand Up @@ -185,7 +185,7 @@ fn tableaction_hot_path_setup(case: RustRuleTableActionBenchCase) -> RustRuleBen
"rust_rule_tableaction_hot_path_fill",
fill_ruleset,
vars![x: i64],
facts![(R x)],
query![(R x)].unwrap(),
move |mut ctx, values| {
let [x] = values else { unreachable!() };
let x = ctx.value_to_base::<i64>(*x);
Expand All @@ -208,7 +208,7 @@ fn tableaction_hot_path_setup(case: RustRuleTableActionBenchCase) -> RustRuleBen
"rust_rule_tableaction_hot_path_read",
read_ruleset,
vars![x: i64],
facts![(R x)],
query![(R x)].unwrap(),
move |ctx, values| {
let [x] = values else { unreachable!() };
let _ = ctx.lookup("f", *x).ok().flatten()?;
Expand Down Expand Up @@ -344,10 +344,11 @@ fn fib_setup() -> RustRuleBenchInput {
"fib_rule",
ruleset,
vars![x: i64, f0: i64, f1: i64],
facts![
query![
(= f0 (fib x))
(= f1 (fib (+ x 1)))
],
]
.unwrap(),
move |mut ctx, values| {
let [x, f0, f1] = values else { unreachable!() };
let x = ctx.value_to_base::<i64>(*x);
Expand Down
6 changes: 6 additions & 0 deletions egglog-ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ readme = { workspace = true }

[dependencies]
ordered-float = { workspace = true }
# Only for the `tokens` feature (token → egglog-source rendering shared by the
# quasiquote proc-macro crates); off by default, so normal builds don't pull it.
proc-macro2 = { workspace = true, optional = true, features = ["span-locations"] }


[features]
default = []
# Helpers for turning Rust proc-macro tokens into egglog atoms. Enabled by the
# `egglog-quote` and `egglog-static` proc-macro crates.
tokens = ["dep:proc-macro2"]
2 changes: 2 additions & 0 deletions egglog-ast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
pub mod generic_ast;
pub mod generic_ast_helpers;
pub mod span;
#[cfg(feature = "tokens")]
pub mod tokens;
pub mod util;
54 changes: 54 additions & 0 deletions egglog-ast/src/tokens.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Turning Rust proc-macro tokens into egglog atoms.
//!
//! Shared by the quasiquote proc-macro crates (`egglog-quote`, `egglog-static`)
//! so they reconstruct egglog atoms from Rust tokens identically. Gated behind
//! the `tokens` feature so egglog-ast's normal build doesn't pull `proc-macro2`.

use proc_macro2::{Span, TokenTree};
use std::iter::Peekable;

/// The source text of a single token: a punct's char, an identifier's name, or
/// a literal's / group's text.
pub fn tt_str(tt: &TokenTree) -> String {
match tt {
TokenTree::Punct(p) => p.as_char().to_string(),
TokenTree::Ident(i) => i.to_string(),
TokenTree::Literal(l) => l.to_string(),
TokenTree::Group(g) => g.to_string(),
}
}

/// Reassemble one egglog atom starting at `first` by absorbing every following
/// token that begins exactly where the previous one ended — i.e. with no
/// whitespace between them. This mirrors egglog's tokenizer (an atom is a
/// maximal run of non-space, non-paren characters): `?x`, `:no-merge`, `-1.0`,
/// `>=`, `my-ruleset` all become single atoms, while `(+ 6 87)` stays three
/// tokens because the spaces break the run.
///
/// Returns the atom text and the span of its first token, which anchors any
/// diagnostic reported inside the atom.
pub fn atom_run(
first: TokenTree,
it: &mut Peekable<impl Iterator<Item = TokenTree>>,
) -> (String, Span) {
let span = first.span();
let mut s = tt_str(&first);
let mut end = first.span().end();
while let Some(next) = it.peek() {
if matches!(next, TokenTree::Group(_)) {
break;
}
if let TokenTree::Literal(l) = next
&& l.to_string().starts_with('"')
{
break; // a string literal is its own token, never glued
}
if next.span().start() != end {
break; // whitespace between tokens ends the atom
}
s.push_str(&tt_str(next));
end = next.span().end();
it.next();
}
(s, span)
}
19 changes: 19 additions & 0 deletions quote-macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "egglog-quote"
version = { workspace = true }
edition = { workspace = true }
description = { workspace = true }
repository = { workspace = true }
keywords = { workspace = true }
license = { workspace = true }
readme = { workspace = true }

[lib]
proc-macro = true

[dependencies]
proc-macro2 = { workspace = true, features = ["span-locations"] }
quote = { workspace = true }
# Shared token → egglog-atom rendering (also used by `egglog-static`), so both
# crates reconstruct atoms identically. Not `egglog` itself, so no cycle.
egglog-ast = { workspace = true, features = ["tokens"] }
Loading
Loading