grit_pattern_matcher/
effects.rs1use crate::context::ExecContext;
2use crate::pattern::ResolvedPattern;
3use crate::{
4 context::QueryContext,
5 pattern::{Pattern, PatternOrResolved, State},
6};
7use grit_util::error::GritResult;
8use grit_util::{error::GritPatternError, EffectKind};
9
10#[derive(Debug, Clone)]
11pub struct Effect<'a, Q: QueryContext> {
12 pub binding: Q::Binding<'a>,
13 pub pattern: Q::ResolvedPattern<'a>,
14 pub kind: EffectKind,
15}
16
17pub fn insert_effect<'a, Q: QueryContext>(
18 left: &PatternOrResolved<'a, '_, Q>,
19 mut replacement: Q::ResolvedPattern<'a>,
20 state: &mut State<'a, Q>,
21 context: &'a Q::ExecContext<'a>,
22) -> GritResult<bool> {
23 match left {
24 PatternOrResolved::Pattern(Pattern::Variable(var)) => {
25 let var = state.trace_var_mut(var);
26 if let Some(base) = state.bindings[var.try_scope().unwrap() as usize]
27 .last_mut()
28 .unwrap()[var.try_index().unwrap() as usize]
29 .value
30 .as_mut()
31 {
32 base.extend(replacement, &mut state.effects, context.language())?;
33 Ok(true)
34 } else {
35 Err(GritPatternError::new(format!(
36 "Variable {} is not bound",
37 state.bindings[var.try_scope().unwrap() as usize]
38 .last()
39 .unwrap()[var.try_index().unwrap() as usize]
40 .name
41 )))
42 }
43 }
44 PatternOrResolved::Resolved(resolved) => {
45 let Some(bindings) = resolved.get_bindings() else {
46 return Err(
47 GritPatternError::new("variable on left hand side of insert side-conditions can only be bound to bindings")
48 );
49 };
50 let effects: GritResult<Vec<_>> = bindings
51 .map(|binding| {
52 let is_first = !state.effects.iter().any(|e| e.binding == binding);
53 replacement.normalize_insert(&binding, is_first, context.language())?;
54 Ok(Effect {
55 binding,
56 pattern: replacement.clone(),
57 kind: EffectKind::Insert,
58 })
59 })
60 .collect();
61 let effects = effects?;
62 state.effects.extend(effects);
63 Ok(true)
64 }
65 _ => Err(GritPatternError::new(
66 "Invalid left-hand side for insert operation",
67 )),
68 }
69}