From b01927ee88ea180642e66670a2d7bee30ab9cc3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Przemys=C5=82aw=20Uzna=C5=84ski?=
<40573492+izulin@users.noreply.github.com>
Date: Fri, 28 May 2021 14:46:38 +0200
Subject: [PATCH] Pu/vectorization (#673)
* parsing of matrices
* size prediction
* evaluation, parsing, unparsing
* tests
* doc
* linter
* compiles
* linter
* small refactor
* kind of works
* cleanup
* linter
* extra config options
* tests
* config
* Update CHANGELOG.md
* docs
---
CHANGELOG.md | 2 +
docs/guide/built-in-functions.md | 2 +-
docs/guide/custom-functions.md | 8 +
src/MatrixSize.ts | 31 +++-
src/interpreter/plugin/AbsPlugin.ts | 4 +-
src/interpreter/plugin/ArrayPlugin.ts | 7 +-
src/interpreter/plugin/BitShiftPlugin.ts | 6 +-
.../plugin/BitwiseLogicOperationsPlugin.ts | 8 +-
src/interpreter/plugin/BooleanPlugin.ts | 62 +++----
src/interpreter/plugin/CharPlugin.ts | 6 +-
src/interpreter/plugin/CodePlugin.ts | 6 +-
src/interpreter/plugin/ComplexPlugin.ts | 54 +++---
src/interpreter/plugin/CountBlankPlugin.ts | 4 +-
src/interpreter/plugin/CountUniquePlugin.ts | 4 +-
src/interpreter/plugin/DateTimePlugin.ts | 56 +++---
src/interpreter/plugin/DegreesPlugin.ts | 4 +-
src/interpreter/plugin/DeltaPlugin.ts | 4 +-
src/interpreter/plugin/ExpPlugin.ts | 4 +-
src/interpreter/plugin/FinancialPlugin.ts | 56 +++---
src/interpreter/plugin/FormulaTextPlugin.ts | 7 +-
src/interpreter/plugin/FunctionPlugin.ts | 170 +++++++++++-------
src/interpreter/plugin/InformationPlugin.ts | 58 +++---
src/interpreter/plugin/IsEvenPlugin.ts | 4 +-
src/interpreter/plugin/IsOddPlugin.ts | 4 +-
src/interpreter/plugin/LogarithmPlugin.ts | 8 +-
src/interpreter/plugin/LookupPlugin.ts | 8 +-
src/interpreter/plugin/MathConstantsPlugin.ts | 6 +-
src/interpreter/plugin/MathPlugin.ts | 30 ++--
src/interpreter/plugin/MatrixPlugin.ts | 12 +-
src/interpreter/plugin/MedianPlugin.ts | 8 +-
src/interpreter/plugin/ModuloPlugin.ts | 4 +-
src/interpreter/plugin/PowerPlugin.ts | 4 +-
src/interpreter/plugin/RadiansPlugin.ts | 4 +-
.../plugin/RadixConversionPlugin.ts | 30 ++--
src/interpreter/plugin/RandomPlugin.ts | 6 +-
src/interpreter/plugin/RomanPlugin.ts | 6 +-
src/interpreter/plugin/RoundingPlugin.ts | 38 ++--
src/interpreter/plugin/SimpleArithmertic.ts | 32 ++--
src/interpreter/plugin/SqrtPlugin.ts | 4 +-
.../plugin/StatisticalAggregationPlugin.ts | 52 +++---
src/interpreter/plugin/StatisticalPlugin.ts | 94 +++++-----
src/interpreter/plugin/SumifPlugin.ts | 12 +-
src/interpreter/plugin/SumprodPlugin.ts | 4 +-
src/interpreter/plugin/TextPlugin.ts | 38 ++--
src/interpreter/plugin/TrigonometryPlugin.ts | 44 ++---
src/parser/FormulaParser.ts | 3 +
test/arrays.spec.ts | 72 ++++++++
test/interpreter/aliases.spec.ts | 4 +
test/interpreter/function-switch.spec.ts | 8 -
test/interpreter/function-trunc.spec.ts | 70 --------
50 files changed, 627 insertions(+), 545 deletions(-)
delete mode 100644 test/interpreter/function-trunc.spec.ts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index db4a369d84..bf23cf6156 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added ARRAY_CONSTRAIN function. (#661)
- Added casting to scalars from non-range arrays. (#663)
- Added support for range interpolation. (#665)
+- Added parsing of arrays in formulas (together with respective config options for separators). (#671)
+- Added support for vectorization of scalar functions. (#673)
- Added support for time in JS `Date()` objects on the input. (#648)
- Added validation of API argument types for simple types. (#654)
- Added named expression handling to engine factories. (#680)
diff --git a/docs/guide/built-in-functions.md b/docs/guide/built-in-functions.md
index d43e727873..63142f14a6 100644
--- a/docs/guide/built-in-functions.md
+++ b/docs/guide/built-in-functions.md
@@ -216,7 +216,7 @@ Total number of functions: **{{ $page.functionsCount }}**
| IFNA | Returns the value if the cell does not contains the #N/A (value not available) error value, or the alternative value if it does. | IFNA(Value; Alternate_value) |
| IFERROR | Returns the value if the cell does not contains an error value, or the alternative value if it does. | IFERROR(Value; Alternate_value) |
| NOT | Complements (inverts) a logical value. | NOT(Logicalvalue) |
-| SWITCH | For each value on the input array, tests its value against cases and returns corresponding value. | SWITCH(Array; Case1, Value1[, Case2, Value2[..., Case_n, Value_n[, Default]]]) |
+| SWITCH | Evaluates a list of arguments, consisting of an expression followed by a value. | SWITCH(Expression1, Value1[, Expression2, Value2[..., Expression_n, Value_n]]) |
| OR | Returns TRUE if at least one argument is TRUE. | OR(Logicalvalue1; Logicalvalue2 ...Logicalvalue30) |
| TRUE | The logical value is set to TRUE. | TRUE() |
| XOR | Returns true if an odd number of arguments evaluates to TRUE. | XOR(Logicalvalue1; Logicalvalue2 ...Logicalvalue30) |
diff --git a/docs/guide/custom-functions.md b/docs/guide/custom-functions.md
index 87486f7007..e3cbad067f 100644
--- a/docs/guide/custom-functions.md
+++ b/docs/guide/custom-functions.md
@@ -57,6 +57,14 @@ class CountHF extends FunctionPlugin {
};
}
```
+
+Similarly, there are other useful properties.
+`isDependentOnSheetStructureChange` marks functions that need to be recalculated with
+each change of the shape of the engine sheets.
+`doesNotNeedArgumentsToBeComputed` marks functions that treat references or ranges in their arguments
+as arguments that do not create dependency. Other arguments are properly evaluated.
+`arrayFunction` denotes functions that enable array arithmetic in its arguments and nested expressions.
+`vectorizationForbidden` when set prevents function from ever being vectorized (however, it is up to implementation of a function to properly handle vectorization).
## Aliases
Aliases are available since the version.
diff --git a/src/MatrixSize.ts b/src/MatrixSize.ts
index 315d9214c7..cde19ea675 100644
--- a/src/MatrixSize.ts
+++ b/src/MatrixSize.ts
@@ -4,10 +4,13 @@
*/
import {AbsoluteCellRange} from './AbsoluteCellRange'
-import {SimpleCellAddress} from './Cell'
+import {CellError, ErrorType, SimpleCellAddress} from './Cell'
import {Config} from './Config'
+import {ErrorMessage} from './error-message'
import {FunctionRegistry} from './interpreter/FunctionRegistry'
import {InterpreterState} from './interpreter/InterpreterState'
+import {ArgumentTypes} from './interpreter/plugin/FunctionPlugin'
+import {SimpleRangeValue} from './interpreter/SimpleRangeValue'
import {Ast, AstNodeType} from './parser'
export class MatrixSize {
@@ -169,7 +172,31 @@ export class MatrixSizePredictor {
return new MatrixSize(width, height)
}
default: {
- return new MatrixSize(1, 1)
+ if(metadata === undefined || metadata.expandRanges || !state.arraysFlag || metadata.vectorizationForbidden || metadata.parameters === undefined) {
+ return new MatrixSize(1, 1)
+ }
+ const argumentDefinitions = [...metadata.parameters]
+ if (metadata.repeatLastArgs === undefined && argumentDefinitions.length < subChecks.length) {
+ return MatrixSize.error()
+ }
+ if (metadata.repeatLastArgs !== undefined && argumentDefinitions.length < subChecks.length &&
+ (subChecks.length - argumentDefinitions.length) % metadata.repeatLastArgs !== 0) {
+ return MatrixSize.error()
+ }
+
+ while(argumentDefinitions.length < subChecks.length) {
+ argumentDefinitions.push(...argumentDefinitions.slice(argumentDefinitions.length-metadata.repeatLastArgs!))
+ }
+
+ let maxWidth = 1
+ let maxHeight = 1
+ for(let i=0;i{
@@ -18,7 +18,7 @@ export class AbsPlugin extends FunctionPlugin implements FunctionPluginTypecheck
},
}
- public abs(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public abs(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ABS'), Math.abs)
}
}
diff --git a/src/interpreter/plugin/ArrayPlugin.ts b/src/interpreter/plugin/ArrayPlugin.ts
index 957ab94929..bd0a2f24be 100644
--- a/src/interpreter/plugin/ArrayPlugin.ts
+++ b/src/interpreter/plugin/ArrayPlugin.ts
@@ -28,6 +28,7 @@ export class ArrayPlugin extends FunctionPlugin implements FunctionPluginTypeche
{argumentType: ArgumentTypes.INTEGER, minValue: 1},
{argumentType: ArgumentTypes.INTEGER, minValue: 1},
],
+ vectorizationForbidden: true,
},
'FILTER': {
method: 'filter',
@@ -40,12 +41,12 @@ export class ArrayPlugin extends FunctionPlugin implements FunctionPluginTypeche
}
}
- public arrayformula(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public arrayformula(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ARRAYFORMULA'), (value) => value)
}
public arrayconstrain(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('ARRAY_CONSTRAIN'), (range: SimpleRangeValue, numRows: number, numCols: number) => {
+ return this.runFunction(ast.args, state, this.metadata('ARRAY_CONSTRAIN'), (range: SimpleRangeValue, numRows: number, numCols: number) => {
numRows = Math.min(numRows, range.height())
numCols = Math.min(numCols, range.width())
const data: InternalScalarValue[][] = range.data
@@ -58,7 +59,7 @@ export class ArrayPlugin extends FunctionPlugin implements FunctionPluginTypeche
}
public filter(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('FILTER'), (rangeVals: SimpleRangeValue, ...rangeFilters: SimpleRangeValue[]) => {
+ return this.runFunction(ast.args, state, this.metadata('FILTER'), (rangeVals: SimpleRangeValue, ...rangeFilters: SimpleRangeValue[]) => {
for(const filter of rangeFilters) {
if (rangeVals.width() !== filter.width() || rangeVals.height() !== filter.height()) {
return new CellError(ErrorType.NA, ErrorMessage.EqualLength)
diff --git a/src/interpreter/plugin/BitShiftPlugin.ts b/src/interpreter/plugin/BitShiftPlugin.ts
index 99eea2a973..a22dcf1965 100644
--- a/src/interpreter/plugin/BitShiftPlugin.ts
+++ b/src/interpreter/plugin/BitShiftPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
const MAX_48BIT_INTEGER = 281474976710655
@@ -32,11 +32,11 @@ export class BitShiftPlugin extends FunctionPlugin implements FunctionPluginType
},
}
- public bitlshift(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bitlshift(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BITLSHIFT'), shiftLeft)
}
- public bitrshift(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bitrshift(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BITRSHIFT'), shiftRight)
}
}
diff --git a/src/interpreter/plugin/BitwiseLogicOperationsPlugin.ts b/src/interpreter/plugin/BitwiseLogicOperationsPlugin.ts
index 8a2f90c540..90ec6dab3f 100644
--- a/src/interpreter/plugin/BitwiseLogicOperationsPlugin.ts
+++ b/src/interpreter/plugin/BitwiseLogicOperationsPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class BitwiseLogicOperationsPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -33,19 +33,19 @@ export class BitwiseLogicOperationsPlugin extends FunctionPlugin implements Func
},
}
- public bitand(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bitand(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BITAND'),
(left: number, right: number) => left & right
)
}
- public bitor(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bitor(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BITOR'),
(left: number, right: number) => left | right
)
}
- public bitxor(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bitxor(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BITXOR'),
(left: number, right: number) => left ^ right
)
diff --git a/src/interpreter/plugin/BooleanPlugin.ts b/src/interpreter/plugin/BooleanPlugin.ts
index 43d621dd30..d7dd2cffa8 100644
--- a/src/interpreter/plugin/BooleanPlugin.ts
+++ b/src/interpreter/plugin/BooleanPlugin.ts
@@ -65,11 +65,11 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
'SWITCH': {
method: 'switch',
parameters: [
- {argumentType: ArgumentTypes.RANGE},
+ {argumentType: ArgumentTypes.NOERROR},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
],
- repeatLastArgs: 1,
+ repeatLastArgs: 1,
},
'IFERROR': {
method: 'iferror',
@@ -103,7 +103,7 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
* @param ast
* @param state
*/
- public literalTrue(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public literalTrue(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TRUE'), () => true)
}
@@ -115,7 +115,7 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
* @param ast
* @param state
*/
- public literalFalse(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public literalFalse(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FALSE'), () => false)
}
@@ -141,7 +141,7 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
* @param ast
* @param state
*/
- public and(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public and(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('AND'),
(...args) => !args.some((arg: boolean) => !arg)
)
@@ -155,17 +155,17 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
* @param ast
* @param state
*/
- public or(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public or(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('OR'),
(...args) => args.some((arg: boolean) => arg)
)
}
- public not(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public not(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NOT'), (arg) => !arg)
}
- public xor(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public xor(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('XOR'), (...args) => {
let cnt = 0
args.forEach((arg: boolean) => {
@@ -177,37 +177,27 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
})
}
- public switch(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('SWITCH'), (selectorArr: SimpleRangeValue, ...args) => {
+ public switch(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
+ return this.runFunction(ast.args, state, this.metadata('SWITCH'), (selector, ...args) => {
const n = args.length
- const ret: InternalScalarValue[][] = []
- for(const row of selectorArr.data) {
- const newrow: InternalScalarValue[] = row.map( (selector) => {
- let i = 0
- if(selector instanceof CellError) {
- return selector
- }
- for (; i + 1 < n; i += 2) {
- if (args[i] instanceof CellError) {
- continue
- }
- if (this.interpreter.arithmeticHelper.eq(selector, args[i] as InternalNoErrorScalarValue)) {
- return args[i + 1]
- }
- }
- if (i < n) {
- return args[i]
- } else {
- return new CellError(ErrorType.NA, ErrorMessage.NoDefault)
- }
- })
- ret.push(newrow)
+ let i = 0
+ for (; i + 1 < n; i += 2) {
+ if (args[i] instanceof CellError) {
+ continue
+ }
+ if (this.interpreter.arithmeticHelper.eq(selector, args[i] as InternalNoErrorScalarValue)) {
+ return args[i + 1]
+ }
+ }
+ if (i < n) {
+ return args[i]
+ } else {
+ return new CellError(ErrorType.NA, ErrorMessage.NoDefault)
}
- return SimpleRangeValue.onlyValues(ret)
})
}
- public iferror(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public iferror(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IFERROR'), (arg1: InternalScalarValue, arg2: InternalScalarValue) => {
if (arg1 instanceof CellError) {
return arg2
@@ -217,7 +207,7 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
})
}
- public ifna(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ifna(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IFNA'), (arg1: InternalScalarValue, arg2: InternalScalarValue) => {
if (arg1 instanceof CellError && arg1.type === ErrorType.NA) {
return arg2
@@ -227,7 +217,7 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
})
}
- public choose(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public choose(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHOOSE'), (selector, ...args) => {
if (selector > args.length) {
return new CellError(ErrorType.NUM, ErrorMessage.Selector)
diff --git a/src/interpreter/plugin/CharPlugin.ts b/src/interpreter/plugin/CharPlugin.ts
index 25b63932cf..f82abbc770 100644
--- a/src/interpreter/plugin/CharPlugin.ts
+++ b/src/interpreter/plugin/CharPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class CharPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -26,7 +26,7 @@ export class CharPlugin extends FunctionPlugin implements FunctionPluginTypechec
},
}
- public char(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public char(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHAR'), (value: number) => {
if (value < 1 || value >= 256) {
return new CellError(ErrorType.VALUE, ErrorMessage.CharacterCodeBounds)
@@ -36,7 +36,7 @@ export class CharPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public unichar(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public unichar(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHAR'), (value: number) => {
if (value < 1 || value >= 1114112) {
return new CellError(ErrorType.VALUE, ErrorMessage.CharacterCodeBounds)
diff --git a/src/interpreter/plugin/CodePlugin.ts b/src/interpreter/plugin/CodePlugin.ts
index 68603c47d7..9b26956b39 100644
--- a/src/interpreter/plugin/CodePlugin.ts
+++ b/src/interpreter/plugin/CodePlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class CodePlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -26,7 +26,7 @@ export class CodePlugin extends FunctionPlugin implements FunctionPluginTypechec
},
}
- public code(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public code(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CODE'), (value: string) => {
if (value.length === 0) {
return new CellError(ErrorType.VALUE, ErrorMessage.EmptyString)
@@ -35,7 +35,7 @@ export class CodePlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public unicode(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public unicode(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('UNICODE'), (value: string) => {
return value.codePointAt(0) ?? new CellError(ErrorType.VALUE, ErrorMessage.EmptyString)
})
diff --git a/src/interpreter/plugin/ComplexPlugin.ts b/src/interpreter/plugin/ComplexPlugin.ts
index 460c341187..e3c7adeed9 100644
--- a/src/interpreter/plugin/ComplexPlugin.ts
+++ b/src/interpreter/plugin/ComplexPlugin.ts
@@ -8,7 +8,7 @@ import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {coerceComplexToString, complex} from '../ArithmeticHelper'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue, RawInterpreterValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue, RawInterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class ComplexPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -178,7 +178,7 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
},
}
- public complex(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public complex(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COMPLEX'),
(re: number, im: number, unit: string) => {
if(unit !== 'i' && unit !== 'j') {
@@ -189,23 +189,23 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public imabs(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imabs(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMABS'), abs)
}
- public imaginary(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imaginary(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMAGINARY'),
([re, im]: complex) => im
)
}
- public imreal(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imreal(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMREAL'),
([re, im]: complex) => re
)
}
- public imargument(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imargument(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMARGUMENT'),
([re, im]: complex) => {
if(re===0 && im===0) {
@@ -216,79 +216,79 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public imconjugate(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imconjugate(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMCONJUGATE'),
([re, im]: complex) => coerceComplexToString([re, -im])
)
}
- public imcos(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imcos(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMCOS'),
(arg: complex) => coerceComplexToString(cos(arg))
)
}
- public imcosh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imcosh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMCOSH'),
(arg: complex) => coerceComplexToString(cosh(arg))
)
}
- public imcot(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imcot(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMCOT'),
(arg: complex) => coerceComplexToString(div(cos(arg), sin(arg)))
)
}
- public imcsc(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imcsc(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMCSC'),
(arg: complex) => coerceComplexToString(div([1, 0], sin(arg)))
)
}
- public imcsch(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imcsch(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMCSCH'),
(arg: complex) => coerceComplexToString(div([1, 0], sinh(arg)))
)
}
- public imsec(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsec(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSEC'),
(arg: complex) => coerceComplexToString(div([1, 0], cos(arg)))
)
}
- public imsech(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsech(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSECH'),
(arg: complex) => coerceComplexToString(div([1, 0], cosh(arg)))
)
}
- public imsin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSIN'),
(arg: complex) => coerceComplexToString(sin(arg))
)
}
- public imsinh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsinh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSINH'),
(arg: complex) => coerceComplexToString(sinh(arg))
)
}
- public imtan(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imtan(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMTAN'),
(arg: complex) => coerceComplexToString(div(sin(arg), cos(arg)))
)
}
- public imdiv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imdiv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMDIV'),
(arg1: complex, arg2: complex) => coerceComplexToString(div(arg1, arg2))
)
}
- public improduct(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public improduct(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMPRODUCT'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceComplexExactRanges(args)
@@ -304,7 +304,7 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public imsum(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsum(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSUM'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceComplexExactRanges(args)
@@ -320,25 +320,25 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public imsub(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsub(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSUB'),
(arg1: complex, arg2: complex) => coerceComplexToString(sub(arg1, arg2))
)
}
- public imexp(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imexp(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMEXP'),
(arg: complex) => coerceComplexToString(exp(arg))
)
}
- public imln(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imln(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMLN'),
(arg: complex) => coerceComplexToString(ln(arg))
)
}
- public imlog10(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imlog10(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMLOG10'),
(arg: complex) => {
const [re, im] = ln(arg)
@@ -348,7 +348,7 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public imlog2(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imlog2(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMLOG2'),
(arg: complex) => {
const [re, im] = ln(arg)
@@ -358,13 +358,13 @@ export class ComplexPlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public impower(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public impower(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMPOWER'),
(arg: complex, n: number) => coerceComplexToString(power(arg, n))
)
}
- public imsqrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public imsqrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IMSQRT'),
(arg: complex) => coerceComplexToString(power(arg, 0.5))
)
diff --git a/src/interpreter/plugin/CountBlankPlugin.ts b/src/interpreter/plugin/CountBlankPlugin.ts
index 812dd59256..e9327f4eea 100644
--- a/src/interpreter/plugin/CountBlankPlugin.ts
+++ b/src/interpreter/plugin/CountBlankPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {EmptyValue, InternalScalarValue, RawScalarValue} from '../InterpreterValue'
+import {EmptyValue, InternalScalarValue, InterpreterValue, RawScalarValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
/**
@@ -24,7 +24,7 @@ export class CountBlankPlugin extends FunctionPlugin implements FunctionPluginTy
},
}
- public countblank(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public countblank(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COUNTBLANK'), (...args: RawScalarValue[]) => {
let counter = 0
args.forEach((arg) => {
diff --git a/src/interpreter/plugin/CountUniquePlugin.ts b/src/interpreter/plugin/CountUniquePlugin.ts
index 929619dc0c..35cdba5220 100644
--- a/src/interpreter/plugin/CountUniquePlugin.ts
+++ b/src/interpreter/plugin/CountUniquePlugin.ts
@@ -6,7 +6,7 @@
import {CellError, ErrorType} from '../../Cell'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {EmptyValueType, InternalScalarValue, RawScalarValue} from '../InterpreterValue'
+import {EmptyValueType, InternalScalarValue, InterpreterValue, RawScalarValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
/**
@@ -32,7 +32,7 @@ export class CountUniquePlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public countunique(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public countunique(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COUNTUNIQUE'), (...args: RawScalarValue[]) => {
const valuesSet = new Set()
const errorsSet = new Set()
diff --git a/src/interpreter/plugin/DateTimePlugin.ts b/src/interpreter/plugin/DateTimePlugin.ts
index 67c643f3cd..5f55615fba 100644
--- a/src/interpreter/plugin/DateTimePlugin.ts
+++ b/src/interpreter/plugin/DateTimePlugin.ts
@@ -24,7 +24,7 @@ import {
EmptyValue,
getRawValue,
InternalNoErrorScalarValue,
- InternalScalarValue,
+ InternalScalarValue, InterpreterValue,
isExtendedNumber,
NumberType,
RawNoErrorScalarValue,
@@ -242,7 +242,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
* @param ast
* @param state
*/
- public date(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public date(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DATE'), (year, month, day) => {
const d = Math.trunc(day)
let m = Math.trunc(month)
@@ -267,7 +267,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public time(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public time(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TIME'),
(h, m, s) => {
const ret = timeToNumber({hours: Math.trunc(h), minutes: Math.trunc(m), seconds: Math.trunc(s)})
@@ -279,7 +279,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public eomonth(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public eomonth(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EOMONTH'), (dateNumber, numberOfMonthsToShift) => {
const date = this.interpreter.dateHelper.numberToSimpleDate(dateNumber)
let ret: Maybe = this.interpreter.dateHelper.dateToNumber(this.interpreter.dateHelper.endOfMonth(offsetMonth(date, numberOfMonthsToShift)))
@@ -291,13 +291,13 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public day(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public day(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DAY'),
(dateNumber) => this.interpreter.dateHelper.numberToSimpleDate(dateNumber).day
)
}
- public days(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public days(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DAYS'), (endDate, startDate) => Math.trunc(endDate) - Math.trunc(startDate))
}
@@ -309,7 +309,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
* @param ast
* @param state
*/
- public month(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public month(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MONTH'),
(dateNumber) => this.interpreter.dateHelper.numberToSimpleDate(dateNumber).month
)
@@ -323,25 +323,25 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
* @param ast
* @param state
*/
- public year(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public year(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('YEAR'),
(dateNumber) => this.interpreter.dateHelper.numberToSimpleDate(dateNumber).year
)
}
- public hour(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public hour(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HOUR'),
(timeNumber) => numberToSimpleTime(roundToNearestSecond(timeNumber)%1).hours
)
}
- public minute(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public minute(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MINUTE'),
(timeNumber) => numberToSimpleTime(roundToNearestSecond(timeNumber)%1).minutes
)
}
- public second(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public second(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SECOND'),
(timeNumber) => numberToSimpleTime(roundToNearestSecond(timeNumber)%1).seconds
)
@@ -355,13 +355,13 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
* @param ast
* @param state
*/
- public text(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public text(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TEXT'),
(numberRepresentation, formatArg) => format(numberRepresentation, formatArg, this.config, this.interpreter.dateHelper)
)
}
- public weekday(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public weekday(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('WEEKDAY'),
(day: number, type: number) => {
const absoluteDay = Math.floor(this.interpreter.dateHelper.relativeNumberToAbsoluteNumber(day))
@@ -377,7 +377,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public weeknum(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public weeknum(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('WEEKNUM'),
(day: number, type: number) => {
const absoluteDay = Math.floor(this.interpreter.dateHelper.relativeNumberToAbsoluteNumber(day))
@@ -396,7 +396,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public isoweeknum(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isoweeknum(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISOWEEKNUM'), this.isoweeknumCore)
}
@@ -413,7 +413,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
return ret
}
- public datevalue(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public datevalue(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DATEVALUE'),
(date: string) => {
const {dateTime} = this.interpreter.dateHelper.parseDateTimeFromConfigFormats(date)
@@ -429,7 +429,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public timevalue(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public timevalue(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TIMEVALUE'),
(date: string) => {
const dateNumber = this.interpreter.dateHelper.dateStringToDateNumber(date)
@@ -441,7 +441,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public now(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public now(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NOW'),
() => {
const now = new Date()
@@ -451,7 +451,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public today(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public today(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TODAY'),
() => {
const now = new Date()
@@ -460,7 +460,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public edate(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public edate(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EDATE'),
(dateNumber: number, delta: number) => {
const date = this.interpreter.dateHelper.numberToSimpleDate(dateNumber)
@@ -475,7 +475,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public datedif(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public datedif(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DATEDIF'),
(startDate: number, endDate: number, unit: string) => {
if(startDate > endDate) {
@@ -522,7 +522,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public days360(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public days360(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DAYS360'), this.days360Core)
}
@@ -539,7 +539,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
return 360 * (nEnd.year - nStart.year) + 30*(nEnd.month-nStart.month) + nEnd.day-nStart.day
}
- public yearfrac(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public yearfrac(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('YEARFRAC'),
(startDate: number, endDate: number, mode: number) => {
startDate = Math.trunc(startDate)
@@ -567,7 +567,7 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public interval(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public interval(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('INTERVAL'),
(arg: number) => {
arg = Math.trunc(arg)
@@ -593,25 +593,25 @@ export class DateTimePlugin extends FunctionPlugin implements FunctionPluginType
)
}
- public networkdays(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public networkdays(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NETWORKDAYS'),
(start, end, holidays) => this.networkdayscore(start, end, 1, holidays)
)
}
- public networkdaysintl(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public networkdaysintl(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NETWORKDAYS.INTL'),
(start, end, weekend, holidays) => this.networkdayscore(start, end, weekend, holidays)
)
}
- public workday(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public workday(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('WORKDAY'),
(start, end, holidays) => this.workdaycore(start, end, 1, holidays)
)
}
- public workdayintl(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public workdayintl(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('WORKDAY.INTL'),
(start, end, weekend, holidays) => this.workdaycore(start, end, weekend, holidays)
)
diff --git a/src/interpreter/plugin/DegreesPlugin.ts b/src/interpreter/plugin/DegreesPlugin.ts
index d7167e4b6a..b1c68b2aa4 100644
--- a/src/interpreter/plugin/DegreesPlugin.ts
+++ b/src/interpreter/plugin/DegreesPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class DegreesPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -18,7 +18,7 @@ export class DegreesPlugin extends FunctionPlugin implements FunctionPluginTypec
},
}
- public degrees(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public degrees(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DEGREES'),
(arg) => arg * (180 / Math.PI)
)
diff --git a/src/interpreter/plugin/DeltaPlugin.ts b/src/interpreter/plugin/DeltaPlugin.ts
index 8a96c567bc..aee6d74869 100644
--- a/src/interpreter/plugin/DeltaPlugin.ts
+++ b/src/interpreter/plugin/DeltaPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class DeltaPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -19,7 +19,7 @@ export class DeltaPlugin extends FunctionPlugin implements FunctionPluginTypeche
},
}
- public delta(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public delta(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DELTA'),
(left: number, right: number) => (left === right ? 1 : 0)
)
diff --git a/src/interpreter/plugin/ExpPlugin.ts b/src/interpreter/plugin/ExpPlugin.ts
index 9ce4d19ccc..cce6ef8d80 100644
--- a/src/interpreter/plugin/ExpPlugin.ts
+++ b/src/interpreter/plugin/ExpPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class ExpPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -26,7 +26,7 @@ export class ExpPlugin extends FunctionPlugin implements FunctionPluginTypecheck
* @param ast
* @param state
*/
- public exp(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public exp(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EXP'), Math.exp)
}
}
diff --git a/src/interpreter/plugin/FinancialPlugin.ts b/src/interpreter/plugin/FinancialPlugin.ts
index 5389231d9c..bcd1020360 100644
--- a/src/interpreter/plugin/FinancialPlugin.ts
+++ b/src/interpreter/plugin/FinancialPlugin.ts
@@ -10,7 +10,7 @@ import {InterpreterState} from '../InterpreterState'
import {
EmptyValue,
getRawValue,
- InternalScalarValue,
+ InternalScalarValue, InterpreterValue,
isExtendedNumber,
NumberType,
RawInterpreterValue
@@ -283,23 +283,23 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
},
}
- public pmt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public pmt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PMT'), pmtCore)
}
- public ipmt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ipmt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('IPMT'), ipmtCore)
}
- public ppmt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ppmt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PPMT'), ppmtCore)
}
- public fv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FV'), fvCore)
}
- public cumipmt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public cumipmt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CUMIPMT'),
(rate: number, periods: number, value: number, start: number, end: number, type: number) => {
if (start > end) {
@@ -314,7 +314,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public cumprinc(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public cumprinc(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CUMPRINC'),
(rate: number, periods: number, value: number, start: number, end: number, type: number) => {
if (start > end) {
@@ -329,7 +329,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public db(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public db(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DB'),
(cost: number, salvage: number, life: number, period: number, month: number) => {
if ((month===12 && period > life) || (period > life+1)) {
@@ -361,7 +361,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public ddb(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ddb(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DDB'),
(cost: number, salvage: number, life: number, period: number, factor: number) => {
if (period > life) {
@@ -385,7 +385,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public dollarde(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public dollarde(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DOLLARDE'),
(dollar, fraction) => {
if (fraction < 1) {
@@ -401,7 +401,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public dollarfr(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public dollarfr(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DOLLARFR'),
(dollar, fraction) => {
if (fraction < 1) {
@@ -417,7 +417,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public effect(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public effect(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EFFECT'),
(rate: number, periods: number) => {
periods = Math.trunc(periods)
@@ -426,7 +426,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public ispmt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ispmt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISPMT'),
(rate, period, periods, value) => {
if(periods===0) {
@@ -437,7 +437,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public nominal(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public nominal(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NOMINAL'),
(rate: number, periods: number) => {
periods = Math.trunc(periods)
@@ -446,7 +446,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public nper(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public nper(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NPER'),
(rate, payment, present, future, type) => {
if(rate === 0) {
@@ -463,7 +463,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public rate(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public rate(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RATE'),
(periods, payment, present, future, type, guess) => {
if(guess<=-1) {
@@ -505,7 +505,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public pv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public pv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PV'),
(rate, periods, payment, future, type) => {
type = type ? 1 : 0
@@ -525,7 +525,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public rri(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public rri(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RRI'),
(periods, present, future) => {
if (present === 0 || (future < 0 && present > 0) || (future > 0 && present < 0)) {
@@ -537,7 +537,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public sln(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sln(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SLN'),
(cost, salvage, life) => {
if (life === 0) {
@@ -548,7 +548,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public syd(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public syd(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SYD'),
(cost, salvage, life, period) => {
if (period > life) {
@@ -559,7 +559,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public tbilleq(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tbilleq(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TBILLEQ'),
(settlement, maturity, discount) => {
settlement = Math.round(settlement)
@@ -585,7 +585,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public tbillprice(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tbillprice(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TBILLPRICE'),
(settlement, maturity, discount) => {
settlement = Math.round(settlement)
@@ -611,7 +611,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public tbillyield(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tbillyield(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TBILLYIELD'),
(settlement, maturity, price) => {
settlement = Math.round(settlement)
@@ -630,7 +630,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public fvschedule(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fvschedule(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FVSCHEDULE'),
(value: number, ratios: SimpleRangeValue) => {
const vals = ratios.valuesFromTopLeftCorner()
@@ -650,7 +650,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
})
}
- public npv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public npv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NPV'),
(rate: number, ...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -662,7 +662,7 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public mirr(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public mirr(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MIRR'),
(range: SimpleRangeValue, frate: number, rrate: number) => {
const vals = this.interpreter.arithmeticHelper.manyToExactNumbers(range.valuesFromTopLeftCorner())
@@ -707,13 +707,13 @@ export class FinancialPlugin extends FunctionPlugin implements FunctionPluginTyp
)
}
- public pduration(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public pduration(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PDURATION'),
(rate: number, pv: number, fv: number) => (Math.log(fv) - Math.log(pv))/Math.log(1+rate)
)
}
- public xnpv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public xnpv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('XNPV'),
(rate: number, values: SimpleRangeValue, dates: SimpleRangeValue) => {
const valArr = values.valuesFromTopLeftCorner()
diff --git a/src/interpreter/plugin/FormulaTextPlugin.ts b/src/interpreter/plugin/FormulaTextPlugin.ts
index d90f4f25bf..9df0739250 100644
--- a/src/interpreter/plugin/FormulaTextPlugin.ts
+++ b/src/interpreter/plugin/FormulaTextPlugin.ts
@@ -8,7 +8,7 @@ import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {FunctionPlugin} from '../index'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPluginTypecheck} from './FunctionPlugin'
export class FormulaTextPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -19,7 +19,8 @@ export class FormulaTextPlugin extends FunctionPlugin implements FunctionPluginT
{argumentType: ArgumentTypes.NOERROR}
],
doesNotNeedArgumentsToBeComputed: true,
- isDependentOnSheetStructureChange: true
+ isDependentOnSheetStructureChange: true,
+ vectorizationForbidden: true,
},
}
@@ -31,7 +32,7 @@ export class FormulaTextPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public formulatext(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public formulatext(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('FORMULATEXT'),
() => new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber),
(cellReference: SimpleCellAddress) => this.serialization.getCellFormula(cellReference) ?? new CellError(ErrorType.NA, ErrorMessage.Formula)
diff --git a/src/interpreter/plugin/FunctionPlugin.ts b/src/interpreter/plugin/FunctionPlugin.ts
index 73376f3ad6..257a9240df 100644
--- a/src/interpreter/plugin/FunctionPlugin.ts
+++ b/src/interpreter/plugin/FunctionPlugin.ts
@@ -38,30 +38,55 @@ export interface ImplementedFunctions {
[formulaId: string]: FunctionMetadata,
}
-export interface FunctionArguments {
+export interface FunctionMetadata {
+ /**
+ * Internal and engine.
+ */
parameters?: FunctionArgument[],
+
/**
+ * Internal.
* Used for functions with variable number of arguments -- tells how many last arguments can be repeated indefinitely.
*/
repeatLastArgs?: number,
/**
+ * Internal.
* Ranges in arguments are inlined to (possibly multiple) scalar arguments.
*/
expandRanges?: boolean,
/**
+ * Internal.
* Return number value is packed into this subtype.
*/
returnNumberType?: NumberType,
-}
-
-export interface FunctionMetadata extends FunctionArguments {
+ /**
+ * Engine.
+ */
method: string,
+ /**
+ * Engine.
+ */
isVolatile?: boolean,
+ /**
+ * Engine.
+ */
isDependentOnSheetStructureChange?: boolean,
+ /**
+ * Engine.
+ */
doesNotNeedArgumentsToBeComputed?: boolean,
+ /**
+ * Engine.
+ */
arrayFunction?: boolean,
+
+ /**
+ * Internal.
+ * Some function do not allow vectorization: array-output, and special functions.
+ */
+ vectorizationForbidden?: boolean,
}
export interface FunctionPluginDefinition {
@@ -289,90 +314,109 @@ export abstract class FunctionPlugin implements FunctionPluginTypecheck InternalScalarValue
- ) => {
- return this.runFunctionTemplate(args, state, functionDefinition, fn)
- }
-
- protected runMatrixFunction = (
- args: Ast[],
- state: InterpreterState,
- functionDefinition: FunctionArguments,
- fn: (...arg: any) => InterpreterValue
+ metadata: FunctionMetadata,
+ fn: (...arg: any) => InterpreterValue,
) => {
- return this.runFunctionTemplate(args, state, functionDefinition, fn)
- }
+ let argumentDefinitions: FunctionArgument[] = metadata.parameters!
+ let argValues: [InterpreterValue, boolean][]
- private runFunctionTemplate = (
- args: Ast[],
- state: InterpreterState,
- functionDefinition: FunctionArguments,
- fn: (...arg: any) => any
- ) => {
- const argumentDefinitions: FunctionArgument[] = functionDefinition.parameters!
- let scalarValues: [InterpreterValue, boolean][]
-
- if (functionDefinition.expandRanges) {
- scalarValues = this.listOfScalarValues(args, state)
+ if (metadata.expandRanges) {
+ argValues = this.listOfScalarValues(args, state)
} else {
- scalarValues = args.map((ast) => [this.evaluateAst(ast, state), false])
+ argValues = args.map((ast) => [this.evaluateAst(ast, state), false])
}
- const coercedArguments: Maybe[] = []
- let argCoerceFailure: Maybe = undefined
- if (functionDefinition.repeatLastArgs === undefined && argumentDefinitions.length < scalarValues.length) {
+ if (metadata.repeatLastArgs === undefined && argumentDefinitions.length < argValues.length) {
return new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber)
}
- if (functionDefinition.repeatLastArgs !== undefined && scalarValues.length > argumentDefinitions.length &&
- (scalarValues.length - argumentDefinitions.length) % functionDefinition.repeatLastArgs !== 0) {
+ if (metadata.repeatLastArgs !== undefined && argumentDefinitions.length < argValues.length &&
+ (argValues.length - argumentDefinitions.length) % metadata.repeatLastArgs !== 0) {
return new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber)
}
- for (let i = 0, j = 0; i < Math.max(scalarValues.length, argumentDefinitions.length); i++, j++) {
- // i points to where are we in the scalarValues list,
- // j points to where are we in the argumentDefinitions list
- if (j === argumentDefinitions.length) {
- j -= functionDefinition.repeatLastArgs!
+ argumentDefinitions = [...argumentDefinitions]
+ while(argumentDefinitions.length < argValues.length) {
+ argumentDefinitions.push(...argumentDefinitions.slice(argumentDefinitions.length-metadata.repeatLastArgs!))
+ }
+
+ let maxWidth = 1
+ let maxHeight = 1
+ if(!metadata.vectorizationForbidden && state.arraysFlag) {
+ for(let i=0;i = undefined
+ const coercedArguments: Maybe[] = []
+ for (let i = 0; i < argumentDefinitions.length; i++) {
+ // eslint-disable-next-line prefer-const
+ let [val, ignorable] = argValues[i] ?? [undefined, undefined]
+ if(val instanceof SimpleRangeValue && argumentDefinitions[i].argumentType !== ArgumentTypes.RANGE && argumentDefinitions[i].argumentType !== ArgumentTypes.ANY) {
+ if(!metadata.vectorizationForbidden && state.arraysFlag) {
+ val = val.data[val.height()!==1 ? row : 0]?.[val.width()!==1 ? col : 0]
+ }
}
- coercedArguments.push(coercedArg)
- } else if (!ignorable) {
- //if this is first error encountered, store it
- argCoerceFailure = argCoerceFailure ?? (new CellError(ErrorType.VALUE, ErrorMessage.WrongType))
+ const arg = val ?? argumentDefinitions[i]?.defaultValue
+ if (arg === undefined) {
+ coercedArguments.push(undefined) //we verified in previous loop that this arg is optional
+ } else {
+ //we apply coerce only to non-default values
+ const coercedArg = val !== undefined ? this.coerceToType(arg, argumentDefinitions[i], state) : arg
+ if (coercedArg !== undefined) {
+ if (coercedArg instanceof CellError && argumentDefinitions[i].argumentType !== ArgumentTypes.SCALAR) {
+ //if this is first error encountered, store it
+ argCoerceFailure = argCoerceFailure ?? coercedArg
+ }
+ coercedArguments.push(coercedArg)
+ } else if (!ignorable) {
+ //if this is first error encountered, store it
+ argCoerceFailure = argCoerceFailure ?? (new CellError(ErrorType.VALUE, ErrorMessage.WrongType))
+ }
+ }
+ }
+
+ const ret = argCoerceFailure ?? this.returnNumberWrapper(fn(...coercedArguments), metadata.returnNumberType)
+ if(maxHeight === 1 && maxWidth === 1) {
+ return ret
}
+ if(ret instanceof SimpleRangeValue) {
+ throw 'Function returning array cannot be vectorized.'
+ }
+ rowArr.push(ret)
}
+ retArr.push(rowArr)
}
-
- return argCoerceFailure ?? this.returnNumberWrapper(fn(...coercedArguments), functionDefinition.returnNumberType)
+ return SimpleRangeValue.onlyValues(retArr)
}
protected runFunctionWithReferenceArgument = (
args: Ast[],
state: InterpreterState,
- argumentDefinitions: FunctionArguments,
+ metadata: FunctionMetadata,
noArgCallback: () => InternalScalarValue | RawScalarValue,
referenceCallback: (reference: SimpleCellAddress) => InternalScalarValue,
nonReferenceCallback: (...arg: any) => InternalScalarValue = () => new CellError(ErrorType.NA, ErrorMessage.CellRefExpected)
) => {
if (args.length === 0) {
- return this.returnNumberWrapper(noArgCallback(), argumentDefinitions.returnNumberType)
+ return this.returnNumberWrapper(noArgCallback(), metadata.returnNumberType)
} else if (args.length > 1) {
return new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber)
}
@@ -395,10 +439,10 @@ export abstract class FunctionPlugin implements FunctionPluginTypecheck(val: T | ExtendedNumber, type?: NumberType, format?: FormatInfo): T | ExtendedNumber {
if(type !== undefined && isExtendedNumber(val)) {
return this.interpreter.arithmeticHelper.ExtendedNumberFactory(getRawValue(val), {type, format})
} else {
diff --git a/src/interpreter/plugin/InformationPlugin.ts b/src/interpreter/plugin/InformationPlugin.ts
index 6b83bc7a73..8ba8355570 100644
--- a/src/interpreter/plugin/InformationPlugin.ts
+++ b/src/interpreter/plugin/InformationPlugin.ts
@@ -8,7 +8,7 @@ import {FormulaVertex} from '../../DependencyGraph/FormulaCellVertex'
import {ErrorMessage} from '../../error-message'
import {AstNodeType, ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {EmptyValue, InternalScalarValue, isExtendedNumber} from '../InterpreterValue'
+import {EmptyValue, InternalScalarValue, InterpreterValue, isExtendedNumber} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
@@ -24,6 +24,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
],
isDependentOnSheetStructureChange: true,
doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
},
'COLUMNS': {
method: 'columns',
@@ -32,6 +33,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
],
isDependentOnSheetStructureChange: true,
doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
},
'ISBINARY': {
method: 'isbinary',
@@ -50,7 +52,8 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
parameters: [
{argumentType: ArgumentTypes.NOERROR}
],
- doesNotNeedArgumentsToBeComputed: true
+ doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
},
'ISNA': {
method: 'isna',
@@ -62,7 +65,8 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
method: 'isref',
parameters: [
{argumentType: ArgumentTypes.SCALAR}
- ]
+ ],
+ vectorizationForbidden: true,
},
'ISERROR': {
method: 'iserror',
@@ -119,6 +123,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
],
isDependentOnSheetStructureChange: true,
doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
},
'ROWS': {
method: 'rows',
@@ -127,20 +132,23 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
],
isDependentOnSheetStructureChange: true,
doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
},
'SHEET': {
method: 'sheet',
parameters: [
- {argumentType: ArgumentTypes.NOERROR}
+ {argumentType: ArgumentTypes.STRING}
],
- doesNotNeedArgumentsToBeComputed: true
+ doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
},
'SHEETS': {
method: 'sheets',
parameters: [
- {argumentType: ArgumentTypes.NOERROR}
+ {argumentType: ArgumentTypes.STRING}
],
- doesNotNeedArgumentsToBeComputed: true
+ doesNotNeedArgumentsToBeComputed: true,
+ vectorizationForbidden: true,
}
}
@@ -152,7 +160,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isbinary(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isbinary(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISBINARY'), (arg: string) =>
/^[01]{1,10}$/.test(arg)
)
@@ -166,7 +174,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public iserr(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public iserr(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISERR'), (arg: InternalScalarValue) =>
(arg instanceof CellError && arg.type !== ErrorType.NA)
)
@@ -180,7 +188,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public iserror(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public iserror(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISERROR'), (arg: InternalScalarValue) =>
(arg instanceof CellError)
)
@@ -194,7 +202,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isformula(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isformula(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('ISFORMULA'),
() => new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber),
(reference: SimpleCellAddress) => {
@@ -212,7 +220,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isblank(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isblank(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISBLANK'), (arg: InternalScalarValue) =>
(arg === EmptyValue)
)
@@ -226,7 +234,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isna(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isna(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISNA'), (arg: InternalScalarValue) =>
(arg instanceof CellError && arg.type == ErrorType.NA)
)
@@ -240,7 +248,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isnumber(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isnumber(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISNUMBER'), isExtendedNumber)
}
@@ -252,7 +260,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public islogical(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public islogical(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISLOGICAL'), (arg: InternalScalarValue) =>
(typeof arg === 'boolean')
)
@@ -266,7 +274,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isref(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isref(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISREF'), (arg: InternalScalarValue) =>
(arg instanceof CellError && (arg.type == ErrorType.REF || arg.type == ErrorType.CYCLE))
)
@@ -280,7 +288,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public istext(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public istext(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISTEXT'), (arg: InternalScalarValue) =>
(typeof arg === 'string')
)
@@ -294,7 +302,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public isnontext(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isnontext(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISNONTEXT'), (arg: InternalScalarValue) =>
!(typeof arg === 'string')
)
@@ -308,7 +316,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public column(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public column(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('COLUMN'),
() => state.formulaAddress.col + 1,
(reference: SimpleCellAddress) => reference.col + 1
@@ -346,7 +354,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public row(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public row(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('ROW'),
() => state.formulaAddress.row + 1,
(reference: SimpleCellAddress) => reference.row + 1
@@ -384,7 +392,7 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
*/
- public index(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public index(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('INDEX'), (rangeValue: SimpleRangeValue, row: number, col: number) => {
if (col < 1 || row < 1) {
return new CellError(ErrorType.VALUE, ErrorMessage.LessThanOne)
@@ -419,8 +427,8 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
* */
- public sheet(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
- return this.runFunctionWithReferenceArgument(ast.args, state, {parameters: [{argumentType: ArgumentTypes.STRING}]},
+ public sheet(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
+ return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('SHEET'),
() => state.formulaAddress.sheet + 1,
(reference: SimpleCellAddress) => reference.sheet + 1,
(value: string) => {
@@ -443,8 +451,8 @@ export class InformationPlugin extends FunctionPlugin implements FunctionPluginT
* @param ast
* @param state
* */
- public sheets(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
- return this.runFunctionWithReferenceArgument(ast.args, state, {parameters: [{argumentType: ArgumentTypes.STRING}]},
+ public sheets(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
+ return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('SHEETS'),
() => this.dependencyGraph.sheetMapping.numberOfSheets(), // return number of sheets if no argument
() => 1, // return 1 for valid reference
() => new CellError(ErrorType.VALUE, ErrorMessage.CellRefExpected) // error otherwise
diff --git a/src/interpreter/plugin/IsEvenPlugin.ts b/src/interpreter/plugin/IsEvenPlugin.ts
index b62a2c2105..49edd7ef03 100644
--- a/src/interpreter/plugin/IsEvenPlugin.ts
+++ b/src/interpreter/plugin/IsEvenPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class IsEvenPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -18,7 +18,7 @@ export class IsEvenPlugin extends FunctionPlugin implements FunctionPluginTypech
},
}
- public iseven(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public iseven(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISEVEN'),
(val) => (val % 2 === 0)
)
diff --git a/src/interpreter/plugin/IsOddPlugin.ts b/src/interpreter/plugin/IsOddPlugin.ts
index c5b7d6a927..ba15165781 100644
--- a/src/interpreter/plugin/IsOddPlugin.ts
+++ b/src/interpreter/plugin/IsOddPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class IsOddPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -18,7 +18,7 @@ export class IsOddPlugin extends FunctionPlugin implements FunctionPluginTypeche
},
}
- public isodd(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public isodd(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ISODD'),
(val) => (val % 2 === 1)
)
diff --git a/src/interpreter/plugin/LogarithmPlugin.ts b/src/interpreter/plugin/LogarithmPlugin.ts
index 72882f1561..7b264395f9 100644
--- a/src/interpreter/plugin/LogarithmPlugin.ts
+++ b/src/interpreter/plugin/LogarithmPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class LogarithmPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -32,17 +32,17 @@ export class LogarithmPlugin extends FunctionPlugin implements FunctionPluginTyp
},
}
- public log10(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public log10(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LOG10'), Math.log10)
}
- public log(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public log(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LOG'),
(arg: number, base: number) => Math.log(arg) / Math.log(base)
)
}
- public ln(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ln(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LN'), Math.log)
}
}
diff --git a/src/interpreter/plugin/LookupPlugin.ts b/src/interpreter/plugin/LookupPlugin.ts
index cf6de715fb..5e48336737 100644
--- a/src/interpreter/plugin/LookupPlugin.ts
+++ b/src/interpreter/plugin/LookupPlugin.ts
@@ -12,7 +12,7 @@ import {ProcedureAst} from '../../parser'
import {StatType} from '../../statistics'
import {zeroIfEmpty} from '../ArithmeticHelper'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue, RawNoErrorScalarValue, } from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue, RawNoErrorScalarValue, } from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
@@ -54,7 +54,7 @@ export class LookupPlugin extends FunctionPlugin implements FunctionPluginTypech
* @param ast
* @param state
*/
- public vlookup(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public vlookup(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('VLOOKUP'), (key: RawNoErrorScalarValue, rangeValue: SimpleRangeValue, index: number, sorted: boolean) => {
const range = rangeValue.range
@@ -78,7 +78,7 @@ export class LookupPlugin extends FunctionPlugin implements FunctionPluginTypech
* @param ast
* @param formulaAddress
*/
- public hlookup(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public hlookup(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HLOOKUP'), (key: RawNoErrorScalarValue, rangeValue: SimpleRangeValue, index: number, sorted: boolean) => {
const range = rangeValue.range
if (range === undefined) {
@@ -95,7 +95,7 @@ export class LookupPlugin extends FunctionPlugin implements FunctionPluginTypech
})
}
- public match(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public match(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MATCH'), (key: RawNoErrorScalarValue, rangeValue: SimpleRangeValue, sorted: number) => {
return this.doMatch(zeroIfEmpty(key), rangeValue, sorted)
})
diff --git a/src/interpreter/plugin/MathConstantsPlugin.ts b/src/interpreter/plugin/MathConstantsPlugin.ts
index 45b03e25d0..b2124c1c97 100644
--- a/src/interpreter/plugin/MathConstantsPlugin.ts
+++ b/src/interpreter/plugin/MathConstantsPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export const PI = parseFloat(Math.PI.toFixed(14))
@@ -24,13 +24,13 @@ export class MathConstantsPlugin extends FunctionPlugin implements FunctionPlugi
},
}
- public pi(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public pi(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PI'),
() => PI
)
}
- public sqrtpi(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sqrtpi(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SQRTPI'),
(arg: number) => Math.sqrt(PI*arg)
)
diff --git a/src/interpreter/plugin/MathPlugin.ts b/src/interpreter/plugin/MathPlugin.ts
index 1d6339f4a9..3784e8720d 100644
--- a/src/interpreter/plugin/MathPlugin.ts
+++ b/src/interpreter/plugin/MathPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue, RawInterpreterValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue, RawInterpreterValue} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
@@ -113,7 +113,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
},
}
- public fact(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fact(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FACT'),
(arg: number) => {
arg = Math.trunc(arg)
@@ -125,7 +125,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public factdouble(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public factdouble(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FACTDOUBLE'),
(arg: number) => {
arg = Math.trunc(arg)
@@ -138,7 +138,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public combin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public combin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COMBIN'),
(n: number, m: number) => {
if(m>n) {
@@ -150,7 +150,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public combina(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public combina(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COMBINA'),
(n: number, m: number) => {
n = Math.trunc(n)
@@ -167,7 +167,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public gcd(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gcd(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GCD'),
(...args: RawInterpreterValue[]) => {
const processedArgs = this.interpreter.arithmeticHelper.coerceNumbersCoerceRangesDropNulls(args)
@@ -190,7 +190,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public lcm(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public lcm(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LCM'),
(...args: RawInterpreterValue[]) => {
const processedArgs = this.interpreter.arithmeticHelper.coerceNumbersCoerceRangesDropNulls(args)
@@ -213,7 +213,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public mround(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public mround(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MROUND'),
(nom: number, denom: number) => {
if(denom===0) {
@@ -227,7 +227,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public multinomial(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public multinomial(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MULTINOMIAL'),
(...args: number[]) => {
let n = 0
@@ -247,7 +247,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public quotient(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public quotient(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('QUOTIENT'),
(nom: number, denom: number) => {
if(denom===0) {
@@ -258,7 +258,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public seriessum(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public seriessum(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SERIESSUM'),
(x: number, n: number, m: number, range: SimpleRangeValue) => {
const coefs = this.interpreter.arithmeticHelper.manyToOnlyNumbersDropNulls(range.valuesFromTopLeftCorner())
@@ -276,7 +276,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public sign(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sign(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SIGN'),
(arg: number) => {
if(arg>0) {
@@ -290,7 +290,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public sumx2my2(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sumx2my2(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUMX2MY2'),
(rangeX: SimpleRangeValue, rangeY: SimpleRangeValue) => {
const valsX = rangeX.valuesFromTopLeftCorner()
@@ -318,7 +318,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public sumx2py2(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sumx2py2(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUMX2PY2'),
(rangeX: SimpleRangeValue, rangeY: SimpleRangeValue) => {
const valsX = rangeX.valuesFromTopLeftCorner()
@@ -346,7 +346,7 @@ export class MathPlugin extends FunctionPlugin implements FunctionPluginTypechec
)
}
- public sumxmy2(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sumxmy2(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUMXMY2'),
(rangeX: SimpleRangeValue, rangeY: SimpleRangeValue) => {
const valsX = rangeX.valuesFromTopLeftCorner()
diff --git a/src/interpreter/plugin/MatrixPlugin.ts b/src/interpreter/plugin/MatrixPlugin.ts
index e4e17a2b51..d0cae3595b 100644
--- a/src/interpreter/plugin/MatrixPlugin.ts
+++ b/src/interpreter/plugin/MatrixPlugin.ts
@@ -36,12 +36,14 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
{argumentType: ArgumentTypes.RANGE},
{argumentType: ArgumentTypes.RANGE},
],
+ vectorizationForbidden: true,
},
'TRANSPOSE': {
method: 'transpose',
parameters: [
{argumentType: ArgumentTypes.RANGE},
],
+ vectorizationForbidden: true,
},
'MAXPOOL': {
method: 'maxpool',
@@ -50,6 +52,7 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
{argumentType: ArgumentTypes.NUMBER},
{argumentType: ArgumentTypes.NUMBER, optionalArg: true},
],
+ vectorizationForbidden: true,
},
'MEDIANPOOL': {
method: 'medianpool',
@@ -58,6 +61,7 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
{argumentType: ArgumentTypes.NUMBER},
{argumentType: ArgumentTypes.NUMBER, optionalArg: true},
],
+ vectorizationForbidden: true,
},
}
@@ -73,7 +77,7 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
}
public mmult(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('MMULT'), (leftMatrix: SimpleRangeValue, rightMatrix: SimpleRangeValue) => {
+ return this.runFunction(ast.args, state, this.metadata('MMULT'), (leftMatrix: SimpleRangeValue, rightMatrix: SimpleRangeValue) => {
if (!leftMatrix.hasOnlyNumbers() || !rightMatrix.hasOnlyNumbers()) {
return new CellError(ErrorType.VALUE, ErrorMessage.NumberRange)
}
@@ -95,7 +99,7 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
}
public maxpool(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('MAXPOOL'), (matrix: SimpleRangeValue, windowSize: number, stride: number = windowSize) => {
+ return this.runFunction(ast.args, state, this.metadata('MAXPOOL'), (matrix: SimpleRangeValue, windowSize: number, stride: number = windowSize) => {
if (!matrix.hasOnlyNumbers()) {
return new CellError(ErrorType.VALUE, ErrorMessage.NumberRange)
}
@@ -118,7 +122,7 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
}
public medianpool(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('MEDIANPOOL'), (matrix: SimpleRangeValue, windowSize: number, stride: number = windowSize) => {
+ return this.runFunction(ast.args, state, this.metadata('MEDIANPOOL'), (matrix: SimpleRangeValue, windowSize: number, stride: number = windowSize) => {
if (!matrix.hasOnlyNumbers()) {
return new CellError(ErrorType.VALUE, ErrorMessage.NumberRange)
}
@@ -183,7 +187,7 @@ export class MatrixPlugin extends FunctionPlugin implements FunctionPluginTypech
}
public transpose(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
- return this.runMatrixFunction(ast.args, state, this.metadata('TRANSPOSE'), (matrix: SimpleRangeValue) => {
+ return this.runFunction(ast.args, state, this.metadata('TRANSPOSE'), (matrix: SimpleRangeValue) => {
if (!matrix.hasOnlyNumbers()) {
return new CellError(ErrorType.VALUE, ErrorMessage.NumberRange)
}
diff --git a/src/interpreter/plugin/MedianPlugin.ts b/src/interpreter/plugin/MedianPlugin.ts
index 49e4817d63..c82468234e 100644
--- a/src/interpreter/plugin/MedianPlugin.ts
+++ b/src/interpreter/plugin/MedianPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue, RawScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue, RawScalarValue} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
@@ -48,7 +48,7 @@ export class MedianPlugin extends FunctionPlugin implements FunctionPluginTypech
* @param ast
* @param state
*/
- public median(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public median(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MEDIAN'),
(...args: RawScalarValue[]) => {
const values = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -67,7 +67,7 @@ export class MedianPlugin extends FunctionPlugin implements FunctionPluginTypech
})
}
- public large(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public large(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LARGE'),
(range: SimpleRangeValue, n: number) => {
const vals = this.interpreter.arithmeticHelper.manyToExactNumbers(range.valuesFromTopLeftCorner())
@@ -84,7 +84,7 @@ export class MedianPlugin extends FunctionPlugin implements FunctionPluginTypech
)
}
- public small(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public small(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SMALL'),
(range: SimpleRangeValue, n: number) => {
const vals = this.interpreter.arithmeticHelper.manyToExactNumbers(range.valuesFromTopLeftCorner())
diff --git a/src/interpreter/plugin/ModuloPlugin.ts b/src/interpreter/plugin/ModuloPlugin.ts
index c1a7b0ebf0..b1ae60eae9 100644
--- a/src/interpreter/plugin/ModuloPlugin.ts
+++ b/src/interpreter/plugin/ModuloPlugin.ts
@@ -6,7 +6,7 @@
import {CellError, ErrorType} from '../../Cell'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class ModuloPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -20,7 +20,7 @@ export class ModuloPlugin extends FunctionPlugin implements FunctionPluginTypech
},
}
- public mod(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public mod(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MOD'), (dividend: number, divisor: number) => {
if (divisor === 0) {
return new CellError(ErrorType.DIV_BY_ZERO)
diff --git a/src/interpreter/plugin/PowerPlugin.ts b/src/interpreter/plugin/PowerPlugin.ts
index fb55232e10..e41ad1a369 100644
--- a/src/interpreter/plugin/PowerPlugin.ts
+++ b/src/interpreter/plugin/PowerPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class PowerPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -19,7 +19,7 @@ export class PowerPlugin extends FunctionPlugin implements FunctionPluginTypeche
},
}
- public power(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public power(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('POWER'), Math.pow)
}
}
diff --git a/src/interpreter/plugin/RadiansPlugin.ts b/src/interpreter/plugin/RadiansPlugin.ts
index 4512be8cdc..35da007a02 100644
--- a/src/interpreter/plugin/RadiansPlugin.ts
+++ b/src/interpreter/plugin/RadiansPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class RadiansPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -18,7 +18,7 @@ export class RadiansPlugin extends FunctionPlugin implements FunctionPluginTypec
},
}
- public radians(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public radians(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RADIANS'),
(arg) => arg * (Math.PI / 180)
)
diff --git a/src/interpreter/plugin/RadixConversionPlugin.ts b/src/interpreter/plugin/RadixConversionPlugin.ts
index 1d87d4d08b..4e1861f2ef 100644
--- a/src/interpreter/plugin/RadixConversionPlugin.ts
+++ b/src/interpreter/plugin/RadixConversionPlugin.ts
@@ -9,7 +9,7 @@ import {padLeft} from '../../format/format'
import {Maybe} from '../../Maybe'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
const MAX_LENGTH = 10
@@ -118,25 +118,25 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
},
}
- public dec2bin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public dec2bin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DEC2BIN'),
(value, places) => decimalToBaseWithExactPadding(value, 2, places)
)
}
- public dec2oct(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public dec2oct(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DEC2OCT'),
(value, places) => decimalToBaseWithExactPadding(value, 8, places)
)
}
- public dec2hex(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public dec2hex(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DEC2HEX'),
(value, places) => decimalToBaseWithExactPadding(value, 16, places)
)
}
- public bin2dec(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bin2dec(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BIN2DEC'), (binary) => {
const binaryWithSign = coerceStringToBase(binary, 2, MAX_LENGTH)
if(binaryWithSign === undefined) {
@@ -146,7 +146,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public bin2oct(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bin2oct(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BIN2OCT'), (binary, places) => {
const binaryWithSign = coerceStringToBase(binary, 2, MAX_LENGTH)
if(binaryWithSign === undefined) {
@@ -156,7 +156,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public bin2hex(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public bin2hex(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BIN2HEX'), (binary, places) => {
const binaryWithSign = coerceStringToBase(binary, 2, MAX_LENGTH)
if(binaryWithSign === undefined) {
@@ -166,7 +166,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public oct2dec(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public oct2dec(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('OCT2DEC'), (octal) => {
const octalWithSign = coerceStringToBase(octal, 8, MAX_LENGTH)
if(octalWithSign === undefined) {
@@ -176,7 +176,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public oct2bin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public oct2bin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('OCT2BIN'), (octal, places) => {
const octalWithSign = coerceStringToBase(octal, 8, MAX_LENGTH)
if(octalWithSign === undefined) {
@@ -186,7 +186,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public oct2hex(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public oct2hex(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('OCT2HEX'), (octal, places) => {
const octalWithSign = coerceStringToBase(octal, 8, MAX_LENGTH)
if(octalWithSign === undefined) {
@@ -196,7 +196,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public hex2dec(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public hex2dec(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HEX2DEC'), (hexadecimal) => {
const hexadecimalWithSign = coerceStringToBase(hexadecimal, 16, MAX_LENGTH)
if(hexadecimalWithSign === undefined) {
@@ -206,7 +206,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public hex2bin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public hex2bin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HEX2BIN'), (hexadecimal, places) => {
const hexadecimalWithSign = coerceStringToBase(hexadecimal, 16, MAX_LENGTH)
if(hexadecimalWithSign === undefined) {
@@ -216,7 +216,7 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public hex2oct(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public hex2oct(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HEX2OCT'), (hexadecimal, places) => {
const hexadecimalWithSign = coerceStringToBase(hexadecimal, 16, MAX_LENGTH)
if(hexadecimalWithSign === undefined) {
@@ -226,11 +226,11 @@ export class RadixConversionPlugin extends FunctionPlugin implements FunctionPlu
})
}
- public base(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public base(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BASE'), decimalToBaseWithMinimumPadding)
}
- public decimal(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public decimal(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DECIMAL'), (arg, base) => {
const input = coerceStringToBase(arg, base, DECIMAL_NUMBER_OF_BITS)
if(input === undefined) {
diff --git a/src/interpreter/plugin/RandomPlugin.ts b/src/interpreter/plugin/RandomPlugin.ts
index a49185d264..457c3b7f55 100644
--- a/src/interpreter/plugin/RandomPlugin.ts
+++ b/src/interpreter/plugin/RandomPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class RandomPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -36,11 +36,11 @@ export class RandomPlugin extends FunctionPlugin implements FunctionPluginTypech
* @param ast
* @param state
*/
- public rand(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public rand(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RAND'), Math.random)
}
- public randbetween(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public randbetween(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RANDBETWEEN'),
(lower: number, upper: number) => {
if(upper{
@@ -27,7 +27,7 @@ export class RomanPlugin extends FunctionPlugin implements FunctionPluginTypeche
},
}
- public roman(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public roman(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ROMAN'),
(val: number, mode: RawScalarValue) => {
val = Math.trunc(val)
@@ -52,7 +52,7 @@ export class RomanPlugin extends FunctionPlugin implements FunctionPluginTypeche
)
}
- public arabic(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public arabic(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ARABIC'),
(inputString: string) => {
inputString = inputString.trim().toUpperCase()
diff --git a/src/interpreter/plugin/RoundingPlugin.ts b/src/interpreter/plugin/RoundingPlugin.ts
index 9db385b6c7..d6cebdfd23 100644
--- a/src/interpreter/plugin/RoundingPlugin.ts
+++ b/src/interpreter/plugin/RoundingPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export function findNextOddNumber(arg: number): number {
@@ -43,13 +43,6 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
{ argumentType: ArgumentTypes.NUMBER, defaultValue: 0},
],
},
- 'TRUNC': {
- method: 'trunc',
- parameters: [
- { argumentType: ArgumentTypes.NUMBER },
- { argumentType: ArgumentTypes.NUMBER, defaultValue: 0},
- ],
- },
'INT': {
method: 'intFunc',
parameters: [
@@ -116,9 +109,10 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
public static aliases = {
'ISO.CEILING': 'CEILING.PRECISE',
+ 'TRUNC': 'ROUNDDOWN',
}
- public roundup(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public roundup(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ROUNDDOWN'), (numberToRound: number, places: number): number => {
const placesMultiplier = Math.pow(10, places)
if (numberToRound < 0) {
@@ -129,7 +123,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public rounddown(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public rounddown(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ROUNDDOWN'), (numberToRound: number, places: number): number => {
const placesMultiplier = Math.pow(10, places)
if (numberToRound < 0) {
@@ -140,7 +134,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public round(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public round(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ROUND'), (numberToRound: number, places: number): number => {
const placesMultiplier = Math.pow(10, places)
if (numberToRound < 0) {
@@ -151,11 +145,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public trunc(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
- return this.rounddown(ast, state)
- }
-
- public intFunc(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public intFunc(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('INT'), (coercedNumberToRound) => {
if (coercedNumberToRound < 0) {
return -Math.floor(-coercedNumberToRound)
@@ -165,7 +155,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public even(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public even(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EVEN'), (coercedNumberToRound) => {
if (coercedNumberToRound < 0) {
return -findNextEvenNumber(-coercedNumberToRound)
@@ -175,7 +165,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public odd(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public odd(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ODD'), (coercedNumberToRound) => {
if (coercedNumberToRound < 0) {
return -findNextOddNumber(-coercedNumberToRound)
@@ -185,7 +175,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public ceilingmath(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ceilingmath(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CEILING.MATH'),
(value: number, significance: number, mode: number) => {
if (significance === 0 || value === 0) {
@@ -201,7 +191,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public ceiling(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ceiling(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CEILING'),
(value: number, significance: number) => {
if(value === 0) {
@@ -219,7 +209,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public ceilingprecise(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ceilingprecise(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CEILING.PRECISE'),
(value: number, significance: number) => {
if (significance === 0 || value === 0) {
@@ -230,7 +220,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public floormath(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public floormath(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FLOOR.MATH'),
(value: number, significance: number, mode: number) => {
if (significance === 0 || value === 0) {
@@ -246,7 +236,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public floor(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public floor(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FLOOR'),
(value: number, significance: number) => {
if(value === 0) {
@@ -264,7 +254,7 @@ export class RoundingPlugin extends FunctionPlugin implements FunctionPluginType
})
}
- public floorprecise(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public floorprecise(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FLOOR.PRECISE'),
(value: number, significance: number) => {
if (significance === 0 || value === 0) {
diff --git a/src/interpreter/plugin/SimpleArithmertic.ts b/src/interpreter/plugin/SimpleArithmertic.ts
index 3b0fb8690e..d6ba1cd931 100644
--- a/src/interpreter/plugin/SimpleArithmertic.ts
+++ b/src/interpreter/plugin/SimpleArithmertic.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class SimpleArithmerticPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -114,91 +114,91 @@ export class SimpleArithmerticPlugin extends FunctionPlugin implements FunctionP
},
}
- public add(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public add(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.ADD'),
this.interpreter.arithmeticHelper.addWithEpsilon
)
}
- public concat(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public concat(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.CONCAT'),
this.interpreter.arithmeticHelper.concat
)
}
- public divide(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public divide(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.DIVIDE'),
this.interpreter.arithmeticHelper.divide
)
}
- public eq(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public eq(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.EQ'),
this.interpreter.arithmeticHelper.eq
)
}
- public gt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.GT'),
this.interpreter.arithmeticHelper.gt
)
}
- public gte(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gte(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.GTE'),
this.interpreter.arithmeticHelper.geq
)
}
- public lt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public lt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.LT'),
this.interpreter.arithmeticHelper.lt
)
}
- public lte(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public lte(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.LTE'),
this.interpreter.arithmeticHelper.leq
)
}
- public minus(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public minus(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.MINUS'),
this.interpreter.arithmeticHelper.subtract
)
}
- public multiply(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public multiply(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.MULTIPLY'),
this.interpreter.arithmeticHelper.multiply
)
}
- public ne(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ne(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.NE'),
this.interpreter.arithmeticHelper.neq
)
}
- public pow(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public pow(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.POW'),
this.interpreter.arithmeticHelper.pow
)
}
- public uminus(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public uminus(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.UMINUS'),
this.interpreter.arithmeticHelper.unaryMinus
)
}
- public upercent(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public upercent(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.UNARY_PERCENT'),
this.interpreter.arithmeticHelper.unaryPercent
)
}
- public uplus(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public uplus(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HF.UPLUS'),
this.interpreter.arithmeticHelper.unaryPlus
)
diff --git a/src/interpreter/plugin/SqrtPlugin.ts b/src/interpreter/plugin/SqrtPlugin.ts
index cbb4ef3679..7b75a5fd1d 100644
--- a/src/interpreter/plugin/SqrtPlugin.ts
+++ b/src/interpreter/plugin/SqrtPlugin.ts
@@ -5,7 +5,7 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
export class SqrtPlugin extends FunctionPlugin implements FunctionPluginTypecheck{
@@ -18,7 +18,7 @@ export class SqrtPlugin extends FunctionPlugin implements FunctionPluginTypeche
},
}
- public sqrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sqrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SQRT'), Math.sqrt)
}
}
diff --git a/src/interpreter/plugin/StatisticalAggregationPlugin.ts b/src/interpreter/plugin/StatisticalAggregationPlugin.ts
index 89a30d48e7..ee72979721 100644
--- a/src/interpreter/plugin/StatisticalAggregationPlugin.ts
+++ b/src/interpreter/plugin/StatisticalAggregationPlugin.ts
@@ -7,7 +7,13 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {getRawValue, InternalScalarValue, isExtendedNumber, RawInterpreterValue} from '../InterpreterValue'
+import {
+ getRawValue,
+ InternalScalarValue,
+ InterpreterValue,
+ isExtendedNumber,
+ RawInterpreterValue
+} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {
centralF,
@@ -31,28 +37,28 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
parameters: [
{argumentType: ArgumentTypes.ANY},
],
- repeatLastArgs: 1
+ repeatLastArgs: 1,
},
'DEVSQ': {
method: 'devsq',
parameters: [
{argumentType: ArgumentTypes.ANY},
],
- repeatLastArgs: 1
+ repeatLastArgs: 1,
},
'GEOMEAN': {
method: 'geomean',
parameters: [
{argumentType: ArgumentTypes.ANY},
],
- repeatLastArgs: 1
+ repeatLastArgs: 1,
},
'HARMEAN': {
method: 'harmean',
parameters: [
{argumentType: ArgumentTypes.ANY},
],
- repeatLastArgs: 1
+ repeatLastArgs: 1,
},
'CORREL': {
method: 'correl',
@@ -132,14 +138,14 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
parameters: [
{argumentType: ArgumentTypes.ANY},
],
- repeatLastArgs: 1
+ repeatLastArgs: 1,
},
'SKEW.P': {
method: 'skewp',
parameters: [
{argumentType: ArgumentTypes.ANY},
],
- repeatLastArgs: 1
+ repeatLastArgs: 1,
},
}
public static aliases = {
@@ -154,7 +160,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
SKEWP: 'SKEW.P',
}
- public avedev(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public avedev(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('AVEDEV'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -169,7 +175,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public devsq(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public devsq(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('DEVSQ'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -183,7 +189,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public geomean(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public geomean(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GEOMEAN'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -202,7 +208,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public harmean(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public harmean(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HARMEAN'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -221,7 +227,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public correl(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public correl(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CORREL'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
if (dataX.numberOfElements() !== dataY.numberOfElements()) {
@@ -239,7 +245,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public rsq(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public rsq(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RSQ'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
if (dataX.numberOfElements() !== dataY.numberOfElements()) {
@@ -258,7 +264,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public covariancep(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public covariancep(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COVARIANCE.P'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
if (dataX.numberOfElements() !== dataY.numberOfElements()) {
@@ -280,7 +286,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public covariances(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public covariances(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COVARIANCE.S'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
if (dataX.numberOfElements() !== dataY.numberOfElements()) {
@@ -299,7 +305,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public ztest(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ztest(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('Z.TEST'),
(range: SimpleRangeValue, x: number, sigma?: number) => {
const vals = this.interpreter.arithmeticHelper.manyToExactNumbers(range.valuesFromTopLeftCorner())
@@ -324,7 +330,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
)
}
- public ftest(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ftest(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('F.TEST'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
const arrX = this.interpreter.arithmeticHelper.manyToExactNumbers(dataX.valuesFromTopLeftCorner())
@@ -349,7 +355,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public steyx(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public steyx(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('STEYX'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
if (dataX.numberOfElements() !== dataY.numberOfElements()) {
@@ -368,7 +374,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public slope(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public slope(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SLOPE'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
if (dataX.numberOfElements() !== dataY.numberOfElements()) {
@@ -387,7 +393,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public chisqtest(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public chisqtest(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHISQ.TEST'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue) => {
const r = dataX.height()
@@ -417,7 +423,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public ttest(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public ttest(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T.TEST'),
(dataX: SimpleRangeValue, dataY: SimpleRangeValue, tails: number, type: number) => {
const arrX = this.interpreter.arithmeticHelper.manyToExactNumbers(dataX.valuesFromTopLeftCorner())
@@ -473,7 +479,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public skew(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public skew(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SKEW'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
@@ -493,7 +499,7 @@ export class StatisticalAggregationPlugin extends FunctionPlugin implements Fun
})
}
- public skewp(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public skewp(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SKEW.P'),
(...args: RawInterpreterValue[]) => {
const coerced = this.interpreter.arithmeticHelper.coerceNumbersExactRanges(args)
diff --git a/src/interpreter/plugin/StatisticalPlugin.ts b/src/interpreter/plugin/StatisticalPlugin.ts
index 66fd3e00c5..8a03f037dc 100644
--- a/src/interpreter/plugin/StatisticalPlugin.ts
+++ b/src/interpreter/plugin/StatisticalPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {besseli, besselj, besselk, bessely} from './3rdparty/bessel/bessel'
import {
beta,
@@ -426,7 +426,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
POISSONDIST: 'POISSON.DIST',
}
- public erf(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public erf(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ERF'), (lowerBound, upperBound) => {
if (upperBound === undefined) {
return erf(lowerBound)
@@ -436,12 +436,12 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
})
}
- public erfc(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public erfc(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ERFC'), erfc)
}
- public expondist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public expondist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EXPON.DIST'),
(x: number, lambda: number, cumulative: boolean) => {
if(cumulative) {
@@ -453,23 +453,23 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public fisher(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fisher(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FISHER'),
(x: number) => Math.log((1 + x) / (1 - x)) / 2
)
}
- public fisherinv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fisherinv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FISHERINV'),
(y: number) => 1 - 2 / (Math.exp(2 * y) + 1)
)
}
- public gamma(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gamma(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GAMMA'), gammafn)
}
- public gammadist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gammadist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GAMMA.DIST'),
(value: number, alphaVal: number, betaVal: number, cumulative: boolean) => {
if(cumulative) {
@@ -481,21 +481,21 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public gammaln(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gammaln(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GAMMALN'), gammaln)
}
- public gammainv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gammainv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GAMMA.INV'), gamma.inv)
}
- public gauss(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public gauss(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('GAUSS'),
(z: number) => normal.cdf(z, 0, 1) - 0.5
)
}
- public betadist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public betadist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BETA.DIST'),
(x: number, alphaVal: number, betaVal: number, cumulative: boolean, A: number, B: number) => {
if(x<=A) {
@@ -513,7 +513,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public betainv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public betainv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BETA.INV'),
(x: number, alphaVal: number, betaVal: number, A: number, B: number) => {
if (A >= B) {
@@ -525,7 +525,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public binomialdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public binomialdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BINOM.DIST'),
(succ: number, trials: number, prob: number, cumulative: boolean) => {
if(succ>trials) {
@@ -542,7 +542,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public binomialinv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public binomialinv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BINOM.INV'),
(trials: number, prob: number, alpha: number) => {
trials = Math.trunc(trials)
@@ -561,31 +561,31 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public besselifn(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public besselifn(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BESSELI'),
(x: number, n: number) => besseli(x, Math.trunc(n))
)
}
- public besseljfn(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public besseljfn(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BESSELJ'),
(x: number, n: number) => besselj(x, Math.trunc(n))
)
}
- public besselkfn(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public besselkfn(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BESSELK'),
(x: number, n: number) => besselk(x, Math.trunc(n))
)
}
- public besselyfn(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public besselyfn(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('BESSELY'),
(x: number, n: number) => bessely(x, Math.trunc(n))
)
}
- public chisqdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public chisqdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHISQ.DIST'),
(x: number, deg: number, cumulative: boolean) => {
deg = Math.trunc(deg)
@@ -598,25 +598,25 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public chisqdistrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public chisqdistrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHISQ.DIST.RT'),
(x: number, deg: number) => 1 - chisquare.cdf(x, Math.trunc(deg))
)
}
- public chisqinv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public chisqinv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHISQ.INV'),
(p: number, deg: number) => chisquare.inv(p, Math.trunc(deg))
)
}
- public chisqinvrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public chisqinvrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CHISQ.INV.RT'),
(p: number, deg: number) => chisquare.inv(1.0 - p, Math.trunc(deg))
)
}
- public fdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('F.DIST'),
(x: number, deg1: number, deg2: number, cumulative: boolean) => {
deg1 = Math.trunc(deg1)
@@ -630,26 +630,26 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public fdistrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public fdistrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('F.DIST.RT'),
(x: number, deg1: number, deg2: number) => 1 - centralF.cdf(x, Math.trunc(deg1), Math.trunc(deg2))
)
}
- public finv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public finv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('F.INV'),
(p: number, deg1: number, deg2: number) => centralF.inv(p, Math.trunc(deg1), Math.trunc(deg2))
)
}
- public finvrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public finvrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('F.INV.RT'),
(p: number, deg1: number, deg2: number) => centralF.inv(1.0 - p, Math.trunc(deg1), Math.trunc(deg2))
)
}
- public weibulldist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public weibulldist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('WEIBULL.DIST'),
(x: number, shape: number, scale: number, cumulative: boolean) => {
if(cumulative) {
@@ -661,7 +661,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public poissondist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public poissondist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('POISSON.DIST'),
(x: number, mean: number, cumulative: boolean) => {
x = Math.trunc(x)
@@ -674,7 +674,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public hypgeomdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public hypgeomdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('HYPGEOM.DIST'),
(s: number, numberS: number, populationS: number, numberPop: number, cumulative: boolean) => {
if(s > numberS || s > populationS || numberS > numberPop || populationS > numberPop) {
@@ -697,7 +697,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public tdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T.DIST'),
(x: number, deg: number, cumulative: boolean) => {
deg = Math.trunc(deg)
@@ -710,37 +710,37 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public tdist2t(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tdist2t(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T.DIST.2T'),
(x: number, deg: number) => (1 - studentt.cdf(x, Math.trunc(deg))) * 2
)
}
- public tdistrt(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tdistrt(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T.DIST.RT'),
(x: number, deg: number) => 1 - studentt.cdf(x, Math.trunc(deg))
)
}
- public tdistold(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tdistold(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TDIST'),
(x: number, deg: number, mode: number) => mode*(1 - studentt.cdf(x, Math.trunc(deg)))
)
}
- public tinv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tinv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T.INV'),
(p: number, deg: number) => studentt.inv(p, Math.trunc(deg))
)
}
- public tinv2t(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tinv2t(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T.INV.2T'),
(p: number, deg: number) => studentt.inv(1-p/2, Math.trunc(deg))
)
}
- public lognormdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public lognormdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LOGNORM.DIST'),
(x: number, mean: number, stddev: number, cumulative: boolean) => {
if(cumulative) {
@@ -752,13 +752,13 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public lognorminv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public lognorminv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LOGNORM.INV'),
(p: number, mean: number, stddev: number) => lognormal.inv(p, mean, stddev)
)
}
- public normdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public normdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NORM.DIST'),
(x: number, mean: number, stddev: number, cumulative: boolean) => {
if(cumulative) {
@@ -770,13 +770,13 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public norminv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public norminv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NORM.INV'),
(p: number, mean: number, stddev: number) => normal.inv(p, mean, stddev)
)
}
- public normsdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public normsdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NORM.S.DIST'),
(x: number, cumulative: boolean) => {
if(cumulative) {
@@ -788,19 +788,19 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public normsinv(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public normsinv(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NORM.S.INV'),
(p: number) => normal.inv(p, 0, 1)
)
}
- public phi(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public phi(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PHI'),
(x: number) => normal.pdf(x, 0, 1)
)
}
- public negbinomdist(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public negbinomdist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('NEGBINOM.DIST'),
(nf: number, ns: number, p: number, cumulative: boolean) => {
nf = Math.trunc(nf)
@@ -814,7 +814,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public confidencenorm(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public confidencenorm(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CONFIDENCE.NORM'),
// eslint-disable-next-line
// @ts-ignore
@@ -822,7 +822,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public confidencet(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public confidencet(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CONFIDENCE.T'),
(alpha: number, stddev: number, size: number) => {
size = Math.trunc(size)
@@ -836,7 +836,7 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public standardize(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public standardize(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('STANDARDIZE'),
(x: number, mean: number, stddev: number) => (x-mean)/stddev
)
diff --git a/src/interpreter/plugin/SumifPlugin.ts b/src/interpreter/plugin/SumifPlugin.ts
index b42100c63a..1c5c57a763 100644
--- a/src/interpreter/plugin/SumifPlugin.ts
+++ b/src/interpreter/plugin/SumifPlugin.ts
@@ -9,7 +9,7 @@ import {Maybe} from '../../Maybe'
import {ProcedureAst} from '../../parser'
import {Condition, CriterionFunctionCompute} from '../CriterionFunctionCompute'
import {InterpreterState} from '../InterpreterState'
-import {getRawValue, InternalScalarValue, isExtendedNumber, RawScalarValue} from '../InterpreterValue'
+import {getRawValue, InternalScalarValue, InterpreterValue, isExtendedNumber, RawScalarValue} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
@@ -113,7 +113,7 @@ export class SumifPlugin extends FunctionPlugin implements FunctionPluginTypeche
* @param ast
* @param state
*/
- public sumif(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sumif(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUMIF'),
(conditionArg: SimpleRangeValue, criterionValue: RawScalarValue, valuesArg: Maybe) => {
const criterion = this.interpreter.criterionBuilder.fromCellValue(criterionValue, this.interpreter.arithmeticHelper)
@@ -134,7 +134,7 @@ export class SumifPlugin extends FunctionPlugin implements FunctionPluginTypeche
)
}
- public sumifs(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sumifs(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUMIFS'), (values: SimpleRangeValue, ...args) => {
const conditions: Condition[] = []
for (let i = 0; i < args.length; i += 2) {
@@ -156,7 +156,7 @@ export class SumifPlugin extends FunctionPlugin implements FunctionPluginTypeche
})
}
- public averageif(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public averageif(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('AVERAGEIF'),
(conditionArg: SimpleRangeValue, criterionValue: RawScalarValue, valuesArg: Maybe) => {
const criterion = this.interpreter.criterionBuilder.fromCellValue(criterionValue, this.interpreter.arithmeticHelper)
@@ -199,7 +199,7 @@ export class SumifPlugin extends FunctionPlugin implements FunctionPluginTypeche
* @param ast
* @param state
*/
- public countif(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public countif(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COUNTIF'),
(conditionArg: SimpleRangeValue, criterionValue: RawScalarValue) => {
const criterion = this.interpreter.criterionBuilder.fromCellValue(criterionValue, this.interpreter.arithmeticHelper)
@@ -218,7 +218,7 @@ export class SumifPlugin extends FunctionPlugin implements FunctionPluginTypeche
)
}
- public countifs(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public countifs(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COUNTIFS'), (...args) => {
const conditions: Condition[] = []
for (let i = 0; i < args.length; i += 2) {
diff --git a/src/interpreter/plugin/SumprodPlugin.ts b/src/interpreter/plugin/SumprodPlugin.ts
index 2ce06cfd93..2d7bbd4cc4 100644
--- a/src/interpreter/plugin/SumprodPlugin.ts
+++ b/src/interpreter/plugin/SumprodPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {getRawValue, InternalScalarValue, isExtendedNumber} from '../InterpreterValue'
+import {getRawValue, InternalScalarValue, InterpreterValue, isExtendedNumber} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
@@ -22,7 +22,7 @@ export class SumprodPlugin extends FunctionPlugin implements FunctionPluginTypec
},
}
- public sumproduct(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sumproduct(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUMPRODUCT'), (left: SimpleRangeValue, right: SimpleRangeValue) => {
if (left.numberOfElements() !== right.numberOfElements()) {
return new CellError(ErrorType.VALUE, ErrorMessage.EqualLength)
diff --git a/src/interpreter/plugin/TextPlugin.ts b/src/interpreter/plugin/TextPlugin.ts
index 8323007ccf..316b803633 100644
--- a/src/interpreter/plugin/TextPlugin.ts
+++ b/src/interpreter/plugin/TextPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue, RawScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue, RawScalarValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
/**
@@ -152,7 +152,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
* @param ast
* @param state
*/
- public concatenate(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public concatenate(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CONCATENATE'), (...args) => {
return ''.concat(...args)
})
@@ -166,7 +166,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
* @param ast
* @param state
*/
- public split(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public split(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SPLIT'), (stringToSplit: string, indexToUse: number) => {
const splittedString = stringToSplit.split(' ')
@@ -178,44 +178,44 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public len(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public len(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LEN'), (arg: string) => {
return arg.length
})
}
- public lower(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public lower(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LOWER'), (arg: string) => {
return arg.toLowerCase()
})
}
- public trim(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public trim(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TRIM'), (arg: string) => {
return arg.replace(/^ +| +$/g, '').replace(/ +/g, ' ')
})
}
- public proper(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public proper(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('PROPER'), (arg: string) => {
return arg.replace(/\w\S*/g, word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase())
})
}
- public clean(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public clean(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CLEAN'), (arg: string) => {
// eslint-disable-next-line no-control-regex
return arg.replace(/[\u0000-\u001F]/g, '')
})
}
- public exact(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public exact(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('EXACT'), (left: string, right: string) => {
return left === right
})
}
- public rept(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public rept(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('REPT'), (text: string, count: number) => {
if (count < 0) {
return new CellError(ErrorType.VALUE, ErrorMessage.NegativeCount)
@@ -224,7 +224,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public right(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public right(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('RIGHT'), (text: string, length: number) => {
if (length < 0) {
return new CellError(ErrorType.VALUE, ErrorMessage.NegativeLength)
@@ -235,7 +235,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public left(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public left(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('LEFT'), (text: string, length: number) => {
if (length < 0) {
return new CellError(ErrorType.VALUE, ErrorMessage.NegativeLength)
@@ -244,7 +244,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public mid(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public mid(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('MID'), (text: string, startPosition: number, numberOfChars: number) => {
if (startPosition < 1) {
return new CellError(ErrorType.VALUE, ErrorMessage.LessThanOne)
@@ -256,7 +256,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public replace(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public replace(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('REPLACE'), (text: string, startPosition: number, numberOfChars: number, newText: string) => {
if (startPosition < 1) {
return new CellError(ErrorType.VALUE, ErrorMessage.LessThanOne)
@@ -268,7 +268,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public search(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public search(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SEARCH'), (pattern, text: string, startIndex: number) => {
if (startIndex < 1 || startIndex > text.length) {
return new CellError(ErrorType.VALUE, ErrorMessage.LengthBounds)
@@ -288,7 +288,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public substitute(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public substitute(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SUBSTITUTE'), (text: string, oldText: string, newText: string, occurrence: number | undefined) => {
const oldTextRegexp = new RegExp(oldText, 'g')
@@ -312,7 +312,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public find(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public find(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('FIND'), (pattern, text: string, startIndex: number) => {
if (startIndex < 1 || startIndex > text.length) {
return new CellError(ErrorType.VALUE, ErrorMessage.IndexBounds)
@@ -325,7 +325,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public t(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public t(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('T'), (arg: RawScalarValue) => {
if (arg instanceof CellError) {
return arg
@@ -334,7 +334,7 @@ export class TextPlugin extends FunctionPlugin implements FunctionPluginTypechec
})
}
- public upper(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public upper(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('UPPER'), (arg: string) => {
return arg.toUpperCase()
})
diff --git a/src/interpreter/plugin/TrigonometryPlugin.ts b/src/interpreter/plugin/TrigonometryPlugin.ts
index 2d0e55fd0a..89db32d532 100644
--- a/src/interpreter/plugin/TrigonometryPlugin.ts
+++ b/src/interpreter/plugin/TrigonometryPlugin.ts
@@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
-import {InternalScalarValue} from '../InterpreterValue'
+import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {PI} from './MathConstantsPlugin'
@@ -154,31 +154,31 @@ export class TrigonometryPlugin extends FunctionPlugin implements FunctionPlugin
* @param ast
* @param state
*/
- public acos(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public acos(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ACOS'), Math.acos)
}
- public asin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public asin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ASIN'), Math.asin)
}
- public cos(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public cos(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COS'), Math.cos)
}
- public sin(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sin(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SIN'), Math.sin)
}
- public tan(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tan(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TAN'), Math.tan)
}
- public atan(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public atan(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ATAN'), Math.atan)
}
- public atan2(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public atan2(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ATAN2'),
(x: number, y: number) => {
if(x===0 && y===0) {
@@ -189,73 +189,73 @@ export class TrigonometryPlugin extends FunctionPlugin implements FunctionPlugin
)
}
- public cot(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public cot(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COT'),
(arg) => (arg === 0) ? new CellError(ErrorType.DIV_BY_ZERO) : (1 / Math.tan(arg))
)
}
- public acot(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public acot(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ACOT'),
(arg) => (arg === 0) ? PI/2 : Math.atan(1/arg)
)
}
- public sec(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sec(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SEC'),
(arg: number) => 1 / Math.cos(arg)
)
}
- public csc(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public csc(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CSC'),
(arg) => (arg === 0) ? new CellError(ErrorType.DIV_BY_ZERO) : (1 / Math.sin(arg))
)
}
- public sinh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sinh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SINH'), Math.sinh)
}
- public asinh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public asinh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ASINH'), Math.asinh)
}
- public cosh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public cosh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COSH'), Math.cosh)
}
- public acosh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public acosh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ACOSH'), Math.acosh)
}
- public tanh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public tanh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('TANH'), Math.tanh)
}
- public atanh(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public atanh(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ATANH'), Math.atanh)
}
- public coth(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public coth(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('COTH'),
(arg) => (arg === 0) ? new CellError(ErrorType.DIV_BY_ZERO) : (1 / Math.tanh(arg))
)
}
- public acoth(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public acoth(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ACOTH'),
(arg) => (arg === 0) ? new CellError(ErrorType.NUM, ErrorMessage.NonZero) : Math.atanh(1/arg)
)
}
- public sech(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public sech(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('SECH'),
(arg: number) => 1 / Math.cosh(arg)
)
}
- public csch(ast: ProcedureAst, state: InterpreterState): InternalScalarValue {
+ public csch(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('CSCH'),
(arg) => (arg === 0) ? new CellError(ErrorType.DIV_BY_ZERO) : (1 / Math.sinh(arg))
)
diff --git a/src/parser/FormulaParser.ts b/src/parser/FormulaParser.ts
index 0867093b17..3a873c0a12 100644
--- a/src/parser/FormulaParser.ts
+++ b/src/parser/FormulaParser.ts
@@ -766,6 +766,9 @@ export class FormulaParser extends EmbeddedActionsParser {
return buildParenthesisAst(expression, lParenToken.leadingWhitespace, rParenToken.leadingWhitespace)
})
+
+
+
/**
* Returns {@link CellReferenceAst} or {@link CellRangeAst} based on OFFSET function arguments
*
diff --git a/test/arrays.spec.ts b/test/arrays.spec.ts
index 9687b36b0c..0d2928631f 100644
--- a/test/arrays.spec.ts
+++ b/test/arrays.spec.ts
@@ -249,3 +249,75 @@ describe('array parsing', () => {
expect(engine.getSheetValues(0)).toEqual([[1, 2, 3, 4], [5, 14, 16, -11], [6, 18, 20, -12], [13, 14, 15, 16]])
})
})
+
+describe('vectorization', () => {
+ it('1 arg function row', () => {
+ const engine = HyperFormula.buildFromArray([['=ABS({-2,-1,1,2})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[2, 1, 1, 2]])
+ })
+
+ it('1 arg function column', () => {
+ const engine = HyperFormula.buildFromArray([['=ABS({2;-2})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[2], [2]])
+ })
+
+ it('1 arg function square', () => {
+ const engine = HyperFormula.buildFromArray([['=ABS({1,2;-1,-2})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[1, 2], [1, 2]])
+ })
+
+ it('1 arg function no flag - should cast to scalar', () => {
+ const engine = HyperFormula.buildFromArray([['=ABS({-2,-1,1,2})']], {useArrayArithmetic: false})
+ expect(engine.getSheetValues(0)).toEqual([[2]])
+ })
+
+ it('multi arg function', () => {
+ const engine = HyperFormula.buildFromArray([['=DATE({1,2},1,1)']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[367, 732]])
+ })
+
+ it('multi arg function #2', () => {
+ const engine = HyperFormula.buildFromArray([['=DATE({1,2},{1,2},{1,2})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[367, 764]])
+ })
+
+ it('multi arg function #3', () => {
+ const engine = HyperFormula.buildFromArray([['=DATE({1,2},{1;2},{1})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[367, 732], [398, 763]])
+ })
+
+ it('multi arg function #4', () => {
+ const engine = HyperFormula.buildFromArray([['=DATE({1,2},{1,2,3},{1})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[367, 763, detailedError(ErrorType.VALUE, ErrorMessage.InvalidDate)]])
+ })
+
+ it('mixed types', () => {
+ const engine = HyperFormula.buildFromArray([['=ZTEST({1,2,1},{2;3})']], {useArrayArithmetic: true})
+ const val = engine.getSheetValues(0)
+ expect(val.length).toEqual(2)
+ expect(val[0].length).toEqual(1)
+ expect(val[1].length).toEqual(1)
+ })
+
+ it('no vectorization here #1', () => {
+ const engine = HyperFormula.buildFromArray([['=SUM({1,2,1},{2;3})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[9]])
+ })
+
+ it('no vectorization here #2', () => {
+ const engine = HyperFormula.buildFromArray([['=AND({TRUE(),FALSE()},{TRUE();FALSE()})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[false]])
+ })
+
+ it('vectorize with defaults', () => {
+ const engine = HyperFormula.buildFromArray([['=IF({TRUE(),FALSE()},{1;2;3}, {2;3})']], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[1, 2], [2, 3], [3, false]])
+ })
+
+ it('should work with switch', () => {
+ const engine = HyperFormula.buildFromArray([
+ ['=SWITCH({1,2,3},1,2,3,4,5)']
+ ], {useArrayArithmetic: true})
+ expect(engine.getSheetValues(0)).toEqual([[2, 5, 4]])
+ })
+})
diff --git a/test/interpreter/aliases.spec.ts b/test/interpreter/aliases.spec.ts
index 6de40e1362..76800ba875 100644
--- a/test/interpreter/aliases.spec.ts
+++ b/test/interpreter/aliases.spec.ts
@@ -203,4 +203,8 @@ describe('Function aliases', () => {
it('ISO.CEILING should be an alias of CEILING.PRECISE', () => {
expect(engine.getFunctionPlugin('ISO.CEILING')!.aliases!['ISO.CEILING']).toEqual('CEILING.PRECISE')
})
+
+ it('TRUNC should be an alias of ROUNDDOWN', () => {
+ expect(engine.getFunctionPlugin('TRUNC')!.aliases!['TRUNC']).toEqual('ROUNDDOWN')
+ })
})
diff --git a/test/interpreter/function-switch.spec.ts b/test/interpreter/function-switch.spec.ts
index 2019a0790b..eeda8ac9b1 100644
--- a/test/interpreter/function-switch.spec.ts
+++ b/test/interpreter/function-switch.spec.ts
@@ -21,14 +21,6 @@ describe('Interpreter - SWITCH function', () => {
expect(engine.getCellValue(adr('C1'))).toEqualError(detailedError(ErrorType.NA, ErrorMessage.NoDefault))
})
- it('Should work with arrays', () => {
- const engine = HyperFormula.buildFromArray([
- [1, 2, 3],
- ['=SWITCH(A1:C1,1,2,3,4,5)']
- ], {useArrayArithmetic: false})
- expect(engine.getSheetValues(0)).toEqual([[1, 2, 3], [2, 5, 4]])
- })
-
it('Should work with precision', () => {
const engine = HyperFormula.buildFromArray([
['1', '1.0000000001', '3', '1.0000000000001', '5'],
diff --git a/test/interpreter/function-trunc.spec.ts b/test/interpreter/function-trunc.spec.ts
deleted file mode 100644
index a741b4e38f..0000000000
--- a/test/interpreter/function-trunc.spec.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import {HyperFormula} from '../../src'
-import {ErrorType} from '../../src/Cell'
-import {ErrorMessage} from '../../src/error-message'
-import {adr, detailedError} from '../testUtils'
-
-describe('Function TRUNC', () => {
- it('number of arguments', () => {
- const engine = HyperFormula.buildFromArray([
- ['=TRUNC()', '=TRUNC(1, 2, 3)'],
- ])
-
- expect(engine.getCellValue(adr('A1'))).toEqualError(detailedError(ErrorType.NA, ErrorMessage.WrongArgNumber))
- expect(engine.getCellValue(adr('B1'))).toEqualError(detailedError(ErrorType.NA, ErrorMessage.WrongArgNumber))
- })
-
- it('works for positive numbers', () => {
- const engine = HyperFormula.buildFromArray([
- ['=TRUNC(1.3)', '=TRUNC(1.7)'],
- ])
-
- expect(engine.getCellValue(adr('A1'))).toBe(1)
- expect(engine.getCellValue(adr('B1'))).toBe(1)
- })
-
- it('works for negative numbers', () => {
- const engine = HyperFormula.buildFromArray([
- ['=TRUNC(-1.3)', '=TRUNC(-1.7)'],
- ])
-
- expect(engine.getCellValue(adr('A1'))).toBe(-1)
- expect(engine.getCellValue(adr('B1'))).toBe(-1)
- })
-
- it('works with positive rounding argument', () => {
- const engine = HyperFormula.buildFromArray([
- ['=TRUNC(1.43, 1)', '=TRUNC(1.47, 1)'],
- ])
-
- expect(engine.getCellValue(adr('A1'))).toBe(1.4)
- expect(engine.getCellValue(adr('B1'))).toBe(1.4)
- })
-
- it('works with negative rounding argument', () => {
- const engine = HyperFormula.buildFromArray([
- ['=TRUNC(43, -1)', '=TRUNC(47, -1)'],
- ])
-
- expect(engine.getCellValue(adr('A1'))).toBe(40)
- expect(engine.getCellValue(adr('B1'))).toBe(40)
- })
-
- it('use coercion', () => {
- const engine = HyperFormula.buildFromArray([
- ['=TRUNC("42.3")'],
- ])
-
- expect(engine.getCellValue(adr('A1'))).toBe(42)
- })
-
- it('propagates error', () => {
- const engine = HyperFormula.buildFromArray([
- ['=4/0'],
- ['=TRUNC(A1)', '=TRUNC(42, A1)', '=TRUNC(A1, FOO())'],
- ])
-
- expect(engine.getCellValue(adr('A2'))).toEqualError(detailedError(ErrorType.DIV_BY_ZERO))
- expect(engine.getCellValue(adr('B2'))).toEqualError(detailedError(ErrorType.DIV_BY_ZERO))
- expect(engine.getCellValue(adr('C2'))).toEqualError(detailedError(ErrorType.DIV_BY_ZERO))
- })
-})