Skip to main content

ironcalc_base/expressions/parser/
static_analysis.rs

1use crate::functions::Function;
2
3use super::Node;
4
5#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
6use regex_lite as regex;
7
8use regex::Regex;
9use std::sync::OnceLock;
10
11static RANGE_REFERENCE_REGEX: OnceLock<Regex> = OnceLock::new();
12
13#[allow(clippy::expect_used)]
14fn get_re() -> &'static Regex {
15    RANGE_REFERENCE_REGEX
16        .get_or_init(|| Regex::new(r":[A-Z]*[0-9]*$").expect("Regex is known to be valid"))
17}
18
19fn is_range_reference(s: &str) -> bool {
20    get_re().is_match(s)
21}
22
23/*
24
25# NOTES on the Implicit Intersection operator: @
26
27 Sometimes we obtain a range where we expected a single argument. This can happen:
28
29 * As an argument of a function, eg: `SIN(A1:A5)`
30 * As the result of a computation of a formula `=A1:A5`
31
32 In previous versions of the Friendly Giant the spreadsheet engine would perform an operation called _implicit intersection_
33 that tries to find a single cell within the range. It works by picking a cell in the range that is the same row or the same column
34 as the cell. If there is just one we return that otherwise we return the `#REF!` error.
35
36 Examples:
37
38 * Siting on `C3` the formula `=D1:D5` will return `D3`
39 * Sitting on `C3` the formula `=D:D` will return `D3`
40 * Sitting on `C3` the formula `=A1:A7` will return `A3`
41 * Sitting on `C3` the formula `=A5:A8` will return `#REF!`
42 * Sitting on `C3` the formula `D1:G7` will return `#REF!`
43
44 Today's version of the engine will result in a dynamic array spilling the result through several cells.
45 To force the old behaviour we can use the _implicit intersection operator_: @
46
47 * `=@A1:A7` or `=SIN(@A1:A7)
48
49 When parsing formulas that come form old workbooks this is done automatically.
50 We call this version of the II operator the _automatic_ II operator.
51
52 We can also insert the II operator in places where before was impossible:
53
54 * `=SUM(@A1:A7)`
55
56 This formulas will not be compatible with old versions of the engine. The FG will stringify this as `=SUM(_xlfn.SIMPLE(A1:A7))`.
57 */
58
59/// Traverses the formula tree adding the implicit intersection operator in all arguments of functions that
60/// expect a scalar but get a range.
61///  * A:A => @A:A
62///  * SIN(A1:D1) => SIN(@A1:D1)
63///
64/// Assumes formula return a scalar
65pub fn add_implicit_intersection(node: &mut Node, add: bool) {
66    match node {
67        Node::BooleanKind(_)
68        | Node::NumberKind(_)
69        | Node::StringKind(_)
70        | Node::ErrorKind(_)
71        | Node::EmptyArgKind
72        | Node::ParseErrorKind { .. }
73        | Node::WrongReferenceKind { .. }
74        | Node::WrongRangeKind { .. }
75        | Node::NamedFunctionKind { .. }
76        | Node::ArrayKind(_)
77        | Node::ReferenceKind { .. }
78        | Node::LambdaDefKind { .. }
79        | Node::LambdaCallKind { .. } => {}
80        Node::ImplicitIntersection { child, .. } => {
81            // We need to check wether the II can be automatic or not
82            let mut new_node = child.as_ref().clone();
83            add_implicit_intersection(&mut new_node, add);
84            if matches!(&new_node, Node::ImplicitIntersection { .. }) {
85                *node = new_node
86            }
87        }
88        Node::SpillRangeOperator { child } => {
89            add_implicit_intersection(child, add);
90        }
91        Node::RangeKind {
92            row1,
93            column1,
94            row2,
95            column2,
96            sheet_name,
97            sheet_index,
98            absolute_row1,
99            absolute_column1,
100            absolute_row2,
101            absolute_column2,
102        } => {
103            if add {
104                *node = Node::ImplicitIntersection {
105                    automatic: true,
106                    child: Box::new(Node::RangeKind {
107                        sheet_name: sheet_name.clone(),
108                        sheet_index: *sheet_index,
109                        absolute_row1: *absolute_row1,
110                        absolute_column1: *absolute_column1,
111                        row1: *row1,
112                        column1: *column1,
113                        absolute_row2: *absolute_row2,
114                        absolute_column2: *absolute_column2,
115                        row2: *row2,
116                        column2: *column2,
117                    }),
118                };
119            }
120        }
121        Node::OpRangeKind { left, right } => {
122            if add {
123                *node = Node::ImplicitIntersection {
124                    automatic: true,
125                    child: Box::new(Node::OpRangeKind {
126                        left: left.clone(),
127                        right: right.clone(),
128                    }),
129                }
130            }
131        }
132
133        // operations
134        Node::UnaryKind { right, .. } => add_implicit_intersection(right, add),
135        Node::OpConcatenateKind { left, right }
136        | Node::OpSumKind { left, right, .. }
137        | Node::OpProductKind { left, right, .. }
138        | Node::OpPowerKind { left, right, .. }
139        | Node::CompareKind { left, right, .. } => {
140            add_implicit_intersection(left, add);
141            add_implicit_intersection(right, add);
142        }
143
144        Node::DefinedNameKind(v) => {
145            if add {
146                // Not all defined names deserve the II operator
147                // For instance =Sheet1!A1 doesn't need to be intersected
148                if is_range_reference(&v.2) {
149                    *node = Node::ImplicitIntersection {
150                        automatic: true,
151                        child: Box::new(Node::DefinedNameKind(v.to_owned())),
152                    }
153                }
154            }
155        }
156        Node::NamedVariableKind { name, id } => {
157            if add {
158                *node = Node::ImplicitIntersection {
159                    automatic: true,
160                    child: Box::new(Node::NamedVariableKind {
161                        name: name.clone(),
162                        id: *id,
163                    }),
164                }
165            }
166        }
167        Node::TableNameKind(_) => {
168            // noop for now
169        }
170        Node::FunctionKind { kind, args } => {
171            let arg_count = args.len();
172            let signature = get_function_args_signature(kind, arg_count);
173            for index in 0..arg_count {
174                if matches!(signature[index], Signature::Scalar)
175                    && matches!(
176                        run_static_analysis_on_node(&args[index]),
177                        StaticResult::Range(_, _) | StaticResult::Unknown
178                    )
179                {
180                    add_implicit_intersection(&mut args[index], true);
181                } else {
182                    add_implicit_intersection(&mut args[index], false);
183                }
184            }
185            // There are some function that will never add an automatic II:
186            let new_function = matches!(kind, Function::Let | Function::Lambda);
187            if !new_function
188                && add
189                && matches!(
190                    run_static_analysis_on_node(node),
191                    StaticResult::Range(_, _) | StaticResult::Unknown
192                )
193            {
194                *node = Node::ImplicitIntersection {
195                    automatic: true,
196                    child: Box::new(node.clone()),
197                }
198            }
199        }
200    };
201}
202
203/// Inverse of [`add_implicit_intersection`], used when exporting to Excel.
204///
205/// The internal (RC) representation stores every implicit intersection as `@`,
206/// losing the `automatic` flag. When exporting we must decide, for each `@`,
207/// whether it should be written as `_xlfn.SINGLE(...)` (because it is meaningful)
208/// or dropped (because `add_implicit_intersection` would re-insert it on import).
209///
210/// That decision depends on the *context* of the operator, exactly like
211/// `add_implicit_intersection`: an `@` is redundant only in a position that
212/// expects a scalar (`add == true`). Crucially, an `@` sitting in a `Vector`
213/// argument of a function such as `SUM` is **not** redundant: on import no
214/// automatic intersection is added there, so dropping it would change the result
215/// (e.g. `SUM(A1,B1,@J:J)` would become `SUM(A1,B1,J:J)`, scanning the whole
216/// column). This pass removes only the redundant operators, leaving the rest to
217/// be stringified as `_xlfn.SINGLE`.
218///
219/// `add` mirrors the flag in `add_implicit_intersection` and must start `true`
220/// (a formula is evaluated in a scalar context).
221pub fn remove_redundant_implicit_intersection(node: &mut Node, add: bool) {
222    match node {
223        // Leaves and nodes that never contain a nested implicit intersection.
224        Node::BooleanKind(_)
225        | Node::NumberKind(_)
226        | Node::StringKind(_)
227        | Node::ErrorKind(_)
228        | Node::EmptyArgKind
229        | Node::ParseErrorKind { .. }
230        | Node::WrongReferenceKind { .. }
231        | Node::WrongRangeKind { .. }
232        | Node::NamedFunctionKind { .. }
233        | Node::ArrayKind(_)
234        | Node::ReferenceKind { .. }
235        | Node::RangeKind { .. }
236        | Node::OpRangeKind { .. }
237        | Node::DefinedNameKind(_)
238        | Node::NamedVariableKind { .. }
239        | Node::TableNameKind(_)
240        | Node::LambdaDefKind { .. }
241        | Node::LambdaCallKind { .. } => {}
242        Node::ImplicitIntersection { child, .. } => {
243            if add {
244                // Would `add_implicit_intersection` re-insert this operator on
245                // import? Probe the child in a scalar context to find out.
246                let mut probe = child.as_ref().clone();
247                add_implicit_intersection(&mut probe, true);
248                if matches!(probe, Node::ImplicitIntersection { .. }) {
249                    // Redundant: drop the operator and keep cleaning the child.
250                    // The child is still in the same (scalar) context, so recurse
251                    // with `add` to also remove any nested redundant operators.
252                    let mut inner = child.as_ref().clone();
253                    remove_redundant_implicit_intersection(&mut inner, add);
254                    *node = inner;
255                    return;
256                }
257            }
258            // Meaningful operator: keep it, but still clean any nested ones.
259            remove_redundant_implicit_intersection(child, false);
260        }
261        Node::SpillRangeOperator { child } => {
262            remove_redundant_implicit_intersection(child, add);
263        }
264        Node::UnaryKind { right, .. } => remove_redundant_implicit_intersection(right, add),
265        Node::OpConcatenateKind { left, right }
266        | Node::OpSumKind { left, right, .. }
267        | Node::OpProductKind { left, right, .. }
268        | Node::OpPowerKind { left, right, .. }
269        | Node::CompareKind { left, right, .. } => {
270            remove_redundant_implicit_intersection(left, add);
271            remove_redundant_implicit_intersection(right, add);
272        }
273        Node::FunctionKind { kind, args } => {
274            let arg_count = args.len();
275            let signature = get_function_args_signature(kind, arg_count);
276            for index in 0..arg_count {
277                // Scalar arguments are an intersecting context; vector arguments
278                // (ranges/arrays) are not.
279                let child_add = matches!(signature[index], Signature::Scalar);
280                remove_redundant_implicit_intersection(&mut args[index], child_add);
281            }
282        }
283    };
284}
285
286/// The result of the static analysis of a node
287pub enum StaticResult {
288    // The result of the evaluation is a single value (number, string, boolean, error)
289    Scalar,
290    // The result of the evaluation is an array with dimensions (rows, columns)
291    Array(i32, i32),
292    // The result of the evaluation is a range with dimensions (rows, columns)
293    Range(i32, i32),
294    // The result of the evaluation is unknown, we cannot guaranty it is a scalar, an array or a range
295    Unknown,
296    // TODO: What if one of the dimensions is known?
297    // what if the dimensions are unknown but bounded?
298}
299
300fn static_analysis_op_nodes(left: &Node, right: &Node) -> StaticResult {
301    let lhs = run_static_analysis_on_node(left);
302    let rhs = run_static_analysis_on_node(right);
303    match (lhs, rhs) {
304        (StaticResult::Scalar, StaticResult::Scalar) => StaticResult::Scalar,
305        (StaticResult::Scalar, StaticResult::Array(a, b) | StaticResult::Range(a, b)) => {
306            StaticResult::Array(a, b)
307        }
308
309        (StaticResult::Array(a, b) | StaticResult::Range(a, b), StaticResult::Scalar) => {
310            StaticResult::Array(a, b)
311        }
312        (
313            StaticResult::Array(a1, b1) | StaticResult::Range(a1, b1),
314            StaticResult::Array(a2, b2) | StaticResult::Range(a2, b2),
315        ) => StaticResult::Array(a1.max(a2), b1.max(b2)),
316
317        (_, StaticResult::Unknown) => StaticResult::Unknown,
318        (StaticResult::Unknown, _) => StaticResult::Unknown,
319    }
320}
321
322// Returns:
323//  * Scalar if we can proof the result of the evaluation is a scalar
324//  * Array(a, b) if we know it will be an a x b array.
325//  * Range(a, b) if we know it will be a a x b range.
326//  * Unknown if we cannot guaranty either
327pub(crate) fn run_static_analysis_on_node(node: &Node) -> StaticResult {
328    match node {
329        Node::BooleanKind(_)
330        | Node::NumberKind(_)
331        | Node::StringKind(_)
332        | Node::ErrorKind(_)
333        | Node::EmptyArgKind => StaticResult::Scalar,
334        Node::UnaryKind { right, .. } => run_static_analysis_on_node(right),
335        Node::ParseErrorKind { .. } => {
336            // StaticResult::Unknown is also valid
337            StaticResult::Scalar
338        }
339        Node::WrongReferenceKind { .. } => {
340            // StaticResult::Unknown is also valid
341            StaticResult::Scalar
342        }
343        Node::WrongRangeKind { .. } => {
344            // StaticResult::Unknown or Array is also valid
345            StaticResult::Scalar
346        }
347        Node::NamedFunctionKind { .. } => {
348            // A named-function call invokes a LAMBDA (defined-name or LET-bound) whose
349            // result shape is unknown at parse time — it may well be an array that needs
350            // to spill (e.g. a LAMBDA wrapping SEQUENCE). Treat it like LambdaCallKind.
351            StaticResult::Unknown
352        }
353        Node::ArrayKind(array) => {
354            let n = array.len() as i32;
355            let m = array.first().map(|row| row.len() as i32).unwrap_or(0);
356            StaticResult::Array(n, m)
357        }
358        Node::RangeKind {
359            row1,
360            column1,
361            row2,
362            column2,
363            ..
364        } => StaticResult::Range(row2 - row1, column2 - column1),
365        Node::OpRangeKind { .. } => {
366            // TODO: We could do a bit better here
367            StaticResult::Unknown
368        }
369        Node::ReferenceKind { .. } => StaticResult::Scalar,
370
371        // binary operations
372        Node::OpConcatenateKind { left, right }
373        | Node::OpSumKind { left, right, .. }
374        | Node::OpProductKind { left, right, .. }
375        | Node::OpPowerKind { left, right, .. }
376        | Node::CompareKind { left, right, .. } => static_analysis_op_nodes(left, right),
377
378        // defined names
379        Node::DefinedNameKind(_) => {
380            // TODO: We could do better if we tracked the defined names
381            StaticResult::Unknown
382        }
383        Node::NamedVariableKind { .. } => StaticResult::Scalar,
384        Node::TableNameKind(_) => StaticResult::Unknown,
385        Node::FunctionKind { kind, args } => static_analysis_on_function(kind, args),
386        Node::ImplicitIntersection { .. } => StaticResult::Scalar,
387        Node::SpillRangeOperator { .. } => StaticResult::Unknown,
388        Node::LambdaDefKind { .. } => StaticResult::Unknown,
389        Node::LambdaCallKind { .. } => StaticResult::Unknown,
390    }
391}
392
393// If all the arguments are scalars the function will return a scalar
394// If any of the arguments is a range or an array it will return an array
395fn scalar_arguments(args: &[Node]) -> StaticResult {
396    let mut n = 0;
397    let mut m = 0;
398    for arg in args {
399        match run_static_analysis_on_node(arg) {
400            StaticResult::Scalar => {
401                // noop
402            }
403            StaticResult::Array(a, b) | StaticResult::Range(a, b) => {
404                n = n.max(a);
405                m = m.max(b);
406            }
407            StaticResult::Unknown => return StaticResult::Unknown,
408        }
409    }
410    if n == 0 && m == 0 {
411        return StaticResult::Scalar;
412    }
413    StaticResult::Array(n, m)
414}
415
416// We only care if the function can return a range or not
417fn not_implemented(_args: &[Node]) -> StaticResult {
418    StaticResult::Scalar
419}
420
421/// ROW and COLUMN give a single number for a single cell, and when the
422/// reference stays within one row (ROW) or one column (COLUMN). Otherwise they
423/// give a vector of numbers, one for each row or column of the reference.
424fn static_analysis_row_column(args: &[Node], is_row: bool) -> StaticResult {
425    let Some(reference) = args.first() else {
426        return StaticResult::Scalar;
427    };
428    // The vector is `Unknown` and not `Array`: a formula from before dynamic
429    // arrays expects a single number here, and it is the unknown results that
430    // are intersected (see `add_implicit_intersection`).
431    match reference {
432        Node::RangeKind {
433            absolute_row1,
434            absolute_column1,
435            row1,
436            column1,
437            absolute_row2,
438            absolute_column2,
439            row2,
440            column2,
441            ..
442        } => {
443            // The two ends are only comparable if both are absolute or both
444            // are relative to the cell.
445            let single = if is_row {
446                absolute_row1 == absolute_row2 && row1 == row2
447            } else {
448                absolute_column1 == absolute_column2 && column1 == column2
449            };
450            if single {
451                StaticResult::Scalar
452            } else {
453                StaticResult::Unknown
454            }
455        }
456        other => match run_static_analysis_on_node(other) {
457            StaticResult::Scalar => StaticResult::Scalar,
458            _ => StaticResult::Unknown,
459        },
460    }
461}
462
463/// SUMIF spills according to the shape of its criteria argument (`args[1]`); the
464/// criteria_range and sum_range arguments are consumed, not broadcast. A scalar
465/// criterion yields a scalar; a range/array criterion yields an array of the
466/// same dimensions.
467fn sumif_static_result(args: &[Node]) -> StaticResult {
468    match args.get(1) {
469        Some(criteria) => match run_static_analysis_on_node(criteria) {
470            StaticResult::Array(a, b) | StaticResult::Range(a, b) => StaticResult::Array(a, b),
471            StaticResult::Scalar => StaticResult::Scalar,
472            StaticResult::Unknown => StaticResult::Unknown,
473        },
474        None => StaticResult::Scalar,
475    }
476}
477
478fn static_analysis_offset(args: &[Node]) -> StaticResult {
479    // If first argument is a single cell reference and there are no4th and 5th argument,
480    // or they are 1, then it is a scalar
481    let arg_count = args.len();
482    if arg_count < 3 {
483        // Actually an error
484        return StaticResult::Scalar;
485    }
486    if !matches!(args[0], Node::ReferenceKind { .. }) {
487        return StaticResult::Unknown;
488    }
489    if arg_count == 3 {
490        return StaticResult::Scalar;
491    }
492    match args[3] {
493        Node::NumberKind(f) => {
494            if f != 1.0 {
495                return StaticResult::Unknown;
496            }
497        }
498        _ => return StaticResult::Unknown,
499    };
500    if arg_count == 4 {
501        return StaticResult::Scalar;
502    }
503    match args[4] {
504        Node::NumberKind(f) => {
505            if f != 1.0 {
506                return StaticResult::Unknown;
507            }
508        }
509        _ => return StaticResult::Unknown,
510    };
511    // Both height and width are explicitly 1, so OFFSET will return a single cell
512    StaticResult::Scalar
513}
514
515// fn static_analysis_choose(_args: &[Node]) -> StaticResult {
516//     // We will always insert the @ in CHOOSE, but technically it is only needed if one of the elements is a range
517//     StaticResult::Unknown
518// }
519
520fn static_analysis_indirect(_args: &[Node]) -> StaticResult {
521    // We will always insert the @, but we don't need to do that in every scenario`
522    StaticResult::Unknown
523}
524
525fn static_analysis_index(_args: &[Node]) -> StaticResult {
526    // INDEX has two forms, but they are indistinguishable at parse time.
527    StaticResult::Unknown
528}
529
530#[derive(Clone)]
531enum Signature {
532    Scalar,
533    Vector,
534    Error,
535}
536
537fn args_signature_no_args(arg_count: usize) -> Vec<Signature> {
538    if arg_count == 0 {
539        vec![]
540    } else {
541        vec![Signature::Error; arg_count]
542    }
543}
544
545fn args_signature_scalars(
546    arg_count: usize,
547    required_count: usize,
548    optional_count: usize,
549) -> Vec<Signature> {
550    if arg_count >= required_count && arg_count <= required_count + optional_count {
551        vec![Signature::Scalar; arg_count]
552    } else {
553        vec![Signature::Error; arg_count]
554    }
555}
556
557fn args_signature_lambda(arg_count: usize) -> Vec<Signature> {
558    // LAMBDA([param1, param2, ...], body) — at least 1 arg (the body)
559    if arg_count == 0 {
560        return vec![Signature::Error; arg_count];
561    }
562    // All parameter names are Scalar; the final body argument is Vector.
563    let mut sig = vec![Signature::Scalar; arg_count];
564    sig[arg_count - 1] = Signature::Vector;
565    sig
566}
567
568fn args_signature_let(arg_count: usize) -> Vec<Signature> {
569    // LET requires an odd number of args >= 3: name1, value1, [name2, value2, ...], body
570    if arg_count < 3 || arg_count.is_multiple_of(2) {
571        return vec![Signature::Error; arg_count];
572    }
573    (0..arg_count)
574        .map(|i| {
575            // Odd indices are value expressions; last index is the body.
576            // Both should be Vector so range references are not implicitly intersected.
577            // Even indices (except last) are name declarations — Scalar is fine since
578            // they are never actually evaluated as range expressions.
579            if i % 2 == 1 || i == arg_count - 1 {
580                Signature::Vector
581            } else {
582                Signature::Scalar
583            }
584        })
585        .collect()
586}
587
588fn args_signature_arraytotext(arg_count: usize) -> Vec<Signature> {
589    match arg_count {
590        1 => vec![Signature::Vector],
591        2 => vec![Signature::Vector, Signature::Scalar],
592        _ => vec![Signature::Error; arg_count],
593    }
594}
595
596fn args_signature_one_vector(arg_count: usize) -> Vec<Signature> {
597    if arg_count == 1 {
598        vec![Signature::Vector]
599    } else {
600        vec![Signature::Error; arg_count]
601    }
602}
603
604fn args_signature_sumif(arg_count: usize) -> Vec<Signature> {
605    if arg_count == 2 {
606        vec![Signature::Vector, Signature::Scalar]
607    } else if arg_count == 3 {
608        vec![Signature::Vector, Signature::Scalar, Signature::Vector]
609    } else {
610        vec![Signature::Error; arg_count]
611    }
612}
613
614/// SUMIF signature with the criteria argument as a `Vector` instead of a
615/// `Scalar`. This stops a range/array criteria from being collapsed by implicit
616/// intersection, so SUMIF can spill one sum per criterion. (COUNTIF/AVERAGEIF
617/// keep the classic [`args_signature_sumif`], intersecting range criteria.)
618fn args_signature_sumif_spill(arg_count: usize) -> Vec<Signature> {
619    if arg_count == 2 {
620        vec![Signature::Vector, Signature::Vector]
621    } else if arg_count == 3 {
622        vec![Signature::Vector, Signature::Vector, Signature::Vector]
623    } else {
624        vec![Signature::Error; arg_count]
625    }
626}
627
628// 1 or none scalars
629fn args_signature_sheet(arg_count: usize) -> Vec<Signature> {
630    if arg_count == 0 {
631        vec![]
632    } else if arg_count == 1 {
633        vec![Signature::Scalar]
634    } else {
635        vec![Signature::Error; arg_count]
636    }
637}
638
639fn args_signature_hlookup(arg_count: usize) -> Vec<Signature> {
640    if arg_count == 3 {
641        vec![Signature::Vector, Signature::Vector, Signature::Scalar]
642    } else if arg_count == 4 {
643        vec![
644            Signature::Vector,
645            Signature::Vector,
646            Signature::Scalar,
647            Signature::Vector,
648        ]
649    } else {
650        vec![Signature::Error; arg_count]
651    }
652}
653
654fn args_signature_index(arg_count: usize) -> Vec<Signature> {
655    if arg_count == 2 {
656        vec![Signature::Vector, Signature::Scalar]
657    } else if arg_count == 3 {
658        vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
659    } else if arg_count == 4 {
660        vec![
661            Signature::Vector,
662            Signature::Scalar,
663            Signature::Scalar,
664            Signature::Scalar,
665        ]
666    } else {
667        vec![Signature::Error; arg_count]
668    }
669}
670
671fn args_signature_lookup(arg_count: usize) -> Vec<Signature> {
672    if arg_count == 2 {
673        vec![Signature::Vector, Signature::Vector]
674    } else if arg_count == 3 {
675        vec![Signature::Vector, Signature::Vector, Signature::Vector]
676    } else {
677        vec![Signature::Error; arg_count]
678    }
679}
680
681fn args_signature_match(arg_count: usize) -> Vec<Signature> {
682    if arg_count == 2 {
683        vec![Signature::Vector, Signature::Vector]
684    } else if arg_count == 3 {
685        vec![Signature::Vector, Signature::Vector, Signature::Scalar]
686    } else {
687        vec![Signature::Error; arg_count]
688    }
689}
690
691fn args_signature_offset(arg_count: usize) -> Vec<Signature> {
692    if arg_count == 3 {
693        vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
694    } else if arg_count == 4 {
695        vec![
696            Signature::Vector,
697            Signature::Scalar,
698            Signature::Scalar,
699            Signature::Scalar,
700        ]
701    } else if arg_count == 5 {
702        vec![
703            Signature::Vector,
704            Signature::Scalar,
705            Signature::Scalar,
706            Signature::Scalar,
707            Signature::Scalar,
708        ]
709    } else {
710        vec![Signature::Error; arg_count]
711    }
712}
713
714fn args_signature_row(arg_count: usize) -> Vec<Signature> {
715    if arg_count == 0 {
716        vec![]
717    } else if arg_count == 1 {
718        vec![Signature::Vector]
719    } else {
720        vec![Signature::Error; arg_count]
721    }
722}
723
724fn args_signature_xlookup(arg_count: usize) -> Vec<Signature> {
725    if !(3..=6).contains(&arg_count) {
726        return vec![Signature::Error; arg_count];
727    }
728    let mut result = vec![Signature::Scalar; arg_count];
729    result[0] = Signature::Vector;
730    result[1] = Signature::Vector;
731    result[2] = Signature::Vector;
732    result
733}
734
735fn args_signature_sort(arg_count: usize) -> Vec<Signature> {
736    if !(1..=4).contains(&arg_count) {
737        return vec![Signature::Error; arg_count];
738    }
739    let mut result = vec![Signature::Scalar; arg_count];
740    result[0] = Signature::Vector;
741    result
742}
743
744fn args_signature_sortby(arg_count: usize) -> Vec<Signature> {
745    // Valid: 2, 3, 5, 7, ... (n==2 || n==3 || n>=5 with odd count)
746    if arg_count < 2 || (arg_count > 3 && arg_count.is_multiple_of(2)) {
747        return vec![Signature::Error; arg_count];
748    }
749    // arg[0] = array (Vector), arg[1] = by_array1 (Vector),
750    // optional arg[2] = sort_order1 (Scalar), then pairs (Vector, Scalar)
751    let mut result = vec![Signature::Scalar; arg_count];
752    result[0] = Signature::Vector;
753    let mut i = 1;
754    while i < arg_count {
755        result[i] = Signature::Vector; // by_array
756        i += 2; // skip the sort_order (Scalar)
757    }
758    result
759}
760
761fn args_signature_unique(arg_count: usize) -> Vec<Signature> {
762    if !(1..=3).contains(&arg_count) {
763        return vec![Signature::Error; arg_count];
764    }
765    let mut result = vec![Signature::Scalar; arg_count];
766    result[0] = Signature::Vector;
767    result
768}
769
770fn args_signature_filter(arg_count: usize) -> Vec<Signature> {
771    if !(2..=3).contains(&arg_count) {
772        return vec![Signature::Error; arg_count];
773    }
774    let mut result = vec![Signature::Scalar; arg_count];
775    result[0] = Signature::Vector;
776    result[1] = Signature::Vector;
777    result
778}
779
780fn args_signature_sequence(arg_count: usize) -> Vec<Signature> {
781    if !(1..=4).contains(&arg_count) {
782        return vec![Signature::Error; arg_count];
783    }
784    vec![Signature::Scalar; arg_count]
785}
786
787fn args_signature_randarray(arg_count: usize) -> Vec<Signature> {
788    if arg_count > 5 {
789        return vec![Signature::Error; arg_count];
790    }
791    vec![Signature::Scalar; arg_count]
792}
793
794fn args_signature_take(arg_count: usize) -> Vec<Signature> {
795    if !(2..=3).contains(&arg_count) {
796        return vec![Signature::Error; arg_count];
797    }
798    let mut result = vec![Signature::Scalar; arg_count];
799    result[0] = Signature::Vector;
800    result
801}
802
803fn args_signature_drop(arg_count: usize) -> Vec<Signature> {
804    if !(2..=3).contains(&arg_count) {
805        return vec![Signature::Error; arg_count];
806    }
807    let mut result = vec![Signature::Scalar; arg_count];
808    result[0] = Signature::Vector;
809    result
810}
811
812fn args_signature_tocol(arg_count: usize) -> Vec<Signature> {
813    if !(1..=3).contains(&arg_count) {
814        return vec![Signature::Error; arg_count];
815    }
816    let mut result = vec![Signature::Scalar; arg_count];
817    result[0] = Signature::Vector;
818    result
819}
820
821fn args_signature_bycol_byrow(arg_count: usize) -> Vec<Signature> {
822    if arg_count != 2 {
823        return vec![Signature::Error; arg_count];
824    }
825    vec![Signature::Vector, Signature::Scalar]
826}
827
828fn args_signature_map(arg_count: usize) -> Vec<Signature> {
829    if arg_count < 2 {
830        return vec![Signature::Error; arg_count];
831    }
832    // All args except the last (lambda) are Vector; the lambda is Scalar.
833    let mut result = vec![Signature::Vector; arg_count];
834    result[arg_count - 1] = Signature::Scalar;
835    result
836}
837
838fn args_signature_reduce(arg_count: usize) -> Vec<Signature> {
839    match arg_count {
840        2 => vec![Signature::Vector, Signature::Scalar],
841        3 => vec![Signature::Scalar, Signature::Vector, Signature::Scalar],
842        _ => vec![Signature::Error; arg_count],
843    }
844}
845
846fn args_signature_scan(arg_count: usize) -> Vec<Signature> {
847    match arg_count {
848        2 => vec![Signature::Vector, Signature::Scalar],
849        3 => vec![Signature::Scalar, Signature::Vector, Signature::Scalar],
850        _ => vec![Signature::Error; arg_count],
851    }
852}
853
854fn args_signature_textsplit(arg_count: usize) -> Vec<Signature> {
855    if !(2..=6).contains(&arg_count) {
856        return vec![Signature::Error; arg_count];
857    }
858    // col_delimiter (index 1) and row_delimiter (index 2) can be arrays
859    let mut result = vec![Signature::Scalar; arg_count];
860    result[1] = Signature::Vector;
861    if arg_count >= 3 {
862        result[2] = Signature::Vector;
863    }
864    result
865}
866
867fn args_signature_textafter(arg_count: usize) -> Vec<Signature> {
868    if !(2..=6).contains(&arg_count) {
869        vec![Signature::Scalar; arg_count]
870    } else {
871        vec![Signature::Error; arg_count]
872    }
873}
874
875fn args_signature_textjoin(arg_count: usize) -> Vec<Signature> {
876    if arg_count >= 3 {
877        let mut result = vec![Signature::Vector; arg_count];
878        result[0] = Signature::Scalar;
879        result[1] = Signature::Scalar;
880        result
881    } else {
882        vec![Signature::Error; arg_count]
883    }
884}
885
886fn args_signature_npv(arg_count: usize) -> Vec<Signature> {
887    if arg_count < 2 {
888        return vec![Signature::Error; arg_count];
889    }
890    let mut result = vec![Signature::Vector; arg_count];
891    result[0] = Signature::Scalar;
892    result
893}
894
895fn args_signature_irr(arg_count: usize) -> Vec<Signature> {
896    if arg_count > 2 {
897        vec![Signature::Error; arg_count]
898    } else if arg_count == 1 {
899        vec![Signature::Vector]
900    } else {
901        vec![Signature::Vector, Signature::Scalar]
902    }
903}
904
905fn args_signature_xirr(arg_count: usize) -> Vec<Signature> {
906    if arg_count == 2 {
907        vec![Signature::Vector; arg_count]
908    } else if arg_count == 3 {
909        vec![Signature::Vector, Signature::Vector, Signature::Scalar]
910    } else {
911        vec![Signature::Error; arg_count]
912    }
913}
914
915fn args_signature_mirr(arg_count: usize) -> Vec<Signature> {
916    if arg_count != 3 {
917        vec![Signature::Error; arg_count]
918    } else {
919        vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
920    }
921}
922
923fn args_signature_xnpv(arg_count: usize) -> Vec<Signature> {
924    if arg_count != 3 {
925        vec![Signature::Error; arg_count]
926    } else {
927        vec![Signature::Scalar, Signature::Vector, Signature::Vector]
928    }
929}
930
931// NETWORKDAYS(start_date, end_date, [holidays])
932// Parameters: start_date (scalar), end_date (scalar), holidays (optional vector)
933fn args_signature_networkdays(arg_count: usize) -> Vec<Signature> {
934    if arg_count == 2 {
935        vec![Signature::Scalar, Signature::Scalar]
936    } else if arg_count == 3 {
937        vec![Signature::Scalar, Signature::Scalar, Signature::Vector]
938    } else {
939        vec![Signature::Error; arg_count]
940    }
941}
942
943// NETWORKDAYS.INTL(start_date, end_date, [weekend], [holidays])
944// Parameters: start_date (scalar), end_date (scalar), weekend (optional scalar), holidays (optional vector)
945fn args_signature_networkdays_intl(arg_count: usize) -> Vec<Signature> {
946    if arg_count == 2 {
947        vec![Signature::Scalar, Signature::Scalar]
948    } else if arg_count == 3 {
949        vec![Signature::Scalar, Signature::Scalar, Signature::Scalar]
950    } else if arg_count == 4 {
951        vec![
952            Signature::Scalar,
953            Signature::Scalar,
954            Signature::Scalar,
955            Signature::Vector,
956        ]
957    } else {
958        vec![Signature::Error; arg_count]
959    }
960}
961
962// FIXME: This is terrible duplications of efforts. We use the signature in at least three different places:
963// 1. When computing the function
964// 2. Checking the arguments to see if we need to insert the implicit intersection operator
965// 3. Understanding the return value
966//
967fn args_signature_xmatch(arg_count: usize) -> Vec<Signature> {
968    if !(2..=4).contains(&arg_count) {
969        return vec![Signature::Error; arg_count];
970    }
971    let mut result = vec![Signature::Scalar; arg_count];
972    result[1] = Signature::Vector;
973    result
974}
975
976fn args_signature_trimrange(arg_count: usize) -> Vec<Signature> {
977    if !(1..=3).contains(&arg_count) {
978        return vec![Signature::Error; arg_count];
979    }
980    let mut result = vec![Signature::Scalar; arg_count];
981    result[0] = Signature::Vector;
982    result
983}
984
985fn args_signature_address(arg_count: usize) -> Vec<Signature> {
986    if !(2..=5).contains(&arg_count) {
987        return vec![Signature::Error; arg_count];
988    }
989    vec![Signature::Scalar; arg_count]
990}
991
992fn args_signature_choose(arg_count: usize) -> Vec<Signature> {
993    // CHOOSE(index, value1, ...): the index is a scalar; the value arguments
994    // pass references through untouched (Excel: SUM(CHOOSE(2, A1:A5, B1:B5))
995    // sums the chosen range). In scalar context the implicit intersection is
996    // applied to the CHOOSE call itself, never to its arms.
997    if arg_count < 2 {
998        return vec![Signature::Error; arg_count];
999    }
1000    let mut result = vec![Signature::Vector; arg_count];
1001    result[0] = Signature::Scalar;
1002    result
1003}
1004
1005fn args_signature_choosecols(arg_count: usize) -> Vec<Signature> {
1006    if arg_count < 2 {
1007        return vec![Signature::Error; arg_count];
1008    }
1009    let mut result = vec![Signature::Scalar; arg_count];
1010    result[0] = Signature::Vector;
1011    result
1012}
1013
1014fn args_signature_expand(arg_count: usize) -> Vec<Signature> {
1015    if !(2..=4).contains(&arg_count) {
1016        return vec![Signature::Error; arg_count];
1017    }
1018    let mut result = vec![Signature::Scalar; arg_count];
1019    result[0] = Signature::Vector;
1020    result
1021}
1022
1023fn args_signature_wrapcols(arg_count: usize) -> Vec<Signature> {
1024    if !(2..=3).contains(&arg_count) {
1025        return vec![Signature::Error; arg_count];
1026    }
1027    let mut result = vec![Signature::Scalar; arg_count];
1028    result[0] = Signature::Vector;
1029    result
1030}
1031
1032// The signature of the functions should be defined only once
1033
1034// Given a function and a number of arguments this returns the arguments at each position
1035// are expected to be scalars or vectors (array/ranges).
1036// Sets signature::Error to all arguments if the number of arguments is incorrect.
1037fn get_function_args_signature(kind: &Function, arg_count: usize) -> Vec<Signature> {
1038    match kind {
1039        Function::And => vec![Signature::Vector; arg_count],
1040        Function::False => args_signature_no_args(arg_count),
1041        Function::If => args_signature_scalars(arg_count, 2, 1),
1042        Function::Iferror => args_signature_scalars(arg_count, 2, 0),
1043        Function::Ifna => args_signature_scalars(arg_count, 2, 0),
1044        Function::Ifs => vec![Signature::Scalar; arg_count],
1045        Function::Lambda => args_signature_lambda(arg_count),
1046        Function::Let => args_signature_let(arg_count),
1047        Function::Not => args_signature_scalars(arg_count, 1, 0),
1048        Function::Or => vec![Signature::Vector; arg_count],
1049        Function::Switch => vec![Signature::Scalar; arg_count],
1050        Function::True => args_signature_no_args(arg_count),
1051        Function::Xor => vec![Signature::Vector; arg_count],
1052        Function::Abs => args_signature_scalars(arg_count, 1, 0),
1053        Function::Acos => args_signature_scalars(arg_count, 1, 0),
1054        Function::Acosh => args_signature_scalars(arg_count, 1, 0),
1055        Function::Asin => args_signature_scalars(arg_count, 1, 0),
1056        Function::Asinh => args_signature_scalars(arg_count, 1, 0),
1057        Function::Atan => args_signature_scalars(arg_count, 1, 0),
1058        Function::Atan2 => args_signature_scalars(arg_count, 2, 0),
1059        Function::Atanh => args_signature_scalars(arg_count, 1, 0),
1060        Function::Choose => args_signature_choose(arg_count),
1061        Function::Column => args_signature_row(arg_count),
1062        Function::Columns => args_signature_one_vector(arg_count),
1063        Function::Ln => args_signature_scalars(arg_count, 1, 0),
1064        Function::Log => args_signature_scalars(arg_count, 1, 1),
1065        Function::Log10 => args_signature_scalars(arg_count, 1, 0),
1066        Function::Cos => args_signature_scalars(arg_count, 1, 0),
1067        Function::Cosh => args_signature_scalars(arg_count, 1, 0),
1068        Function::Max => vec![Signature::Vector; arg_count],
1069        Function::Min => vec![Signature::Vector; arg_count],
1070        Function::Pi => args_signature_no_args(arg_count),
1071        Function::Power => args_signature_scalars(arg_count, 2, 0),
1072        Function::Product => vec![Signature::Vector; arg_count],
1073        Function::Round => args_signature_scalars(arg_count, 2, 0),
1074        Function::Rounddown => args_signature_scalars(arg_count, 2, 0),
1075        Function::Roundup => args_signature_scalars(arg_count, 2, 0),
1076        Function::Sin => args_signature_scalars(arg_count, 1, 0),
1077        Function::Sinh => args_signature_scalars(arg_count, 1, 0),
1078        Function::Sqrt => args_signature_scalars(arg_count, 1, 0),
1079        Function::Sqrtpi => args_signature_scalars(arg_count, 1, 0),
1080        Function::Sum => vec![Signature::Vector; arg_count],
1081        Function::Sumif => args_signature_sumif_spill(arg_count),
1082        Function::Sumifs => vec![Signature::Vector; arg_count],
1083        Function::Tan => args_signature_scalars(arg_count, 1, 0),
1084        Function::Tanh => args_signature_scalars(arg_count, 1, 0),
1085        Function::ErrorType => args_signature_scalars(arg_count, 1, 0),
1086        Function::Isblank => args_signature_scalars(arg_count, 1, 0),
1087        Function::Iserr => args_signature_scalars(arg_count, 1, 0),
1088        Function::Iserror => args_signature_scalars(arg_count, 1, 0),
1089        Function::Iseven => args_signature_scalars(arg_count, 1, 0),
1090        Function::Isformula => args_signature_scalars(arg_count, 1, 0),
1091        Function::Islogical => args_signature_scalars(arg_count, 1, 0),
1092        Function::Isna => args_signature_scalars(arg_count, 1, 0),
1093        Function::Isnontext => args_signature_scalars(arg_count, 1, 0),
1094        Function::Isnumber => args_signature_scalars(arg_count, 1, 0),
1095        Function::Isodd => args_signature_scalars(arg_count, 1, 0),
1096        Function::Isomitted => args_signature_scalars(arg_count, 1, 0),
1097        Function::Isref => args_signature_one_vector(arg_count),
1098        Function::Istext => args_signature_scalars(arg_count, 1, 0),
1099        Function::Na => args_signature_no_args(arg_count),
1100        Function::Sheet => args_signature_sheet(arg_count),
1101        Function::Type => args_signature_one_vector(arg_count),
1102        Function::Address => args_signature_address(arg_count),
1103        Function::Areas => args_signature_one_vector(arg_count),
1104        Function::Choosecols => args_signature_choosecols(arg_count),
1105        Function::Chooserows => args_signature_choosecols(arg_count),
1106        Function::Expand => args_signature_expand(arg_count),
1107        Function::Hlookup => args_signature_hlookup(arg_count),
1108        Function::Hstack => vec![Signature::Vector; arg_count],
1109        Function::Hyperlink => args_signature_scalars(arg_count, 1, 1),
1110        Function::Index => args_signature_index(arg_count),
1111        Function::Indirect => args_signature_scalars(arg_count, 1, 1),
1112        Function::Lookup => args_signature_lookup(arg_count),
1113        Function::Match => args_signature_match(arg_count),
1114        Function::Offset => args_signature_offset(arg_count),
1115        Function::Row => args_signature_row(arg_count),
1116        Function::Rows => args_signature_one_vector(arg_count),
1117        Function::Vlookup => args_signature_hlookup(arg_count),
1118        Function::Vstack => vec![Signature::Vector; arg_count],
1119        Function::Wrapcols => args_signature_wrapcols(arg_count),
1120        Function::Wraprows => args_signature_wrapcols(arg_count),
1121        Function::Xlookup => args_signature_xlookup(arg_count),
1122        Function::Xmatch => args_signature_xmatch(arg_count),
1123        Function::Trimrange => args_signature_trimrange(arg_count),
1124        Function::Sort => args_signature_sort(arg_count),
1125        Function::Sortby => args_signature_sortby(arg_count),
1126        Function::Unique => args_signature_unique(arg_count),
1127        Function::Filter => args_signature_filter(arg_count),
1128        Function::Take => args_signature_take(arg_count),
1129        Function::Drop => args_signature_drop(arg_count),
1130        Function::Tocol => args_signature_tocol(arg_count),
1131        Function::Torow => args_signature_tocol(arg_count),
1132        Function::Transpose => args_signature_one_vector(arg_count),
1133        Function::Mmult => {
1134            if arg_count == 2 {
1135                vec![Signature::Vector, Signature::Vector]
1136            } else {
1137                vec![Signature::Error; arg_count]
1138            }
1139        }
1140        Function::Bycol => args_signature_bycol_byrow(arg_count),
1141        Function::Byrow => args_signature_bycol_byrow(arg_count),
1142        Function::Map => args_signature_map(arg_count),
1143        Function::Reduce => args_signature_reduce(arg_count),
1144        Function::Scan => args_signature_scan(arg_count),
1145        Function::Makearray => vec![Signature::Scalar; 3],
1146        Function::Sequence => args_signature_sequence(arg_count),
1147        Function::Randarray => args_signature_randarray(arg_count),
1148        Function::Textsplit => args_signature_textsplit(arg_count),
1149        Function::Concat => vec![Signature::Vector; arg_count],
1150        Function::Concatenate => vec![Signature::Scalar; arg_count],
1151        Function::Exact => args_signature_scalars(arg_count, 2, 0),
1152        Function::Find => args_signature_scalars(arg_count, 2, 1),
1153        Function::Left => args_signature_scalars(arg_count, 1, 1),
1154        Function::Len => args_signature_scalars(arg_count, 1, 0),
1155        Function::Lower => args_signature_scalars(arg_count, 1, 0),
1156        Function::Mid => args_signature_scalars(arg_count, 3, 0),
1157        Function::Rept => args_signature_scalars(arg_count, 2, 0),
1158        Function::Right => args_signature_scalars(arg_count, 2, 1),
1159        Function::Search => args_signature_scalars(arg_count, 2, 1),
1160        Function::Substitute => args_signature_scalars(arg_count, 3, 1),
1161        Function::Regexextract => args_signature_scalars(arg_count, 2, 1),
1162        Function::Regexreplace => args_signature_scalars(arg_count, 3, 0),
1163        Function::Regextest => args_signature_scalars(arg_count, 2, 0),
1164        Function::T => args_signature_scalars(arg_count, 1, 0),
1165        Function::Text => args_signature_scalars(arg_count, 2, 0),
1166        Function::Textafter => args_signature_textafter(arg_count),
1167        Function::Textbefore => args_signature_textafter(arg_count),
1168        Function::Textjoin => args_signature_textjoin(arg_count),
1169        Function::Trim => args_signature_scalars(arg_count, 1, 0),
1170        Function::Upper => args_signature_scalars(arg_count, 1, 0),
1171        Function::Value => args_signature_scalars(arg_count, 1, 0),
1172        Function::Valuetotext => args_signature_scalars(arg_count, 1, 1),
1173        Function::Average => vec![Signature::Vector; arg_count],
1174        Function::Avedev => vec![Signature::Vector; arg_count],
1175        Function::Averagea => vec![Signature::Vector; arg_count],
1176        Function::Averageif => args_signature_sumif(arg_count),
1177        Function::Averageifs => vec![Signature::Vector; arg_count],
1178        Function::Count => vec![Signature::Vector; arg_count],
1179        Function::Counta => vec![Signature::Vector; arg_count],
1180        Function::Countblank => vec![Signature::Vector; arg_count],
1181        Function::Countif => args_signature_sumif(arg_count),
1182        Function::Countifs => vec![Signature::Vector; arg_count],
1183        Function::Maxifs => vec![Signature::Vector; arg_count],
1184        Function::Minifs => vec![Signature::Vector; arg_count],
1185        Function::Date => args_signature_scalars(arg_count, 3, 0),
1186        Function::Datedif => args_signature_scalars(arg_count, 3, 0),
1187        Function::Datevalue => args_signature_scalars(arg_count, 1, 0),
1188        Function::Day => args_signature_scalars(arg_count, 1, 0),
1189        Function::Edate => args_signature_scalars(arg_count, 2, 0),
1190        Function::Eomonth => args_signature_scalars(arg_count, 2, 0),
1191        Function::Month => args_signature_scalars(arg_count, 1, 0),
1192        Function::Time => args_signature_scalars(arg_count, 3, 0),
1193        Function::Timevalue => args_signature_scalars(arg_count, 1, 0),
1194        Function::Hour => args_signature_scalars(arg_count, 1, 0),
1195        Function::Minute => args_signature_scalars(arg_count, 1, 0),
1196        Function::Second => args_signature_scalars(arg_count, 1, 0),
1197        Function::Now => args_signature_no_args(arg_count),
1198        Function::Today => args_signature_no_args(arg_count),
1199        Function::Year => args_signature_scalars(arg_count, 1, 0),
1200        Function::Days => args_signature_scalars(arg_count, 2, 0),
1201        Function::Days360 => args_signature_scalars(arg_count, 2, 1),
1202        Function::Weekday => args_signature_scalars(arg_count, 1, 1),
1203        Function::Weeknum => args_signature_scalars(arg_count, 1, 1),
1204        Function::Workday => args_signature_scalars(arg_count, 2, 1),
1205        Function::WorkdayIntl => args_signature_scalars(arg_count, 2, 2),
1206        Function::Yearfrac => args_signature_scalars(arg_count, 2, 1),
1207        Function::Isoweeknum => args_signature_scalars(arg_count, 1, 0),
1208        Function::Accrint => args_signature_scalars(arg_count, 6, 2),
1209        Function::Accrintm => args_signature_scalars(arg_count, 3, 2),
1210        Function::Disc => args_signature_scalars(arg_count, 4, 1),
1211        Function::Fvschedule => vec![Signature::Scalar, Signature::Vector],
1212        Function::Intrate => args_signature_scalars(arg_count, 4, 1),
1213        Function::Pricedisc => args_signature_scalars(arg_count, 4, 1),
1214        Function::Pricemat => args_signature_scalars(arg_count, 5, 1),
1215        Function::Received => args_signature_scalars(arg_count, 4, 1),
1216        Function::Yielddisc => args_signature_scalars(arg_count, 4, 1),
1217        Function::Yieldmat => args_signature_scalars(arg_count, 5, 1),
1218        Function::Cumipmt => args_signature_scalars(arg_count, 6, 0),
1219        Function::Cumprinc => args_signature_scalars(arg_count, 6, 0),
1220        Function::Db => args_signature_scalars(arg_count, 4, 1),
1221        Function::Ddb => args_signature_scalars(arg_count, 4, 1),
1222        Function::Dollarde => args_signature_scalars(arg_count, 2, 0),
1223        Function::Dollarfr => args_signature_scalars(arg_count, 2, 0),
1224        Function::Effect => args_signature_scalars(arg_count, 2, 0),
1225        Function::Fv => args_signature_scalars(arg_count, 3, 2),
1226        Function::Ipmt => args_signature_scalars(arg_count, 4, 2),
1227        Function::Irr => args_signature_irr(arg_count),
1228        Function::Ispmt => args_signature_scalars(arg_count, 4, 0),
1229        Function::Mirr => args_signature_mirr(arg_count),
1230        Function::Nominal => args_signature_scalars(arg_count, 2, 0),
1231        Function::Nper => args_signature_scalars(arg_count, 3, 2),
1232        Function::Npv => args_signature_npv(arg_count),
1233        Function::Pduration => args_signature_scalars(arg_count, 3, 0),
1234        Function::Pmt => args_signature_scalars(arg_count, 3, 2),
1235        Function::Ppmt => args_signature_scalars(arg_count, 4, 2),
1236        Function::Pv => args_signature_scalars(arg_count, 3, 2),
1237        Function::Rate => args_signature_scalars(arg_count, 3, 3),
1238        Function::Rri => args_signature_scalars(arg_count, 3, 0),
1239        Function::Sln => args_signature_scalars(arg_count, 3, 0),
1240        Function::Syd => args_signature_scalars(arg_count, 4, 0),
1241        Function::Tbilleq => args_signature_scalars(arg_count, 3, 0),
1242        Function::Tbillprice => args_signature_scalars(arg_count, 3, 0),
1243        Function::Tbillyield => args_signature_scalars(arg_count, 3, 0),
1244        Function::Xirr => args_signature_xirr(arg_count),
1245        Function::Xnpv => args_signature_xnpv(arg_count),
1246        Function::Duration => args_signature_scalars(arg_count, 5, 1),
1247        Function::Mduration => args_signature_scalars(arg_count, 5, 1),
1248        Function::Price => args_signature_scalars(arg_count, 6, 1),
1249        Function::Yield => args_signature_scalars(arg_count, 6, 1),
1250        Function::Oddfprice => args_signature_scalars(arg_count, 8, 1),
1251        Function::Oddfyield => args_signature_scalars(arg_count, 8, 1),
1252        Function::Oddlprice => args_signature_scalars(arg_count, 7, 1),
1253        Function::Oddlyield => args_signature_scalars(arg_count, 7, 1),
1254        Function::Coupdaybs => args_signature_scalars(arg_count, 3, 1),
1255        Function::Coupdays => args_signature_scalars(arg_count, 3, 1),
1256        Function::Coupdaysnc => args_signature_scalars(arg_count, 3, 1),
1257        Function::Coupncd => args_signature_scalars(arg_count, 3, 1),
1258        Function::Coupnum => args_signature_scalars(arg_count, 3, 1),
1259        Function::Couppcd => args_signature_scalars(arg_count, 3, 1),
1260        Function::Amordegrc => args_signature_scalars(arg_count, 6, 1),
1261        Function::Amorlinc => args_signature_scalars(arg_count, 6, 1),
1262        Function::Vdb => args_signature_scalars(arg_count, 5, 2),
1263        Function::Besseli => args_signature_scalars(arg_count, 2, 0),
1264        Function::Besselj => args_signature_scalars(arg_count, 2, 0),
1265        Function::Besselk => args_signature_scalars(arg_count, 2, 0),
1266        Function::Bessely => args_signature_scalars(arg_count, 2, 0),
1267        Function::Erf => args_signature_scalars(arg_count, 1, 1),
1268        Function::Erfc => args_signature_scalars(arg_count, 1, 0),
1269        Function::ErfcPrecise => args_signature_scalars(arg_count, 1, 0),
1270        Function::ErfPrecise => args_signature_scalars(arg_count, 1, 0),
1271        Function::Bin2dec => args_signature_scalars(arg_count, 1, 0),
1272        Function::Bin2hex => args_signature_scalars(arg_count, 1, 0),
1273        Function::Bin2oct => args_signature_scalars(arg_count, 1, 0),
1274        Function::Dec2Bin => args_signature_scalars(arg_count, 1, 0),
1275        Function::Dec2hex => args_signature_scalars(arg_count, 1, 0),
1276        Function::Dec2oct => args_signature_scalars(arg_count, 1, 0),
1277        Function::Hex2bin => args_signature_scalars(arg_count, 1, 0),
1278        Function::Hex2dec => args_signature_scalars(arg_count, 1, 0),
1279        Function::Hex2oct => args_signature_scalars(arg_count, 1, 0),
1280        Function::Oct2bin => args_signature_scalars(arg_count, 1, 0),
1281        Function::Oct2dec => args_signature_scalars(arg_count, 1, 0),
1282        Function::Oct2hex => args_signature_scalars(arg_count, 1, 0),
1283        Function::Bitand => args_signature_scalars(arg_count, 2, 0),
1284        Function::Bitlshift => args_signature_scalars(arg_count, 2, 0),
1285        Function::Bitor => args_signature_scalars(arg_count, 2, 0),
1286        Function::Bitrshift => args_signature_scalars(arg_count, 2, 0),
1287        Function::Bitxor => args_signature_scalars(arg_count, 2, 0),
1288        Function::Complex => args_signature_scalars(arg_count, 2, 1),
1289        Function::Imabs => args_signature_scalars(arg_count, 1, 0),
1290        Function::Imaginary => args_signature_scalars(arg_count, 1, 0),
1291        Function::Imargument => args_signature_scalars(arg_count, 1, 0),
1292        Function::Imconjugate => args_signature_scalars(arg_count, 1, 0),
1293        Function::Imcos => args_signature_scalars(arg_count, 1, 0),
1294        Function::Imcosh => args_signature_scalars(arg_count, 1, 0),
1295        Function::Imcot => args_signature_scalars(arg_count, 1, 0),
1296        Function::Imcsc => args_signature_scalars(arg_count, 1, 0),
1297        Function::Imcsch => args_signature_scalars(arg_count, 1, 0),
1298        Function::Imdiv => args_signature_scalars(arg_count, 2, 0),
1299        Function::Imexp => args_signature_scalars(arg_count, 1, 0),
1300        Function::Imln => args_signature_scalars(arg_count, 1, 0),
1301        Function::Imlog10 => args_signature_scalars(arg_count, 1, 0),
1302        Function::Imlog2 => args_signature_scalars(arg_count, 1, 0),
1303        Function::Impower => args_signature_scalars(arg_count, 2, 0),
1304        Function::Improduct => args_signature_scalars(arg_count, 2, 0),
1305        Function::Imreal => args_signature_scalars(arg_count, 1, 0),
1306        Function::Imsec => args_signature_scalars(arg_count, 1, 0),
1307        Function::Imsech => args_signature_scalars(arg_count, 1, 0),
1308        Function::Imsin => args_signature_scalars(arg_count, 1, 0),
1309        Function::Imsinh => args_signature_scalars(arg_count, 1, 0),
1310        Function::Imsqrt => args_signature_scalars(arg_count, 1, 0),
1311        Function::Imsub => args_signature_scalars(arg_count, 2, 0),
1312        Function::Imsum => args_signature_scalars(arg_count, 2, 0),
1313        Function::Imtan => args_signature_scalars(arg_count, 1, 0),
1314        Function::Convert => args_signature_scalars(arg_count, 3, 0),
1315        Function::Delta => args_signature_scalars(arg_count, 1, 1),
1316        Function::Gestep => args_signature_scalars(arg_count, 1, 1),
1317        Function::Subtotal => args_signature_npv(arg_count),
1318        Function::Rand => args_signature_no_args(arg_count),
1319        Function::Randbetween => args_signature_scalars(arg_count, 2, 0),
1320        Function::Formulatext => args_signature_scalars(arg_count, 1, 0),
1321        Function::Unicode => args_signature_scalars(arg_count, 1, 0),
1322        Function::Unichar => args_signature_scalars(arg_count, 1, 0),
1323        Function::Char => args_signature_scalars(arg_count, 1, 0),
1324        Function::Clean => args_signature_scalars(arg_count, 1, 0),
1325        Function::Code => args_signature_scalars(arg_count, 1, 0),
1326        Function::Asc => args_signature_scalars(arg_count, 1, 0),
1327        Function::Arraytotext => args_signature_arraytotext(arg_count),
1328        Function::Dollar => args_signature_scalars(arg_count, 1, 1),
1329        Function::Encodeurl => args_signature_scalars(arg_count, 1, 0),
1330        Function::EcmaCeiling => args_signature_scalars(arg_count, 2, 0),
1331        Function::Findb => args_signature_scalars(arg_count, 2, 1),
1332        Function::Fixed => args_signature_scalars(arg_count, 1, 2),
1333        Function::Leftb => args_signature_scalars(arg_count, 1, 1),
1334        Function::Lenb => args_signature_scalars(arg_count, 1, 0),
1335        Function::Midb => args_signature_scalars(arg_count, 3, 0),
1336        Function::Numbervalue => args_signature_scalars(arg_count, 1, 2),
1337        Function::Proper => args_signature_scalars(arg_count, 1, 0),
1338        Function::Replace => args_signature_scalars(arg_count, 4, 0),
1339        Function::Replaceb => args_signature_scalars(arg_count, 4, 0),
1340        Function::Rightb => args_signature_scalars(arg_count, 1, 1),
1341        Function::Searchb => args_signature_scalars(arg_count, 2, 1),
1342        Function::Geomean => vec![Signature::Vector; arg_count],
1343        Function::Networkdays => args_signature_networkdays(arg_count),
1344        Function::NetworkdaysIntl => args_signature_networkdays_intl(arg_count),
1345        Function::Acot => args_signature_scalars(arg_count, 1, 0),
1346        Function::Acoth => args_signature_scalars(arg_count, 1, 0),
1347        Function::Cot => args_signature_scalars(arg_count, 1, 0),
1348        Function::Coth => args_signature_scalars(arg_count, 1, 0),
1349        Function::Csc => args_signature_scalars(arg_count, 1, 0),
1350        Function::Csch => args_signature_scalars(arg_count, 1, 0),
1351        Function::Sec => args_signature_scalars(arg_count, 1, 0),
1352        Function::Sech => args_signature_scalars(arg_count, 1, 0),
1353        Function::Exp => args_signature_scalars(arg_count, 1, 0),
1354        Function::Fact => args_signature_scalars(arg_count, 1, 0),
1355        Function::Factdouble => args_signature_scalars(arg_count, 1, 0),
1356        Function::Sign => args_signature_scalars(arg_count, 1, 0),
1357        Function::Radians => args_signature_scalars(arg_count, 1, 0),
1358        Function::Degrees => args_signature_scalars(arg_count, 1, 0),
1359        Function::Int => args_signature_scalars(arg_count, 1, 0),
1360        Function::Even => args_signature_scalars(arg_count, 1, 0),
1361        Function::Odd => args_signature_scalars(arg_count, 1, 0),
1362        Function::Ceiling => args_signature_scalars(arg_count, 2, 0),
1363        Function::CeilingMath => args_signature_scalars(arg_count, 1, 2),
1364        Function::CeilingPrecise => args_signature_scalars(arg_count, 1, 1),
1365        Function::Floor => args_signature_scalars(arg_count, 2, 0),
1366        Function::FloorMath => args_signature_scalars(arg_count, 1, 2),
1367        Function::FloorPrecise => args_signature_scalars(arg_count, 1, 1),
1368        Function::IsoCeiling => args_signature_scalars(arg_count, 1, 1),
1369        Function::Mod => args_signature_scalars(arg_count, 2, 0),
1370        Function::Quotient => args_signature_scalars(arg_count, 2, 0),
1371        Function::Mround => args_signature_scalars(arg_count, 2, 0),
1372        Function::Trunc => args_signature_scalars(arg_count, 1, 1),
1373        Function::Gcd => vec![Signature::Vector; arg_count],
1374        Function::Lcm => vec![Signature::Vector; arg_count],
1375        Function::Base => args_signature_scalars(arg_count, 2, 1),
1376        Function::Decimal => args_signature_scalars(arg_count, 2, 0),
1377        Function::Roman => args_signature_scalars(arg_count, 1, 1),
1378        Function::Arabic => args_signature_scalars(arg_count, 1, 0),
1379        Function::Combin => args_signature_scalars(arg_count, 2, 0),
1380        Function::Combina => args_signature_scalars(arg_count, 2, 0),
1381        Function::Sumsq => vec![Signature::Vector; arg_count],
1382        Function::Mdeterm => args_signature_one_vector(arg_count),
1383        Function::Minverse => args_signature_one_vector(arg_count),
1384        Function::Munit => args_signature_scalars(arg_count, 1, 0),
1385        Function::Multinomial => vec![Signature::Vector; arg_count],
1386        Function::Seriessum => {
1387            if arg_count == 4 {
1388                vec![
1389                    Signature::Scalar,
1390                    Signature::Scalar,
1391                    Signature::Scalar,
1392                    Signature::Vector,
1393                ]
1394            } else {
1395                vec![Signature::Error; arg_count]
1396            }
1397        }
1398        Function::Sumproduct => vec![Signature::Vector; arg_count],
1399        Function::Percentof => {
1400            if arg_count == 2 {
1401                vec![Signature::Vector, Signature::Vector]
1402            } else {
1403                vec![Signature::Error; arg_count]
1404            }
1405        }
1406        Function::N => args_signature_scalars(arg_count, 1, 0),
1407        Function::Sheets => args_signature_scalars(arg_count, 0, 1),
1408        Function::Cell => args_signature_scalars(arg_count, 1, 1),
1409        Function::Info => args_signature_scalars(arg_count, 1, 1),
1410        Function::Daverage => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1411        Function::Dcount => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1412        Function::Dget => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1413        Function::Dmax => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1414        Function::Dmin => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1415        Function::Dsum => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1416        Function::Dcounta => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1417        Function::Dproduct => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1418        Function::Dstdev => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1419        Function::Dvar => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1420        Function::Dvarp => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1421        Function::Dstdevp => vec![Signature::Vector, Signature::Scalar, Signature::Vector],
1422        Function::BetaDist => args_signature_scalars(arg_count, 4, 2),
1423        Function::BetaInv => args_signature_scalars(arg_count, 3, 2),
1424        Function::BinomDist => args_signature_scalars(arg_count, 4, 0),
1425        Function::BinomDistRange => args_signature_scalars(arg_count, 3, 1),
1426        Function::BinomInv => args_signature_scalars(arg_count, 3, 0),
1427        Function::ChisqDist => args_signature_scalars(arg_count, 4, 0),
1428        Function::ChisqDistRT => args_signature_scalars(arg_count, 3, 0),
1429        Function::ChisqInv => args_signature_scalars(arg_count, 3, 0),
1430        Function::ChisqInvRT => args_signature_scalars(arg_count, 2, 0),
1431        Function::ChisqTest => {
1432            if arg_count == 2 {
1433                vec![Signature::Vector, Signature::Vector]
1434            } else {
1435                vec![Signature::Error; arg_count]
1436            }
1437        }
1438        Function::ConfidenceNorm => args_signature_scalars(arg_count, 3, 0),
1439        Function::ConfidenceT => args_signature_scalars(arg_count, 3, 0),
1440        Function::CovarianceP => {
1441            if arg_count == 2 {
1442                vec![Signature::Vector, Signature::Vector]
1443            } else {
1444                vec![Signature::Error; arg_count]
1445            }
1446        }
1447        Function::CovarianceS => {
1448            if arg_count == 2 {
1449                vec![Signature::Vector, Signature::Vector]
1450            } else {
1451                vec![Signature::Error; arg_count]
1452            }
1453        }
1454        Function::Devsq => vec![Signature::Vector; arg_count],
1455        Function::ExponDist => args_signature_scalars(arg_count, 3, 0),
1456        Function::FDist => args_signature_scalars(arg_count, 4, 0),
1457        Function::FDistRT => args_signature_scalars(arg_count, 3, 0),
1458        Function::FInv => args_signature_scalars(arg_count, 3, 0),
1459        Function::FInvRT => args_signature_scalars(arg_count, 3, 0),
1460        Function::FTest => vec![Signature::Vector; 2],
1461        Function::Fisher => args_signature_scalars(arg_count, 1, 0),
1462        Function::FisherInv => args_signature_scalars(arg_count, 1, 0),
1463        Function::Gamma => args_signature_scalars(arg_count, 1, 0),
1464        Function::GammaDist => args_signature_scalars(arg_count, 4, 0),
1465        Function::GammaInv => args_signature_scalars(arg_count, 3, 0),
1466        Function::GammaLn => args_signature_scalars(arg_count, 1, 0),
1467        Function::GammaLnPrecise => args_signature_scalars(arg_count, 1, 0),
1468        Function::HypGeomDist => args_signature_scalars(arg_count, 5, 0),
1469        Function::LogNormDist => args_signature_scalars(arg_count, 4, 0),
1470        Function::LogNormInv => args_signature_scalars(arg_count, 3, 0),
1471        Function::NegbinomDist => args_signature_scalars(arg_count, 4, 0),
1472        Function::NormDist => args_signature_scalars(arg_count, 4, 0),
1473        Function::NormInv => args_signature_scalars(arg_count, 3, 0),
1474        Function::NormSdist => args_signature_scalars(arg_count, 2, 0),
1475        Function::NormSInv => args_signature_scalars(arg_count, 1, 0),
1476        Function::Pearson => {
1477            if arg_count == 2 {
1478                vec![Signature::Vector, Signature::Vector]
1479            } else {
1480                vec![Signature::Error; arg_count]
1481            }
1482        }
1483        Function::Phi => args_signature_scalars(arg_count, 1, 0),
1484        Function::PoissonDist => args_signature_scalars(arg_count, 3, 0),
1485        Function::Standardize => args_signature_scalars(arg_count, 3, 0),
1486        Function::Stdev => vec![Signature::Vector; arg_count],
1487        Function::StDevP => vec![Signature::Vector; arg_count],
1488        Function::StDevS => vec![Signature::Vector; arg_count],
1489        Function::Stdeva => vec![Signature::Vector; arg_count],
1490        Function::Stdevpa => vec![Signature::Vector; arg_count],
1491        Function::TDist => args_signature_scalars(arg_count, 3, 0),
1492        Function::TDist2T => args_signature_scalars(arg_count, 2, 0),
1493        Function::TDistRT => args_signature_scalars(arg_count, 2, 0),
1494        Function::TInv => args_signature_scalars(arg_count, 2, 0),
1495        Function::TInv2T => args_signature_scalars(arg_count, 2, 0),
1496        Function::TTest => {
1497            if arg_count == 4 {
1498                vec![
1499                    Signature::Vector,
1500                    Signature::Vector,
1501                    Signature::Scalar,
1502                    Signature::Scalar,
1503                ]
1504            } else {
1505                vec![Signature::Error; arg_count]
1506            }
1507        }
1508        Function::VarP => vec![Signature::Vector; arg_count],
1509        Function::VarS => vec![Signature::Vector; arg_count],
1510        Function::VarpA => vec![Signature::Vector; arg_count],
1511        Function::VarA => vec![Signature::Vector; arg_count],
1512        Function::WeibullDist => args_signature_scalars(arg_count, 4, 0),
1513        Function::ZTest => {
1514            if arg_count == 2 {
1515                vec![Signature::Vector, Signature::Scalar]
1516            } else if arg_count == 3 {
1517                vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
1518            } else {
1519                vec![Signature::Error; arg_count]
1520            }
1521        }
1522        // Compatibility wrappers
1523        Function::BetaDistCompat => args_signature_scalars(arg_count, 3, 2),
1524        Function::HypGeomDistCompat => args_signature_scalars(arg_count, 4, 0),
1525        Function::LogNormDistCompat => args_signature_scalars(arg_count, 3, 0),
1526        Function::NegbinomDistCompat => args_signature_scalars(arg_count, 3, 0),
1527        Function::NormSDistCompat => args_signature_scalars(arg_count, 1, 0),
1528        Function::TDistCompat => args_signature_scalars(arg_count, 3, 0),
1529        // Compatibility aliases
1530        Function::BetaInvCompat => args_signature_scalars(arg_count, 3, 2),
1531        Function::BinomDistCompat => args_signature_scalars(arg_count, 4, 0),
1532        Function::ChiDistCompat => args_signature_scalars(arg_count, 2, 0),
1533        Function::ChiInvCompat => args_signature_scalars(arg_count, 2, 0),
1534        Function::ChiTestCompat => {
1535            if arg_count == 2 {
1536                vec![Signature::Vector, Signature::Vector]
1537            } else {
1538                vec![Signature::Error; arg_count]
1539            }
1540        }
1541        Function::ConfidenceCompat => args_signature_scalars(arg_count, 3, 0),
1542        Function::CovarCompat => {
1543            if arg_count == 2 {
1544                vec![Signature::Vector, Signature::Vector]
1545            } else {
1546                vec![Signature::Error; arg_count]
1547            }
1548        }
1549        Function::CritbinomCompat => args_signature_scalars(arg_count, 3, 0),
1550        Function::ExponDistCompat => args_signature_scalars(arg_count, 3, 0),
1551        Function::FDistCompat => args_signature_scalars(arg_count, 3, 0),
1552        Function::FInvCompat => args_signature_scalars(arg_count, 3, 0),
1553        Function::FTestCompat => vec![Signature::Vector; 2],
1554        Function::GammaDistCompat => args_signature_scalars(arg_count, 4, 0),
1555        Function::GammaInvCompat => args_signature_scalars(arg_count, 3, 0),
1556        Function::LoginvCompat => args_signature_scalars(arg_count, 3, 0),
1557        Function::ModeCompat => vec![Signature::Vector; arg_count],
1558        Function::NormDistCompat => args_signature_scalars(arg_count, 4, 0),
1559        Function::NormInvCompat => args_signature_scalars(arg_count, 3, 0),
1560        Function::NormSInvCompat => args_signature_scalars(arg_count, 1, 0),
1561        Function::PercentileCompat => {
1562            if arg_count == 2 {
1563                vec![Signature::Vector, Signature::Scalar]
1564            } else {
1565                vec![Signature::Error; arg_count]
1566            }
1567        }
1568        Function::PercentrankCompat => {
1569            if arg_count == 2 {
1570                vec![Signature::Vector, Signature::Scalar]
1571            } else if arg_count == 3 {
1572                vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
1573            } else {
1574                vec![Signature::Error; arg_count]
1575            }
1576        }
1577        Function::PoissonCompat => args_signature_scalars(arg_count, 3, 0),
1578        Function::QuartileCompat => {
1579            if arg_count == 2 {
1580                vec![Signature::Vector, Signature::Scalar]
1581            } else {
1582                vec![Signature::Error; arg_count]
1583            }
1584        }
1585        Function::RankCompat => vec![Signature::Scalar, Signature::Vector, Signature::Scalar],
1586        Function::StDevPCompat => vec![Signature::Vector; arg_count],
1587        Function::TInvCompat => args_signature_scalars(arg_count, 2, 0),
1588        Function::TTestCompat => {
1589            if arg_count == 4 {
1590                vec![
1591                    Signature::Vector,
1592                    Signature::Vector,
1593                    Signature::Scalar,
1594                    Signature::Scalar,
1595                ]
1596            } else {
1597                vec![Signature::Error; arg_count]
1598            }
1599        }
1600        Function::VarCompat => vec![Signature::Vector; arg_count],
1601        Function::VarPCompat => vec![Signature::Vector; arg_count],
1602        Function::WeibullCompat => args_signature_scalars(arg_count, 4, 0),
1603        Function::ZTestCompat => {
1604            if arg_count == 2 {
1605                vec![Signature::Vector, Signature::Scalar]
1606            } else if arg_count == 3 {
1607                vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
1608            } else {
1609                vec![Signature::Error; arg_count]
1610            }
1611        }
1612        Function::Sumx2my2 => vec![Signature::Vector; 2],
1613        Function::Sumx2py2 => vec![Signature::Vector; 2],
1614        Function::Sumxmy2 => vec![Signature::Vector; 2],
1615        Function::Correl => vec![Signature::Vector; 2],
1616        Function::Rsq => vec![Signature::Vector; 2],
1617        Function::Intercept => vec![Signature::Vector; 2],
1618        Function::Slope => vec![Signature::Vector; 2],
1619        Function::Steyx => vec![Signature::Vector; 2],
1620        Function::Forecast | Function::ForecastLinear => {
1621            vec![Signature::Scalar, Signature::Vector, Signature::Vector]
1622        }
1623        Function::ForecastEts
1624        | Function::ForecastEtsConfint
1625        | Function::ForecastEtsSeasonality
1626        | Function::ForecastEtsStat => vec![Signature::Vector; arg_count],
1627        Function::Frequency => vec![Signature::Vector, Signature::Vector],
1628        Function::Growth | Function::Trend => match arg_count {
1629            1 => vec![Signature::Vector],
1630            2 => vec![Signature::Vector, Signature::Vector],
1631            3 => vec![Signature::Vector, Signature::Vector, Signature::Vector],
1632            4 => vec![
1633                Signature::Vector,
1634                Signature::Vector,
1635                Signature::Vector,
1636                Signature::Scalar,
1637            ],
1638            _ => vec![Signature::Error; arg_count],
1639        },
1640        Function::Linest | Function::Logest => match arg_count {
1641            1 => vec![Signature::Vector],
1642            2 => vec![Signature::Vector, Signature::Vector],
1643            3 => vec![Signature::Vector, Signature::Vector, Signature::Scalar],
1644            4 => vec![
1645                Signature::Vector,
1646                Signature::Vector,
1647                Signature::Scalar,
1648                Signature::Scalar,
1649            ],
1650            _ => vec![Signature::Error; arg_count],
1651        },
1652        Function::ModeMult | Function::ModeSingl => vec![Signature::Vector; arg_count],
1653        Function::PercentileExc | Function::PercentileInc => {
1654            vec![Signature::Vector, Signature::Scalar]
1655        }
1656        Function::PercentrankExc | Function::PercentrankInc => {
1657            vec![Signature::Vector, Signature::Scalar, Signature::Scalar]
1658        }
1659        Function::Permut | Function::Permutationa => vec![Signature::Scalar; 2],
1660        Function::Prob => match arg_count {
1661            3 => vec![Signature::Vector, Signature::Vector, Signature::Scalar],
1662            4 => vec![
1663                Signature::Vector,
1664                Signature::Vector,
1665                Signature::Scalar,
1666                Signature::Scalar,
1667            ],
1668            _ => vec![Signature::Error; arg_count],
1669        },
1670        Function::QuartileExc | Function::QuartileInc => {
1671            vec![Signature::Vector, Signature::Scalar]
1672        }
1673        Function::Trimmean => vec![Signature::Vector, Signature::Scalar],
1674        Function::Gauss => args_signature_scalars(arg_count, 1, 0),
1675        Function::Harmean => vec![Signature::Vector; arg_count],
1676        Function::Kurt => vec![Signature::Vector; arg_count],
1677        Function::Large => vec![Signature::Vector, Signature::Scalar],
1678        Function::MaxA => vec![Signature::Vector; arg_count],
1679        Function::Median => vec![Signature::Vector; arg_count],
1680        Function::MinA => vec![Signature::Vector; arg_count],
1681        Function::RankAvg => vec![Signature::Scalar, Signature::Vector, Signature::Scalar],
1682        Function::RankEq => vec![Signature::Scalar, Signature::Vector, Signature::Scalar],
1683        Function::Skew => vec![Signature::Vector; arg_count],
1684        Function::SkewP => vec![Signature::Vector; arg_count],
1685        Function::Small => vec![Signature::Vector, Signature::Scalar],
1686    }
1687}
1688
1689// Returns the type of the result (Scalar, Array or Range) depending on the arguments
1690fn static_analysis_on_function(kind: &Function, args: &[Node]) -> StaticResult {
1691    match kind {
1692        Function::And => StaticResult::Scalar,
1693        Function::False => StaticResult::Scalar,
1694        Function::If => scalar_arguments(args),
1695        Function::Iferror => scalar_arguments(args),
1696        Function::Ifna => scalar_arguments(args),
1697        Function::Ifs => not_implemented(args),
1698        Function::Lambda => StaticResult::Unknown,
1699        Function::Let => StaticResult::Unknown,
1700        Function::Not => StaticResult::Scalar,
1701        Function::Or => StaticResult::Scalar,
1702        Function::Switch => not_implemented(args),
1703        Function::True => StaticResult::Scalar,
1704        Function::Xor => StaticResult::Scalar,
1705        Function::Abs => scalar_arguments(args),
1706        Function::Acos => scalar_arguments(args),
1707        Function::Acosh => scalar_arguments(args),
1708        Function::Asin => scalar_arguments(args),
1709        Function::Asinh => scalar_arguments(args),
1710        Function::Atan => scalar_arguments(args),
1711        Function::Atan2 => scalar_arguments(args),
1712        Function::Atanh => scalar_arguments(args),
1713        // CHOOSE is a reference function: with a range arm the call itself is
1714        // reference-shaped, so legacy import wraps the whole CALL in `@`
1715        // (Excel upgrades `=CHOOSE(2,A1:A10,B1:B10)` to `=@CHOOSE(...)`).
1716        Function::Choose => match scalar_arguments(args) {
1717            StaticResult::Array(n, m) => StaticResult::Range(n, m),
1718            other => other,
1719        },
1720        Function::Column => static_analysis_row_column(args, false),
1721        Function::Columns => not_implemented(args),
1722        Function::Cos => scalar_arguments(args),
1723        Function::Cosh => scalar_arguments(args),
1724        Function::Max => StaticResult::Scalar,
1725        Function::Min => StaticResult::Scalar,
1726        Function::Pi => StaticResult::Scalar,
1727        Function::Power => scalar_arguments(args),
1728        Function::Product => not_implemented(args),
1729        Function::Round => scalar_arguments(args),
1730        Function::Rounddown => scalar_arguments(args),
1731        Function::Roundup => scalar_arguments(args),
1732        Function::Ln => scalar_arguments(args),
1733        Function::Log => scalar_arguments(args),
1734        Function::Log10 => scalar_arguments(args),
1735        Function::Sin => scalar_arguments(args),
1736        Function::Sinh => scalar_arguments(args),
1737        Function::Sqrt => scalar_arguments(args),
1738        Function::Sqrtpi => StaticResult::Scalar,
1739        Function::Sum => StaticResult::Scalar,
1740        Function::Sumif => sumif_static_result(args),
1741        Function::Sumifs => not_implemented(args),
1742        Function::Tan => scalar_arguments(args),
1743        Function::Tanh => scalar_arguments(args),
1744        Function::ErrorType => not_implemented(args),
1745        Function::Isblank => not_implemented(args),
1746        Function::Iserr => not_implemented(args),
1747        Function::Iserror => not_implemented(args),
1748        Function::Iseven => not_implemented(args),
1749        Function::Isformula => not_implemented(args),
1750        Function::Islogical => not_implemented(args),
1751        Function::Isna => not_implemented(args),
1752        Function::Isnontext => not_implemented(args),
1753        Function::Isnumber => not_implemented(args),
1754        Function::Isodd => not_implemented(args),
1755        Function::Isomitted => not_implemented(args),
1756        Function::Isref => not_implemented(args),
1757        Function::Istext => not_implemented(args),
1758        Function::Na => StaticResult::Scalar,
1759        Function::Sheet => StaticResult::Scalar,
1760        Function::Type => not_implemented(args),
1761        Function::Address => not_implemented(args),
1762        Function::Areas => StaticResult::Scalar,
1763        Function::Choosecols => StaticResult::Unknown,
1764        Function::Chooserows => StaticResult::Unknown,
1765        Function::Expand => StaticResult::Unknown,
1766        Function::Hlookup => not_implemented(args),
1767        Function::Hstack => StaticResult::Unknown,
1768        Function::Hyperlink => StaticResult::Scalar,
1769        Function::Index => static_analysis_index(args),
1770        Function::Indirect => static_analysis_indirect(args),
1771        Function::Lookup => not_implemented(args),
1772        Function::Match => not_implemented(args),
1773        Function::Offset => static_analysis_offset(args),
1774        Function::Row => static_analysis_row_column(args, true),
1775        Function::Rows => not_implemented(args),
1776        Function::Vlookup => not_implemented(args),
1777        Function::Vstack => StaticResult::Unknown,
1778        Function::Wrapcols => StaticResult::Unknown,
1779        Function::Wraprows => StaticResult::Unknown,
1780        Function::Xlookup => not_implemented(args),
1781        Function::Xmatch => not_implemented(args),
1782        Function::Trimrange => StaticResult::Unknown,
1783        Function::Sort => StaticResult::Unknown,
1784        Function::Sortby => StaticResult::Unknown,
1785        Function::Unique => StaticResult::Unknown,
1786        Function::Filter => StaticResult::Unknown,
1787        Function::Take => StaticResult::Unknown,
1788        Function::Drop => StaticResult::Unknown,
1789        Function::Tocol => StaticResult::Unknown,
1790        Function::Torow => StaticResult::Unknown,
1791        Function::Transpose => StaticResult::Unknown,
1792        Function::Mmult => StaticResult::Unknown,
1793        Function::Bycol => StaticResult::Unknown,
1794        Function::Byrow => StaticResult::Unknown,
1795        Function::Map => StaticResult::Unknown,
1796        Function::Reduce => StaticResult::Unknown,
1797        Function::Scan => StaticResult::Unknown,
1798        Function::Makearray => StaticResult::Unknown,
1799        Function::Sequence => StaticResult::Unknown,
1800        Function::Randarray => StaticResult::Unknown,
1801        Function::Textsplit => StaticResult::Unknown,
1802        Function::Concat => not_implemented(args),
1803        Function::Concatenate => not_implemented(args),
1804        Function::Exact => scalar_arguments(args),
1805        Function::Find => scalar_arguments(args),
1806        // LEFT/MID/RIGHT broadcast element-wise: an array/range argument yields an array.
1807        Function::Left => scalar_arguments(args),
1808        Function::Len => scalar_arguments(args),
1809        // UPPER/LOWER broadcast element-wise: an array/range argument yields an array.
1810        Function::Lower => scalar_arguments(args),
1811        Function::Mid => scalar_arguments(args),
1812        Function::Rept => scalar_arguments(args),
1813        Function::Right => scalar_arguments(args),
1814        Function::Search => scalar_arguments(args),
1815        Function::Substitute => scalar_arguments(args),
1816        Function::Regexextract => {
1817            if args.len() == 3 {
1818                StaticResult::Unknown
1819            } else {
1820                not_implemented(args)
1821            }
1822        }
1823        Function::Regexreplace => not_implemented(args),
1824        Function::Regextest => not_implemented(args),
1825        Function::T => not_implemented(args),
1826        Function::Text => scalar_arguments(args),
1827        Function::Textafter => not_implemented(args),
1828        Function::Textbefore => not_implemented(args),
1829        Function::Textjoin => not_implemented(args),
1830        Function::Trim => scalar_arguments(args),
1831        Function::Unicode => not_implemented(args),
1832        Function::Unichar => not_implemented(args),
1833        Function::Char => not_implemented(args),
1834        Function::Clean => scalar_arguments(args),
1835        Function::Code => not_implemented(args),
1836        Function::Asc => not_implemented(args),
1837        Function::Arraytotext => not_implemented(args),
1838        Function::Dollar => not_implemented(args),
1839        Function::Encodeurl => not_implemented(args),
1840        Function::EcmaCeiling => scalar_arguments(args),
1841        Function::Findb => not_implemented(args),
1842        Function::Fixed => not_implemented(args),
1843        Function::Leftb => not_implemented(args),
1844        Function::Lenb => not_implemented(args),
1845        Function::Midb => not_implemented(args),
1846        Function::Numbervalue => not_implemented(args),
1847        Function::Proper => scalar_arguments(args),
1848        Function::Replace => scalar_arguments(args),
1849        Function::Replaceb => not_implemented(args),
1850        Function::Rightb => not_implemented(args),
1851        Function::Searchb => not_implemented(args),
1852        Function::Upper => scalar_arguments(args),
1853        Function::Value => not_implemented(args),
1854        Function::Valuetotext => not_implemented(args),
1855        Function::Average => not_implemented(args),
1856        Function::Averagea => not_implemented(args),
1857        Function::Avedev => not_implemented(args),
1858        Function::Averageif => not_implemented(args),
1859        Function::Averageifs => not_implemented(args),
1860        Function::Count => not_implemented(args),
1861        Function::Counta => not_implemented(args),
1862        Function::Countblank => not_implemented(args),
1863        Function::Countif => not_implemented(args),
1864        Function::Countifs => not_implemented(args),
1865        Function::Maxifs => not_implemented(args),
1866        Function::Minifs => not_implemented(args),
1867        // DATE broadcasts element-wise: an array/range argument yields an array.
1868        Function::Date => scalar_arguments(args),
1869        Function::Datedif => not_implemented(args),
1870        Function::Datevalue => not_implemented(args),
1871        Function::Day => scalar_arguments(args),
1872        Function::Edate => not_implemented(args),
1873        Function::Month => scalar_arguments(args),
1874        Function::Time => not_implemented(args),
1875        Function::Timevalue => not_implemented(args),
1876        Function::Hour => not_implemented(args),
1877        Function::Minute => not_implemented(args),
1878        Function::Second => not_implemented(args),
1879        Function::Now => not_implemented(args),
1880        Function::Today => not_implemented(args),
1881        Function::Year => scalar_arguments(args),
1882        Function::Days => not_implemented(args),
1883        Function::Days360 => not_implemented(args),
1884        Function::Weekday => scalar_arguments(args),
1885        Function::Weeknum => not_implemented(args),
1886        Function::Workday => not_implemented(args),
1887        Function::WorkdayIntl => not_implemented(args),
1888        Function::Yearfrac => not_implemented(args),
1889        Function::Isoweeknum => scalar_arguments(args),
1890        Function::Accrint => scalar_arguments(args),
1891        Function::Accrintm => scalar_arguments(args),
1892        Function::Disc => StaticResult::Scalar,
1893        Function::Fvschedule => StaticResult::Scalar,
1894        Function::Intrate => StaticResult::Scalar,
1895        Function::Pricedisc => StaticResult::Scalar,
1896        Function::Pricemat => StaticResult::Scalar,
1897        Function::Received => StaticResult::Scalar,
1898        Function::Yielddisc => StaticResult::Scalar,
1899        Function::Yieldmat => StaticResult::Scalar,
1900        Function::Cumipmt => not_implemented(args),
1901        Function::Cumprinc => not_implemented(args),
1902        Function::Db => not_implemented(args),
1903        Function::Ddb => not_implemented(args),
1904        Function::Dollarde => not_implemented(args),
1905        Function::Dollarfr => not_implemented(args),
1906        Function::Effect => not_implemented(args),
1907        Function::Fv => not_implemented(args),
1908        Function::Ipmt => not_implemented(args),
1909        Function::Irr => not_implemented(args),
1910        Function::Ispmt => not_implemented(args),
1911        Function::Mirr => not_implemented(args),
1912        Function::Nominal => not_implemented(args),
1913        Function::Nper => not_implemented(args),
1914        Function::Npv => not_implemented(args),
1915        Function::Pduration => not_implemented(args),
1916        Function::Pmt => not_implemented(args),
1917        Function::Ppmt => not_implemented(args),
1918        Function::Pv => not_implemented(args),
1919        Function::Rate => not_implemented(args),
1920        Function::Rri => not_implemented(args),
1921        Function::Sln => not_implemented(args),
1922        Function::Syd => not_implemented(args),
1923        Function::Tbilleq => not_implemented(args),
1924        Function::Tbillprice => not_implemented(args),
1925        Function::Tbillyield => not_implemented(args),
1926        Function::Xirr => not_implemented(args),
1927        Function::Xnpv => not_implemented(args),
1928        Function::Duration => StaticResult::Scalar,
1929        Function::Mduration => StaticResult::Scalar,
1930        Function::Price => StaticResult::Scalar,
1931        Function::Yield => StaticResult::Scalar,
1932        Function::Oddfprice => StaticResult::Scalar,
1933        Function::Oddfyield => StaticResult::Scalar,
1934        Function::Oddlprice => StaticResult::Scalar,
1935        Function::Oddlyield => StaticResult::Scalar,
1936        Function::Coupdaybs => StaticResult::Scalar,
1937        Function::Coupdays => StaticResult::Scalar,
1938        Function::Coupdaysnc => StaticResult::Scalar,
1939        Function::Coupncd => StaticResult::Scalar,
1940        Function::Coupnum => StaticResult::Scalar,
1941        Function::Couppcd => StaticResult::Scalar,
1942        Function::Amordegrc => StaticResult::Scalar,
1943        Function::Amorlinc => StaticResult::Scalar,
1944        Function::Vdb => StaticResult::Scalar,
1945        Function::Besseli => scalar_arguments(args),
1946        Function::Besselj => scalar_arguments(args),
1947        Function::Besselk => scalar_arguments(args),
1948        Function::Bessely => scalar_arguments(args),
1949        Function::Erf => scalar_arguments(args),
1950        Function::Erfc => scalar_arguments(args),
1951        Function::ErfcPrecise => scalar_arguments(args),
1952        Function::ErfPrecise => scalar_arguments(args),
1953        Function::Bin2dec => scalar_arguments(args),
1954        Function::Bin2hex => scalar_arguments(args),
1955        Function::Bin2oct => scalar_arguments(args),
1956        Function::Dec2Bin => scalar_arguments(args),
1957        Function::Dec2hex => scalar_arguments(args),
1958        Function::Dec2oct => scalar_arguments(args),
1959        Function::Hex2bin => scalar_arguments(args),
1960        Function::Hex2dec => scalar_arguments(args),
1961        Function::Hex2oct => scalar_arguments(args),
1962        Function::Oct2bin => scalar_arguments(args),
1963        Function::Oct2dec => scalar_arguments(args),
1964        Function::Oct2hex => scalar_arguments(args),
1965        Function::Bitand => scalar_arguments(args),
1966        Function::Bitlshift => scalar_arguments(args),
1967        Function::Bitor => scalar_arguments(args),
1968        Function::Bitrshift => scalar_arguments(args),
1969        Function::Bitxor => scalar_arguments(args),
1970        Function::Complex => scalar_arguments(args),
1971        Function::Imabs => scalar_arguments(args),
1972        Function::Imaginary => scalar_arguments(args),
1973        Function::Imargument => scalar_arguments(args),
1974        Function::Imconjugate => scalar_arguments(args),
1975        Function::Imcos => scalar_arguments(args),
1976        Function::Imcosh => scalar_arguments(args),
1977        Function::Imcot => scalar_arguments(args),
1978        Function::Imcsc => scalar_arguments(args),
1979        Function::Imcsch => scalar_arguments(args),
1980        Function::Imdiv => scalar_arguments(args),
1981        Function::Imexp => scalar_arguments(args),
1982        Function::Imln => scalar_arguments(args),
1983        Function::Imlog10 => scalar_arguments(args),
1984        Function::Imlog2 => scalar_arguments(args),
1985        Function::Impower => scalar_arguments(args),
1986        Function::Improduct => scalar_arguments(args),
1987        Function::Imreal => scalar_arguments(args),
1988        Function::Imsec => scalar_arguments(args),
1989        Function::Imsech => scalar_arguments(args),
1990        Function::Imsin => scalar_arguments(args),
1991        Function::Imsinh => scalar_arguments(args),
1992        Function::Imsqrt => scalar_arguments(args),
1993        Function::Imsub => scalar_arguments(args),
1994        Function::Imsum => scalar_arguments(args),
1995        Function::Imtan => scalar_arguments(args),
1996        Function::Convert => not_implemented(args),
1997        Function::Delta => not_implemented(args),
1998        Function::Gestep => not_implemented(args),
1999        Function::Subtotal => not_implemented(args),
2000        Function::Rand => not_implemented(args),
2001        Function::Randbetween => scalar_arguments(args),
2002        Function::Eomonth => scalar_arguments(args),
2003        Function::Formulatext => not_implemented(args),
2004        Function::Geomean => not_implemented(args),
2005        Function::Networkdays => not_implemented(args),
2006        Function::NetworkdaysIntl => not_implemented(args),
2007        Function::Acot => scalar_arguments(args),
2008        Function::Acoth => scalar_arguments(args),
2009        Function::Cot => scalar_arguments(args),
2010        Function::Coth => scalar_arguments(args),
2011        Function::Csc => scalar_arguments(args),
2012        Function::Csch => scalar_arguments(args),
2013        Function::Sec => scalar_arguments(args),
2014        Function::Sech => scalar_arguments(args),
2015        Function::Exp => scalar_arguments(args),
2016        Function::Fact => scalar_arguments(args),
2017        Function::Factdouble => scalar_arguments(args),
2018        Function::Sign => scalar_arguments(args),
2019        Function::Radians => scalar_arguments(args),
2020        Function::Degrees => scalar_arguments(args),
2021        Function::Int => scalar_arguments(args),
2022        Function::Even => scalar_arguments(args),
2023        Function::Odd => scalar_arguments(args),
2024        Function::Ceiling => scalar_arguments(args),
2025        Function::CeilingMath => scalar_arguments(args),
2026        Function::CeilingPrecise => scalar_arguments(args),
2027        Function::Floor => scalar_arguments(args),
2028        Function::FloorMath => scalar_arguments(args),
2029        Function::FloorPrecise => scalar_arguments(args),
2030        Function::IsoCeiling => scalar_arguments(args),
2031        Function::Mod => scalar_arguments(args),
2032        Function::Quotient => scalar_arguments(args),
2033        Function::Mround => scalar_arguments(args),
2034        Function::Trunc => scalar_arguments(args),
2035        Function::Gcd => StaticResult::Scalar,
2036        Function::Lcm => StaticResult::Scalar,
2037        Function::Base => scalar_arguments(args),
2038        Function::Decimal => scalar_arguments(args),
2039        Function::Roman => scalar_arguments(args),
2040        Function::Arabic => scalar_arguments(args),
2041        Function::Combin => scalar_arguments(args),
2042        Function::Combina => scalar_arguments(args),
2043        Function::Sumsq => StaticResult::Scalar,
2044        Function::Mdeterm => StaticResult::Scalar,
2045        Function::Minverse => StaticResult::Unknown,
2046        Function::Munit => StaticResult::Unknown,
2047        Function::Multinomial => StaticResult::Scalar,
2048        Function::Seriessum => StaticResult::Scalar,
2049        Function::Sumproduct => StaticResult::Scalar,
2050        Function::Percentof => StaticResult::Scalar,
2051        Function::N => scalar_arguments(args),
2052        Function::Sheets => scalar_arguments(args),
2053        Function::Cell => StaticResult::Unknown,
2054        Function::Info => StaticResult::Unknown,
2055        Function::Dget => not_implemented(args),
2056        Function::Dmax => not_implemented(args),
2057        Function::Dmin => not_implemented(args),
2058        Function::Dcount => not_implemented(args),
2059        Function::Daverage => not_implemented(args),
2060        Function::Dsum => not_implemented(args),
2061        Function::Dcounta => not_implemented(args),
2062        Function::Dproduct => not_implemented(args),
2063        Function::Dstdev => not_implemented(args),
2064        Function::Dvar => not_implemented(args),
2065        Function::Dvarp => not_implemented(args),
2066        Function::Dstdevp => not_implemented(args),
2067        Function::BetaDist => StaticResult::Scalar,
2068        Function::BetaInv => StaticResult::Scalar,
2069        Function::BinomDist => StaticResult::Scalar,
2070        Function::BinomDistRange => StaticResult::Scalar,
2071        Function::BinomInv => StaticResult::Scalar,
2072        Function::ChisqDist => StaticResult::Scalar,
2073        Function::ChisqDistRT => StaticResult::Scalar,
2074        Function::ChisqInv => StaticResult::Scalar,
2075        Function::ChisqInvRT => StaticResult::Scalar,
2076        Function::ChisqTest => StaticResult::Scalar,
2077        Function::ConfidenceNorm => StaticResult::Scalar,
2078        Function::ConfidenceT => StaticResult::Scalar,
2079        Function::CovarianceP => StaticResult::Scalar,
2080        Function::CovarianceS => StaticResult::Scalar,
2081        Function::Devsq => StaticResult::Scalar,
2082        Function::ExponDist => StaticResult::Scalar,
2083        Function::FDist => StaticResult::Scalar,
2084        Function::FDistRT => StaticResult::Scalar,
2085        Function::FInv => StaticResult::Scalar,
2086        Function::FInvRT => StaticResult::Scalar,
2087        Function::FTest => StaticResult::Scalar,
2088        Function::Fisher => StaticResult::Scalar,
2089        Function::FisherInv => StaticResult::Scalar,
2090        Function::Gamma => StaticResult::Scalar,
2091        Function::GammaDist => StaticResult::Scalar,
2092        Function::GammaInv => StaticResult::Scalar,
2093        Function::GammaLn => StaticResult::Scalar,
2094        Function::GammaLnPrecise => StaticResult::Scalar,
2095        Function::HypGeomDist => StaticResult::Scalar,
2096        Function::LogNormDist => StaticResult::Scalar,
2097        Function::LogNormInv => StaticResult::Scalar,
2098        Function::NegbinomDist => StaticResult::Scalar,
2099        Function::NormDist => StaticResult::Scalar,
2100        Function::NormInv => StaticResult::Scalar,
2101        Function::NormSdist => StaticResult::Scalar,
2102        Function::NormSInv => StaticResult::Scalar,
2103        Function::Pearson => StaticResult::Scalar,
2104        Function::Phi => StaticResult::Scalar,
2105        Function::PoissonDist => StaticResult::Scalar,
2106        Function::Standardize => StaticResult::Scalar,
2107        Function::Stdev => StaticResult::Scalar,
2108        Function::StDevP => StaticResult::Scalar,
2109        Function::StDevS => StaticResult::Scalar,
2110        Function::Stdeva => StaticResult::Scalar,
2111        Function::Stdevpa => StaticResult::Scalar,
2112        Function::TDist => StaticResult::Scalar,
2113        Function::TDist2T => StaticResult::Scalar,
2114        Function::TDistRT => StaticResult::Scalar,
2115        Function::TInv => StaticResult::Scalar,
2116        Function::TInv2T => StaticResult::Scalar,
2117        Function::TTest => StaticResult::Scalar,
2118        Function::VarP => StaticResult::Scalar,
2119        Function::VarS => StaticResult::Scalar,
2120        Function::VarpA => StaticResult::Scalar,
2121        Function::VarA => StaticResult::Scalar,
2122        Function::WeibullDist => StaticResult::Scalar,
2123        Function::ZTest => StaticResult::Scalar,
2124        Function::BetaDistCompat => StaticResult::Scalar,
2125        Function::HypGeomDistCompat => StaticResult::Scalar,
2126        Function::LogNormDistCompat => StaticResult::Scalar,
2127        Function::NegbinomDistCompat => StaticResult::Scalar,
2128        Function::NormSDistCompat => StaticResult::Scalar,
2129        Function::TDistCompat => StaticResult::Scalar,
2130        Function::BetaInvCompat => StaticResult::Scalar,
2131        Function::BinomDistCompat => StaticResult::Scalar,
2132        Function::ChiDistCompat => StaticResult::Scalar,
2133        Function::ChiInvCompat => StaticResult::Scalar,
2134        Function::ChiTestCompat => StaticResult::Scalar,
2135        Function::ConfidenceCompat => StaticResult::Scalar,
2136        Function::CovarCompat => StaticResult::Scalar,
2137        Function::CritbinomCompat => StaticResult::Scalar,
2138        Function::ExponDistCompat => StaticResult::Scalar,
2139        Function::FDistCompat => StaticResult::Scalar,
2140        Function::FInvCompat => StaticResult::Scalar,
2141        Function::FTestCompat => StaticResult::Scalar,
2142        Function::GammaDistCompat => StaticResult::Scalar,
2143        Function::GammaInvCompat => StaticResult::Scalar,
2144        Function::LoginvCompat => StaticResult::Scalar,
2145        Function::ModeCompat => StaticResult::Scalar,
2146        Function::NormDistCompat => StaticResult::Scalar,
2147        Function::NormInvCompat => StaticResult::Scalar,
2148        Function::NormSInvCompat => StaticResult::Scalar,
2149        Function::PercentileCompat => StaticResult::Scalar,
2150        Function::PercentrankCompat => StaticResult::Scalar,
2151        Function::PoissonCompat => StaticResult::Scalar,
2152        Function::QuartileCompat => StaticResult::Scalar,
2153        Function::RankCompat => StaticResult::Scalar,
2154        Function::StDevPCompat => StaticResult::Scalar,
2155        Function::TInvCompat => StaticResult::Scalar,
2156        Function::TTestCompat => StaticResult::Scalar,
2157        Function::VarCompat => StaticResult::Scalar,
2158        Function::VarPCompat => StaticResult::Scalar,
2159        Function::WeibullCompat => StaticResult::Scalar,
2160        Function::ZTestCompat => StaticResult::Scalar,
2161        Function::Sumx2my2 => StaticResult::Scalar,
2162        Function::Sumx2py2 => StaticResult::Scalar,
2163        Function::Sumxmy2 => StaticResult::Scalar,
2164        Function::Correl => StaticResult::Scalar,
2165        Function::Rsq => StaticResult::Scalar,
2166        Function::Intercept => StaticResult::Scalar,
2167        Function::Slope => StaticResult::Scalar,
2168        Function::Steyx => StaticResult::Scalar,
2169        Function::Forecast => StaticResult::Scalar,
2170        Function::ForecastLinear => StaticResult::Scalar,
2171        Function::ForecastEts => StaticResult::Scalar,
2172        Function::ForecastEtsConfint => StaticResult::Scalar,
2173        Function::ForecastEtsSeasonality => StaticResult::Scalar,
2174        Function::ForecastEtsStat => StaticResult::Scalar,
2175        // Spill-returning functions
2176        Function::Frequency => StaticResult::Unknown,
2177        Function::Growth => StaticResult::Unknown,
2178        Function::Linest => StaticResult::Unknown,
2179        Function::Logest => StaticResult::Unknown,
2180        Function::ModeMult => StaticResult::Unknown,
2181        Function::Trend => StaticResult::Unknown,
2182        // Scalar-returning functions
2183        Function::ModeSingl => StaticResult::Scalar,
2184        Function::PercentileExc => StaticResult::Scalar,
2185        Function::PercentileInc => StaticResult::Scalar,
2186        Function::PercentrankExc => StaticResult::Scalar,
2187        Function::PercentrankInc => StaticResult::Scalar,
2188        Function::Permut => StaticResult::Scalar,
2189        Function::Permutationa => StaticResult::Scalar,
2190        Function::Prob => StaticResult::Scalar,
2191        Function::QuartileExc => StaticResult::Scalar,
2192        Function::QuartileInc => StaticResult::Scalar,
2193        Function::Trimmean => StaticResult::Scalar,
2194        Function::Gauss => StaticResult::Scalar,
2195        Function::Harmean => StaticResult::Scalar,
2196        Function::Kurt => StaticResult::Scalar,
2197        Function::Large => StaticResult::Scalar,
2198        Function::MaxA => StaticResult::Scalar,
2199        Function::Median => StaticResult::Scalar,
2200        Function::MinA => StaticResult::Scalar,
2201        Function::RankAvg => StaticResult::Scalar,
2202        Function::RankEq => StaticResult::Scalar,
2203        Function::Skew => StaticResult::Scalar,
2204        Function::SkewP => StaticResult::Scalar,
2205        Function::Small => StaticResult::Scalar,
2206    }
2207}