Skip to main content

bc_envelope_pattern/pattern/
matcher.rs

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