[−][src]Trait egg::Applier
The righthand side of a Rewrite
.
An Applier
is anything that can do something with a
substitition (Subst
). This allows you to implement rewrites
that determine when and how to respond to a match using custom
logic, including access to the Analysis
data of an EClass
.
Notably, Pattern
implements Applier
, which suffices in
most cases.
Additionally, egg
provides ConditionalApplier
to stack
Condition
s onto an Applier
, which in many cases can save
you from having to implement your own applier.
Example
use egg::{rewrite as rw, *}; define_language! { enum Math { Num(i32), "+" = Add([Id; 2]), "*" = Mul([Id; 2]), Symbol(Symbol), } } type EGraph = egg::EGraph<Math, MinSize>; // Our metadata in this case will be size of the smallest // represented expression in the eclass. #[derive(Default)] struct MinSize; impl Analysis<Math> for MinSize { type Data = usize; fn merge(&self, to: &mut Self::Data, from: Self::Data) -> bool { merge_if_different(to, (*to).min(from)) } fn make(egraph: &EGraph, enode: &Math) -> Self::Data { let get_size = |i: Id| egraph[i].data; AstSize.cost(enode, get_size) } } let rules = &[ rw!("commute-add"; "(+ ?a ?b)" => "(+ ?b ?a)"), rw!("commute-mul"; "(* ?a ?b)" => "(* ?b ?a)"), rw!("add-0"; "(+ ?a 0)" => "?a"), rw!("mul-0"; "(* ?a 0)" => "0"), rw!("mul-1"; "(* ?a 1)" => "?a"), // the rewrite macro parses the rhs as a single token tree, so // we wrap it in braces (parens work too). rw!("funky"; "(+ ?a (* ?b ?c))" => { Funky { a: "?a".parse().unwrap(), b: "?b".parse().unwrap(), c: "?c".parse().unwrap(), }}), ]; #[derive(Debug, Clone, PartialEq, Eq)] struct Funky { a: Var, b: Var, c: Var, } impl Applier<Math, MinSize> for Funky { fn apply_one(&self, egraph: &mut EGraph, matched_id: Id, subst: &Subst) -> Vec<Id> { let a: Id = subst[self.a]; // In a custom Applier, you can inspect the analysis data, // which is powerful combination! let size_of_a = egraph[a].data; if size_of_a > 50 { println!("Too big! Not doing anything"); vec![] } else { // we're going to manually add: // (+ (+ ?a 0) (* (+ ?b 0) (+ ?c 0))) // to be unified with the original: // (+ ?a (* ?b ?c )) let b: Id = subst[self.b]; let c: Id = subst[self.c]; let zero = egraph.add(Math::Num(0)); let a0 = egraph.add(Math::Add([a, zero])); let b0 = egraph.add(Math::Add([b, zero])); let c0 = egraph.add(Math::Add([c, zero])); let b0c0 = egraph.add(Math::Mul([b0, c0])); let a0b0c0 = egraph.add(Math::Add([a0, b0c0])); // NOTE: we just return the id according to what we // want unified with matched_id. The `apply_matches` // method actually does the union, _not_ `apply_one`. vec![a0b0c0] } } } let start = "(+ x (* y z))".parse().unwrap(); Runner::default().with_expr(&start).run(rules);
Required methods
fn apply_one(
&self,
egraph: &mut EGraph<L, N>,
eclass: Id,
subst: &Subst
) -> Vec<Id>
&self,
egraph: &mut EGraph<L, N>,
eclass: Id,
subst: &Subst
) -> Vec<Id>
Apply a single substitition.
An Applier
should only add things to the egraph here,
not union them with the id eclass
.
That is the responsibility of the apply_matches
method.
The eclass
parameter allows the implementer to inspect the
eclass where the match was found if they need to.
This should return a list of Id
s of things you'd like to
be unioned with eclass
. There can be zero, one, or many.
Provided methods
fn apply_matches(
&self,
egraph: &mut EGraph<L, N>,
matches: &[SearchMatches]
) -> Vec<Id>
&self,
egraph: &mut EGraph<L, N>,
matches: &[SearchMatches]
) -> Vec<Id>
Apply many substititions.
This method should call apply_one
for each match and then
unify the results with the matched eclass.
This should return a list of Id
s where the union actually
did something.
The default implementation does this and should suffice for most use cases.
fn vars(&self) -> Vec<Var>
Returns a list of variables that this Applier assumes are bound.
egg
will check that the corresponding Searcher
binds those
variables.
By default this return an empty Vec
, which basically turns off the
checking.
Implementors
impl<C, A, N, L> Applier<L, N> for ConditionalApplier<C, A> where
L: Language,
C: Condition<L, N>,
A: Applier<L, N>,
N: Analysis<L>,
[src]
L: Language,
C: Condition<L, N>,
A: Applier<L, N>,
N: Analysis<L>,
fn apply_one(
&self,
egraph: &mut EGraph<L, N>,
eclass: Id,
subst: &Subst
) -> Vec<Id>
[src]
&self,
egraph: &mut EGraph<L, N>,
eclass: Id,
subst: &Subst
) -> Vec<Id>
fn vars(&self) -> Vec<Var>
[src]
impl<L, A> Applier<L, A> for Pattern<L> where
L: Language,
A: Analysis<L>,
[src]
L: Language,
A: Analysis<L>,