1use std::collections::HashMap;
18use std::fmt;
19use std::slice;
20
21use itertools::Itertools as _;
22use pest::RuleType;
23use pest::iterators::Pair;
24use pest::iterators::Pairs;
25
26pub use crate::symbol_util::escape_string;
27pub use crate::symbol_util::format_string;
28use crate::symbol_util::unescape_char;
29
30#[derive(Debug)]
35pub struct Diagnostics<T> {
36 diagnostics: Vec<T>,
38}
39
40impl<T> Diagnostics<T> {
41 pub fn new() -> Self {
43 Self {
44 diagnostics: Vec::new(),
45 }
46 }
47
48 pub fn is_empty(&self) -> bool {
50 self.diagnostics.is_empty()
51 }
52
53 pub fn len(&self) -> usize {
55 self.diagnostics.len()
56 }
57
58 pub fn iter(&self) -> slice::Iter<'_, T> {
60 self.diagnostics.iter()
61 }
62
63 pub fn add_warning(&mut self, diag: T) {
65 self.diagnostics.push(diag);
66 }
67
68 pub fn extend_with<U>(&mut self, diagnostics: Diagnostics<U>, mut f: impl FnMut(U) -> T) {
71 self.diagnostics
72 .extend(diagnostics.diagnostics.into_iter().map(&mut f));
73 }
74}
75
76impl<T> Default for Diagnostics<T> {
77 fn default() -> Self {
78 Self::new()
79 }
80}
81
82impl<'a, T> IntoIterator for &'a Diagnostics<T> {
83 type Item = &'a T;
84 type IntoIter = slice::Iter<'a, T>;
85
86 fn into_iter(self) -> Self::IntoIter {
87 self.iter()
88 }
89}
90
91#[derive(Clone, Debug, Eq, PartialEq)]
93pub struct ExpressionNode<'i, T> {
94 pub kind: T,
96 pub span: pest::Span<'i>,
98}
99
100impl<'i, T> ExpressionNode<'i, T> {
101 pub fn new(kind: T, span: pest::Span<'i>) -> Self {
103 Self { kind, span }
104 }
105}
106
107#[derive(Clone, Debug, Eq, PartialEq)]
109pub struct PatternNode<'i, T> {
110 pub name: &'i str,
112 pub name_span: pest::Span<'i>,
114 pub value: ExpressionNode<'i, T>,
116}
117
118#[derive(Clone, Debug, Eq, PartialEq)]
120pub struct FunctionCallNode<'i, T> {
121 pub name: &'i str,
123 pub name_span: pest::Span<'i>,
125 pub args: Vec<ExpressionNode<'i, T>>,
127 pub keyword_args: Vec<KeywordArgument<'i, T>>,
129 pub args_span: pest::Span<'i>,
131}
132
133#[derive(Clone, Debug, Eq, PartialEq)]
135pub struct KeywordArgument<'i, T> {
136 pub name: &'i str,
138 pub name_span: pest::Span<'i>,
140 pub value: ExpressionNode<'i, T>,
142}
143
144impl<'i, T> FunctionCallNode<'i, T> {
145 pub fn arity(&self) -> usize {
147 self.args.len() + self.keyword_args.len()
148 }
149
150 pub fn expect_no_arguments(&self) -> Result<(), InvalidArguments<'i>> {
152 let ([], []) = self.expect_arguments()?;
153 Ok(())
154 }
155
156 pub fn expect_exact_arguments<const N: usize>(
158 &self,
159 ) -> Result<&[ExpressionNode<'i, T>; N], InvalidArguments<'i>> {
160 let (args, []) = self.expect_arguments()?;
161 Ok(args)
162 }
163
164 #[expect(clippy::type_complexity)]
174 pub fn expect_some_arguments<const N: usize>(
175 &self,
176 ) -> Result<(&[ExpressionNode<'i, T>; N], &[ExpressionNode<'i, T>]), InvalidArguments<'i>> {
177 self.ensure_no_keyword_arguments()?;
178 if self.args.len() >= N {
179 let (required, rest) = self.args.split_at(N);
180 Ok((required.try_into().unwrap(), rest))
181 } else {
182 Err(self.invalid_arguments_count(N, None))
183 }
184 }
185
186 #[expect(clippy::type_complexity)]
188 pub fn expect_arguments<const N: usize, const M: usize>(
189 &self,
190 ) -> Result<
191 (
192 &[ExpressionNode<'i, T>; N],
193 [Option<&ExpressionNode<'i, T>>; M],
194 ),
195 InvalidArguments<'i>,
196 > {
197 self.ensure_no_keyword_arguments()?;
198 let count_range = N..=(N + M);
199 if count_range.contains(&self.args.len()) {
200 let (required, rest) = self.args.split_at(N);
201 let mut optional = rest.iter().map(Some).collect_vec();
202 optional.resize(M, None);
203 Ok((
204 required.try_into().unwrap(),
205 optional.try_into().ok().unwrap(),
206 ))
207 } else {
208 let (min, max) = count_range.into_inner();
209 Err(self.invalid_arguments_count(min, Some(max)))
210 }
211 }
212
213 #[expect(clippy::type_complexity)]
219 pub fn expect_named_arguments<const N: usize, const M: usize>(
220 &self,
221 names: &[&str],
222 ) -> Result<
223 (
224 [&ExpressionNode<'i, T>; N],
225 [Option<&ExpressionNode<'i, T>>; M],
226 ),
227 InvalidArguments<'i>,
228 > {
229 if self.keyword_args.is_empty() {
230 let (required, optional) = self.expect_arguments::<N, M>()?;
231 Ok((required.each_ref(), optional))
232 } else {
233 let (required, optional) = self.expect_named_arguments_vec(names, N, N + M)?;
234 Ok((
235 required.try_into().ok().unwrap(),
236 optional.try_into().ok().unwrap(),
237 ))
238 }
239 }
240
241 #[expect(clippy::type_complexity)]
242 fn expect_named_arguments_vec(
243 &self,
244 names: &[&str],
245 min: usize,
246 max: usize,
247 ) -> Result<
248 (
249 Vec<&ExpressionNode<'i, T>>,
250 Vec<Option<&ExpressionNode<'i, T>>>,
251 ),
252 InvalidArguments<'i>,
253 > {
254 assert!(names.len() <= max);
255
256 if self.args.len() > max {
257 return Err(self.invalid_arguments_count(min, Some(max)));
258 }
259 let mut extracted = Vec::with_capacity(max);
260 extracted.extend(self.args.iter().map(Some));
261 extracted.resize(max, None);
262
263 for arg in &self.keyword_args {
264 let name = arg.name;
265 let span = arg.name_span.start_pos().span(&arg.value.span.end_pos());
266 let pos = names.iter().position(|&n| n == name).ok_or_else(|| {
267 self.invalid_arguments(format!(r#"Unexpected keyword argument "{name}""#), span)
268 })?;
269 if extracted[pos].is_some() {
270 return Err(self.invalid_arguments(
271 format!(r#"Got multiple values for keyword "{name}""#),
272 span,
273 ));
274 }
275 extracted[pos] = Some(&arg.value);
276 }
277
278 let optional = extracted.split_off(min);
279 let required = extracted.into_iter().flatten().collect_vec();
280 if required.len() != min {
281 return Err(self.invalid_arguments_count(min, Some(max)));
282 }
283 Ok((required, optional))
284 }
285
286 fn ensure_no_keyword_arguments(&self) -> Result<(), InvalidArguments<'i>> {
287 if let (Some(first), Some(last)) = (self.keyword_args.first(), self.keyword_args.last()) {
288 let span = first.name_span.start_pos().span(&last.value.span.end_pos());
289 Err(self.invalid_arguments("Unexpected keyword arguments".to_owned(), span))
290 } else {
291 Ok(())
292 }
293 }
294
295 fn invalid_arguments(&self, message: String, span: pest::Span<'i>) -> InvalidArguments<'i> {
296 InvalidArguments {
297 name: self.name,
298 message,
299 span,
300 }
301 }
302
303 fn invalid_arguments_count(&self, min: usize, max: Option<usize>) -> InvalidArguments<'i> {
304 let message = match (min, max) {
305 (min, Some(max)) if min == max => format!("Expected {min} arguments"),
306 (min, Some(max)) => format!("Expected {min} to {max} arguments"),
307 (min, None) => format!("Expected at least {min} arguments"),
308 };
309 self.invalid_arguments(message, self.args_span)
310 }
311
312 fn invalid_arguments_count_with_arities(
313 &self,
314 arities: impl IntoIterator<Item = usize>,
315 ) -> InvalidArguments<'i> {
316 let message = format!("Expected {} arguments", arities.into_iter().join(", "));
317 self.invalid_arguments(message, self.args_span)
318 }
319}
320
321#[derive(Clone, Debug)]
326pub struct InvalidArguments<'i> {
327 pub name: &'i str,
329 pub message: String,
331 pub span: pest::Span<'i>,
333}
334
335pub trait FoldableExpression<'i>: Sized {
337 fn fold<F>(self, folder: &mut F, span: pest::Span<'i>) -> Result<Self, F::Error>
339 where
340 F: ExpressionFolder<'i, Self> + ?Sized;
341}
342
343pub trait ExpressionFolder<'i, T: FoldableExpression<'i>> {
345 type Error;
347
348 fn fold_expression(
351 &mut self,
352 node: ExpressionNode<'i, T>,
353 ) -> Result<ExpressionNode<'i, T>, Self::Error> {
354 let ExpressionNode { kind, span } = node;
355 let kind = kind.fold(self, span)?;
356 Ok(ExpressionNode { kind, span })
357 }
358
359 fn fold_identifier(&mut self, name: &'i str, span: pest::Span<'i>) -> Result<T, Self::Error>;
361
362 fn fold_pattern(
364 &mut self,
365 pattern: Box<PatternNode<'i, T>>,
366 span: pest::Span<'i>,
367 ) -> Result<T, Self::Error>;
368
369 fn fold_function_call(
371 &mut self,
372 function: Box<FunctionCallNode<'i, T>>,
373 span: pest::Span<'i>,
374 ) -> Result<T, Self::Error>;
375}
376
377pub fn fold_expression_nodes<'i, F, T>(
379 folder: &mut F,
380 nodes: Vec<ExpressionNode<'i, T>>,
381) -> Result<Vec<ExpressionNode<'i, T>>, F::Error>
382where
383 F: ExpressionFolder<'i, T> + ?Sized,
384 T: FoldableExpression<'i>,
385{
386 nodes
387 .into_iter()
388 .map(|node| folder.fold_expression(node))
389 .try_collect()
390}
391
392pub fn fold_pattern_value<'i, F, T>(
394 folder: &mut F,
395 pattern: PatternNode<'i, T>,
396) -> Result<PatternNode<'i, T>, F::Error>
397where
398 F: ExpressionFolder<'i, T> + ?Sized,
399 T: FoldableExpression<'i>,
400{
401 Ok(PatternNode {
402 name: pattern.name,
403 name_span: pattern.name_span,
404 value: folder.fold_expression(pattern.value)?,
405 })
406}
407
408pub fn fold_function_call_args<'i, F, T>(
410 folder: &mut F,
411 function: FunctionCallNode<'i, T>,
412) -> Result<FunctionCallNode<'i, T>, F::Error>
413where
414 F: ExpressionFolder<'i, T> + ?Sized,
415 T: FoldableExpression<'i>,
416{
417 Ok(FunctionCallNode {
418 name: function.name,
419 name_span: function.name_span,
420 args: fold_expression_nodes(folder, function.args)?,
421 keyword_args: function
422 .keyword_args
423 .into_iter()
424 .map(|arg| {
425 Ok(KeywordArgument {
426 name: arg.name,
427 name_span: arg.name_span,
428 value: folder.fold_expression(arg.value)?,
429 })
430 })
431 .try_collect()?,
432 args_span: function.args_span,
433 })
434}
435
436#[derive(Debug)]
438pub struct StringLiteralParser<R> {
439 pub content_rule: R,
441 pub escape_rule: R,
443}
444
445impl<R: RuleType> StringLiteralParser<R> {
446 pub fn parse(&self, pairs: Pairs<R>) -> String {
448 let mut result = String::new();
449 for part in pairs {
450 if part.as_rule() == self.content_rule {
451 result.push_str(part.as_str());
452 } else if part.as_rule() == self.escape_rule {
453 result.push(unescape_char(part.as_str()));
454 } else {
455 panic!("unexpected part of string: {part:?}");
456 }
457 }
458 result
459 }
460}
461
462#[derive(Debug)]
464pub struct FunctionCallParser<R> {
465 pub function_name_rule: R,
467 pub function_arguments_rule: R,
469 pub keyword_argument_rule: R,
471 pub argument_name_rule: R,
473 pub argument_value_rule: R,
475}
476
477impl<R: RuleType> FunctionCallParser<R> {
478 pub fn parse<'i, T, E: From<InvalidArguments<'i>>>(
480 &self,
481 pair: Pair<'i, R>,
482 parse_name: impl Fn(Pair<'i, R>) -> Result<&'i str, E>,
485 parse_value: impl Fn(Pair<'i, R>) -> Result<ExpressionNode<'i, T>, E>,
486 ) -> Result<FunctionCallNode<'i, T>, E> {
487 let [name_pair, args_pair] = pair.into_inner().collect_array().unwrap();
488 assert_eq!(name_pair.as_rule(), self.function_name_rule);
489 assert_eq!(args_pair.as_rule(), self.function_arguments_rule);
490 let name_span = name_pair.as_span();
491 let args_span = args_pair.as_span();
492 let function_name = parse_name(name_pair)?;
493 let mut args = Vec::new();
494 let mut keyword_args = Vec::new();
495 for pair in args_pair.into_inner() {
496 let span = pair.as_span();
497 if pair.as_rule() == self.argument_value_rule {
498 if !keyword_args.is_empty() {
499 return Err(InvalidArguments {
500 name: function_name,
501 message: "Positional argument follows keyword argument".to_owned(),
502 span,
503 }
504 .into());
505 }
506 args.push(parse_value(pair)?);
507 } else if pair.as_rule() == self.keyword_argument_rule {
508 let [name_pair, value_pair] = pair.into_inner().collect_array().unwrap();
509 assert_eq!(name_pair.as_rule(), self.argument_name_rule);
510 assert_eq!(value_pair.as_rule(), self.argument_value_rule);
511 let name_span = name_pair.as_span();
512 let arg = KeywordArgument {
513 name: parse_name(name_pair)?,
514 name_span,
515 value: parse_value(value_pair)?,
516 };
517 keyword_args.push(arg);
518 } else {
519 panic!("unexpected argument rule {pair:?}");
520 }
521 }
522 Ok(FunctionCallNode {
523 name: function_name,
524 name_span,
525 args,
526 keyword_args,
527 args_span,
528 })
529 }
530}
531
532type FunctionAlias<V> = (Vec<String>, V, Option<String>);
534
535#[derive(Clone, Debug, Default)]
537pub struct AliasesMap<P, V> {
538 symbol_aliases: HashMap<String, (V, Option<String>)>,
539 pattern_aliases: HashMap<String, (String, V, Option<String>)>,
541 function_aliases: HashMap<String, Vec<FunctionAlias<V>>>,
543 parser: P,
545}
546
547impl<P, V> AliasesMap<P, V> {
548 pub fn new() -> Self
550 where
551 P: Default,
552 {
553 Self {
554 symbol_aliases: Default::default(),
555 pattern_aliases: Default::default(),
556 function_aliases: Default::default(),
557 parser: Default::default(),
558 }
559 }
560
561 pub fn insert(
566 &mut self,
567 decl: impl AsRef<str>,
568 defn: impl Into<V>,
569 doc: Option<String>,
570 ) -> Result<(), P::Error>
571 where
572 P: AliasDeclarationParser,
573 {
574 match self.parser.parse_declaration(decl.as_ref())? {
575 AliasDeclaration::Symbol(name) => {
576 self.symbol_aliases.insert(name, (defn.into(), doc));
577 }
578 AliasDeclaration::Pattern(name, param) => {
579 self.pattern_aliases.insert(name, (param, defn.into(), doc));
580 }
581 AliasDeclaration::Function(name, params) => {
582 let overloads = self.function_aliases.entry(name).or_default();
583 match overloads.binary_search_by_key(¶ms.len(), |(params, _, _)| params.len()) {
584 Ok(i) => overloads[i] = (params, defn.into(), doc),
585 Err(i) => overloads.insert(i, (params, defn.into(), doc)),
586 }
587 }
588 }
589 Ok(())
590 }
591
592 pub fn symbol_names(&self) -> impl Iterator<Item = &str> {
594 self.symbol_aliases.keys().map(|n| n.as_ref())
595 }
596
597 pub fn pattern_names(&self) -> impl Iterator<Item = &str> {
599 self.pattern_aliases.keys().map(|n| n.as_ref())
600 }
601
602 pub fn function_names(&self) -> impl Iterator<Item = &str> {
604 self.function_aliases.keys().map(|n| n.as_ref())
605 }
606
607 pub fn get_symbol(&self, name: &str) -> Option<(AliasId<'_>, &V, Option<&str>)> {
610 self.symbol_aliases
611 .get_key_value(name)
612 .map(|(name, (defn, doc))| (AliasId::Symbol(name), defn, doc.as_deref()))
613 }
614
615 pub fn get_pattern(&self, name: &str) -> Option<(AliasId<'_>, &str, &V, Option<&str>)> {
618 self.pattern_aliases
619 .get_key_value(name)
620 .map(|(name, (param, defn, doc))| {
621 (
622 AliasId::Pattern(name, param),
623 param.as_ref(),
624 defn,
625 doc.as_deref(),
626 )
627 })
628 }
629
630 pub fn get_function(
633 &self,
634 name: &str,
635 arity: usize,
636 ) -> Option<(AliasId<'_>, &[String], &V, Option<&str>)> {
637 let overloads = self.get_function_overloads(name)?;
638 overloads.find_by_arity(arity)
639 }
640
641 fn get_function_overloads(&self, name: &str) -> Option<AliasFunctionOverloads<'_, V>> {
643 let (name, overloads) = self.function_aliases.get_key_value(name)?;
644 Some(AliasFunctionOverloads { name, overloads })
645 }
646}
647
648#[derive(Clone, Debug)]
649struct AliasFunctionOverloads<'a, V> {
650 name: &'a String,
651 overloads: &'a Vec<(Vec<String>, V, Option<String>)>,
652}
653
654impl<'a, V> AliasFunctionOverloads<'a, V> {
655 fn arities(&self) -> impl DoubleEndedIterator<Item = usize> + ExactSizeIterator {
656 self.overloads.iter().map(|(params, _, _)| params.len())
657 }
658
659 fn min_arity(&self) -> usize {
660 self.arities().next().unwrap()
661 }
662
663 fn max_arity(&self) -> usize {
664 self.arities().next_back().unwrap()
665 }
666
667 fn find_by_arity(
668 &self,
669 arity: usize,
670 ) -> Option<(AliasId<'a>, &'a [String], &'a V, Option<&'a str>)> {
671 let index = self
672 .overloads
673 .binary_search_by_key(&arity, |(params, _, _)| params.len())
674 .ok()?;
675 let (params, defn, doc) = &self.overloads[index];
676 Some((
680 AliasId::Function(self.name, params),
681 params,
682 defn,
683 doc.as_deref(),
684 ))
685 }
686}
687
688#[derive(Clone, Copy, Debug, Eq, PartialEq)]
690pub enum AliasId<'a> {
691 Symbol(&'a str),
693 Pattern(&'a str, &'a str),
695 Function(&'a str, &'a [String]),
697 Parameter(&'a str),
699}
700
701impl fmt::Display for AliasId<'_> {
702 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
703 match self {
704 Self::Symbol(name) => write!(f, "{name}"),
705 Self::Pattern(name, param) => write!(f, "{name}:{param}"),
706 Self::Function(name, params) => {
707 write!(f, "{name}({params})", params = params.join(", "))
708 }
709 Self::Parameter(name) => write!(f, "{name}"),
710 }
711 }
712}
713
714#[derive(Clone, Debug)]
716pub enum AliasDeclaration {
717 Symbol(String),
719 Pattern(String, String),
721 Function(String, Vec<String>),
723}
724
725pub trait AliasDeclarationParser {
730 type Error;
732
733 fn parse_declaration(&self, source: &str) -> Result<AliasDeclaration, Self::Error>;
735}
736
737pub trait AliasDefinitionParser {
739 type Output<'i>;
741 type Error;
743
744 fn parse_definition<'i>(
746 &self,
747 source: &'i str,
748 ) -> Result<ExpressionNode<'i, Self::Output<'i>>, Self::Error>;
749}
750
751pub trait AliasExpandableExpression<'i>: FoldableExpression<'i> {
753 fn identifier(name: &'i str) -> Self;
755 fn pattern(pattern: Box<PatternNode<'i, Self>>) -> Self;
757 fn function_call(function: Box<FunctionCallNode<'i, Self>>) -> Self;
759 fn alias_expanded(id: AliasId<'i>, subst: Box<ExpressionNode<'i, Self>>) -> Self;
761}
762
763pub trait AliasExpandError: Sized {
765 fn invalid_arguments(err: InvalidArguments<'_>) -> Self;
767 fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self;
769 fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self;
771}
772
773#[derive(Debug)]
775struct AliasExpander<'i, 'a, T, P> {
776 aliases_map: &'i AliasesMap<P, String>,
778 locals: &'a HashMap<&'i str, ExpressionNode<'i, T>>,
780 states: Vec<AliasExpandingState<'i, T>>,
782}
783
784#[derive(Debug)]
785struct AliasExpandingState<'i, T> {
786 id: AliasId<'i>,
787 locals: HashMap<&'i str, ExpressionNode<'i, T>>,
788}
789
790impl<'i, T, P, E> AliasExpander<'i, '_, T, P>
791where
792 T: AliasExpandableExpression<'i> + Clone,
793 P: AliasDefinitionParser<Output<'i> = T, Error = E>,
794 E: AliasExpandError,
795{
796 fn current_locals(&self) -> &HashMap<&'i str, ExpressionNode<'i, T>> {
798 self.states.last().map_or(self.locals, |s| &s.locals)
799 }
800
801 fn expand_defn(
802 &mut self,
803 id: AliasId<'i>,
804 defn: &'i str,
805 locals: HashMap<&'i str, ExpressionNode<'i, T>>,
806 span: pest::Span<'i>,
807 ) -> Result<T, E> {
808 if self.states.iter().any(|s| s.id == id) {
810 return Err(E::recursive_expansion(id, span));
811 }
812 self.states.push(AliasExpandingState { id, locals });
813 let result = self
815 .aliases_map
816 .parser
817 .parse_definition(defn)
818 .and_then(|node| self.fold_expression(node))
819 .map(|node| T::alias_expanded(id, Box::new(node)))
820 .map_err(|e| e.within_alias_expansion(id, span));
821 self.states.pop();
822 result
823 }
824}
825
826impl<'i, T, P, E> ExpressionFolder<'i, T> for AliasExpander<'i, '_, T, P>
827where
828 T: AliasExpandableExpression<'i> + Clone,
829 P: AliasDefinitionParser<Output<'i> = T, Error = E>,
830 E: AliasExpandError,
831{
832 type Error = E;
833
834 fn fold_identifier(&mut self, name: &'i str, span: pest::Span<'i>) -> Result<T, Self::Error> {
835 if let Some(subst) = self.current_locals().get(name) {
836 let id = AliasId::Parameter(name);
837 Ok(T::alias_expanded(id, Box::new(subst.clone())))
838 } else if let Some((id, defn, _doc)) = self.aliases_map.get_symbol(name) {
839 let locals = HashMap::new(); self.expand_defn(id, defn, locals, span)
841 } else {
842 Ok(T::identifier(name))
843 }
844 }
845
846 fn fold_pattern(
847 &mut self,
848 pattern: Box<PatternNode<'i, T>>,
849 span: pest::Span<'i>,
850 ) -> Result<T, Self::Error> {
851 if let Some((id, param, defn, _doc)) = self.aliases_map.get_pattern(pattern.name) {
852 let arg = self.fold_expression(pattern.value)?;
855 let locals = HashMap::from([(param, arg)]);
856 self.expand_defn(id, defn, locals, span)
857 } else {
858 let pattern = Box::new(fold_pattern_value(self, *pattern)?);
859 Ok(T::pattern(pattern))
860 }
861 }
862
863 fn fold_function_call(
864 &mut self,
865 function: Box<FunctionCallNode<'i, T>>,
866 span: pest::Span<'i>,
867 ) -> Result<T, Self::Error> {
868 if let Some(overloads) = self.aliases_map.get_function_overloads(function.name) {
871 function
873 .ensure_no_keyword_arguments()
874 .map_err(E::invalid_arguments)?;
875 let Some((id, params, defn, _doc)) = overloads.find_by_arity(function.arity()) else {
876 let min = overloads.min_arity();
877 let max = overloads.max_arity();
878 let err = if max - min + 1 == overloads.arities().len() {
879 function.invalid_arguments_count(min, Some(max))
880 } else {
881 function.invalid_arguments_count_with_arities(overloads.arities())
882 };
883 return Err(E::invalid_arguments(err));
884 };
885 let args = fold_expression_nodes(self, function.args)?;
888 let locals = params.iter().map(|s| s.as_str()).zip(args).collect();
889 self.expand_defn(id, defn, locals, span)
890 } else {
891 let function = Box::new(fold_function_call_args(self, *function)?);
892 Ok(T::function_call(function))
893 }
894 }
895}
896
897pub fn expand_aliases<'i, T, P>(
899 node: ExpressionNode<'i, T>,
900 aliases_map: &'i AliasesMap<P, String>,
901) -> Result<ExpressionNode<'i, T>, P::Error>
902where
903 T: AliasExpandableExpression<'i> + Clone,
904 P: AliasDefinitionParser<Output<'i> = T>,
905 P::Error: AliasExpandError,
906{
907 expand_aliases_with_locals(node, aliases_map, &HashMap::new())
908}
909
910pub fn expand_aliases_with_locals<'i, T, P>(
915 node: ExpressionNode<'i, T>,
916 aliases_map: &'i AliasesMap<P, String>,
917 locals: &HashMap<&'i str, ExpressionNode<'i, T>>,
918) -> Result<ExpressionNode<'i, T>, P::Error>
919where
920 T: AliasExpandableExpression<'i> + Clone,
921 P: AliasDefinitionParser<Output<'i> = T>,
922 P::Error: AliasExpandError,
923{
924 let mut expander = AliasExpander {
925 aliases_map,
926 locals,
927 states: Vec::new(),
928 };
929 expander.fold_expression(node)
930}
931
932pub fn collect_similar<I>(name: &str, candidates: I) -> Vec<String>
934where
935 I: IntoIterator,
936 I::Item: AsRef<str>,
937{
938 candidates
939 .into_iter()
940 .filter(|cand| {
941 strsim::jaro(name, cand.as_ref()) > 0.7
943 })
944 .map(|s| s.as_ref().to_owned())
945 .sorted_unstable()
946 .collect()
947}
948
949#[cfg(test)]
950mod tests {
951 use super::*;
952
953 #[test]
954 fn test_expect_arguments() {
955 fn empty_span() -> pest::Span<'static> {
956 pest::Span::new("", 0, 0).unwrap()
957 }
958
959 fn function(
960 name: &'static str,
961 args: impl Into<Vec<ExpressionNode<'static, u32>>>,
962 keyword_args: impl Into<Vec<KeywordArgument<'static, u32>>>,
963 ) -> FunctionCallNode<'static, u32> {
964 FunctionCallNode {
965 name,
966 name_span: empty_span(),
967 args: args.into(),
968 keyword_args: keyword_args.into(),
969 args_span: empty_span(),
970 }
971 }
972
973 fn value(v: u32) -> ExpressionNode<'static, u32> {
974 ExpressionNode::new(v, empty_span())
975 }
976
977 fn keyword(name: &'static str, v: u32) -> KeywordArgument<'static, u32> {
978 KeywordArgument {
979 name,
980 name_span: empty_span(),
981 value: value(v),
982 }
983 }
984
985 let f = function("foo", [], []);
986 assert!(f.expect_no_arguments().is_ok());
987 assert!(f.expect_some_arguments::<0>().is_ok());
988 assert!(f.expect_arguments::<0, 0>().is_ok());
989 assert!(f.expect_named_arguments::<0, 0>(&[]).is_ok());
990
991 let f = function("foo", [value(0)], []);
992 assert!(f.expect_no_arguments().is_err());
993 assert_eq!(
994 f.expect_some_arguments::<0>().unwrap(),
995 (&[], [value(0)].as_slice())
996 );
997 assert_eq!(
998 f.expect_some_arguments::<1>().unwrap(),
999 (&[value(0)], [].as_slice())
1000 );
1001 assert!(f.expect_arguments::<0, 0>().is_err());
1002 assert_eq!(
1003 f.expect_arguments::<0, 1>().unwrap(),
1004 (&[], [Some(&value(0))])
1005 );
1006 assert_eq!(f.expect_arguments::<1, 1>().unwrap(), (&[value(0)], [None]));
1007 assert!(f.expect_named_arguments::<0, 0>(&[]).is_err());
1008 assert_eq!(
1009 f.expect_named_arguments::<0, 1>(&["a"]).unwrap(),
1010 ([], [Some(&value(0))])
1011 );
1012 assert_eq!(
1013 f.expect_named_arguments::<1, 0>(&["a"]).unwrap(),
1014 ([&value(0)], [])
1015 );
1016
1017 let f = function("foo", [], [keyword("a", 0)]);
1018 assert!(f.expect_no_arguments().is_err());
1019 assert!(f.expect_some_arguments::<1>().is_err());
1020 assert!(f.expect_arguments::<0, 1>().is_err());
1021 assert!(f.expect_arguments::<1, 0>().is_err());
1022 assert!(f.expect_named_arguments::<0, 0>(&[]).is_err());
1023 assert!(f.expect_named_arguments::<0, 1>(&[]).is_err());
1024 assert!(f.expect_named_arguments::<1, 0>(&[]).is_err());
1025 assert_eq!(
1026 f.expect_named_arguments::<1, 0>(&["a"]).unwrap(),
1027 ([&value(0)], [])
1028 );
1029 assert_eq!(
1030 f.expect_named_arguments::<1, 1>(&["a", "b"]).unwrap(),
1031 ([&value(0)], [None])
1032 );
1033 assert!(f.expect_named_arguments::<1, 1>(&["b", "a"]).is_err());
1034
1035 let f = function("foo", [value(0)], [keyword("a", 1), keyword("b", 2)]);
1036 assert!(f.expect_named_arguments::<0, 0>(&[]).is_err());
1037 assert!(f.expect_named_arguments::<1, 1>(&["a", "b"]).is_err());
1038 assert_eq!(
1039 f.expect_named_arguments::<1, 2>(&["c", "a", "b"]).unwrap(),
1040 ([&value(0)], [Some(&value(1)), Some(&value(2))])
1041 );
1042 assert_eq!(
1043 f.expect_named_arguments::<2, 1>(&["c", "b", "a"]).unwrap(),
1044 ([&value(0), &value(2)], [Some(&value(1))])
1045 );
1046 assert_eq!(
1047 f.expect_named_arguments::<0, 3>(&["c", "b", "a"]).unwrap(),
1048 ([], [Some(&value(0)), Some(&value(2)), Some(&value(1))])
1049 );
1050
1051 let f = function("foo", [], [keyword("a", 0), keyword("a", 1)]);
1052 assert!(f.expect_named_arguments::<1, 1>(&["", "a"]).is_err());
1053 }
1054}