grit_pattern_matcher/pattern/
container.rs

1use grit_util::error::{GritPatternError, GritResult};
2
3use super::{
4    accessor::Accessor, list_index::ListIndex, patterns::Pattern, state::State, variable::Variable,
5    CallBuiltIn,
6};
7use crate::context::QueryContext;
8
9/// A `Container` represents anything which "contains" a reference to a Pattern.
10///
11/// We have three types of containers:
12/// - Variable: a variable reference (ex. `$foo`)
13/// - Accessor: a map accessor (ex. `$foo.bar`)
14/// - ListIndex: a list index (ex. `$foo[0]`)
15#[derive(Debug, Clone)]
16pub enum Container<Q: QueryContext> {
17    Variable(Variable),
18    Accessor(Box<Accessor<Q>>),
19    ListIndex(Box<ListIndex<Q>>),
20    FunctionCall(Box<CallBuiltIn<Q>>),
21}
22
23#[derive(Debug)]
24pub enum PatternOrResolved<'a, 'b, Q: QueryContext> {
25    Pattern(&'a Pattern<Q>),
26    Resolved(&'b Q::ResolvedPattern<'a>),
27    ResolvedBinding(Q::ResolvedPattern<'a>),
28}
29
30#[derive(Debug)]
31pub enum PatternOrResolvedMut<'a, 'b, Q: QueryContext> {
32    Pattern(&'a Pattern<Q>),
33    Resolved(&'b mut Q::ResolvedPattern<'a>),
34    _ResolvedBinding,
35}
36
37impl<Q: QueryContext> Container<Q> {
38    pub fn set_resolved<'a>(
39        &'a self,
40        state: &mut State<'a, Q>,
41        lang: &Q::Language<'a>,
42        value: Q::ResolvedPattern<'a>,
43    ) -> GritResult<bool> {
44        match self {
45            Container::Variable(v) => {
46                let var = state.trace_var_mut(v);
47                let content = &mut state.bindings[var.try_scope().unwrap() as usize]
48                    .last_mut()
49                    .unwrap()[var.try_index().unwrap() as usize];
50                match content.pattern {
51                    Some(Pattern::Accessor(a)) => a.set_resolved(state, lang, value),
52                    Some(Pattern::ListIndex(l)) => l.set_resolved(state, lang, value),
53                    None | Some(_) => {
54                        content.set_value(value);
55                        Ok(true)
56                    }
57                }
58            }
59            Container::Accessor(a) => a.set_resolved(state, lang, value),
60            Container::ListIndex(l) => l.set_resolved(state, lang, value),
61            Container::FunctionCall(f) => Err(GritPatternError::new(format!(
62                "You cannot assign to the result of a function call: {:?}",
63                f
64            ))),
65        }
66    }
67
68    pub fn get_pattern_or_resolved<'a, 'b>(
69        &'a self,
70        state: &'b State<'a, Q>,
71        lang: &Q::Language<'a>,
72    ) -> GritResult<Option<PatternOrResolved<'a, 'b, Q>>> {
73        match self {
74            Container::Variable(v) => v.get_pattern_or_resolved(state),
75            Container::Accessor(a) => a.get(state, lang),
76            Container::ListIndex(a) => a.get(state, lang),
77            Container::FunctionCall(f) => Err(GritPatternError::new(format!(
78                "You cannot get the value of a function call: {:?}",
79                f
80            ))),
81        }
82    }
83
84    pub fn get_pattern_or_resolved_mut<'a, 'b>(
85        &'a self,
86        state: &'b mut State<'a, Q>,
87        lang: &Q::Language<'a>,
88    ) -> GritResult<Option<PatternOrResolvedMut<'a, 'b, Q>>> {
89        match self {
90            Container::Variable(v) => v.get_pattern_or_resolved_mut(state),
91            Container::Accessor(a) => a.get_mut(state, lang),
92            Container::ListIndex(l) => l.get_mut(state, lang),
93            Container::FunctionCall(f) => Err(GritPatternError::new(format!(
94                "You cannot get the value of a function call: {:?}",
95                f
96            ))),
97        }
98    }
99}