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