import type { FunctionLibrary } from './function-library'; import type { Cell, ICellAddress, UnionValue, CellValue, ArrayUnion, IArea, FunctionUnion } from '../../treb-base-types/src/index'; import { ValueType } from '../../treb-base-types/src/index'; import type { Parser, ExpressionUnit, UnitBinary, UnitIdentifier, UnitGroup, UnitUnary, UnitAddress, UnitCall, UnitDimensionedQuantity, UnitStructuredReference, UnitImplicitCall } from '../../treb-parser/src/index'; import type { DataModel, MacroFunction } from '../../treb-data-model/src/index'; import * as Primitives from './primitives'; /** * dynamically adding a user data field to the expression so we can * cache a function call, avoiding type switching and function lookups. * * we use the generic type so we can cover the composite type as well * before specifying */ type AttachCachedFunction = (T & { fn: (arg0: T) => UnionValue; }); /** * expression unit with cached function */ type ExpressionWithCachedFunction = T extends { type: T['type']; } ? AttachCachedFunction : never; /** * @internal */ export type ExtendedExpressionUnit = ExpressionWithCachedFunction; export declare const UnionIsExpressionUnit: (test: UnionValue) => test is { type: ValueType.object; value: ExpressionUnit; }; export declare const UnionIsMetadata: (test: UnionValue) => test is { type: ValueType.object; value: ReferenceMetadata; }; export interface ReferenceMetadata { type: 'metadata'; address: UnitAddress; value: CellValue; format?: string; } export type BindingFrame = Record; export type PositionalFrame = ExpressionUnit[]; export interface CalculationContext { address: ICellAddress; area?: IArea; volatile: boolean; /** new for lambdas */ bindings: BindingFrame[]; } export declare class ExpressionCalculator { protected readonly data_model: DataModel; protected readonly library: FunctionLibrary; protected readonly parser: Parser; context: CalculationContext; constructor(data_model: DataModel, library: FunctionLibrary, parser: Parser); /** * there's a case where we are calling this from within a function * (which is weird, but hey) and to do that we need to preserve flags. */ Calculate(expr: ExpressionUnit, addr: ICellAddress, area?: IArea, preserve_flags?: boolean): { value: UnionValue; volatile: boolean; }; /** * resolve value from cell. returns a function bound to specific cell. */ protected CellFunction2(expr: UnitAddress): () => UnionValue; /** * returns range as union type. returns a single value for a single cell, * or a 2d array (never a 1d array) */ protected CellFunction4(start: ICellAddress, end: ICellAddress): UnionValue; /** breaking this out to de-dupe */ protected GetMetadata(arg: ExpressionUnit, transform: (cell_data: Cell, address: ICellAddress) => T): UnionValue; protected RewriteMacro(unit: ExpressionUnit, names: Record): ExpressionUnit; protected CallMacro(outer: UnitCall, macro: MacroFunction): (expr: UnitCall) => UnionValue; /** * split out from ImplicitCall so we can reuse */ ImplicitCallTail(result: FunctionUnion, args: ExpressionUnit[]): UnionValue; /** * an FP call will need to set bindings and call an expression, * possibly multiple times. this is a support function for that. */ protected Apply(fn: FunctionUnion, args: UnionValue[]): UnionValue; /** * this method can take a `call` type if it looked like a call at * the parsing stage, it's a simple translation between the two */ protected ImplicitCall(): (expr: UnitImplicitCall | UnitCall) => UnionValue; protected NormalizeBindings(context: BindingFrame): Record; /** * excute a function call */ protected CallExpression(outer: UnitCall, return_reference?: boolean): (expr: UnitCall) => UnionValue; protected ResolveStructuredReference(expr: UnitStructuredReference): () => UnionValue; protected ResolveDimensionedQuantity(): (exp: UnitDimensionedQuantity) => UnionValue; protected UnaryExpression(x: UnitUnary, return_reference?: boolean): (expr: UnitUnary) => UnionValue; /** * expands the size of an array by recycling values in columns and rows * * FIXME: seems like this is more a generic thing, -> utils lib * * @param arr 2d array * @param columns target columns * @param rows target rows */ protected RecycleArray(arr: T[][], columns: number, rows: number): T[][]; protected ElementwiseBinaryExpression(fn: Primitives.PrimitiveBinaryExpression, left: ArrayUnion, right: ArrayUnion): ArrayUnion; /** * convert expr to a cell address, possibly calculating the contents. * returns single address only (ranges with len > 1 will fail) */ protected AsReference(expr: ExpressionUnit): ICellAddress | undefined; protected BinaryExpression(x: UnitBinary): (expr: UnitBinary) => UnionValue; protected Identifier(expr: UnitIdentifier): () => UnionValue; /** * look up an identifier in any binding frames. we do LIFO binding. * * @param name * @returns */ protected LookupBinding(name: string): ExpressionUnit | undefined; protected GroupExpression(x: UnitGroup): (expr: UnitGroup) => UnionValue; protected CalculateExpression(expr: ExtendedExpressionUnit, return_reference?: boolean): UnionValue; } export {};