grit_pattern_matcher/pattern/
functions.rs

1use super::{
2    function_definition::FunctionDefinition,
3    patterns::{Pattern, PatternName},
4    state::State,
5};
6use crate::{context::ExecContext, context::QueryContext};
7use core::fmt::Debug;
8use grit_util::{
9    error::{GritPatternError, GritResult},
10    AnalysisLogs,
11};
12
13#[derive(Debug, Clone)]
14pub struct FuncEvaluation<'a, Q: QueryContext> {
15    pub predicator: bool,
16    pub ret_val: Option<Q::ResolvedPattern<'a>>,
17}
18
19pub trait Evaluator<Q: QueryContext>: Debug {
20    fn execute_func<'a>(
21        &'a self,
22        state: &mut State<'a, Q>,
23        context: &'a Q::ExecContext<'a>,
24        logs: &mut AnalysisLogs,
25    ) -> GritResult<FuncEvaluation<Q>>;
26}
27
28#[derive(Debug, Clone)]
29pub struct CallFunction<Q: QueryContext> {
30    pub index: usize,
31    pub args: Vec<Option<Pattern<Q>>>,
32}
33
34pub trait GritCall<Q: QueryContext> {
35    fn call<'a>(
36        &'a self,
37        state: &mut State<'a, Q>,
38        context: &'a Q::ExecContext<'a>,
39        logs: &mut AnalysisLogs,
40    ) -> GritResult<Q::ResolvedPattern<'a>>;
41}
42
43impl<Q: QueryContext> CallFunction<Q> {
44    pub fn new(index: usize, args: Vec<Option<Pattern<Q>>>) -> Self {
45        Self { index, args }
46    }
47}
48
49impl<Q: QueryContext> GritCall<Q> for CallFunction<Q> {
50    fn call<'a>(
51        &'a self,
52        state: &mut State<'a, Q>,
53        context: &'a Q::ExecContext<'a>,
54        logs: &mut AnalysisLogs,
55    ) -> GritResult<Q::ResolvedPattern<'a>> {
56        let function_definition = &context.function_definitions()[self.index];
57
58        match function_definition
59            .call(state, context, &self.args, logs)?
60            .ret_val
61        {
62            Some(pattern) => Ok(pattern),
63            None => Err(GritPatternError::new(
64                "Function call did not return a value",
65            )),
66        }
67    }
68}
69
70impl<Q: QueryContext> PatternName for CallFunction<Q> {
71    fn name(&self) -> &'static str {
72        "CALL_FUNCTION"
73    }
74}
75
76#[derive(Debug, Clone)]
77pub struct CallForeignFunction<Q: QueryContext> {
78    pub index: usize,
79    pub args: Vec<Option<Pattern<Q>>>,
80}
81
82impl<Q: QueryContext> CallForeignFunction<Q> {
83    pub fn new(index: usize, args: Vec<Option<Pattern<Q>>>) -> Self {
84        Self { index, args }
85    }
86}
87
88impl<Q: QueryContext> PatternName for CallForeignFunction<Q> {
89    fn name(&self) -> &'static str {
90        "CALL_FUNCTION"
91    }
92}