1use std::collections::HashMap;
11use std::sync::Arc;
12
13use crate::execution::error::ExecutionError;
14use crate::graph::Graph;
15use crate::graph::Value;
16use crate::Identifier;
17
18pub trait Function {
27 fn call(
28 &self,
29 graph: &mut Graph,
30 source: &str,
31 parameters: &mut dyn Parameters,
32 ) -> Result<Value, ExecutionError>;
33}
34
35pub trait Parameters {
54 fn param(&mut self) -> Result<Value, ExecutionError>;
57
58 fn finish(&mut self) -> Result<(), ExecutionError>;
60}
61
62impl<I> Parameters for I
63where
64 I: Iterator<Item = Value>,
65{
66 fn param(&mut self) -> Result<Value, ExecutionError> {
67 let value = self
68 .next()
69 .ok_or(ExecutionError::InvalidParameters(format!(
70 "expected more parameters"
71 )))?;
72 Ok(value)
73 }
74
75 fn finish(&mut self) -> Result<(), ExecutionError> {
76 let value = self.next();
77 if value.is_some() {
78 return Err(ExecutionError::InvalidParameters(format!(
79 "unexpected extra parameter"
80 )));
81 }
82 Ok(())
83 }
84}
85
86#[derive(Default)]
88pub struct Functions {
89 functions: HashMap<Identifier, Arc<dyn Function + Send + Sync>>,
90}
91
92impl Functions {
93 pub fn new() -> Functions {
95 Functions::default()
96 }
97
98 pub fn stdlib() -> Functions {
101 let mut functions = Functions::new();
102 functions.add(Identifier::from("eq"), stdlib::Eq);
104 functions.add(Identifier::from("is-null"), stdlib::IsNull);
105 functions.add(
107 Identifier::from("named-child-index"),
108 stdlib::syntax::NamedChildIndex,
109 );
110 functions.add(Identifier::from("source-text"), stdlib::syntax::SourceText);
111 functions.add(Identifier::from("start-row"), stdlib::syntax::StartRow);
112 functions.add(
113 Identifier::from("start-column"),
114 stdlib::syntax::StartColumn,
115 );
116 functions.add(Identifier::from("end-row"), stdlib::syntax::EndRow);
117 functions.add(Identifier::from("end-column"), stdlib::syntax::EndColumn);
118 functions.add(Identifier::from("node-type"), stdlib::syntax::NodeType);
119 functions.add(
120 Identifier::from("named-child-count"),
121 stdlib::syntax::NamedChildCount,
122 );
123 functions.add(Identifier::from("node"), stdlib::graph::Node);
125 functions.add(Identifier::from("not"), stdlib::bool::Not);
127 functions.add(Identifier::from("and"), stdlib::bool::And);
128 functions.add(Identifier::from("or"), stdlib::bool::Or);
129 functions.add(Identifier::from("plus"), stdlib::math::Plus);
131 functions.add(Identifier::from("format"), stdlib::string::Format);
133 functions.add(Identifier::from("replace"), stdlib::string::Replace);
134 functions.add(Identifier::from("concat"), stdlib::list::Concat);
136 functions.add(Identifier::from("is-empty"), stdlib::list::IsEmpty);
137 functions.add(Identifier::from("join"), stdlib::list::Join);
138 functions.add(Identifier::from("length"), stdlib::list::Length);
139 functions
140 }
141
142 pub fn add<F>(&mut self, name: Identifier, function: F)
144 where
145 F: Function + Send + Sync + 'static,
146 {
147 self.functions.insert(name, Arc::new(function));
148 }
149
150 pub fn call(
152 &self,
153 name: &Identifier,
154 graph: &mut Graph,
155 source: &str,
156 parameters: &mut dyn Parameters,
157 ) -> Result<Value, ExecutionError> {
158 let function = self
159 .functions
160 .get(name)
161 .ok_or(ExecutionError::UndefinedFunction(format!("{}", name)))?;
162 function.call(graph, source, parameters)
163 }
164}
165
166pub mod stdlib {
168 use regex::Regex;
169
170 use crate::execution::error::ExecutionError;
171 use crate::graph::Graph;
172 use crate::graph::Value;
173
174 use super::Function;
175 use super::Parameters;
176
177 pub struct Eq;
179
180 impl Function for Eq {
181 fn call(
182 &self,
183 _graph: &mut Graph,
184 _source: &str,
185 parameters: &mut dyn Parameters,
186 ) -> Result<Value, ExecutionError> {
187 let left = parameters.param()?;
188 let right = parameters.param()?;
189 parameters.finish()?;
190
191 match &left {
192 Value::Null => match right {
193 Value::Null => return Ok(true.into()),
194 _ => return Ok(false.into()),
195 },
196 Value::Boolean(left) => match &right {
197 Value::Null => return Ok(false.into()),
198 Value::Boolean(right) => return Ok((left == right).into()),
199 _ => {}
200 },
201 Value::Integer(left) => match &right {
202 Value::Null => return Ok(false.into()),
203 Value::Integer(right) => return Ok((left == right).into()),
204 _ => {}
205 },
206 Value::String(left) => match &right {
207 Value::Null => return Ok(false.into()),
208 Value::String(right) => return Ok((left == right).into()),
209 _ => {}
210 },
211 Value::List(left) => match &right {
212 Value::Null => return Ok(false.into()),
213 Value::List(right) => return Ok((left == right).into()),
214 _ => {}
215 },
216 Value::Set(left) => match &right {
217 Value::Null => return Ok(false.into()),
218 Value::Set(right) => return Ok((left == right).into()),
219 _ => {}
220 },
221 Value::SyntaxNode(left) => match &right {
222 Value::Null => return Ok(false.into()),
223 Value::SyntaxNode(right) => return Ok((left == right).into()),
224 _ => {}
225 },
226 Value::GraphNode(left) => match &right {
227 Value::Null => return Ok(false.into()),
228 Value::GraphNode(right) => return Ok((left == right).into()),
229 _ => {}
230 },
231 };
232 Err(ExecutionError::FunctionFailed(
233 "eq".into(),
234 format!(
235 "Cannot compare values of different types: {} and {}",
236 left, right
237 ),
238 ))
239 }
240 }
241
242 pub struct IsNull;
244
245 impl Function for IsNull {
246 fn call(
247 &self,
248 _graph: &mut Graph,
249 _source: &str,
250 parameters: &mut dyn Parameters,
251 ) -> Result<Value, ExecutionError> {
252 let parameter = parameters.param()?;
253 parameters.finish()?;
254 let result = if let Value::Null = parameter {
255 true
256 } else {
257 false
258 };
259 Ok(result.into())
260 }
261 }
262
263 pub mod syntax {
264 use super::*;
265
266 pub struct NamedChildIndex;
269
270 impl Function for NamedChildIndex {
271 fn call(
272 &self,
273 graph: &mut Graph,
274 _source: &str,
275 parameters: &mut dyn Parameters,
276 ) -> Result<Value, ExecutionError> {
277 let node = graph[parameters.param()?.into_syntax_node_ref()?];
278 parameters.finish()?;
279 let parent = match node.parent() {
280 Some(parent) => parent,
281 None => {
282 return Err(ExecutionError::FunctionFailed(
283 "named-child-index".into(),
284 format!("Cannot call named-child-index on the root node"),
285 ))
286 }
287 };
288 let mut tree_cursor = parent.walk();
289 let index = parent
290 .named_children(&mut tree_cursor)
291 .position(|child| child == node)
292 .ok_or(ExecutionError::FunctionFailed(
293 "named-child-index".into(),
294 format!("Called named-child-index on a non-named child"),
295 ))?;
296 Ok(Value::Integer(index as u32))
297 }
298 }
299
300 pub struct SourceText;
303
304 impl Function for SourceText {
305 fn call(
306 &self,
307 graph: &mut Graph,
308 source: &str,
309 parameters: &mut dyn Parameters,
310 ) -> Result<Value, ExecutionError> {
311 let node = graph[parameters.param()?.into_syntax_node_ref()?];
312 parameters.finish()?;
313 Ok(Value::String(source[node.byte_range()].to_string()))
314 }
315 }
316
317 pub struct StartRow;
320
321 impl Function for StartRow {
322 fn call(
323 &self,
324 graph: &mut Graph,
325 _source: &str,
326 parameters: &mut dyn Parameters,
327 ) -> Result<Value, ExecutionError> {
328 let node = graph[parameters.param()?.into_syntax_node_ref()?];
329 parameters.finish()?;
330 Ok(Value::Integer(node.start_position().row as u32))
331 }
332 }
333
334 pub struct StartColumn;
338
339 impl Function for StartColumn {
340 fn call(
341 &self,
342 graph: &mut Graph,
343 _source: &str,
344 parameters: &mut dyn Parameters,
345 ) -> Result<Value, ExecutionError> {
346 let node = graph[parameters.param()?.into_syntax_node_ref()?];
347 parameters.finish()?;
348 Ok(Value::Integer(node.start_position().column as u32))
349 }
350 }
351
352 pub struct EndRow;
355
356 impl Function for EndRow {
357 fn call(
358 &self,
359 graph: &mut Graph,
360 _source: &str,
361 parameters: &mut dyn Parameters,
362 ) -> Result<Value, ExecutionError> {
363 let node = graph[parameters.param()?.into_syntax_node_ref()?];
364 parameters.finish()?;
365 Ok(Value::Integer(node.end_position().row as u32))
366 }
367 }
368
369 pub struct EndColumn;
372
373 impl Function for EndColumn {
374 fn call(
375 &self,
376 graph: &mut Graph,
377 _source: &str,
378 parameters: &mut dyn Parameters,
379 ) -> Result<Value, ExecutionError> {
380 let node = graph[parameters.param()?.into_syntax_node_ref()?];
381 parameters.finish()?;
382 Ok(Value::Integer(node.end_position().column as u32))
383 }
384 }
385
386 pub struct NodeType;
389
390 impl Function for NodeType {
391 fn call(
392 &self,
393 graph: &mut Graph,
394 _source: &str,
395 parameters: &mut dyn Parameters,
396 ) -> Result<Value, ExecutionError> {
397 let node = graph[parameters.param()?.into_syntax_node_ref()?];
398 parameters.finish()?;
399 Ok(Value::String(node.kind().to_string()))
400 }
401 }
402
403 pub struct NamedChildCount;
407
408 impl Function for NamedChildCount {
409 fn call(
410 &self,
411 graph: &mut Graph,
412 _source: &str,
413 parameters: &mut dyn Parameters,
414 ) -> Result<Value, ExecutionError> {
415 let node = graph[parameters.param()?.into_syntax_node_ref()?];
416 parameters.finish()?;
417 Ok(Value::Integer(node.named_child_count() as u32))
418 }
419 }
420 }
421
422 pub mod graph {
423 use super::*;
424
425 pub struct Node;
427
428 impl Function for Node {
429 fn call(
430 &self,
431 graph: &mut Graph,
432 _source: &str,
433 parameters: &mut dyn Parameters,
434 ) -> Result<Value, ExecutionError> {
435 parameters.finish()?;
436 let node = graph.add_graph_node();
437 Ok(Value::GraphNode(node))
438 }
439 }
440 }
441
442 pub mod bool {
443 use super::*;
444
445 pub struct Not;
447
448 impl Function for Not {
449 fn call(
450 &self,
451 _graph: &mut Graph,
452 _source: &str,
453 parameters: &mut dyn Parameters,
454 ) -> Result<Value, ExecutionError> {
455 let result = !parameters.param()?.as_boolean()?;
456 parameters.finish()?;
457 Ok(result.into())
458 }
459 }
460
461 pub struct And;
463
464 impl Function for And {
465 fn call(
466 &self,
467 _graph: &mut Graph,
468 _source: &str,
469 parameters: &mut dyn Parameters,
470 ) -> Result<Value, ExecutionError> {
471 let mut result = true;
472 while let Ok(parameter) = parameters.param() {
473 result &= parameter.as_boolean()?;
474 }
475 Ok(result.into())
476 }
477 }
478
479 pub struct Or;
481
482 impl Function for Or {
483 fn call(
484 &self,
485 _graph: &mut Graph,
486 _source: &str,
487 parameters: &mut dyn Parameters,
488 ) -> Result<Value, ExecutionError> {
489 let mut result = false;
490 while let Ok(parameter) = parameters.param() {
491 result |= parameter.as_boolean()?;
492 }
493 Ok(result.into())
494 }
495 }
496 }
497
498 pub mod math {
499 use super::*;
500
501 pub struct Plus;
503
504 impl Function for Plus {
505 fn call(
506 &self,
507 _graph: &mut Graph,
508 _source: &str,
509 parameters: &mut dyn Parameters,
510 ) -> Result<Value, ExecutionError> {
511 let mut result = 0;
512 while let Ok(parameter) = parameters.param() {
513 result += parameter.as_integer()?;
514 }
515 Ok(Value::Integer(result))
516 }
517 }
518 }
519
520 pub mod string {
521 use super::*;
522
523 pub struct Format;
525
526 impl Function for Format {
527 fn call(
528 &self,
529 _graph: &mut Graph,
530 _source: &str,
531 parameters: &mut dyn Parameters,
532 ) -> Result<Value, ExecutionError> {
533 let format = parameters.param()?.into_string()?;
534 let mut result = String::new();
535 let mut it = format.chars().enumerate().into_iter();
536 while let Some((_, c)) = it.next() {
537 match c {
538 '{' => match it.next() {
539 Some((_, '{')) => result.push('{'),
540 Some((_, '}')) => {
541 let value = parameters.param()?;
542 result += &value.to_string();
543 },
544 Some((i, c)) => return Err(ExecutionError::FunctionFailed("format".into(), format!("Unexpected character `{}` after `{{` at position {} in format string `{}`. Expected `{{` or `}}`.", c, i + 1, format))),
545 None => return Err(ExecutionError::FunctionFailed("format".into(), format!("Unexpected end of format string `{}` after `{{`. Expected `{{` or `}}`.", format))),
546 },
547 '}' => match it.next() {
548 Some((_, '}')) => result.push('}'),
549 Some((i, c)) => return Err(ExecutionError::FunctionFailed("format".into(), format!("Unexpected character `{}` after `}}` at position {} in format string `{}`. Expected `}}`.", c, i + 1, format))),
550 None => return Err(ExecutionError::FunctionFailed("format".into(), format!("Unexpected end of format string `{}` after `{{. Expected `}}`.", format))),
551 },
552 c => result.push(c),
553 }
554 }
555 parameters.finish()?;
556 Ok(result.into())
557 }
558 }
559
560 pub struct Replace;
562
563 impl Function for Replace {
564 fn call(
565 &self,
566 _graph: &mut Graph,
567 _source: &str,
568 parameters: &mut dyn Parameters,
569 ) -> Result<Value, ExecutionError> {
570 let text = parameters.param()?.into_string()?;
571 let pattern = parameters.param()?.into_string()?;
572 let pattern = Regex::new(&pattern).map_err(|e| {
573 ExecutionError::FunctionFailed("replace".into(), format!("{}", e))
574 })?;
575 let replacement = parameters.param()?.into_string()?;
576 parameters.finish()?;
577 Ok(Value::String(
578 pattern.replace_all(&text, replacement.as_str()).to_string(),
579 ))
580 }
581 }
582 }
583
584 pub mod list {
585 use super::*;
586
587 pub struct Concat;
589
590 impl Function for Concat {
591 fn call(
592 &self,
593 _graph: &mut Graph,
594 _source: &str,
595 parameters: &mut dyn Parameters,
596 ) -> Result<Value, ExecutionError> {
597 let mut result = Vec::new();
598 while let Ok(list) = parameters.param() {
599 result.append(&mut list.into_list()?);
600 }
601 Ok(result.into())
602 }
603 }
604
605 pub struct IsEmpty;
607
608 impl Function for IsEmpty {
609 fn call(
610 &self,
611 _graph: &mut Graph,
612 _source: &str,
613 parameters: &mut dyn Parameters,
614 ) -> Result<Value, ExecutionError> {
615 let list = parameters.param()?.into_list()?;
616 Ok(list.is_empty().into())
617 }
618 }
619
620 pub struct Join;
622
623 impl Function for Join {
624 fn call(
625 &self,
626 _graph: &mut Graph,
627 _source: &str,
628 parameters: &mut dyn Parameters,
629 ) -> Result<Value, ExecutionError> {
630 let list = parameters.param()?.into_list()?;
631 let sep = match parameters.param() {
632 Ok(sep) => sep.into_string()?,
633 Err(_) => "".to_string(),
634 };
635 parameters.finish()?;
636 let result = list
637 .into_iter()
638 .map(|x| format!("{}", x))
639 .collect::<Vec<_>>()
640 .join(&sep);
641 Ok(result.into())
642 }
643 }
644
645 pub struct Length;
647
648 impl Function for Length {
649 fn call(
650 &self,
651 _graph: &mut Graph,
652 _source: &str,
653 parameters: &mut dyn Parameters,
654 ) -> Result<Value, ExecutionError> {
655 let list = parameters.param()?.into_list()?;
656 Ok((list.len() as u32).into())
657 }
658 }
659 }
660}