grit_pattern_matcher/pattern/
pattern_definition.rs1use super::{
2 patterns::{Matcher, Pattern},
3 variable::Variable,
4 State,
5};
6use crate::context::QueryContext;
7use grit_util::{
8 error::{GritPatternError, GritResult},
9 AnalysisLogs,
10};
11use rand::Rng as _;
12
13#[derive(Clone, Debug)]
14pub enum PatternDefinitionInternal {
15 Static { scope: usize },
16 Dynamic,
17}
18
19#[derive(Clone, Debug)]
20pub struct PatternDefinition<Q: QueryContext> {
21 pub name: String,
22 pattern: Pattern<Q>,
23 params: Vec<(String, Variable)>,
24 internal: PatternDefinitionInternal,
25}
26
27impl<Q: QueryContext> PatternDefinition<Q> {
28 pub fn new(
29 name: String,
30 scope: usize,
31 params: Vec<(String, Variable)>,
32 pattern: Pattern<Q>,
33 ) -> Self {
34 Self {
35 name,
36 pattern,
37 params,
38 internal: PatternDefinitionInternal::Static { scope },
39 }
40 }
41
42 pub fn new_ephemeral(params: Vec<(String, Variable)>, pattern: Pattern<Q>) -> Self {
45 let random_name = format!("<bubble:{}>", rand::thread_rng().gen::<u32>());
46
47 Self {
48 name: random_name,
49 pattern,
50 params,
51 internal: PatternDefinitionInternal::Dynamic,
52 }
53 }
54
55 pub fn try_scope(&self) -> GritResult<usize> {
56 match &self.internal {
57 PatternDefinitionInternal::Static { scope } => Ok(*scope),
58 PatternDefinitionInternal::Dynamic {} => Err(GritPatternError::new(
59 "Dynamic pattern definitions do not have a scope",
60 )),
61 }
62 }
63
64 pub fn replace_pattern(&mut self, new_pattern: Pattern<Q>) {
65 self.pattern = new_pattern;
66 }
67
68 fn get_scope(&self, state: &mut State<'_, Q>) -> usize {
69 match &self.internal {
70 PatternDefinitionInternal::Static { scope } => *scope,
71 PatternDefinitionInternal::Dynamic { .. } => {
72 state.register_pattern_definition(&self.name)
73 }
74 }
75 }
76
77 pub(crate) fn call<'a>(
78 &'a self,
79 state: &mut State<'a, Q>,
80 binding: &Q::ResolvedPattern<'a>,
81 context: &'a Q::ExecContext<'a>,
82 logs: &mut AnalysisLogs,
83 args: &'a [Option<Pattern<Q>>],
84 ) -> GritResult<bool> {
85 let scope = self.get_scope(state);
86 let tracker = state.enter_scope(scope, args);
87
88 let res = self.pattern.execute(binding, state, context, logs);
89 state.exit_scope(tracker);
90
91 let fn_state = state.bindings[scope].pop().unwrap();
92 let cur_fn_state = state.bindings[scope].last_mut().unwrap();
93 for (cur, last) in cur_fn_state.iter_mut().zip(fn_state) {
94 cur.value_history.extend(last.value_history)
95 }
96 res
97 }
98
99 pub fn params(&self) -> &Vec<(String, Variable)> {
100 &self.params
101 }
102
103 pub fn pattern(&self) -> &Pattern<Q> {
104 &self.pattern
105 }
106}