1use crate::cache::{NoCache, RewriteCache};
4use crate::engine::Engine;
5use crate::events::EventHandlers;
6use crate::helpers::{SelectorFn, select_first};
7use crate::prelude::Rule;
8use crate::rule::RuleGroups;
9
10use paste::paste;
11use uniplate::Uniplate;
12
13pub struct EngineBuilder<T, M, R, C>
15where
16 T: Uniplate + Send + Sync,
17 R: Rule<T, M> + Clone,
18 C: RewriteCache<T>,
19{
20 event_handlers: EventHandlers<T, M, R>,
21
22 rule_groups: Vec<Vec<R>>,
24
25 selector: SelectorFn<T, M, R>,
26
27 cache: C,
28
29 discriminant_fn: Option<fn(&T) -> usize>,
30
31 parallel: bool,
32
33 fixedpoint: bool,
34
35 down_predicate: fn(&T) -> bool,
36}
37
38macro_rules! add_handler_fns {
39 (
40 directions: [$($dir:ident),*]
41 ) => {
42 paste! {$(
43 pub fn [<add_before_ $dir>](mut self, handler: fn(&T, &mut M)) -> Self {
45 self.event_handlers.[<add_before_ $dir>](handler);
46 self
47 }
48
49 pub fn [<add_after_ $dir>](mut self, handler: fn(&T, &mut M)) -> Self {
51 self.event_handlers.[<add_after_ $dir>](handler);
52 self
53 }
54 )*}
55 };
56}
57
58impl<T, M, R> EngineBuilder<T, M, R, NoCache>
59where
60 T: Uniplate + Send + Sync,
61 R: Rule<T, M> + Clone,
62{
63 pub fn new() -> Self {
65 EngineBuilder {
66 event_handlers: EventHandlers::new(),
67 rule_groups: Vec::new(),
68 selector: select_first,
69 cache: NoCache,
70 discriminant_fn: None,
71 parallel: false,
72 fixedpoint: false,
73 down_predicate: |_| true,
74 }
75 }
76}
77
78impl<T, M, R, C> EngineBuilder<T, M, R, C>
79where
80 T: Uniplate + Send + Sync,
81 R: Rule<T, M> + Clone,
82 C: RewriteCache<T>,
83{
84 pub fn build(self) -> Engine<T, M, R, C> {
86 Engine {
87 event_handlers: self.event_handlers,
88 rule_groups: RuleGroups::new(self.rule_groups, self.discriminant_fn),
89 selector: self.selector,
90 cache: self.cache,
91 parallel: self.parallel,
92 fixedpoint: self.fixedpoint,
93 down_predicate: self.down_predicate,
94 }
95 }
96
97 pub fn add_rule_group(mut self, rules: Vec<R>) -> Self {
101 self.rule_groups.push(rules);
102 self
103 }
104
105 pub fn add_rule(self, rule: R) -> Self {
109 self.add_rule_group(vec![rule])
110 }
111
112 pub fn append_rule_groups(mut self, groups: Vec<Vec<R>>) -> Self {
116 self.rule_groups.extend(groups);
117 self
118 }
119
120 add_handler_fns! {
121 directions: [up, down, right]
122 }
123
124 pub fn add_before_rule(mut self, handler: fn(&T, &mut M, &R)) -> Self {
126 self.event_handlers.add_before_rule(handler);
127 self
128 }
129
130 pub fn add_after_rule(mut self, handler: fn(&T, &mut M, &R, bool)) -> Self {
133 self.event_handlers.add_after_rule(handler);
134 self
135 }
136
137 pub fn add_after_apply(mut self, handler: fn(&T, &mut M, &R)) -> Self {
139 self.event_handlers.add_after_apply(handler);
140 self
141 }
142
143 pub fn add_on_cache_hit(mut self, handler: fn(&T, &mut M)) -> Self {
145 self.event_handlers.add_on_cache_hit(handler);
146 self
147 }
148
149 pub fn add_on_cache_miss(mut self, handler: fn(&T, &mut M)) -> Self {
151 self.event_handlers.add_on_cache_miss(handler);
152 self
153 }
154
155 pub fn set_selector(mut self, selector: SelectorFn<T, M, R>) -> Self {
159 self.selector = selector;
160 self
161 }
162
163 pub fn add_cacher<Cache: RewriteCache<T>>(
168 self,
169 cacher: Cache,
170 ) -> EngineBuilder<T, M, R, Cache> {
171 EngineBuilder {
172 event_handlers: self.event_handlers,
173 rule_groups: self.rule_groups,
174 selector: self.selector,
175 cache: cacher,
176 discriminant_fn: self.discriminant_fn,
177 parallel: self.parallel,
178 fixedpoint: self.fixedpoint,
179 down_predicate: self.down_predicate,
180 }
181 }
182
183 pub fn set_parallel(mut self, parallel: bool) -> Self {
188 self.parallel = parallel;
189 self
190 }
191
192 pub fn set_discriminant_fn(mut self, discriminant_fn: Option<fn(&T) -> usize>) -> Self {
198 self.discriminant_fn = discriminant_fn;
199 self
200 }
201
202 pub fn set_fixedpoint(mut self, fixedpoint: bool) -> Self {
205 self.fixedpoint = fixedpoint;
206 self
207 }
208
209 pub fn add_down_predicate(mut self, predicate: fn(&T) -> bool) -> Self {
211 self.down_predicate = predicate;
212 self
213 }
214}
215
216impl<T, M, R> Default for EngineBuilder<T, M, R, NoCache>
217where
218 T: Uniplate + Send + Sync,
219 R: Rule<T, M> + Clone,
220{
221 fn default() -> Self {
222 Self::new()
223 }
224}
225
226impl<T, M, R, C> From<EngineBuilder<T, M, R, C>> for Engine<T, M, R, C>
227where
228 T: Uniplate + Send + Sync,
229 R: Rule<T, M> + Clone,
230 C: RewriteCache<T>,
231{
232 fn from(val: EngineBuilder<T, M, R, C>) -> Self {
233 val.build()
234 }
235}