grit_pattern_matcher/pattern/
where.rs

1use super::{
2    functions::Evaluator,
3    patterns::{Matcher, Pattern, PatternName},
4    predicates::Predicate,
5    State,
6};
7use crate::context::QueryContext;
8use core::fmt::Debug;
9use grit_util::{error::GritResult, AnalysisLogs};
10
11#[derive(Debug, Clone)]
12pub struct Where<Q: QueryContext> {
13    pub pattern: Pattern<Q>,
14    pub side_condition: Predicate<Q>,
15}
16
17impl<Q: QueryContext> Where<Q> {
18    pub fn new(pattern: Pattern<Q>, side_condition: Predicate<Q>) -> Self {
19        Self {
20            pattern,
21            side_condition,
22        }
23    }
24}
25
26impl<Q: QueryContext> PatternName for Where<Q> {
27    fn name(&self) -> &'static str {
28        "WHERE"
29    }
30}
31
32impl<Q: QueryContext> Matcher<Q> for Where<Q> {
33    // order here is pattern then side condition, do we prefer side condition then pattern?
34    // should the state be reset on failure?
35    fn execute<'a>(
36        &'a self,
37        binding: &Q::ResolvedPattern<'a>,
38        init_state: &mut State<'a, Q>,
39        context: &'a Q::ExecContext<'a>,
40        logs: &mut AnalysisLogs,
41    ) -> GritResult<bool> {
42        let mut cur_state = init_state.clone();
43        if !self
44            .pattern
45            .execute(binding, &mut cur_state, context, logs)?
46        {
47            return Ok(false);
48        }
49        if self
50            .side_condition
51            .execute_func(&mut cur_state, context, logs)?
52            .predicator
53        {
54            *init_state = cur_state;
55            Ok(true)
56        } else {
57            Ok(false)
58        }
59    }
60}