bc_envelope_pattern/pattern/
matcher.rs

1use std::collections::HashMap;
2
3use bc_envelope::Envelope;
4
5use crate::pattern::{Pattern, vm::Instr};
6
7/// A sequence of envelopes that match a pattern, starting from the root of the envelope.
8pub type Path = Vec<Envelope>;
9
10#[doc(hidden)]
11pub trait Matcher: std::fmt::Debug + std::fmt::Display + Clone {
12    /// Return all matching paths along with any named captures.
13    fn paths_with_captures(
14        &self,
15        _envelope: &Envelope,
16    ) -> (Vec<Path>, HashMap<String, Vec<Path>>) {
17        unimplemented!(
18            "Matcher::paths_with_captures not implemented for {:?}",
19            self
20        )
21    }
22
23    /// Return only the matching paths, discarding any captures.
24    fn paths(&self, envelope: &Envelope) -> Vec<Path> {
25        self.paths_with_captures(envelope).0
26    }
27
28    fn matches(&self, envelope: &Envelope) -> bool {
29        !self.paths(envelope).is_empty()
30    }
31
32    fn compile(
33        &self,
34        _code: &mut Vec<Instr>,
35        _literals: &mut Vec<Pattern>,
36        _captures: &mut Vec<String>,
37    ) {
38        unimplemented!("Matcher::compile not implemented for {:?}", self);
39    }
40
41    /// Should return true if the Display of the matcher is *complex*,
42    /// i.e. contains nested patterns or other complex structures
43    /// that require its text rendering to be surrounded by grouping
44    /// parentheses.
45    fn is_complex(&self) -> bool { false }
46}
47
48/// Helper you can reuse in many impls: push self into `literals` and
49/// emit a single MatchPredicate.
50pub fn compile_as_atomic(
51    pat: &Pattern,
52    code: &mut Vec<Instr>,
53    lits: &mut Vec<Pattern>,
54    _captures: &mut Vec<String>,
55) {
56    let _ = _captures;
57    let idx = lits.len();
58    lits.push(pat.clone());
59    code.push(Instr::MatchPredicate(idx));
60}