1use crate::context::Context;
5use crate::predicate::CompiledPredicate;
6use crate::predicate::Predicate;
7use crate::schemas::path;
8use crate::CompilationError;
9
10use num::bigint::BigInt;
11use num::traits::cast::FromPrimitive;
12use num::traits::cast::ToPrimitive;
13
14use preserves::AtomClass;
15use preserves::CompoundClass;
16use preserves::IOValue;
17use preserves::SignedInteger;
18use preserves::ValueClass;
19use preserves::ValueImpl;
20
21use preserves_schema::support::interpret;
22
23use std::cell::RefCell;
24use std::iter::Iterator;
25use std::rc::Rc;
26
27pub trait StepMaker {
28 fn connect(&self, step: Node) -> Result<Node, CompilationError>;
29}
30
31pub trait Step: std::fmt::Debug {
32 fn accept(&mut self, ctxt: &mut Context, value: &IOValue);
33 fn finish(&mut self);
34 fn reset(&mut self) -> Vec<IOValue>;
35}
36
37macro_rules! delegate_finish_and_reset {
38 ($self:ident, $target:expr) => {
39 fn finish(&mut $self) { $target.finish() }
40 fn reset(&mut $self) -> Vec<IOValue> { $target.reset() }
41 }
42}
43
44#[derive(Clone, Debug)]
45pub struct Node(pub Rc<RefCell<dyn Step>>);
46
47#[derive(Debug)]
48struct AxisStep {
49 step: Node,
50 axis: path::Axis,
51}
52
53#[derive(Debug)]
54struct CompareStep {
55 op: path::Comparison,
56 literal: IOValue,
57 step: Node,
58}
59
60#[derive(Debug)]
61struct RegexStep {
62 regex: regex::Regex,
63 step: Node,
64}
65
66#[derive(Debug)]
67struct TestStep {
68 pred: CompiledPredicate,
69 step: Node,
70}
71
72#[derive(Debug)]
73struct RealStep {
74 step: Node,
75}
76
77#[derive(Debug)]
78struct IntStep {
79 step: Node,
80}
81
82#[derive(Debug)]
83struct VecCollector {
84 accumulator: Vec<IOValue>,
85}
86
87#[derive(Debug)]
88pub struct BoolCollector {
89 seen_value: bool,
90}
91
92#[derive(Debug)]
93struct KindStep {
94 kind: ValueClass,
95 step: Node,
96}
97
98#[derive(Debug)]
99pub struct CountCollector {
100 count: usize,
101}
102
103#[derive(Debug)]
104struct CountStep {
105 step: Node,
106 counter: Node,
107}
108
109impl Node {
110 fn new<S: Step + 'static>(s: S) -> Self {
111 Node(Rc::new(RefCell::new(s)))
112 }
113
114 pub fn test(&self, ctxt: &mut Context, value: &IOValue) -> bool {
115 !self.exec(ctxt, value).is_empty()
116 }
117
118 pub fn accept(&self, ctxt: &mut Context, value: &IOValue) {
119 self.0.borrow_mut().accept(ctxt, value)
120 }
121
122 pub fn finish(&self) {
123 self.0.borrow_mut().finish()
124 }
125
126 pub fn reset(&self) -> Vec<IOValue> {
127 self.0.borrow_mut().reset()
128 }
129
130 pub fn exec(&self, ctxt: &mut Context, value: &IOValue) -> Vec<IOValue> {
131 self.accept(ctxt, value);
132 self.finish();
133 self.reset()
134 }
135}
136
137impl StepMaker for path::Selector {
138 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
139 self.0.connect(step)
140 }
141}
142
143impl<S: StepMaker> StepMaker for Vec<S> {
144 fn connect(&self, mut step: Node) -> Result<Node, CompilationError> {
145 for s in self.iter().rev() {
146 step = s.connect(step)?;
147 }
148 Ok(step)
149 }
150}
151
152impl StepMaker for path::Step {
153 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
154 match self {
155 path::Step::Axis(b) => b.connect(step),
156 path::Step::Filter(b) => b.connect(step),
157 path::Step::Function(b) => b.connect(step),
158 }
159 }
160}
161
162impl StepMaker for path::Axis {
163 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
164 Ok(Node::new(AxisStep {
165 step,
166 axis: self.clone(),
167 }))
168 }
169}
170
171fn descendants(ctxt: &mut Context, step: &mut Node, v: &IOValue) {
172 step.accept(ctxt, v);
173 for c in v.children() {
174 ctxt.with_path_step(c.as_ref(), |ctxt| descendants(ctxt, step, c.as_ref()));
175 }
176}
177
178impl Step for AxisStep {
179 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
180 ctxt.with_path_step(value, |ctxt| match &self.axis {
181 path::Axis::Values => {
182 for c in value.value().children() {
183 self.step.accept(ctxt, c.as_ref())
184 }
185 }
186 path::Axis::Descendants => descendants(ctxt, &mut self.step, value),
187 path::Axis::At { key } => match value.value_class() {
188 ValueClass::Atomic(AtomClass::String) =>
189 step_index(ctxt,
190 value.as_string().unwrap().chars(),
191 key.into(),
192 |c| IOValue::new(String::from(c)),
193 &mut self.step),
194 ValueClass::Atomic(AtomClass::Symbol) =>
195 step_index(ctxt,
196 value.as_symbol().unwrap().chars(),
197 key.into(),
198 |c| IOValue::new(String::from(c)),
199 &mut self.step),
200 ValueClass::Compound(CompoundClass::Record) |
201 ValueClass::Compound(CompoundClass::Sequence) =>
202 step_index(ctxt, value.iter(), key.into(), |v| v.into(), &mut self.step),
203 ValueClass::Compound(CompoundClass::Dictionary) => {
204 if let Some(v) = value.get(&key) {
205 self.step.accept(ctxt, &v.into())
206 }
207 }
208 _ => (),
209 },
210 path::Axis::Label => {
211 if value.is_record() {
212 self.step.accept(ctxt, value.label().as_ref())
213 }
214 }
215 path::Axis::Keys => match value.value_class() {
216 ValueClass::Atomic(AtomClass::String) =>
217 step_keys(ctxt, value.as_string().unwrap().len(), &mut self.step),
218 ValueClass::Atomic(AtomClass::Symbol) =>
219 step_keys(ctxt, value.as_symbol().unwrap().len(), &mut self.step),
220 ValueClass::Atomic(AtomClass::ByteString) =>
221 step_keys(ctxt, value.as_bytestring().unwrap().len(), &mut self.step),
222 ValueClass::Compound(CompoundClass::Record) |
223 ValueClass::Compound(CompoundClass::Sequence) =>
224 step_keys(ctxt, value.len(), &mut self.step),
225 ValueClass::Compound(CompoundClass::Dictionary) => {
226 for k in value.keys() {
227 self.step.accept(ctxt, k.as_ref())
228 }
229 }
230 _ => (),
231 },
232 path::Axis::Length => match value.value_class() {
233 ValueClass::Atomic(AtomClass::String) =>
234 self.step.accept(ctxt, &IOValue::new(value.as_string().unwrap().len())),
235 ValueClass::Atomic(AtomClass::Symbol) =>
236 self.step.accept(ctxt, &IOValue::new(value.as_symbol().unwrap().len())),
237 ValueClass::Atomic(AtomClass::ByteString) =>
238 self.step.accept(ctxt, &IOValue::new(value.as_bytestring().unwrap().len())),
239 ValueClass::Compound(CompoundClass::Record) |
240 ValueClass::Compound(CompoundClass::Sequence) |
241 ValueClass::Compound(CompoundClass::Dictionary) =>
242 self.step.accept(ctxt, &IOValue::new(value.len())),
243 _ => self.step.accept(ctxt, &IOValue::new(0)),
244 },
245 path::Axis::Annotations => {
246 if let Some(cs) = value.annotations() {
247 for c in cs.iter() {
248 self.step.accept(ctxt, c)
249 }
250 }
251 }
252 path::Axis::Embedded => {
253 if let Some(d) = value.as_embedded() {
254 self.step.accept(ctxt, &d)
255 }
256 }
257 path::Axis::Parse { module, name } => {
258 if let Some(p) =
259 interpret::Context::new(&ctxt.env.0).dynamic_parse(module, name, value.into())
260 {
261 self.step.accept(ctxt, p.as_ref())
262 }
263 }
264 path::Axis::Unparse { module, name } => {
265 if let Some(p) =
266 interpret::Context::new(&ctxt.env.0).dynamic_unparse(module, name, value.into())
267 {
268 self.step.accept(ctxt, p.as_ref())
269 }
270 }
271 })
272 }
273
274 delegate_finish_and_reset!(self, self.step);
275}
276
277fn step_index<T, Ts: Iterator<Item = T>, F: FnOnce(T) -> IOValue>(
278 ctxt: &mut Context,
279 mut vs: Ts,
280 key: &IOValue,
281 f: F,
282 step: &mut Node,
283) {
284 if let Some(Ok(i)) = key.value().as_usize() {
285 match vs.nth(i) {
286 None => (),
287 Some(v) => step.accept(ctxt, &f(v)),
288 }
289 }
290}
291
292fn step_keys(ctxt: &mut Context, count: usize, step: &mut Node) {
293 for i in 0..count {
294 step.accept(ctxt, &IOValue::new(i))
295 }
296}
297
298impl StepMaker for path::Filter {
299 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
300 match self {
301 path::Filter::Nop => Ok(step),
302 path::Filter::Compare { op, literal } => Ok(Node::new(CompareStep {
303 op: op.clone(),
304 literal: literal.clone().into(),
305 step,
306 })),
307 path::Filter::Regex { regex } => Ok(Node::new(RegexStep {
308 regex: regex::Regex::new(regex)?,
309 step,
310 })),
311 path::Filter::Test { pred } => Ok(Node::new(TestStep {
312 pred: pred.compile()?,
313 step,
314 })),
315 path::Filter::Real => Ok(Node::new(RealStep { step })),
316 path::Filter::Int => Ok(Node::new(IntStep { step })),
317 path::Filter::Kind { kind } => Ok(Node::new(KindStep {
318 kind: match kind {
319 path::ValueKind::Boolean => ValueClass::Atomic(AtomClass::Boolean),
320 path::ValueKind::Double => ValueClass::Atomic(AtomClass::Double),
321 path::ValueKind::SignedInteger => ValueClass::Atomic(AtomClass::SignedInteger),
322 path::ValueKind::String => ValueClass::Atomic(AtomClass::String),
323 path::ValueKind::ByteString => ValueClass::Atomic(AtomClass::ByteString),
324 path::ValueKind::Symbol => ValueClass::Atomic(AtomClass::Symbol),
325 path::ValueKind::Record => ValueClass::Compound(CompoundClass::Record),
326 path::ValueKind::Sequence => ValueClass::Compound(CompoundClass::Sequence),
327 path::ValueKind::Set => ValueClass::Compound(CompoundClass::Set),
328 path::ValueKind::Dictionary => ValueClass::Compound(CompoundClass::Dictionary),
329 path::ValueKind::Embedded => ValueClass::Embedded,
330 },
331 step,
332 })),
333 }
334 }
335}
336
337impl Step for CompareStep {
338 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
339 if match self.op {
340 path::Comparison::Eq => value == &self.literal,
341 path::Comparison::Ne => value != &self.literal,
342 path::Comparison::Lt => value < &self.literal,
343 path::Comparison::Ge => value >= &self.literal,
344 path::Comparison::Gt => value > &self.literal,
345 path::Comparison::Le => value <= &self.literal,
346 } {
347 self.step.accept(ctxt, value)
348 }
349 }
350
351 delegate_finish_and_reset!(self, self.step);
352}
353
354impl Step for RegexStep {
355 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
356 if let Some(s) = value.as_string().or_else(|| value.as_symbol()) {
357 if self.regex.is_match(&s) {
358 self.step.accept(ctxt, value)
359 }
360 }
361 }
362
363 delegate_finish_and_reset!(self, self.step);
364}
365
366impl Step for TestStep {
367 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
368 if self.pred.test(ctxt, value) {
369 self.step.accept(ctxt, value)
370 }
371 }
372
373 delegate_finish_and_reset!(self, self.step);
374}
375
376impl Step for RealStep {
377 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
378 if let Some(i) = value.as_signed_integer() {
379 if let Some(r) = BigInt::from(i.as_ref()).to_f64() {
380 self.step.accept(ctxt, &IOValue::new(r))
381 }
382 } else if let Some(_) = value.as_double() {
383 self.step.accept(ctxt, value)
384 }
385 }
386
387 delegate_finish_and_reset!(self, self.step);
388}
389
390impl Step for IntStep {
391 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
392 if let Some(_) = value.as_signed_integer() {
393 self.step.accept(ctxt, value)
394 } else if let Some(d) = value.as_double() {
395 if let Some(i) = BigInt::from_f64(f64::from(d)) {
396 self.step.accept(ctxt, &IOValue::new(SignedInteger::from(i)))
397 }
398 }
399 }
400
401 delegate_finish_and_reset!(self, self.step);
402}
403
404impl VecCollector {
405 fn new() -> Node {
406 Node::new(VecCollector {
407 accumulator: Vec::new(),
408 })
409 }
410}
411
412impl Step for VecCollector {
413 fn accept(&mut self, _ctxt: &mut Context, value: &IOValue) {
414 self.accumulator.push(value.clone())
415 }
416
417 fn finish(&mut self) {}
418
419 fn reset(&mut self) -> Vec<IOValue> {
420 std::mem::take(&mut self.accumulator)
421 }
422}
423
424impl BoolCollector {
425 pub fn new() -> Node {
426 Node::new(BoolCollector { seen_value: false })
427 }
428}
429
430impl Step for BoolCollector {
431 fn accept(&mut self, _ctxt: &mut Context, _value: &IOValue) {
432 self.seen_value = true
433 }
434
435 fn finish(&mut self) {}
436
437 fn reset(&mut self) -> Vec<IOValue> {
438 let result = if self.seen_value {
439 vec![IOValue::new(true)]
440 } else {
441 vec![]
442 };
443 self.seen_value = false;
444 result
445 }
446}
447
448impl Step for KindStep {
449 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
450 if value.value_class() == self.kind {
451 self.step.accept(ctxt, value)
452 }
453 }
454
455 delegate_finish_and_reset!(self, self.step);
456}
457
458impl path::Selector {
459 pub fn compile(&self) -> Result<Node, CompilationError> {
460 self.connect(VecCollector::new())
461 }
462
463 pub fn exec(
464 &self,
465 ctxt: &mut Context,
466 value: &IOValue,
467 ) -> Result<Vec<IOValue>, CompilationError> {
468 Ok(self.compile()?.exec(ctxt, value))
469 }
470}
471
472impl StepMaker for path::Function {
473 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
474 Ok(Node::new(CountStep {
476 step,
477 counter: self.selector.connect(CountCollector::new())?,
478 }))
479 }
480}
481
482impl CountCollector {
483 pub fn new() -> Node {
484 Node::new(CountCollector { count: 0 })
485 }
486}
487
488impl Step for CountCollector {
489 fn accept(&mut self, _ctxt: &mut Context, _value: &IOValue) {
490 self.count += 1
491 }
492
493 fn finish(&mut self) {}
494
495 fn reset(&mut self) -> Vec<IOValue> {
496 let result = vec![IOValue::new(self.count)];
497 self.count = 0;
498 result
499 }
500}
501
502impl Step for CountStep {
503 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
504 let count = &self.counter.exec(ctxt, value)[0];
505 self.step.accept(ctxt, count)
506 }
507
508 delegate_finish_and_reset!(self, self.step);
509}