* Match a list of patterns against operands of expression, appending wildcards (named) to * *substitution* (along the way). If a successful match, returns the new substitution (or the same * if no named wildcard), or *null* for no match. * * @param expr * @param patterns * @param substitution
( expr: Expression, patterns: ReadonlyArray<Expression>, substitution: BoxedSubstitution, options: PatternMatchOptions )
| 956 | if (n > 20 && k > 2 && k < n - 2) { |
| 957 | // For large n and moderate k, combinations grow fast |
| 958 | // Approximate: if n > 15 and k > 3, check more carefully |
| 959 | let approxCount = 1; |
| 960 | for (let i = 0; i < Math.min(k, n - k); i++) { |
| 961 | approxCount = (approxCount * (n - i)) / (i + 1); |
| 962 | if (approxCount > MAX_COMBINATIONS) return []; |
| 963 | } |
| 964 | } |
| 965 | |
| 966 | // Generate all combinations of k indices from 0..n-1 |
| 967 | const result: number[][] = []; |
| 968 | const combo: number[] = []; |
| 969 | |
| 970 | function backtrack(start: number) { |
| 971 | if (result.length >= MAX_COMBINATIONS) return; // Stop if limit reached |
| 972 | if (combo.length === k) { |
| 973 | result.push([...combo]); |
| 974 | return; |
| 975 | } |
| 976 | for (let i = start; i < n; i++) { |
| 977 | combo.push(i); |
| 978 | backtrack(i + 1); |
| 979 | combo.pop(); |
| 980 | } |
| 981 | } |
| 982 | |
| 983 | backtrack(0); |
| 984 | return result; |
| 985 | } |
| 986 | } |
| 987 | |
| 988 | /** |
| 989 | * Match a list of patterns against operands of expression, appending wildcards (named) to |
| 990 | * *substitution* (along the way). If a successful match, returns the new substitution (or the same |
| 991 | * if no named wildcard), or *null* for no match. |
| 992 | * |
| 993 | * @param expr |
| 994 | * @param patterns |
| 995 | * @param substitution |
| 996 | * @param options |
| 997 | * @returns |
| 998 | */ |
| 999 | function matchArguments( |
| 1000 | expr: Expression, |
| 1001 | patterns: ReadonlyArray<Expression>, |
| 1002 | substitution: BoxedSubstitution, |
| 1003 | options: PatternMatchOptions |
| 1004 | ): BoxedSubstitution | null { |
| 1005 | if (patterns.length === 0) { |
| 1006 | if (isFunction(expr) && expr.ops.length === 0) return substitution; |
| 1007 | return null; |
| 1008 | } |
| 1009 | |
| 1010 | const ce = patterns[0].engine; |
| 1011 | |
| 1012 | // We're going to consume the ops array, so make a copy |
| 1013 | if (!isFunction(expr)) return null; |
| 1014 | const ops = [...expr.ops]; |
| 1015 |
no test coverage detected