@sheetxl/primitives 0.8.0-beta.1 → 0.8.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,10 +28,10 @@ import { IRuntime } from './IRuntime';
28
28
  *
29
29
  * | Category | Key methods |
30
30
  * |---|---|
31
- * | Evaluation lifecycle | `markVolatile`, `getRow`, `getColumn`, `getEntireCoords` |
31
+ * | Evaluation lifecycle | `markVolatile`, `getRow`, `getColumn`, `getEntireCoords`, `getRandom` |
32
32
  * | Argument reflection | `getArgs` |
33
33
  * | Output hints | `formatResults` |
34
- * | Range construction | `createRange`, `filterHidden` |
34
+ * | Range construction | `createRange`, `flattenAreas`, `filterHidden` |
35
35
  * | Dynamic references | `getReference`, `getValueAt`, `getFormulaAt`, `getSpillAt` |
36
36
  * | Function lookup | `getFunction` |
37
37
  * | Dates | `getNow`, `toSerialDate`, `fromSerialDate`, `getDateParts`, `getSerialDate`, `parseAsDate`, `parseAsSerialDate`, `isValidDate` |
@@ -54,6 +54,25 @@ export interface IFormulaContext {
54
54
  * invoked per cell. Default is `null` (an empty range).
55
55
  */
56
56
  createRange<TS extends Scalar = Scalar>(rows?: number, columns?: number, values?: Scalar | Scalar[][] | ((value: TS, coords: IRange.CellCoords, range: IRange<TS>) => TS)): IRange;
57
+ /**
58
+ * One range over every cell of a `ReportType` slot's argument — the AREAS of a reference union
59
+ * folded into a single column, or the range returned unchanged.
60
+ *
61
+ * @param value The argument as it arrived: a range, or one range per area.
62
+ *
63
+ * @remarks
64
+ * A union `(A1:A5,B1:B2)` reaches a {@link IFunction.ParameterTypeJSON.reportType} slot as one
65
+ * `IRange` per area. Functions that answer over it do so because they walk MEMBERS and a union
66
+ * simply has more of them — `LARGE((DA1:DA5,DK1:DK2),2)` is the second largest of all seven
67
+ * cells. This is that walk, and it is a helper rather than a marshalling step on purpose: Excel
68
+ * flattens in exactly the same place, a shared reducer its bodies opt into, which is why the
69
+ * same union is flattened by `LARGE`, refused by `SUMPRODUCT` and answered `#REF!` by `ROWS`.
70
+ *
71
+ * The result is a single column in area order, row-major within each area. SHAPE IS NOT
72
+ * PRESERVED — a union has none. A body that needs an extent must ask
73
+ * {@link IFunctionArguments.getAreaCountAt} and answer for itself.
74
+ */
75
+ flattenAreas(value: IRange | IRange[]): IRange;
57
76
  /**
58
77
  * Returns coordinates as an address string.
59
78
  *
@@ -94,6 +113,20 @@ export interface IFormulaContext {
94
113
  * Returns the 0-based column of the cell being evaluated.
95
114
  */
96
115
  getColumn(): number;
116
+ /**
117
+ * Whether the call being evaluated is in Excel's VALUE mode, where a multi-cell reference at a
118
+ * slot that reads ONE value is implicitly intersected with the formula's cell (the `@` rule);
119
+ * `false` is ARRAY mode, where such a slot reads the reference's first cell.
120
+ *
121
+ * @remarks
122
+ * Only a body that accepts a whole reference at a single-value slot and reads it itself asks
123
+ * (`LINEST`'s `const`). The engine decides the mode from the formula around the call — a
124
+ * scalar-valued root, an aggregator or a lookup above it are value mode; a spilling root, an
125
+ * operator or lifting slot over an array-valued operand, a `LAMBDA` body and an array-entered
126
+ * block are array mode — and the mode is inherited through every call that does not set it.
127
+ * Outside a calculation this is `false`.
128
+ */
129
+ isImplicitIntersect(): boolean;
97
130
  /**
98
131
  * Resolves a range reference at runtime, returning an {@link IReferenceRange}.
99
132
  *
@@ -277,6 +310,7 @@ export interface IFormulaContext {
277
310
  *
278
311
  * @param criteria The criteria, exactly as the user wrote it — a comparison (`">10"`, `"<>x"`),
279
312
  * a wildcard pattern (`"a*"`), or a literal of any type.
313
+ * @param options How the criteria is matched. See {@link IFormulaContext.CriteriaOptions}.
280
314
  * @returns A predicate to test cell values with. Call it once per cell.
281
315
  *
282
316
  * @remarks
@@ -298,7 +332,7 @@ export interface IFormulaContext {
298
332
  * const count = range.reduce((total, value) => matches(value) ? total + 1 : total, 0);
299
333
  * ```
300
334
  */
301
- createCriteria(criteria: Scalar): IFormulaContext.CriteriaEvaluator;
335
+ createCriteria(criteria: Scalar, options?: IFormulaContext.CriteriaOptions): IFormulaContext.CriteriaEvaluator;
302
336
  /**
303
337
  * Reads a typed literal in the workbook's language — the parse side of {@link toText}.
304
338
  *
@@ -386,6 +420,30 @@ export interface IFormulaContext {
386
420
  * ```
387
421
  */
388
422
  getNow(): number;
423
+ /**
424
+ * Returns a random number in `[0, 1)`, like `Math.random()`.
425
+ *
426
+ * @remarks
427
+ * Always draw through this, never `Math.random()`. The source is the runtime's, so a test or a
428
+ * replay can seed it, and the engine sees the draw: a draw is a PER-CELL read — two cells calling
429
+ * the same function in one pass differ — where `getNow` is one value for the whole pass, and the
430
+ * engine only shares an evaluation across the cells of a block when nothing per-cell was read.
431
+ * Pair it with `Volatile<T>` so the function draws again on the next pass.
432
+ *
433
+ * Under a seeded runtime ({@link IRuntime.getRandomSeed}) each draw is keyed by the cell, the
434
+ * pass and which draw it is within that cell, so a function that draws more than once gets
435
+ * distinct values and a cell gets the same ones however the pass was ordered. Take the draws
436
+ * where they are used rather than hoisting them, and the values follow the cells rather than
437
+ * the code path.
438
+ *
439
+ * @example
440
+ * ```typescript
441
+ * export function RAND(): Volatile<number> {
442
+ * return FormulaContext.getRandom();
443
+ * }
444
+ * ```
445
+ */
446
+ getRandom(): number;
389
447
  /**
390
448
  * Returns `true` if the value is a usable date — either a `Date` or a number in the
391
449
  * workbook's serial date range.
@@ -447,14 +505,12 @@ export interface IFormulaContext {
447
505
  * Fields may fall outside their normal range and carry, which is what makes `DATE` and
448
506
  * `TIME` arithmetic work: month 13 is January of the next year, hour 50 is two days plus
449
507
  * two hours, and `getSerialDate(1900, 1, 0)` is serial 0. The `day` carries in SERIAL
450
- * space, so it runs through the phantom `1900-02-29` — measured 25/25 by
451
- * `probe-date-1900-day-overflow.ps1`.
508
+ * space, so it runs through the phantom `1900-02-29`.
452
509
  *
453
510
  * **This validates nothing, and that is deliberate — a caller MUST choose its own
454
511
  * policy.** No range check, no clamping, no bounds on any field, and no `DATE`-style
455
512
  * `0..1899 -> +1900` year offset. Those belong to `DATE`'s ARGUMENTS, not to the
456
- * calendar, and the three things that prove it were measured together
457
- * (`probe-date-arg-layer.ps1`, 2026-08-20):
513
+ * calendar, and three things prove it:
458
514
  *
459
515
  * * **The day policy is the caller's.** `DATE` and `DATEDIF`'s `md`/`yd` re-anchoring
460
516
  * want the raw carry above — `DATEDIF("2020-01-31","2020-03-01","md")` is `-1`
@@ -523,6 +579,26 @@ export declare namespace IFormulaContext {
523
579
  * there.
524
580
  */
525
581
  type CriteriaEvaluator = (value: Scalar) => boolean;
582
+ /**
583
+ * How a criteria is matched — see {@link IFormulaContext.createCriteria}.
584
+ */
585
+ interface CriteriaOptions {
586
+ /**
587
+ * Where a TEXT criteria has to line up with the cell: `'whole'` (the default) for the whole
588
+ * cell, `'start'` for a prefix.
589
+ *
590
+ * @remarks
591
+ * The `D` functions' criteria table is the prefix form and the `*IF` family is not: the
592
+ * criterion `appl` takes the row whose value is `Apple` at `DSUM` and no row at all at
593
+ * `COUNTIF`, and the empty criterion — a prefix of everything — takes every TEXT cell at
594
+ * `DSUM` where `COUNTIF` takes only a cell that IS an empty string.
595
+ *
596
+ * It applies to a criteria that stays TEXT and to nothing else. An OPERATOR turns it off
597
+ * (`=appl` selects no row), and so does a criteria that reads as a number, a boolean or an
598
+ * error — `1` does not reach a cell holding `12`.
599
+ */
600
+ anchor?: 'whole' | 'start';
601
+ }
526
602
  /**
527
603
  * A serial date split into fields — see {@link IFormulaContext.getDateParts}.
528
604
  *
@@ -1,6 +1,6 @@
1
1
  import { Scalar } from './Scalar';
2
2
  import { ScalarType } from './ScalarType';
3
- import { CompatFeature } from './Compat';
3
+ import { ValueKind } from './ValueKind';
4
4
  /**
5
5
  * A self-describing, type-safe, executable function.
6
6
  *
@@ -36,6 +36,16 @@ export interface IFunction {
36
36
  * Indicates whether the function is a built-in function.
37
37
  */
38
38
  isBuiltIn(): boolean;
39
+ /**
40
+ * Indicates whether the function is a defined name whose body is `LAMBDA(…)`.
41
+ *
42
+ * @remarks
43
+ * A named lambda is reachable by name like any other function, so signature help and function
44
+ * lookups can describe it: its parameters are the lambda's, and its summary is the name's
45
+ * comment, or the name's formula when it has no comment. A formula calls it through the NAME,
46
+ * never through {@link execute}, which answers `#CALC!`.
47
+ */
48
+ isLambda(): boolean;
39
49
  /**
40
50
  * Returns the execution environment this function belongs to.
41
51
  *
@@ -126,17 +136,47 @@ export declare namespace IFunction {
126
136
  */
127
137
  getName(): string;
128
138
  /**
129
- * The DECLARED error policy, or `null` when the parameter relies on the default.
139
+ * True when a BARE error at this parameter — an error instead of a value or a range, `NA()`,
140
+ * `#NAME?`, a union where one rectangle is needed — is delivered to the body RAW rather than
141
+ * propagated: the `AcceptError<T>` marker. A rule, not a type — the engine's auto-reject is
142
+ * off at this slot, and the body narrows with `FormulaError.isError` if it cares.
130
143
  *
131
144
  * @remarks
132
- * `null` is the common case and it is not "no policy": the default is REJECT in every position
133
- * — scalar, lifted, flattened and range alike — so `null` means reject. There is deliberately
134
- * no `'reject'` value to declare it with; a `RejectError<T>` marker existed, said exactly what
135
- * `null` already says, and was removed rather than left as a second spelling.
145
+ * The default, and the common case, is that the error propagates with its identity and the
146
+ * body never runs. The marker never looks INSIDE a container: an error member of a range
147
+ * reaches the body either way and is the body's to judge (`IRange.firstError`).
136
148
  *
137
- * @see {@link ParameterTypeJSON.errors}
149
+ * @see {@link ParameterTypeJSON.acceptError}
138
150
  */
139
- getErrorPolicy(): 'accept' | 'accept-ref' | null;
151
+ isAcceptError(): boolean;
152
+ /**
153
+ * True when a multi-cell REFERENCE at this scalar parameter is `#VALUE!` rather than a
154
+ * broadcast — the `NoLift<T>` marker.
155
+ *
156
+ * @see {@link ParameterTypeJSON.noLift}
157
+ */
158
+ isNoLift(): boolean;
159
+ /**
160
+ * True when the members reaching this repeating scalar parameter are coerced rather than
161
+ * filtered — the `NoFilter<T>` marker.
162
+ *
163
+ * @see {@link ParameterTypeJSON.noFilter}
164
+ */
165
+ isNoFilter(): boolean;
166
+ /**
167
+ * True when the argument at this parameter may reach the body UNEVALUATED, as an `ILazy`
168
+ * handle — the `Lazy<T>` marker.
169
+ *
170
+ * @see {@link ParameterTypeJSON.lazy}
171
+ */
172
+ isLazy(): boolean;
173
+ /**
174
+ * True when the parameter takes EITHER a value or a range, decided per argument by its kind —
175
+ * an `IRange | Scalar` union.
176
+ *
177
+ * @see {@link ParameterTypeJSON.valueOrRange}
178
+ */
179
+ isValueOrRange(): boolean;
140
180
  /**
141
181
  * Indicates whether the parameter is required.
142
182
  */
@@ -182,11 +222,60 @@ export declare namespace IFunction {
182
222
  */
183
223
  isRest(): boolean;
184
224
  /**
185
- * Indicates that the parameter is limited to a list of specific values.
186
- * If the input value is a `string` it will be passed as a case-insensitive version.
187
- * If the input value is a `number` it will be passed as a value against the offset.
225
+ * The enum the parameter is limited to, or `null` when it takes any value of its type.
226
+ *
227
+ * @remarks
228
+ * Declared by typing the parameter as a TypeScript `enum`, as an alias paired with a same-name
229
+ * `as const` object, or as a union of number or string literals (`0 | 1`).
230
+ *
231
+ * @see {@link IEnum}
232
+ */
233
+ getEnum(): IFunction.IEnum | null;
234
+ }
235
+ /**
236
+ * One member of an {@link IEnum}.
237
+ */
238
+ interface IEnumMember {
239
+ /**
240
+ * The declared member name (`End`). For a union of bare literals, which names nothing, this is
241
+ * the value as text.
242
+ */
243
+ getName(): string;
244
+ /**
245
+ * The value a formula passes. Typed, and never localized.
246
+ */
247
+ getValue(): number | string;
248
+ /**
249
+ * Whether the member is declared but not offered, from the member's `@deprecated` tag.
250
+ *
251
+ * @remarks
252
+ * A deprecated member stays in the set, so a formula that passes it is not refused and the
253
+ * function decides what it answers. It is left out of the argument dropdown and the values
254
+ * a warning lists. A string is the tag's label (`Excel desktop only`).
255
+ */
256
+ isDeprecated(): boolean | string;
257
+ }
258
+ /**
259
+ * A closed set of values a parameter accepts.
260
+ *
261
+ * @remarks
262
+ * All members are numbers or all are strings; the two never mix. The set is free-form: it does
263
+ * not have to be contiguous or start at zero (`-1 | 0 | 1`).
264
+ */
265
+ interface IEnum {
266
+ /**
267
+ * The declared type name (`PaymentType`), unique within the module that declares it. For a
268
+ * union of bare literals it is the values joined by `|`.
269
+ */
270
+ getId(): string;
271
+ /**
272
+ * Whether the members are numbers or strings.
188
273
  */
189
- getEnums(): readonly string[];
274
+ getScalarType(): typeof ScalarType.Number | typeof ScalarType.String;
275
+ /**
276
+ * The members, in declaration order.
277
+ */
278
+ getMembers(): readonly IFunction.IEnumMember[];
190
279
  }
191
280
  /**
192
281
  * Describes the runtime return behavior of a function, including modifiers like
@@ -197,6 +286,14 @@ export declare namespace IFunction {
197
286
  * If none are specified, The value will be returned with no special behavior.
198
287
  */
199
288
  interface IReturnType extends IValueType {
289
+ /**
290
+ * The declared {@link ValueKind} of the result — the declared override where one exists, else
291
+ * the kind the type spellings imply — or `null` when the result's kind follows the value
292
+ * itself (`'*'`, an untyped return).
293
+ *
294
+ * @see {@link ReturnTypeJSON.kind}
295
+ */
296
+ getKind(): ValueKind | null;
200
297
  /**
201
298
  * Indicates the return value is a Promise or Promise-like (i.e., async).
202
299
  * The system will mark the result as pending and re-trigger evaluation once resolved.
@@ -210,6 +307,17 @@ export declare namespace IFunction {
210
307
  * @defaultValue `false`
211
308
  */
212
309
  isStreaming(): boolean;
310
+ /**
311
+ * True when the result can change with nothing dirty, so a cell naming this function
312
+ * recalculates on every pass — the `Volatile<T>` marker.
313
+ *
314
+ * @remarks
315
+ * STATIC, and read from the formula text at compile time: it is true of the call whether or
316
+ * not the call runs, which is what a lazy argument (and Excel) requires.
317
+ *
318
+ * @see {@link ReturnTypeJSON.volatile}
319
+ */
320
+ isVolatile(): boolean;
213
321
  }
214
322
  /**
215
323
  * The type-system metadata the engine reads to coerce arguments, apply broadcasting,
@@ -238,6 +346,17 @@ export declare namespace IFunction {
238
346
  * If not specified, the function is assumed to be volatile (its output might change even if its inputs haven't).
239
347
  */
240
348
  getParameters(): readonly IParameterType[];
349
+ /**
350
+ * The largest number of arguments a call to this function may carry.
351
+ *
352
+ * @remarks
353
+ * Only meaningful for a VARIADIC function; a fixed parameter list is already its own maximum.
354
+ * The number is the whole CALL's argument count, prefix and optional suffix included, and it
355
+ * is refused where Excel refuses it — at entry, before evaluation.
356
+ *
357
+ * @see {@link Repeating}
358
+ */
359
+ getMaxArguments(): number;
241
360
  /**
242
361
  * Metadata describing the type and dimensionality of the return value.
243
362
  *
@@ -253,7 +372,11 @@ export declare namespace IFunction {
253
372
  */
254
373
  interface IDescriptor {
255
374
  /**
256
- * A overwritten name for the function.
375
+ * The canonical name of the function, matching {@link IDeclaration.getName}.
376
+ *
377
+ * @remarks
378
+ * A descriptor may override the name; when it does not, this is the name of the function
379
+ * in code. Use {@link getNameLocal} for display.
257
380
  */
258
381
  getName(): string;
259
382
  /**
@@ -298,6 +421,31 @@ export declare namespace IFunction {
298
421
  example?: string;
299
422
  defaultValue?: Scalar;
300
423
  }>>;
424
+ /**
425
+ * Describe each enum the function's parameters are limited to.
426
+ *
427
+ * @remarks
428
+ * The keys are enum ids (see {@link IEnum.getId}), and within one the member names (see
429
+ * {@link IEnumMember.getName}). Every enum a parameter declares has an entry and every member
430
+ * has one within it, so a caller can read a label without checking: `nameLocal` falls back to
431
+ * the declared name. Values are never localized — they are on the declaration.
432
+ */
433
+ getEnums(): Readonly<Record<string, IFunction.IEnumDescription>>;
434
+ }
435
+ /**
436
+ * The copy for one enum: what it is, and what each member means.
437
+ */
438
+ interface IEnumDescription {
439
+ /** The enum's name in the user's language, or its declared name. */
440
+ readonly nameLocal: string;
441
+ /** What the enum controls. */
442
+ readonly summary?: string;
443
+ /** By member name. */
444
+ readonly members: Readonly<Record<string, {
445
+ /** The member's name in the user's language, or its declared name. */
446
+ readonly nameLocal: string;
447
+ readonly description?: string;
448
+ }>>;
301
449
  }
302
450
  /**
303
451
  * Describes the type characteristics of a function parameter or return value.
@@ -395,7 +543,8 @@ export declare namespace IFunction {
395
543
  * @remarks
396
544
  * Descriptive rather than applied: an absent argument is never pushed, so the initializer
397
545
  * supplies the value itself. It is recorded so help text, tooltips and completions can say
398
- * "defaults to 3" without reading the source.
546
+ * "defaults to 3" without reading the source. The exception is a {@link lazy} slot, which has
547
+ * no initializer to run — `Lazy<T, V>` declares the default here and the engine applies it.
399
548
  *
400
549
  * Present for a literal initializer only. One computed from another argument
401
550
  * (`numberS2: number = numberS`) has no value to record and leaves this undefined.
@@ -455,28 +604,126 @@ export declare namespace IFunction {
455
604
  */
456
605
  repeating?: ParameterTypeJSON[];
457
606
  /**
458
- * The DECLARED error policy, generated from the `AcceptError<T>` / `AcceptRefError<T>`
459
- * parameter markers.
607
+ * A BARE error at this parameter — an error instead of a value or a range — is delivered to
608
+ * the body RAW rather than propagated: the engine's auto-reject is off at this slot, and the
609
+ * body narrows if it cares. Generated from the `AcceptError<T>` marker. A failed COERCION to
610
+ * the declared type is delivered the same way, as the `#VALUE!` it would have raised, so a
611
+ * body that rethrows what it receives answers exactly as the engine would have — and one that
612
+ * reads its arguments in its own order can (`IFS(TRUE,1,"x",2)` is 1: the pair is never
613
+ * reached).
614
+ *
615
+ * @remarks
616
+ * OMITTED is the default (ErrorPolicy.ts): the error propagates with its identity (a scalar
617
+ * argument), becomes an error member of the output (a lifted member), or short-circuits on the
618
+ * first error in argument order (a flattened list) — the body never runs. A
619
+ * `FormulaError.Known`-typed parameter receives without the marker, because the type declares
620
+ * it. On a TYPED range (`IRange<number>`) the marker also lets error members ride through the
621
+ * typed read raw — COUNT's profile. Errors INSIDE a range are otherwise never the marker's
622
+ * business: a valid range is handed over whole.
623
+ */
624
+ acceptError?: boolean;
625
+ /**
626
+ * The argument's subtree may be handed over UNEVALUATED, as an `ILazy` handle the body either
627
+ * returns unread or forces with `getValue()`. Generated from the `Lazy<T>` marker.
628
+ *
629
+ * @remarks
630
+ * A declaration, not a request: the engine defers where it can and DECLINES where it cannot
631
+ * (an absent argument, an async subtree, a lift that needs every arm), handing over a handle
632
+ * that is already full. Either way the body sees a handle and nothing else, which is why the
633
+ * marker is a contract rather than something inferred from what the body happens to read.
634
+ *
635
+ * Only a RESULT position carries it — `IF`'s branches, `CHOOSE`'s arms, `IFERROR`'s fallback.
636
+ * A condition, an index or a case value is eager, so `AND(FALSE,A1)` still reads `A1` and is
637
+ * still a circular reference.
460
638
  *
461
- * - `'accept'`: the body receives `FormulaError` values raw.
462
- * - `'accept-ref'`: per argument SHAPE — reject for a direct/computed argument, accept for a
463
- * reference-shaped one. Resolved to one of the two before any coercion runs, so nothing
464
- * downstream sees this value.
639
+ * {@link defaultValue} is APPLIED at a lazy slot rather than merely recorded: the parameter
640
+ * cannot carry an initializer of its own (`= false` does not typecheck against a handle), so
641
+ * `Lazy<T, V>` declares it and the engine supplies it for an absent argument.
465
642
  *
466
- * OMITTED is the default and the default is REJECT (ErrorPolicy.ts): never call the body — the
467
- * error propagates with its identity (scalar argument), becomes an error member of the output
468
- * (lifted member), or short-circuits on the first error in row-major order (range/array
469
- * member). Only a `FormulaError.Known`-typed parameter receives without a marker, because the
470
- * type declares it. There is no `'reject'` value: it would say what omitting this says.
643
+ * @see {@link Lazy}
471
644
  */
472
- errors?: 'accept' | 'accept-ref';
645
+ lazy?: boolean;
473
646
  /**
474
- * Indicates whether the function requires the address of the calling cell as an input.
475
- * Cannot be combined with `stream`.
647
+ * A multi-cell REFERENCE at this scalar parameter is `#VALUE!` rather than a broadcast.
648
+ * Generated from the `NoLift<T>` marker.
476
649
  *
477
- * @defaultValue `false`
650
+ * @remarks
651
+ * Per parameter, because Excel is: `NETWORKDAYS.INTL` refuses a reference at its date slots
652
+ * and lifts one at `weekend`. An ARRAY at the slot still lifts, a one-cell reference is an
653
+ * ordinary argument, and a repeating slot absorbs a container as members, so the marker only
654
+ * ever applies to a non-repeating scalar parameter.
655
+ */
656
+ noLift?: boolean;
657
+ /**
658
+ * The members reaching this repeating scalar parameter are COERCED rather than filtered, and
659
+ * one that cannot be coerced is `#VALUE!` for the whole call. Generated from the `NoFilter<T>`
660
+ * marker.
661
+ *
662
+ * @remarks
663
+ * Numeric text parses, a blank inside a multi-cell range reads 0, and a boolean or
664
+ * non-numeric text member refuses — Excel's Analysis-ToolPak reading of a repeating slot,
665
+ * where the native family skips all three (`GCD({6,"8",12})` is 2 where `SUM` would answer
666
+ * over 6 and 12 alone). Only a repeating slot has members, so the marker applies nowhere
667
+ * else; a non-repeating scalar's counterpart is {@link noLift}.
478
668
  */
479
- enums?: string[];
669
+ noFilter?: boolean;
670
+ /**
671
+ * The declared type is ADVISORY: the engine delivers it when it can and hands the body the
672
+ * raw argument when it cannot, instead of answering `#VALUE!` at the slot. Generated from the
673
+ * `ReportType<T>` marker.
674
+ *
675
+ * @remarks
676
+ * The type still reaches the function help, the wizard and the linter — it is what the slot
677
+ * means to a caller. It stops being a gate, so the BODY owns every answer the engine would
678
+ * otherwise have given: a union reaches it as `IRange[]`, a value or an error reaches it as
679
+ * itself. See {@link IFunctionArguments.getKindAt} and
680
+ * {@link IFunctionArguments.getAreaCountAt} for the discriminators.
681
+ */
682
+ reportType?: boolean;
683
+ /**
684
+ * The parameter takes EITHER a value or a range — declared as a two-member union of a bare
685
+ * range type and a scalar type (`IRange | Scalar`, `IReferenceRange | number`) — and the
686
+ * marshaller picks the arm by the ARGUMENT's kind: a value, a bare error or a one-cell
687
+ * reference is the scalar arm (dereferenced, coerced to {@link scalar}, its fault raised in
688
+ * argument order like any scalar slot's); a multi-cell reference, an array or a reference
689
+ * union is the range arm, handed over whole. The slot never lifts.
690
+ *
691
+ * @remarks
692
+ * Excel reads a one-cell argument at some array slots as THE ARGUMENT rather than as a
693
+ * one-cell container: `SORT(<#N/A cell>,1,1,<#DIV/0! cell>)` is `#N/A` where
694
+ * `TAKE(<#N/A cell>,<#DIV/0! cell>)` is `#DIV/0!`. The engine's default
695
+ * for a range slot is TAKE's; this flag is SORT's. {@link scalar} and {@link range} each carry
696
+ * their arm, a pair that without this flag reads as a TYPED range (`IRange<number>`).
697
+ */
698
+ valueOrRange?: boolean;
699
+ /**
700
+ * The closed set of values the parameter accepts. Generated from a parameter typed as a
701
+ * TypeScript `enum`, as an alias paired with a same-name `as const` object, or as a union of
702
+ * number or string literals. {@link scalar} carries the members' type.
703
+ *
704
+ * @remarks
705
+ * Parameters that share a declared enum share one `EnumJSON`, by {@link EnumJSON.id}.
706
+ */
707
+ enum?: EnumJSON;
708
+ }
709
+ /**
710
+ * The JSON form of an {@link IEnum}.
711
+ */
712
+ interface EnumJSON {
713
+ /**
714
+ * The declared type name, unique within the declaring module. A union of bare literals has no
715
+ * name, so its id is the values joined by `|`.
716
+ */
717
+ id: string;
718
+ /**
719
+ * Whether the members are numbers or strings. The two never mix.
720
+ */
721
+ type: typeof ScalarType.Number | typeof ScalarType.String;
722
+ /**
723
+ * The members, in declaration order. A union of bare literals names nothing, so each name is
724
+ * the value as text.
725
+ */
726
+ members: [name: string, value: number | string, deprecated?: string | true][];
480
727
  }
481
728
  /**
482
729
  * Describes the runtime return behavior of a function, including modifiers like
@@ -486,6 +733,24 @@ export declare namespace IFunction {
486
733
  * If none are specified, The value will be returned with no special behavior.
487
734
  */
488
735
  interface ReturnTypeJSON extends ValueTypeJSON {
736
+ /**
737
+ * The declared {@link ValueKind} of the result, where the inherited type spellings cannot say
738
+ * it. Generated from the `@returnKind` marker.
739
+ *
740
+ * @remarks
741
+ * A return type is a pair — is the call a REFERENCE, and what is its value kind. Both halves
742
+ * usually derive from the type spellings: {@link ValueTypeJSON.range} `'p'` (an
743
+ * `IReferenceRange` return, which a function whose value paths are casts may also use —
744
+ * `XLOOKUP`, `TAKE`) is `Reference`; `'r'`/`'m'` is `Array`; a concrete
745
+ * {@link ValueTypeJSON.scalar} is that scalar kind; `'*'` or an untyped return follows the
746
+ * value itself. This field overrides the derivation for the one spelling that loses it — a
747
+ * union like `number[] | number[][]` (`ROW`) collapses to `'*'`, yet the function's one-cell
748
+ * answer is a SCALAR (`TYPE(ROW(A1))` is 1 where `TYPE(TRANSPOSE({5}))` is 64).
749
+ *
750
+ * The engine applies the kind at the call exit: a one-cell range result whose declared kind
751
+ * is a scalar is its member value downstream.
752
+ */
753
+ kind?: ValueKind;
489
754
  /**
490
755
  * Indicates the return value is a Promise or Promise-like (i.e., async).
491
756
  * The system will mark the result as pending and re-trigger evaluation once resolved.
@@ -499,6 +764,20 @@ export declare namespace IFunction {
499
764
  * @defaultValue `false`
500
765
  */
501
766
  stream?: boolean;
767
+ /**
768
+ * The result can change with nothing dirty — a cell naming this function recalculates on
769
+ * every pass. Generated from the `Volatile<T>` marker.
770
+ *
771
+ * @remarks
772
+ * Collected at COMPILE time from the formula text (`CompiledFormula.hasVolatile`), because
773
+ * that is where Excel decides it: `=IF(TRUE,1,RAND())` recalculates on every idle pass though
774
+ * no branch selects the arm, and with lazy arguments the call never happens for the engine to
775
+ * observe. Sits beside {@link async} and {@link stream} because all three are about WHEN a
776
+ * result arrives rather than what it is.
777
+ *
778
+ * @see {@link Volatile}
779
+ */
780
+ volatile?: boolean;
502
781
  }
503
782
  /**
504
783
  * Contains metadata about a function declaration, including its name, return type, parameters, and additional documentation.
@@ -510,6 +789,20 @@ export declare namespace IFunction {
510
789
  returnType?: ReturnTypeJSON;
511
790
  /** @inheritdoc IFunction.IDeclaration.getParameters */
512
791
  parameters?: ParameterTypeJSON[];
792
+ /**
793
+ * The largest number of arguments a call may carry, from `Repeating<T, Max>` on the variadic
794
+ * parameter. Omitted at the default of 255.
795
+ *
796
+ * @remarks
797
+ * Excel keeps one such number per NAME and compares it against the whole call's argument
798
+ * count in its front end, so a call past it is refused AT ENTRY rather than answered — which
799
+ * is why the cap lives on the declaration and not in a body. It is not derivable from the
800
+ * shape: `STDEV` takes 255 arguments and `STDEV.S`, the same function under its dotted name,
801
+ * takes 254.
802
+ *
803
+ * @defaultValue 255
804
+ */
805
+ maxArguments?: number;
513
806
  /**
514
807
  * Describes the execution context required by the function.
515
808
  *
@@ -587,6 +880,22 @@ export declare namespace IFunction {
587
880
  example?: string;
588
881
  defaultValue?: Scalar;
589
882
  }>;
883
+ /**
884
+ * Describe each enum the function's parameters are limited to, by enum id.
885
+ */
886
+ enums?: Record<string, EnumDescriptorJSON>;
887
+ }
888
+ /**
889
+ * The JSON form of an {@link IEnumDescription}. Every field is optional: an enum with no doc
890
+ * comments has nothing to say, and a language pack may translate any part of one.
891
+ */
892
+ interface EnumDescriptorJSON {
893
+ nameLocal?: string;
894
+ summary?: string;
895
+ members?: Record<string, {
896
+ nameLocal?: string;
897
+ description?: string;
898
+ }>;
590
899
  }
591
900
  /**
592
901
  * Contains extended metadata about a function that is not be directly inferable from the code itself.
@@ -604,20 +913,6 @@ export declare namespace IFunction {
604
913
  * @defaultValue false
605
914
  */
606
915
  cancelable?: boolean;
607
- /**
608
- * Named engine behaviors this function opts into, from the `@compat` doc tag.
609
- *
610
- * @remarks
611
- * Canonical spellings, deduplicated and in declaration order; a family alias the author wrote
612
- * (`@compat atp`) has already been expanded to its atomic features. An unknown name never
613
- * reaches here — the linter fails the build on one, deliberately: a compatibility rule that
614
- * silently no-ops is the worst failure available, because the fixtures keep passing and the
615
- * behavior is simply absent.
616
- *
617
- * @see {@link CompatFeatures}
618
- * @see {@link CompatAliases}
619
- */
620
- compat?: CompatFeature[];
621
916
  }
622
917
  }
623
918
  //# sourceMappingURL=IFunction.d.ts.map