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::value::AtomClass;
15use preserves::value::CompoundClass;
16use preserves::value::IOValue;
17use preserves::value::NestedValue;
18use preserves::value::Value;
19use preserves::value::ValueClass;
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.value().children() {
174 ctxt.with_path_step(&c, |ctxt| descendants(ctxt, step, &c));
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)
184 }
185 }
186 path::Axis::Descendants => descendants(ctxt, &mut self.step, value),
187 path::Axis::At { key } => match value.value() {
188 Value::String(s) | Value::Symbol(s) => step_index(
189 ctxt,
190 s.chars(),
191 &key,
192 |c| IOValue::new(String::from(c)),
193 &mut self.step,
194 ),
195 Value::Record(r) => {
196 step_index(ctxt, r.fields().iter(), &key, |v| v.clone(), &mut self.step)
197 }
198 Value::Sequence(vs) => {
199 step_index(ctxt, vs.iter(), &key, |v| v.clone(), &mut self.step)
200 }
201 Value::Dictionary(d) => {
202 if let Some(v) = d.get(&key) {
203 self.step.accept(ctxt, v)
204 }
205 }
206 _ => (),
207 },
208 path::Axis::Label => {
209 if let Some(r) = value.value().as_record(None) {
210 self.step.accept(ctxt, r.label())
211 }
212 }
213 path::Axis::Keys => match value.value() {
214 Value::String(s) | Value::Symbol(s) => step_keys(ctxt, s.len(), &mut self.step),
215 Value::ByteString(bs) => step_keys(ctxt, bs.len(), &mut self.step),
216 Value::Record(r) => step_keys(ctxt, r.arity(), &mut self.step),
217 Value::Sequence(vs) => step_keys(ctxt, vs.len(), &mut self.step),
218 Value::Dictionary(d) => {
219 for k in d.keys() {
220 self.step.accept(ctxt, k)
221 }
222 }
223 _ => (),
224 },
225 path::Axis::Length => match value.value() {
226 Value::String(s) | Value::Symbol(s) => {
227 self.step.accept(ctxt, &IOValue::new(s.len()))
228 }
229 Value::ByteString(bs) => self.step.accept(ctxt, &IOValue::new(bs.len())),
230 Value::Record(r) => self.step.accept(ctxt, &IOValue::new(r.arity())),
231 Value::Sequence(vs) => self.step.accept(ctxt, &IOValue::new(vs.len())),
232 Value::Dictionary(d) => self.step.accept(ctxt, &IOValue::new(d.len())),
233 _ => self.step.accept(ctxt, &IOValue::new(0)),
234 },
235 path::Axis::Annotations => {
236 for c in value.annotations().slice() {
237 self.step.accept(ctxt, &c)
238 }
239 }
240 path::Axis::Embedded => {
241 if let Some(d) = value.value().as_embedded() {
242 self.step.accept(ctxt, d)
243 }
244 }
245 path::Axis::Parse { module, name } => {
246 if let Some(p) =
247 interpret::Context::new(&ctxt.env.0).dynamic_parse(module, name, value)
248 {
249 self.step.accept(ctxt, &p)
250 }
251 }
252 path::Axis::Unparse { module, name } => {
253 if let Some(p) =
254 interpret::Context::new(&ctxt.env.0).dynamic_unparse(module, name, value)
255 {
256 self.step.accept(ctxt, &p)
257 }
258 }
259 })
260 }
261
262 delegate_finish_and_reset!(self, self.step);
263}
264
265fn step_index<T, Ts: Iterator<Item = T>, F: FnOnce(T) -> IOValue>(
266 ctxt: &mut Context,
267 mut vs: Ts,
268 key: &IOValue,
269 f: F,
270 step: &mut Node,
271) {
272 if let Some(i) = key.value().as_usize() {
273 match vs.nth(i) {
274 None => (),
275 Some(v) => step.accept(ctxt, &f(v)),
276 }
277 }
278}
279
280fn step_keys(ctxt: &mut Context, count: usize, step: &mut Node) {
281 for i in 0..count {
282 step.accept(ctxt, &IOValue::new(i))
283 }
284}
285
286impl StepMaker for path::Filter {
287 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
288 match self {
289 path::Filter::Nop => Ok(step),
290 path::Filter::Compare { op, literal } => Ok(Node::new(CompareStep {
291 op: (**op).clone(),
292 literal: literal.clone(),
293 step,
294 })),
295 path::Filter::Regex { regex } => Ok(Node::new(RegexStep {
296 regex: regex::Regex::new(regex)?,
297 step,
298 })),
299 path::Filter::Test { pred } => Ok(Node::new(TestStep {
300 pred: (&**pred).compile()?,
301 step,
302 })),
303 path::Filter::Real => Ok(Node::new(RealStep { step })),
304 path::Filter::Int => Ok(Node::new(IntStep { step })),
305 path::Filter::Kind { kind } => Ok(Node::new(KindStep {
306 kind: match &**kind {
307 path::ValueKind::Boolean => ValueClass::Atomic(AtomClass::Boolean),
308 path::ValueKind::Double => ValueClass::Atomic(AtomClass::Double),
309 path::ValueKind::SignedInteger => ValueClass::Atomic(AtomClass::SignedInteger),
310 path::ValueKind::String => ValueClass::Atomic(AtomClass::String),
311 path::ValueKind::ByteString => ValueClass::Atomic(AtomClass::ByteString),
312 path::ValueKind::Symbol => ValueClass::Atomic(AtomClass::Symbol),
313 path::ValueKind::Record => ValueClass::Compound(CompoundClass::Record),
314 path::ValueKind::Sequence => ValueClass::Compound(CompoundClass::Sequence),
315 path::ValueKind::Set => ValueClass::Compound(CompoundClass::Set),
316 path::ValueKind::Dictionary => ValueClass::Compound(CompoundClass::Dictionary),
317 path::ValueKind::Embedded => ValueClass::Embedded,
318 },
319 step,
320 })),
321 }
322 }
323}
324
325impl Step for CompareStep {
326 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
327 if match self.op {
328 path::Comparison::Eq => value == &self.literal,
329 path::Comparison::Ne => value != &self.literal,
330 path::Comparison::Lt => value < &self.literal,
331 path::Comparison::Ge => value >= &self.literal,
332 path::Comparison::Gt => value > &self.literal,
333 path::Comparison::Le => value <= &self.literal,
334 } {
335 self.step.accept(ctxt, value)
336 }
337 }
338
339 delegate_finish_and_reset!(self, self.step);
340}
341
342impl Step for RegexStep {
343 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
344 match value.value() {
345 Value::String(s) | Value::Symbol(s) => {
346 if self.regex.is_match(s) {
347 self.step.accept(ctxt, value)
348 }
349 }
350 _ => (),
351 }
352 }
353
354 delegate_finish_and_reset!(self, self.step);
355}
356
357impl Step for TestStep {
358 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
359 if self.pred.test(ctxt, value) {
360 self.step.accept(ctxt, value)
361 }
362 }
363
364 delegate_finish_and_reset!(self, self.step);
365}
366
367impl Step for RealStep {
368 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
369 match value.value() {
370 Value::SignedInteger(i) => {
371 if let Some(r) = BigInt::from(i).to_f64() {
372 self.step.accept(ctxt, &IOValue::new(r))
373 }
374 }
375 Value::Double(_) => self.step.accept(ctxt, value),
376 _ => (),
377 }
378 }
379
380 delegate_finish_and_reset!(self, self.step);
381}
382
383impl Step for IntStep {
384 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
385 match value.value() {
386 Value::SignedInteger(_) => self.step.accept(ctxt, value),
387 Value::Double(d) => {
388 if let Some(i) = BigInt::from_f64(f64::from(*d)) {
389 self.step.accept(ctxt, &IOValue::new(i))
390 }
391 }
392 _ => (),
393 }
394 }
395
396 delegate_finish_and_reset!(self, self.step);
397}
398
399impl VecCollector {
400 fn new() -> Node {
401 Node::new(VecCollector {
402 accumulator: Vec::new(),
403 })
404 }
405}
406
407impl Step for VecCollector {
408 fn accept(&mut self, _ctxt: &mut Context, value: &IOValue) {
409 self.accumulator.push(value.clone())
410 }
411
412 fn finish(&mut self) {}
413
414 fn reset(&mut self) -> Vec<IOValue> {
415 std::mem::take(&mut self.accumulator)
416 }
417}
418
419impl BoolCollector {
420 pub fn new() -> Node {
421 Node::new(BoolCollector { seen_value: false })
422 }
423}
424
425impl Step for BoolCollector {
426 fn accept(&mut self, _ctxt: &mut Context, _value: &IOValue) {
427 self.seen_value = true
428 }
429
430 fn finish(&mut self) {}
431
432 fn reset(&mut self) -> Vec<IOValue> {
433 let result = if self.seen_value {
434 vec![IOValue::new(true)]
435 } else {
436 vec![]
437 };
438 self.seen_value = false;
439 result
440 }
441}
442
443impl Step for KindStep {
444 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
445 if value.value_class() == self.kind {
446 self.step.accept(ctxt, value)
447 }
448 }
449
450 delegate_finish_and_reset!(self, self.step);
451}
452
453impl path::Selector {
454 pub fn compile(&self) -> Result<Node, CompilationError> {
455 self.connect(VecCollector::new())
456 }
457
458 pub fn exec(
459 &self,
460 ctxt: &mut Context,
461 value: &IOValue,
462 ) -> Result<Vec<IOValue>, CompilationError> {
463 Ok(self.compile()?.exec(ctxt, value))
464 }
465}
466
467impl StepMaker for path::Function {
468 fn connect(&self, step: Node) -> Result<Node, CompilationError> {
469 Ok(Node::new(CountStep {
471 step,
472 counter: self.selector.connect(CountCollector::new())?,
473 }))
474 }
475}
476
477impl CountCollector {
478 pub fn new() -> Node {
479 Node::new(CountCollector { count: 0 })
480 }
481}
482
483impl Step for CountCollector {
484 fn accept(&mut self, _ctxt: &mut Context, _value: &IOValue) {
485 self.count += 1
486 }
487
488 fn finish(&mut self) {}
489
490 fn reset(&mut self) -> Vec<IOValue> {
491 let result = vec![IOValue::new(self.count)];
492 self.count = 0;
493 result
494 }
495}
496
497impl Step for CountStep {
498 fn accept(&mut self, ctxt: &mut Context, value: &IOValue) {
499 let count = &self.counter.exec(ctxt, value)[0];
500 self.step.accept(ctxt, count)
501 }
502
503 delegate_finish_and_reset!(self, self.step);
504}