1use std::collections::BTreeSet;
9use std::collections::HashMap;
10use std::collections::HashSet;
11use streaming_iterator::StreamingIterator;
12use tree_sitter::QueryCursor;
13use tree_sitter::QueryMatch;
14use tree_sitter::Tree;
15
16use crate::ast::AddEdgeAttribute;
17use crate::ast::AddGraphNodeAttribute;
18use crate::ast::Assign;
19use crate::ast::Attribute;
20use crate::ast::AttributeShorthand;
21use crate::ast::AttributeShorthands;
22use crate::ast::Call;
23use crate::ast::Capture;
24use crate::ast::Condition;
25use crate::ast::CreateEdge;
26use crate::ast::CreateGraphNode;
27use crate::ast::DeclareImmutable;
28use crate::ast::DeclareMutable;
29use crate::ast::Expression;
30use crate::ast::File;
31use crate::ast::ForIn;
32use crate::ast::If;
33use crate::ast::IntegerConstant;
34use crate::ast::ListComprehension;
35use crate::ast::ListLiteral;
36use crate::ast::Print;
37use crate::ast::RegexCapture;
38use crate::ast::Scan;
39use crate::ast::ScopedVariable;
40use crate::ast::SetComprehension;
41use crate::ast::SetLiteral;
42use crate::ast::Stanza;
43use crate::ast::Statement;
44use crate::ast::StringConstant;
45use crate::ast::UnscopedVariable;
46use crate::ast::Variable;
47use crate::execution::error::ExecutionError;
48use crate::execution::error::ResultWithExecutionError;
49use crate::execution::error::StatementContext;
50use crate::execution::CancellationFlag;
51use crate::execution::ExecutionConfig;
52use crate::graph::Graph;
53use crate::graph::SyntaxNodeID;
54use crate::graph::SyntaxNodeRef;
55use crate::graph::Value;
56use crate::variables::Globals;
57use crate::variables::MutVariables;
58use crate::variables::VariableMap;
59use crate::variables::Variables;
60use crate::Identifier;
61use crate::Location;
62
63impl File {
64 pub(super) fn execute_strict_into<'a, 'tree>(
70 &self,
71 graph: &mut Graph<'tree>,
72 tree: &'tree Tree,
73 source: &'tree str,
74 config: &ExecutionConfig,
75 cancellation_flag: &dyn CancellationFlag,
76 ) -> Result<(), ExecutionError> {
77 let mut globals = Globals::nested(config.globals);
78 self.check_globals(&mut globals)?;
79 let mut config = ExecutionConfig {
80 functions: config.functions,
81 globals: &globals,
82 lazy: config.lazy,
83 location_attr: config.location_attr.clone(),
84 variable_name_attr: config.variable_name_attr.clone(),
85 match_node_attr: config.match_node_attr.clone(),
86 };
87
88 let mut locals = VariableMap::new();
89 let mut scoped = ScopedVariables::new();
90 let current_regex_captures = Vec::new();
91 let mut function_parameters = Vec::new();
92
93 self.try_visit_matches_strict(tree, source, |stanza, mat| {
94 stanza.execute(
95 source,
96 &mat,
97 graph,
98 &mut config,
99 &mut locals,
100 &mut scoped,
101 ¤t_regex_captures,
102 &mut function_parameters,
103 &self.inherited_variables,
104 &self.shorthands,
105 cancellation_flag,
106 )
107 })?;
108
109 Ok(())
110 }
111
112 pub(super) fn try_visit_matches_strict<'tree, E, F>(
113 &self,
114 tree: &'tree Tree,
115 source: &'tree str,
116 mut visit: F,
117 ) -> Result<(), E>
118 where
119 F: FnMut(&Stanza, &QueryMatch<'_, 'tree>) -> Result<(), E>,
120 {
121 for stanza in &self.stanzas {
122 stanza.try_visit_matches_strict(tree, source, |mat| visit(stanza, mat))?;
123 }
124 Ok(())
125 }
126}
127
128struct ExecutionContext<'a, 'c, 'g, 's, 'tree> {
130 source: &'tree str,
131 graph: &'a mut Graph<'tree>,
132 config: &'a ExecutionConfig<'c, 'g>,
133 locals: &'a mut dyn MutVariables<Value>,
134 scoped: &'a mut ScopedVariables<'s>,
135 current_regex_captures: &'a Vec<String>,
136 function_parameters: &'a mut Vec<Value>,
137 mat: &'a QueryMatch<'a, 'tree>,
138 full_match_stanza_capture_index: usize,
139 error_context: StatementContext,
140 inherited_variables: &'a HashSet<Identifier>,
141 shorthands: &'a AttributeShorthands,
142 cancellation_flag: &'a dyn CancellationFlag,
143}
144
145struct ScopedVariables<'a> {
146 scopes: HashMap<SyntaxNodeID, VariableMap<'a, Value>>,
147}
148
149impl<'a> ScopedVariables<'a> {
150 fn new() -> Self {
151 Self {
152 scopes: HashMap::new(),
153 }
154 }
155
156 fn get_mut(&mut self, scope: SyntaxNodeRef) -> &mut VariableMap<'a, Value> {
157 self.scopes.entry(scope.index).or_insert(VariableMap::new())
158 }
159
160 fn try_get(&self, index: SyntaxNodeID) -> Option<&VariableMap<'a, Value>> {
161 self.scopes.get(&index)
162 }
163}
164
165impl Stanza {
166 fn execute<'a, 'g, 'l, 's, 'tree>(
167 &self,
168 source: &'tree str,
169 mat: &QueryMatch<'_, 'tree>,
170 graph: &mut Graph<'tree>,
171 config: &ExecutionConfig<'_, 'g>,
172 locals: &mut VariableMap<'l, Value>,
173 scoped: &mut ScopedVariables<'s>,
174 current_regex_captures: &Vec<String>,
175 function_parameters: &mut Vec<Value>,
176 inherited_variables: &HashSet<Identifier>,
177 shorthands: &AttributeShorthands,
178 cancellation_flag: &dyn CancellationFlag,
179 ) -> Result<(), ExecutionError> {
180 locals.clear();
181 for statement in &self.statements {
182 let error_context = {
183 let node = mat
184 .nodes_for_capture_index(self.full_match_stanza_capture_index as u32)
185 .next()
186 .expect("missing full capture");
187 StatementContext::new(&statement, &self, &node)
188 };
189 let mut exec = ExecutionContext {
190 source,
191 graph,
192 config,
193 locals,
194 scoped,
195 current_regex_captures,
196 function_parameters,
197 mat: &mat,
198 full_match_stanza_capture_index: self.full_match_stanza_capture_index,
199 error_context,
200 inherited_variables,
201 shorthands,
202 cancellation_flag,
203 };
204 statement
205 .execute(&mut exec)
206 .with_context(|| exec.error_context.into())?;
207 }
208 Ok(())
209 }
210
211 pub(super) fn try_visit_matches_strict<'tree, E, F>(
212 &self,
213 tree: &'tree Tree,
214 source: &'tree str,
215 mut visit: F,
216 ) -> Result<(), E>
217 where
218 F: FnMut(&QueryMatch<'_, 'tree>) -> Result<(), E>,
219 {
220 let mut cursor = QueryCursor::new();
221 let mut matches = cursor.matches(&self.query, tree.root_node(), source.as_bytes());
222 while let Some(mat) = matches.next() {
223 visit(mat)?;
224 }
225 Ok(())
226 }
227}
228
229impl Statement {
230 pub fn location(&self) -> Location {
231 match self {
232 Statement::DeclareImmutable(s) => s.location,
233 Statement::DeclareMutable(s) => s.location,
234 Statement::Assign(s) => s.location,
235 Statement::CreateGraphNode(s) => s.location,
236 Statement::AddGraphNodeAttribute(s) => s.location,
237 Statement::CreateEdge(s) => s.location,
238 Statement::AddEdgeAttribute(s) => s.location,
239 Statement::Scan(s) => s.location,
240 Statement::Print(s) => s.location,
241 Statement::If(s) => s.location,
242 Statement::ForIn(s) => s.location,
243 }
244 }
245
246 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
247 exec.cancellation_flag.check("executing statement")?;
248 match self {
249 Statement::DeclareImmutable(statement) => statement.execute(exec),
250 Statement::DeclareMutable(statement) => statement.execute(exec),
251 Statement::Assign(statement) => statement.execute(exec),
252 Statement::CreateGraphNode(statement) => statement.execute(exec),
253 Statement::AddGraphNodeAttribute(statement) => statement.execute(exec),
254 Statement::CreateEdge(statement) => statement.execute(exec),
255 Statement::AddEdgeAttribute(statement) => statement.execute(exec),
256 Statement::Scan(statement) => statement.execute(exec),
257 Statement::Print(statement) => statement.execute(exec),
258 Statement::If(statement) => statement.execute(exec),
259 Statement::ForIn(statement) => statement.execute(exec),
260 }
261 }
262}
263
264impl DeclareImmutable {
265 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
266 let value = self.value.evaluate(exec)?;
267 self.variable.add(exec, value, false)
268 }
269}
270
271impl DeclareMutable {
272 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
273 let value = self.value.evaluate(exec)?;
274 self.variable.add(exec, value, true)
275 }
276}
277
278impl Assign {
279 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
280 let value = self.value.evaluate(exec)?;
281 self.variable.set(exec, value)
282 }
283}
284
285impl CreateGraphNode {
286 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
287 let graph_node = exec.graph.add_graph_node();
288 self.node
289 .add_debug_attrs(&mut exec.graph[graph_node].attributes, exec.config)?;
290 if let Some(match_node_attr) = &exec.config.match_node_attr {
291 let match_node = exec
292 .mat
293 .nodes_for_capture_index(exec.full_match_stanza_capture_index as u32)
294 .next()
295 .expect("missing capture for full match");
296 let syn_node = exec.graph.add_syntax_node(match_node);
297 exec.graph[graph_node]
298 .attributes
299 .add(match_node_attr.clone(), syn_node)
300 .map_err(|_| {
301 ExecutionError::DuplicateAttribute(format!(
302 " {} on graph node ({}) in {}",
303 match_node_attr, graph_node, self,
304 ))
305 })?;
306 }
307 let value = Value::GraphNode(graph_node);
308 self.node.add(exec, value, false)
309 }
310}
311
312impl AddGraphNodeAttribute {
313 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
314 let node = self.node.evaluate(exec)?.into_graph_node_ref()?;
315 let add_attribute = |exec: &mut ExecutionContext, name: Identifier, value: Value| {
316 exec.graph[node]
317 .attributes
318 .add(name.clone(), value)
319 .map_err(|_| {
320 ExecutionError::DuplicateAttribute(format!(
321 " {} on graph node ({}) in {}",
322 name, node, self,
323 ))
324 })
325 };
326 for attribute in &self.attributes {
327 attribute.execute(exec, &add_attribute)?;
328 }
329 Ok(())
330 }
331}
332
333impl CreateEdge {
334 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
335 let source = self.source.evaluate(exec)?.into_graph_node_ref()?;
336 let sink = self.sink.evaluate(exec)?.into_graph_node_ref()?;
337 let edge = match exec.graph[source].add_edge(sink) {
338 Ok(edge) | Err(edge) => edge,
339 };
340 self.add_debug_attrs(&mut edge.attributes, exec.config)?;
341 Ok(())
342 }
343}
344
345impl AddEdgeAttribute {
346 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
347 let source = self.source.evaluate(exec)?.into_graph_node_ref()?;
348 let sink = self.sink.evaluate(exec)?.into_graph_node_ref()?;
349 let add_attribute = |exec: &mut ExecutionContext, name: Identifier, value: Value| {
350 let edge = match exec.graph[source].get_edge_mut(sink) {
351 Some(edge) => Ok(edge),
352 None => Err(ExecutionError::UndefinedEdge(format!(
353 "({} -> {}) in {}",
354 source, sink, self,
355 ))),
356 }?;
357 edge.attributes.add(name.clone(), value).map_err(|_| {
358 ExecutionError::DuplicateAttribute(format!(
359 " {} on edge ({} -> {}) in {}",
360 name, source, sink, self,
361 ))
362 })
363 };
364 for attribute in &self.attributes {
365 attribute.execute(exec, &add_attribute)?;
366 }
367 Ok(())
368 }
369}
370
371impl Scan {
372 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
373 let match_string = self.value.evaluate(exec)?.into_string()?;
374
375 let mut i = 0;
376 let mut matches = Vec::new();
377 while i < match_string.len() {
378 exec.cancellation_flag.check("processing scan matches")?;
379 matches.clear();
380 for (index, arm) in self.arms.iter().enumerate() {
381 let captures = arm.regex.captures(&match_string[i..]);
382 if let Some(captures) = captures {
383 if captures
384 .get(0)
385 .expect("missing regex capture")
386 .range()
387 .is_empty()
388 {
389 return Err(ExecutionError::EmptyRegexCapture(format!(
390 "for regular expression /{}/",
391 arm.regex
392 )));
393 }
394 matches.push((captures, index));
395 }
396 }
397
398 if matches.is_empty() {
399 return Ok(());
400 }
401
402 matches.sort_by_key(|(captures, index)| {
403 let range = captures.get(0).expect("missing regex capture").range();
404 (range.start, *index)
405 });
406
407 let (regex_captures, block_index) = &matches[0];
408 let arm = &self.arms[*block_index];
409
410 let mut current_regex_captures = Vec::new();
411 for regex_capture in regex_captures.iter() {
412 current_regex_captures
413 .push(regex_capture.map(|m| m.as_str()).unwrap_or("").to_string());
414 }
415
416 let mut arm_locals = VariableMap::nested(exec.locals);
417 let mut arm_exec = ExecutionContext {
418 source: exec.source,
419 graph: exec.graph,
420 config: exec.config,
421 locals: &mut arm_locals,
422 scoped: exec.scoped,
423 current_regex_captures: ¤t_regex_captures,
424 function_parameters: exec.function_parameters,
425 mat: exec.mat,
426 full_match_stanza_capture_index: exec.full_match_stanza_capture_index,
427 error_context: exec.error_context.clone(),
428 inherited_variables: exec.inherited_variables,
429 shorthands: exec.shorthands,
430 cancellation_flag: exec.cancellation_flag,
431 };
432
433 for statement in &arm.statements {
434 arm_exec.error_context.update_statement(statement);
435 statement
436 .execute(&mut arm_exec)
437 .with_context(|| {
438 format!("matching {} with arm \"{}\"", match_string, arm.regex,).into()
439 })
440 .with_context(|| arm_exec.error_context.clone().into())?;
441 }
442
443 i += regex_captures
444 .get(0)
445 .expect("missing regex capture")
446 .range()
447 .end;
448 }
449
450 Ok(())
451 }
452}
453
454impl Print {
455 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
456 for value in &self.values {
457 if let Expression::StringConstant(expr) = value {
458 eprint!("{}", expr.value);
459 } else {
460 let value = value.evaluate(exec)?;
461 eprint!("{:?}", value);
462 }
463 }
464 eprintln!();
465 Ok(())
466 }
467}
468
469impl If {
470 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
471 for arm in &self.arms {
472 let mut result = true;
473 for condition in &arm.conditions {
474 result &= condition.test(exec)?;
475 }
476 if result {
477 let mut arm_locals = VariableMap::nested(exec.locals);
478 let mut arm_exec = ExecutionContext {
479 source: exec.source,
480 graph: exec.graph,
481 config: exec.config,
482 locals: &mut arm_locals,
483 scoped: exec.scoped,
484 current_regex_captures: exec.current_regex_captures,
485 function_parameters: exec.function_parameters,
486 mat: exec.mat,
487 full_match_stanza_capture_index: exec.full_match_stanza_capture_index,
488 error_context: exec.error_context.clone(),
489 inherited_variables: exec.inherited_variables,
490 shorthands: exec.shorthands,
491 cancellation_flag: exec.cancellation_flag,
492 };
493 for stmt in &arm.statements {
494 arm_exec.error_context.update_statement(stmt);
495 stmt.execute(&mut arm_exec)
496 .with_context(|| arm_exec.error_context.clone().into())?;
497 }
498 break;
499 }
500 }
501 Ok(())
502 }
503}
504
505impl Condition {
506 fn test(&self, exec: &mut ExecutionContext) -> Result<bool, ExecutionError> {
507 match self {
508 Condition::Some { value, .. } => Ok(!value.evaluate(exec)?.is_null()),
509 Condition::None { value, .. } => Ok(value.evaluate(exec)?.is_null()),
510 Condition::Bool { value, .. } => Ok(value.evaluate(exec)?.into_boolean()?),
511 }
512 }
513}
514
515impl ForIn {
516 fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
517 let values = self.value.evaluate(exec)?.into_list()?;
518 let mut loop_locals = VariableMap::nested(exec.locals);
519 for value in values {
520 loop_locals.clear();
521 let mut loop_exec = ExecutionContext {
522 source: exec.source,
523 graph: exec.graph,
524 config: exec.config,
525 locals: &mut loop_locals,
526 scoped: exec.scoped,
527 current_regex_captures: exec.current_regex_captures,
528 function_parameters: exec.function_parameters,
529 mat: exec.mat,
530 full_match_stanza_capture_index: exec.full_match_stanza_capture_index,
531 error_context: exec.error_context.clone(),
532 inherited_variables: exec.inherited_variables,
533 shorthands: exec.shorthands,
534 cancellation_flag: exec.cancellation_flag,
535 };
536 self.variable.add(&mut loop_exec, value, false)?;
537 for stmt in &self.statements {
538 loop_exec.error_context.update_statement(stmt);
539 stmt.execute(&mut loop_exec)
540 .with_context(|| loop_exec.error_context.clone().into())?;
541 }
542 }
543 Ok(())
544 }
545}
546
547impl Expression {
548 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
549 match self {
550 Expression::FalseLiteral => Ok(Value::Boolean(false)),
551 Expression::NullLiteral => Ok(Value::Null),
552 Expression::TrueLiteral => Ok(Value::Boolean(true)),
553 Expression::IntegerConstant(expr) => expr.evaluate(exec),
554 Expression::StringConstant(expr) => expr.evaluate(exec),
555 Expression::ListLiteral(expr) => expr.evaluate(exec),
556 Expression::SetLiteral(expr) => expr.evaluate(exec),
557 Expression::ListComprehension(expr) => expr.evaluate(exec),
558 Expression::SetComprehension(expr) => expr.evaluate(exec),
559 Expression::Capture(expr) => expr.evaluate(exec),
560 Expression::Variable(expr) => expr.evaluate(exec),
561 Expression::Call(expr) => expr.evaluate(exec),
562 Expression::RegexCapture(expr) => expr.evaluate(exec),
563 }
564 }
565}
566
567impl IntegerConstant {
568 fn evaluate(&self, _exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
569 Ok(Value::Integer(self.value))
570 }
571}
572
573impl StringConstant {
574 fn evaluate(&self, _exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
575 Ok(Value::String(self.value.clone()))
576 }
577}
578
579impl ListLiteral {
580 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
581 let elements = self
582 .elements
583 .iter()
584 .map(|e| e.evaluate(exec))
585 .collect::<Result<_, _>>()?;
586 Ok(Value::List(elements))
587 }
588}
589
590impl ListComprehension {
591 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
592 let values = self.value.evaluate(exec)?.into_list()?;
593 let mut elements = Vec::new();
594 let mut loop_locals = VariableMap::nested(exec.locals);
595 for value in values {
596 loop_locals.clear();
597 let mut loop_exec = ExecutionContext {
598 source: exec.source,
599 graph: exec.graph,
600 config: exec.config,
601 locals: &mut loop_locals,
602 scoped: exec.scoped,
603 current_regex_captures: exec.current_regex_captures,
604 function_parameters: exec.function_parameters,
605 mat: exec.mat,
606 full_match_stanza_capture_index: exec.full_match_stanza_capture_index,
607 error_context: exec.error_context.clone(),
608 inherited_variables: exec.inherited_variables,
609 shorthands: exec.shorthands,
610 cancellation_flag: exec.cancellation_flag,
611 };
612 self.variable.add(&mut loop_exec, value, false)?;
613 let element = self.element.evaluate(&mut loop_exec)?;
614 elements.push(element);
615 }
616 Ok(Value::List(elements))
617 }
618}
619
620impl SetLiteral {
621 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
622 let elements = self
623 .elements
624 .iter()
625 .map(|e| e.evaluate(exec))
626 .collect::<Result<_, _>>()?;
627 Ok(Value::Set(elements))
628 }
629}
630
631impl SetComprehension {
632 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
633 let values = self.value.evaluate(exec)?.into_list()?;
634 let mut elements = BTreeSet::new();
635 let mut loop_locals = VariableMap::nested(exec.locals);
636 for value in values {
637 loop_locals.clear();
638 let mut loop_exec = ExecutionContext {
639 source: exec.source,
640 graph: exec.graph,
641 config: exec.config,
642 locals: &mut loop_locals,
643 scoped: exec.scoped,
644 current_regex_captures: exec.current_regex_captures,
645 function_parameters: exec.function_parameters,
646 mat: exec.mat,
647 full_match_stanza_capture_index: exec.full_match_stanza_capture_index,
648 error_context: exec.error_context.clone(),
649 inherited_variables: exec.inherited_variables,
650 shorthands: exec.shorthands,
651 cancellation_flag: exec.cancellation_flag,
652 };
653 self.variable.add(&mut loop_exec, value, false)?;
654 let element = self.element.evaluate(&mut loop_exec)?;
655 elements.insert(element);
656 }
657 Ok(Value::Set(elements))
658 }
659}
660
661impl Capture {
662 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
663 Ok(Value::from_nodes(
664 exec.graph,
665 exec.mat
666 .nodes_for_capture_index(self.stanza_capture_index as u32),
667 self.quantifier,
668 )
669 .into())
670 }
671}
672
673impl Call {
674 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
675 for parameter in &self.parameters {
676 let parameter = parameter.evaluate(exec)?;
677 exec.function_parameters.push(parameter);
678 }
679 exec.config.functions.call(
680 &self.function,
681 exec.graph,
682 exec.source,
683 &mut exec
684 .function_parameters
685 .drain(exec.function_parameters.len() - self.parameters.len()..),
686 )
687 }
688}
689
690impl RegexCapture {
691 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
692 let capture = exec
693 .current_regex_captures
694 .get(self.match_index)
695 .ok_or(ExecutionError::UndefinedRegexCapture(format!("{}", self)))?;
696 Ok(Value::String(capture.clone()))
697 }
698}
699
700impl Variable {
701 fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
702 let value = self.get(exec)?;
703 Ok(value.clone())
704 }
705}
706
707impl Variable {
708 fn get<'a>(&self, exec: &'a mut ExecutionContext) -> Result<&'a Value, ExecutionError> {
709 match self {
710 Variable::Scoped(variable) => variable.get(exec),
711 Variable::Unscoped(variable) => variable.get(exec),
712 }
713 }
714
715 fn add(
716 &self,
717 exec: &mut ExecutionContext,
718 value: Value,
719 mutable: bool,
720 ) -> Result<(), ExecutionError> {
721 match self {
722 Variable::Scoped(variable) => variable.add(exec, value, mutable),
723 Variable::Unscoped(variable) => variable.add(exec, value, mutable),
724 }
725 }
726
727 fn set(&self, exec: &mut ExecutionContext, value: Value) -> Result<(), ExecutionError> {
728 match self {
729 Variable::Scoped(variable) => variable.set(exec, value),
730 Variable::Unscoped(variable) => variable.set(exec, value),
731 }
732 }
733}
734
735impl ScopedVariable {
736 fn get<'a>(&self, exec: &'a mut ExecutionContext) -> Result<&'a Value, ExecutionError> {
737 let scope = self.scope.evaluate(exec)?;
738 let scope = match scope {
739 Value::SyntaxNode(scope) => scope,
740 _ => {
741 return Err(ExecutionError::InvalidVariableScope(format!(
742 "got {}",
743 scope
744 )))
745 }
746 };
747
748 if let Some(value) = exec
750 .scoped
751 .try_get(scope.index)
752 .and_then(|v| v.get(&self.name))
753 {
754 return Ok(value);
755 }
756
757 if exec.inherited_variables.contains(&self.name) {
759 let mut parent = exec
760 .graph
761 .syntax_nodes
762 .get(&scope.index)
763 .and_then(|n| n.parent());
764 while let Some(scope) = parent {
765 if let Some(value) = exec
766 .scoped
767 .try_get(scope.id() as u32)
768 .and_then(|v| v.get(&self.name))
769 {
770 return Ok(value);
771 }
772 parent = scope.parent();
773 }
774 }
775
776 Err(ExecutionError::UndefinedVariable(format!(
777 "{} on node {}",
778 self, scope
779 )))
780 }
781
782 fn add(
783 &self,
784 exec: &mut ExecutionContext,
785 value: Value,
786 mutable: bool,
787 ) -> Result<(), ExecutionError> {
788 let scope = self.scope.evaluate(exec)?;
789 let scope = match scope {
790 Value::SyntaxNode(scope) => scope,
791 _ => {
792 return Err(ExecutionError::InvalidVariableScope(format!(
793 "got {}",
794 scope
795 )))
796 }
797 };
798 let variables = exec.scoped.get_mut(scope);
799 variables
800 .add(self.name.clone(), value, mutable)
801 .map_err(|_| ExecutionError::DuplicateVariable(format!("{}", self)))
802 }
803
804 fn set(&self, exec: &mut ExecutionContext, value: Value) -> Result<(), ExecutionError> {
805 let scope = self.scope.evaluate(exec)?;
806 let scope = match scope {
807 Value::SyntaxNode(scope) => scope,
808 _ => {
809 return Err(ExecutionError::InvalidVariableScope(format!(
810 "got {}",
811 scope,
812 )))
813 }
814 };
815 let variables = exec.scoped.get_mut(scope);
816 variables
817 .set(self.name.clone(), value)
818 .map_err(|_| ExecutionError::DuplicateVariable(format!("{}", self)))
819 }
820}
821
822impl UnscopedVariable {
823 fn get<'a>(&self, exec: &'a mut ExecutionContext) -> Result<&'a Value, ExecutionError> {
824 if let Some(value) = exec.config.globals.get(&self.name) {
825 Some(value)
826 } else {
827 exec.locals.get(&self.name)
828 }
829 .ok_or_else(|| ExecutionError::UndefinedVariable(format!("{}", self)))
830 }
831
832 fn add(
833 &self,
834 exec: &mut ExecutionContext,
835 value: Value,
836 mutable: bool,
837 ) -> Result<(), ExecutionError> {
838 if exec.config.globals.get(&self.name).is_some() {
839 return Err(ExecutionError::DuplicateVariable(format!(
840 " global {}",
841 self,
842 )));
843 }
844 exec.locals
845 .add(self.name.clone(), value, mutable)
846 .map_err(|_| ExecutionError::DuplicateVariable(format!(" local {}", self)))
847 }
848
849 fn set(&self, exec: &mut ExecutionContext, value: Value) -> Result<(), ExecutionError> {
850 if exec.config.globals.get(&self.name).is_some() {
851 return Err(ExecutionError::CannotAssignImmutableVariable(format!(
852 " global {}",
853 self,
854 )));
855 }
856 exec.locals.set(self.name.clone(), value).map_err(|_| {
857 if exec.locals.get(&self.name).is_some() {
858 ExecutionError::CannotAssignImmutableVariable(format!("{}", self))
859 } else {
860 ExecutionError::UndefinedVariable(format!("{}", self))
861 }
862 })
863 }
864}
865
866impl Attribute {
867 fn execute<F>(
868 &self,
869 exec: &mut ExecutionContext,
870 add_attribute: &F,
871 ) -> Result<(), ExecutionError>
872 where
873 F: Fn(&mut ExecutionContext, Identifier, Value) -> Result<(), ExecutionError>,
874 {
875 exec.cancellation_flag.check("executing attribute")?;
876 let value = self.value.evaluate(exec)?;
877 if let Some(shorthand) = exec.shorthands.get(&self.name) {
878 shorthand.execute(exec, add_attribute, value)
879 } else {
880 add_attribute(exec, self.name.clone(), value)
881 }
882 }
883}
884
885impl AttributeShorthand {
886 fn execute<F>(
887 &self,
888 exec: &mut ExecutionContext,
889 add_attribute: &F,
890 value: Value,
891 ) -> Result<(), ExecutionError>
892 where
893 F: Fn(&mut ExecutionContext, Identifier, Value) -> Result<(), ExecutionError>,
894 {
895 let mut shorthand_locals = VariableMap::new();
896 let mut shorthand_exec = ExecutionContext {
897 source: exec.source,
898 graph: exec.graph,
899 config: exec.config,
900 locals: &mut shorthand_locals,
901 scoped: exec.scoped,
902 current_regex_captures: exec.current_regex_captures,
903 function_parameters: exec.function_parameters,
904 mat: exec.mat,
905 full_match_stanza_capture_index: exec.full_match_stanza_capture_index,
906 error_context: exec.error_context.clone(),
907 inherited_variables: exec.inherited_variables,
908 shorthands: exec.shorthands,
909 cancellation_flag: exec.cancellation_flag,
910 };
911 self.variable.add(&mut shorthand_exec, value, false)?;
912 for attr in &self.attributes {
913 attr.execute(&mut shorthand_exec, add_attribute)?;
914 }
915 Ok(())
916 }
917}