diff --git a/Cargo.toml b/Cargo.toml index e2b3af6b..d2cb40f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" name = "egg" readme = "README.md" repository = "https://github.com/egraphs-good/egg" -version = "0.9.5" +version = "0.10.0" [dependencies] env_logger = { version = "0.9.0", default-features = false } diff --git a/src/egraph.rs b/src/egraph.rs index 5c15c0a2..9c44eaa8 100644 --- a/src/egraph.rs +++ b/src/egraph.rs @@ -344,7 +344,7 @@ impl> EGraph { /// Calling this function on an uncanonical `Id` returns a representative based on the how it /// was obtained (see [`add_uncanoncial`](EGraph::add_uncanonical), /// [`add_expr_uncanonical`](EGraph::add_expr_uncanonical)) - pub fn id_to_expr(&self, id: Id) -> RecExpr { + pub fn id_to_expr(&self, id: Id) -> Expr { let mut res = Default::default(); let mut cache = Default::default(); self.id_to_expr_internal(&mut res, id, &mut cache); @@ -353,7 +353,7 @@ impl> EGraph { fn id_to_expr_internal( &self, - res: &mut RecExpr, + res: &mut Expr, node_id: Id, cache: &mut HashMap, ) -> Id { @@ -460,8 +460,8 @@ impl> EGraph { /// given by [`get_flat_string`](Explanation::get_flat_string) and [`get_string`](Explanation::get_string). pub fn explain_equivalence( &mut self, - left_expr: &RecExpr, - right_expr: &RecExpr, + left_expr: &Expr, + right_expr: &Expr, ) -> Explanation { let left = self.add_expr_uncanonical(left_expr); let right = self.add_expr_uncanonical(right_expr); @@ -503,7 +503,7 @@ impl> EGraph { /// into the egraph and ends with the given `expr`. /// Note that this function can be called again to explain any intermediate terms /// used in the output [`Explanation`]. - pub fn explain_existance(&mut self, expr: &RecExpr) -> Explanation { + pub fn explain_existance(&mut self, expr: &Expr) -> Explanation { let id = self.add_expr_uncanonical(expr); self.explain_existance_id(id) } @@ -535,7 +535,7 @@ impl> EGraph { /// Get an explanation for why an expression matches a pattern. pub fn explain_matches( &mut self, - left_expr: &RecExpr, + left_expr: &Expr, right_pattern: &PatternAst, subst: &Subst, ) -> Explanation { @@ -825,7 +825,7 @@ impl> std::ops::IndexMut for EGraph { } impl> EGraph { - /// Adds a [`RecExpr`] to the [`EGraph`], returning the id of the RecExpr's eclass. + /// Adds a [`Expr`] to the [`EGraph`], returning the id of the Expr's eclass. /// /// # Example /// ``` @@ -834,12 +834,12 @@ impl> EGraph { /// let x = egraph.add(S::leaf("x")); /// let y = egraph.add(S::leaf("y")); /// let plus = egraph.add(S::new("+", vec![x, y])); - /// let plus_recexpr = "(+ x y)".parse().unwrap(); - /// assert_eq!(plus, egraph.add_expr(&plus_recexpr)); + /// let plus_expr = "(+ x y)".parse().unwrap(); + /// assert_eq!(plus, egraph.add_expr(&plus_expr)); /// ``` /// /// [`add_expr`]: EGraph::add_expr() - pub fn add_expr(&mut self, expr: &RecExpr) -> Id { + pub fn add_expr(&mut self, expr: &Expr) -> Id { let id = self.add_expr_uncanonical(expr); self.find(id) } @@ -847,7 +847,7 @@ impl> EGraph { /// Similar to [`add_expr`](EGraph::add_expr) but the `Id` returned may not be canonical /// /// Calling [`id_to_expr`](EGraph::id_to_expr) on this `Id` return a copy of `expr` when explanations are enabled - pub fn add_expr_uncanonical(&mut self, expr: &RecExpr) -> Id { + pub fn add_expr_uncanonical(&mut self, expr: &Expr) -> Id { let nodes = expr.as_ref(); let mut new_ids = Vec::with_capacity(nodes.len()); let mut new_node_q = Vec::with_capacity(nodes.len()); @@ -962,16 +962,16 @@ impl> EGraph { self.memo.get(enode).copied() } - /// Lookup the eclass of the given [`RecExpr`]. + /// Lookup the eclass of the given [`Expr`]. /// /// Equivalent to the last value in [`EGraph::lookup_expr_ids`]. - pub fn lookup_expr(&self, expr: &RecExpr) -> Option { + pub fn lookup_expr(&self, expr: &Expr) -> Option { self.lookup_expr_ids(expr) .and_then(|ids| ids.last().copied()) } - /// Lookup the eclasses of all the nodes in the given [`RecExpr`]. - pub fn lookup_expr_ids(&self, expr: &RecExpr) -> Option> { + /// Lookup the eclasses of all the nodes in the given [`Expr`]. + pub fn lookup_expr_ids(&self, expr: &Expr) -> Option> { let nodes = expr.as_ref(); let mut new_ids = Vec::with_capacity(nodes.len()); for node in nodes { @@ -1099,11 +1099,11 @@ impl> EGraph { id } - /// Checks whether two [`RecExpr`]s are equivalent. + /// Checks whether two [`Expr`]s are equivalent. /// Returns a list of id where both expression are represented. /// In most cases, there will none or exactly one id. /// - pub fn equivs(&self, expr1: &RecExpr, expr2: &RecExpr) -> Vec { + pub fn equivs(&self, expr1: &Expr, expr2: &Expr) -> Vec { let pat1 = Pattern::from(expr1.as_ref()); let pat2 = Pattern::from(expr2.as_ref()); let matches1 = pat1.search(self); diff --git a/src/explain.rs b/src/explain.rs index 9de2a17e..9b3c2bb0 100644 --- a/src/explain.rs +++ b/src/explain.rs @@ -1,7 +1,7 @@ use crate::Symbol; use crate::{ - util::pretty_print, Analysis, EClass, ENodeOrVar, FromOp, HashMap, HashSet, Id, Language, - PatternAst, RecExpr, Rewrite, UnionFind, Var, + util::pretty_print, Analysis, EClass, ENodeOrVar, Expr, FromOp, HashMap, HashSet, Id, Language, + PatternAst, Rewrite, UnionFind, Var, }; use saturating::Saturating; use std::cmp::Ordering; @@ -702,8 +702,8 @@ impl FlatTerm { expr } - /// Convert this FlatTerm to a RecExpr. - pub fn get_recexpr(&self) -> RecExpr { + /// Convert this FlatTerm to a Expr. + pub fn get_expr(&self) -> Expr { self.remove_rewrites().to_string().parse().unwrap() } } diff --git a/src/extract.rs b/src/extract.rs index 74fbdc60..72d34e4a 100644 --- a/src/extract.rs +++ b/src/extract.rs @@ -2,9 +2,9 @@ use std::cmp::Ordering; use std::fmt::Debug; use crate::util::HashMap; -use crate::{Analysis, EClass, EGraph, Id, Language, RecExpr}; +use crate::{Analysis, EClass, EGraph, Expr, Id, Language}; -/** Extracting a single [`RecExpr`] from an [`EGraph`]. +/** Extracting a single [`Expr`] from an [`EGraph`]. ``` use egg::*; @@ -71,7 +71,7 @@ impl CostFunction for SillyCostFn { } } -let e: RecExpr = "(do_it foo bar baz)".parse().unwrap(); +let e: Expr = "(do_it foo bar baz)".parse().unwrap(); assert_eq!(SillyCostFn.cost_rec(&e), 102.7); assert_eq!(AstSize.cost_rec(&e), 4); assert_eq!(AstDepth.cost_rec(&e), 2); @@ -109,7 +109,7 @@ let _ = extractor.find_best(id); Note that a particular e-class might occur in an expression multiple times. This means that pathological, but nevertheless realistic cases might overflow `usize` if you implement a cost function like [`AstSize`], -even if the actual [`RecExpr`] fits compactly in memory. +even if the actual [`Expr`] fits compactly in memory. You might want to use [`saturating_add`](u64::saturating_add) to ensure your cost function is still monotonic in this situation. **/ @@ -128,12 +128,12 @@ pub trait CostFunction { where C: FnMut(Id) -> Self::Cost; - /// Calculates the total cost of a [`RecExpr`]. + /// Calculates the total cost of a [`Expr`]. /// /// As provided, this just recursively calls `cost` all the way - /// down the [`RecExpr`]. + /// down the [`Expr`]. /// - fn cost_rec(&mut self, expr: &RecExpr) -> Self::Cost { + fn cost_rec(&mut self, expr: &Expr) -> Self::Cost { let mut costs: HashMap = HashMap::default(); for (i, node) in expr.as_ref().iter().enumerate() { let cost = self.cost(node, |i| costs[&i].clone()); @@ -148,7 +148,7 @@ pub trait CostFunction { ``` # use egg::*; -let e: RecExpr = "(do_it foo bar baz)".parse().unwrap(); +let e: Expr = "(do_it foo bar baz)".parse().unwrap(); assert_eq!(AstSize.cost_rec(&e), 4); ``` @@ -169,7 +169,7 @@ impl CostFunction for AstSize { ``` # use egg::*; -let e: RecExpr = "(do_it foo bar baz)".parse().unwrap(); +let e: Expr = "(do_it foo bar baz)".parse().unwrap(); assert_eq!(AstDepth.cost_rec(&e), 2); ``` @@ -220,11 +220,11 @@ where extractor } - /// Find the cheapest (lowest cost) represented `RecExpr` in the + /// Find the cheapest (lowest cost) represented `Expr` in the /// given eclass. - pub fn find_best(&self, eclass: Id) -> (CF::Cost, RecExpr) { + pub fn find_best(&self, eclass: Id) -> (CF::Cost, Expr) { let (cost, root) = self.costs[&self.egraph.find(eclass)].clone(); - let expr = root.build_recexpr(|id| self.find_best_node(id).clone()); + let expr = root.build_expr(|id| self.find_best_node(id).clone()); (cost, expr) } diff --git a/src/language.rs b/src/language.rs index 23616387..ddb8f50d 100644 --- a/src/language.rs +++ b/src/language.rs @@ -115,26 +115,26 @@ pub trait Language: Debug + Clone + Eq + Ord + Hash { self.fold(false, |acc, id| acc || f(id)) } - /// Make a [`RecExpr`] by mapping this enodes children to other [`RecExpr`]s. + /// Make a [`Expr`] by mapping this enodes children to other [`Expr`]s. /// /// This can be used to join together different expression with a new node. /// /// # Example /// ``` /// # use egg::*; - /// let a_plus_2: RecExpr = "(+ a 2)".parse().unwrap(); + /// let a_plus_2: Expr = "(+ a 2)".parse().unwrap(); /// // here's an enode with some meaningless child ids /// let enode = SymbolLang::new("*", vec![Id::from(0), Id::from(0)]); - /// // make a new recexpr, replacing enode's children with a_plus_2 - /// let recexpr = enode.join_recexprs(|_id| &a_plus_2); - /// assert_eq!(recexpr, "(* (+ a 2) (+ a 2))".parse().unwrap()) + /// // make a new expr, replacing enode's children with a_plus_2 + /// let expr = enode.join_exprs(|_id| &a_plus_2); + /// assert_eq!(expr, "(* (+ a 2) (+ a 2))".parse().unwrap()) /// ``` - fn join_recexprs(&self, mut child_recexpr: F) -> RecExpr + fn join_exprs(&self, mut child_expr: F) -> Expr where - F: FnMut(Id) -> Expr, - Expr: AsRef<[Self]>, + F: FnMut(Id) -> Exp, + Exp: AsRef<[Self]>, { - fn build(to: &mut RecExpr, from: &[L]) -> Id { + fn build(to: &mut Expr, from: &[L]) -> Id { let last = from.last().unwrap().clone(); let new_node = last.map_children(|id| { let i = usize::from(id) + 1; @@ -143,15 +143,15 @@ pub trait Language: Debug + Clone + Eq + Ord + Hash { to.add(new_node) } - let mut expr = RecExpr::default(); + let mut expr = Expr::default(); let node = self .clone() - .map_children(|id| build(&mut expr, child_recexpr(id).as_ref())); + .map_children(|id| build(&mut expr, child_expr(id).as_ref())); expr.add(node); expr } - /// Build a [`RecExpr`] from an e-node. + /// Build a [`Expr`] from an e-node. /// /// The provided `get_node` function must return the same node for a given /// [`Id`] on multiple invocations. @@ -166,19 +166,19 @@ pub trait Language: Debug + Clone + Eq + Ord + Hash { /// let expr = "(foo (bar1 (bar2 (bar3 baz))))".parse().unwrap(); /// let root = egraph.add_expr(&expr); /// let get_first_enode = |id| egraph[id].nodes[0].clone(); - /// let expr2 = get_first_enode(root).build_recexpr(get_first_enode); + /// let expr2 = get_first_enode(root).build_expr(get_first_enode); /// assert_eq!(expr, expr2) /// ``` - fn build_recexpr(&self, mut get_node: F) -> RecExpr + fn build_expr(&self, mut get_node: F) -> Expr where F: FnMut(Id) -> Self, { - self.try_build_recexpr::<_, std::convert::Infallible>(|id| Ok(get_node(id))) + self.try_build_expr::<_, std::convert::Infallible>(|id| Ok(get_node(id))) .unwrap() } - /// Same as [`Language::build_recexpr`], but fallible. - fn try_build_recexpr(&self, mut get_node: F) -> Result, Err> + /// Same as [`Language::build_expr`], but fallible. + fn try_build_expr(&self, mut get_node: F) -> Result, Err> where F: FnMut(Id) -> Result, { @@ -215,7 +215,7 @@ pub trait Language: Debug + Clone + Eq + Ord + Hash { // finally, add the root node and create the expression let mut nodes: Vec = set.into_iter().collect(); nodes.push(self.clone().map_children(|id| ids[&id])); - Ok(RecExpr::from(nodes)) + Ok(Expr::from(nodes)) } } @@ -363,25 +363,25 @@ impl LanguageChildren for Id { fn as_mut_slice(&mut self) -> &mut [Id] { std::slice::from_mut(self) } } -/// A recursive expression from a user-defined [`Language`]. +/// An expression from a user-defined [`Language`]. /// -/// This conceptually represents a recursive expression, but it's actually just +/// This conceptually represents an expression, but it's actually just /// a list of enodes. /// -/// [`RecExpr`]s must satisfy the invariant that enodes' children must refer to +/// [`Expr`]s must satisfy the invariant that enodes' children must refer to /// elements that come before it in the list. For example, the expression -/// `(+ (* x 5) x)` could be represented by a recursive expression of the form +/// `(+ (* x 5) x)` could be represented by an expression of the form /// `[Num(5), Var("x"), Mul(1, 0), Add(2, 1)]`. /// /// If the `serde-1` feature is enabled, this implements /// [`serde::Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html). #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct RecExpr { +pub struct Expr { nodes: Vec, } #[cfg(feature = "serde-1")] -impl serde::Serialize for RecExpr { +impl serde::Serialize for Expr { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -391,32 +391,32 @@ impl serde::Serialize for RecExpr { } } -impl Default for RecExpr { +impl Default for Expr { fn default() -> Self { Self::from(vec![]) } } -impl AsRef<[L]> for RecExpr { +impl AsRef<[L]> for Expr { fn as_ref(&self) -> &[L] { &self.nodes } } -impl From> for RecExpr { +impl From> for Expr { fn from(nodes: Vec) -> Self { Self { nodes } } } -impl From> for Vec { - fn from(val: RecExpr) -> Self { +impl From> for Vec { + fn from(val: Expr) -> Self { val.nodes } } -impl RecExpr { - /// Adds a given enode to this `RecExpr`. +impl Expr { + /// Adds a given enode to this `Expr`. /// The enode's children `Id`s must refer to elements already in this list. pub fn add(&mut self, node: L) -> Id { debug_assert!( @@ -442,7 +442,7 @@ impl RecExpr { } pub(crate) fn extract(&self, new_root: Id) -> Self { - self[new_root].build_recexpr(|id| self[id].clone()) + self[new_root].build_expr(|id| self[id].clone()) } /// Checks if this expr is a DAG, i.e. doesn't have any back edges @@ -458,20 +458,20 @@ impl RecExpr { } } -impl Index for RecExpr { +impl Index for Expr { type Output = L; fn index(&self, id: Id) -> &L { &self.nodes[usize::from(id)] } } -impl IndexMut for RecExpr { +impl IndexMut for Expr { fn index_mut(&mut self, id: Id) -> &mut L { &mut self.nodes[usize::from(id)] } } -impl Display for RecExpr { +impl Display for Expr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.nodes.is_empty() { Display::fmt("()", f) @@ -482,8 +482,8 @@ impl Display for RecExpr { } } -impl RecExpr { - /// Convert this RecExpr into an Sexp +impl Expr { + /// Convert this Expr into an Sexp pub(crate) fn to_sexp(&self) -> Sexp { let last = self.nodes.len() - 1; if !self.is_dag() { @@ -519,7 +519,7 @@ impl RecExpr { /// # Example /// ``` /// # use egg::*; - /// let e: RecExpr = "(* (+ 2 2) (+ x y))".parse().unwrap(); + /// let e: Expr = "(* (+ 2 2) (+ x y))".parse().unwrap(); /// assert_eq!(e.pretty(10), " /// (* /// (+ 2 2) @@ -536,9 +536,9 @@ impl RecExpr { } /// An error type for failures when attempting to parse an s-expression as a -/// [`RecExpr`]. +/// [`Expr`]. #[derive(Debug, Error)] -pub enum RecExprParseError { +pub enum ExprParseError { /// An empty s-expression was found. Usually this is caused by an /// empty list "()" somewhere in the input. #[error("found empty s-expression")] @@ -559,16 +559,16 @@ pub enum RecExprParseError { BadSexp(SexpError), } -impl FromStr for RecExpr { - type Err = RecExprParseError; +impl FromStr for Expr { + type Err = ExprParseError; fn from_str(s: &str) -> Result { - use RecExprParseError::*; + use ExprParseError::*; fn parse_sexp_into( sexp: &Sexp, - expr: &mut RecExpr, - ) -> Result> { + expr: &mut Expr, + ) -> Result> { match sexp { Sexp::Empty => Err(EmptySexp), Sexp::String(s) => { @@ -591,7 +591,7 @@ impl FromStr for RecExpr { } } - let mut expr = RecExpr::default(); + let mut expr = Expr::default(); let sexp = symbolic_expressions::parser::parse_str(s.trim()).map_err(BadSexp)?; parse_sexp_into(&sexp, &mut expr)?; Ok(expr) diff --git a/src/lp_extract.rs b/src/lp_extract.rs index 5a4057be..70a5af3f 100644 --- a/src/lp_extract.rs +++ b/src/lp_extract.rs @@ -155,12 +155,12 @@ where /// Extract a single rooted term. /// /// This is just a shortcut for [`LpExtractor::solve_multiple`]. - pub fn solve(&mut self, root: Id) -> RecExpr { + pub fn solve(&mut self, root: Id) -> Expr { self.solve_multiple(&[root]).0 } /// Extract (potentially multiple) roots - pub fn solve_multiple(&mut self, roots: &[Id]) -> (RecExpr, Vec) { + pub fn solve_multiple(&mut self, roots: &[Id]) -> (Expr, Vec) { let egraph = self.egraph; for class in self.vars.values() { @@ -180,7 +180,7 @@ where ); let mut todo: Vec = roots.iter().map(|id| self.egraph.find(*id)).collect(); - let mut expr = RecExpr::default(); + let mut expr = Expr::default(); // converts e-class ids to e-node ids let mut ids: HashMap = HashMap::default(); diff --git a/src/pattern.rs b/src/pattern.rs index 3143e82d..4c0a9716 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -63,14 +63,14 @@ use crate::*; /// [`FromStr`]: std::str::FromStr #[derive(Debug, PartialEq, Eq, Clone)] pub struct Pattern { - /// The actual pattern as a [`RecExpr`] + /// The actual pattern as a [`Expr`] pub ast: PatternAst, program: machine::Program, } -/// A [`RecExpr`] that represents a +/// A [`Expr`] that represents a /// [`Pattern`]. -pub type PatternAst = RecExpr>; +pub type PatternAst = Expr>; impl PatternAst { /// Returns a new `PatternAst` with the variables renames canonically @@ -216,7 +216,7 @@ impl FromOp for ENodeOrVar { } impl std::str::FromStr for Pattern { - type Err = RecExprParseError>; + type Err = ExprParseError>; fn from_str(s: &str) -> Result { PatternAst::from_str(s).map(Self::from) @@ -226,13 +226,13 @@ impl std::str::FromStr for Pattern { impl<'a, L: Language> From<&'a [L]> for Pattern { fn from(expr: &'a [L]) -> Self { let nodes: Vec<_> = expr.iter().cloned().map(ENodeOrVar::ENode).collect(); - let ast = RecExpr::from(nodes); + let ast = Expr::from(nodes); Self::new(ast) } } -impl From<&RecExpr> for Pattern { - fn from(expr: &RecExpr) -> Self { +impl From<&Expr> for Pattern { + fn from(expr: &Expr) -> Self { Self::from(expr.as_ref()) } } @@ -243,7 +243,7 @@ impl From> for Pattern { } } -impl TryFrom> for RecExpr { +impl TryFrom> for Expr { type Error = Var; fn try_from(pat: Pattern) -> Result { let nodes = pat.ast.as_ref().iter().cloned(); @@ -253,7 +253,7 @@ impl TryFrom> for RecExpr { ENodeOrVar::Var(v) => Err(v), }) .collect(); - ns.map(RecExpr::from) + ns.map(Expr::from) } } diff --git a/src/rewrite.rs b/src/rewrite.rs index 1a3ea5f4..18da6788 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -589,8 +589,8 @@ mod tests { crate::init_logger(); let mut egraph = EGraph::default(); - let start = RecExpr::from_str("(+ x y)").unwrap(); - let goal = RecExpr::from_str("xy").unwrap(); + let start = Expr::from_str("(+ x y)").unwrap(); + let goal = Expr::from_str("xy").unwrap(); let root = egraph.add_expr(&start); diff --git a/src/run.rs b/src/run.rs index ae78d84e..830b8e43 100644 --- a/src/run.rs +++ b/src/run.rs @@ -388,7 +388,7 @@ where /// The eclass id of this addition will be recorded in the /// [`roots`](Runner::roots) field, ordered by /// insertion order. - pub fn with_expr(mut self, expr: &RecExpr) -> Self { + pub fn with_expr(mut self, expr: &Expr) -> Self { let id = self.egraph.add_expr(expr); self.roots.push(id); self @@ -458,12 +458,12 @@ where } /// Calls [`EGraph::explain_equivalence`](EGraph::explain_equivalence()). - pub fn explain_equivalence(&mut self, left: &RecExpr, right: &RecExpr) -> Explanation { + pub fn explain_equivalence(&mut self, left: &Expr, right: &Expr) -> Explanation { self.egraph.explain_equivalence(left, right) } /// Calls [`EGraph::explain_existance`](EGraph::explain_existance()). - pub fn explain_existance(&mut self, expr: &RecExpr) -> Explanation { + pub fn explain_existance(&mut self, expr: &Expr) -> Explanation { self.egraph.explain_existance(expr) } @@ -479,7 +479,7 @@ where /// Get an explanation for why an expression matches a pattern. pub fn explain_matches( &mut self, - left: &RecExpr, + left: &Expr, right: &PatternAst, subst: &Subst, ) -> Explanation { diff --git a/src/test.rs b/src/test.rs index 10815d66..a4243c79 100644 --- a/src/test.rs +++ b/src/test.rs @@ -31,7 +31,7 @@ pub fn test_runner( name: &str, runner: Option>, rules: &[Rewrite], - start: RecExpr, + start: Expr, goals: &[Pattern], check_fn: Option)>, should_check: bool, diff --git a/src/tutorials/_02_getting_started.rs b/src/tutorials/_02_getting_started.rs index 895d63f5..b14dc7b8 100644 --- a/src/tutorials/_02_getting_started.rs +++ b/src/tutorials/_02_getting_started.rs @@ -55,16 +55,16 @@ An e-node may have any number of children, which are [`Id`]s. An [`Id`] is basically just a number that `egg` uses to coordinate what children an e-node is associated with. In an [`EGraph`], e-node children refer to e-classes. -In a [`RecExpr`] (`egg`'s version of a plain old expression), - e-node children refer to other e-nodes in that [`RecExpr`]. +In a [`Expr`] (`egg`'s version of a plain old expression), + e-node children refer to other e-nodes in that [`Expr`]. Most [`Language`]s, including [`SymbolLang`], can be parsed and pretty-printed. -That means that [`RecExpr`]s in those languages +That means that [`Expr`]s in those languages implement the [`FromStr`] and [`Display`] traits from the Rust standard library. ``` # use egg::*; // Since parsing can return an error, `unwrap` just panics if the result doesn't return Ok -let my_expression: RecExpr = "(foo a b)".parse().unwrap(); +let my_expression: Expr = "(foo a b)".parse().unwrap(); println!("this is my expression {}", my_expression); // let's try to create an e-node, but hmmm, what do I put as the children? @@ -74,11 +74,11 @@ let my_enode = SymbolLang::new("bar", vec![]); Some e-nodes are just constants and have no children (also called leaves). But it's intentionally kind of awkward to create e-nodes with children in isolation, since you would have to add meaningless [`Id`]s as children. -The way to make meaningful [`Id`]s is by adding e-nodes to either an [`EGraph`] or a [`RecExpr`]: +The way to make meaningful [`Id`]s is by adding e-nodes to either an [`EGraph`] or a [`Expr`]: ``` # use egg::*; -let mut expr = RecExpr::default(); +let mut expr = Expr::default(); let a = expr.add(SymbolLang::leaf("a")); let b = expr.add(SymbolLang::leaf("b")); let foo = expr.add(SymbolLang::new("foo", vec![a, b])); @@ -89,7 +89,7 @@ let a = egraph.add(SymbolLang::leaf("a")); let b = egraph.add(SymbolLang::leaf("b")); let foo = egraph.add(SymbolLang::new("foo", vec![a, b])); -// we can also add RecExprs to an egraph +// we can also add Exprs to an egraph let foo2 = egraph.add_expr(&expr); // note that if you add the same thing to an e-graph twice, you'll get back equivalent Ids assert_eq!(foo, foo2); @@ -112,7 +112,7 @@ let foo = egraph.add(SymbolLang::new("foo", vec![a, b])); // rebuild the e-graph since we modified it egraph.rebuild(); -// we can make Patterns by parsing, similar to RecExprs +// we can make Patterns by parsing, similar to Exprs // names preceded by ? are parsed as Pattern variables and will match anything let pat: Pattern = "(foo ?x ?x)".parse().unwrap(); @@ -134,7 +134,7 @@ assert!(!matches.is_empty()); ## Using [`Runner`] to make an optimizer -Now that we can make [`Pattern`]s and work with [`RecExpr`]s, we can make an optimizer! +Now that we can make [`Pattern`]s and work with [`Expr`]s, we can make an optimizer! We'll use the [`rewrite!`] macro to easily create [`Rewrite`]s which consist of a name, left-hand pattern to search for, and right-hand pattern to apply. @@ -179,7 +179,7 @@ assert_eq!(best_cost, 1); [`Language`]: super::super::Language [`Searcher`]: super::super::Searcher [`Pattern`]: super::super::Pattern -[`RecExpr`]: super::super::RecExpr +[`Expr`]: super::super::Expr [`SymbolLang`]: super::super::SymbolLang [`define_language!`]: super::super::define_language! [`rewrite!`]: super::super::rewrite! diff --git a/tests/math.rs b/tests/math.rs index a0d8c07a..5b4603c2 100644 --- a/tests/math.rs +++ b/tests/math.rs @@ -310,7 +310,7 @@ egg::test_fn! { #[test] fn assoc_mul_saturates() { - let expr: RecExpr = "(* x 1)".parse().unwrap(); + let expr: Expr = "(* x 1)".parse().unwrap(); let runner: Runner = Runner::default() .with_iter_limit(3) @@ -322,7 +322,7 @@ fn assoc_mul_saturates() { #[test] fn test_union_trusted() { - let expr: RecExpr = "(+ (* x 1) y)".parse().unwrap(); + let expr: Expr = "(+ (* x 1) y)".parse().unwrap(); let expr2 = "20".parse().unwrap(); let mut runner: Runner = Runner::default() .with_explanations_enabled() @@ -339,7 +339,7 @@ fn test_union_trusted() { #[cfg(feature = "lp")] #[test] fn math_lp_extract() { - let expr: RecExpr = "(pow (+ x (+ x x)) (+ x x))".parse().unwrap(); + let expr: Expr = "(pow (+ x (+ x x)) (+ x x))".parse().unwrap(); let runner: Runner = Runner::default() .with_iter_limit(3) diff --git a/tests/prop.rs b/tests/prop.rs index ed1c7469..283db7cf 100644 --- a/tests/prop.rs +++ b/tests/prop.rs @@ -100,8 +100,8 @@ fn prove_something(name: &str, start: &str, rewrites: &[Rewrite], goals: &[&str] let _ = env_logger::builder().is_test(true).try_init(); println!("Proving {}", name); - let start_expr: RecExpr<_> = start.parse().unwrap(); - let goal_exprs: Vec> = goals.iter().map(|g| g.parse().unwrap()).collect(); + let start_expr: Expr<_> = start.parse().unwrap(); + let goal_exprs: Vec> = goals.iter().map(|g| g.parse().unwrap()).collect(); let mut runner = Runner::default() .with_iter_limit(20) diff --git a/tests/simple.rs b/tests/simple.rs index 9261a4c0..646e0ce8 100644 --- a/tests/simple.rs +++ b/tests/simple.rs @@ -22,7 +22,7 @@ fn make_rules() -> Vec> { /// parse an expression, simplify it using egg, and pretty print it back out fn simplify(s: &str) -> String { // parse the expression, the type annotation tells it which Language to use - let expr: RecExpr = s.parse().unwrap(); + let expr: Expr = s.parse().unwrap(); // simplify the expression using a Runner, which creates an e-graph with // the given expression and runs the given rules over it