From 0b0f184f7efe90bd6a29ff94bda165952ac14152 Mon Sep 17 00:00:00 2001 From: John Brinkman Date: Mon, 10 Nov 2025 20:13:25 -0500 Subject: [PATCH 1/3] Release 2.0.0 --- README.md | 7 +- .../json-formula-specification-2.0.0.html | 8278 +++++++++++++++++ .../json-formula-specification-2.0.0.pdf | Bin 0 -> 1382935 bytes package.json | 2 +- 4 files changed, 8280 insertions(+), 7 deletions(-) create mode 100644 doc/output/json-formula-specification-2.0.0.html create mode 100644 doc/output/json-formula-specification-2.0.0.pdf diff --git a/README.md b/README.md index 338fb0e7..90f301fb 100644 --- a/README.md +++ b/README.md @@ -46,13 +46,8 @@ Given: Visit the [Playground](https://opensource.adobe.com/json-formula/dist/index.html) # Documentation -Specification / Reference: [HTML](https://opensource.adobe.com/json-formula/doc/output/json-formula-specification-1.1.2.html) / [PDF](https://opensource.adobe.com/json-formula/doc/output/json-formula-specification-1.1.2.pdf) +Specification / Reference: [HTML](https://opensource.adobe.com/json-formula/doc/output/json-formula-specification-2.0.0.html) / [PDF](https://opensource.adobe.com/json-formula/doc/output/json-formula-specification-2.0.0.pdf) [JavaScript API](./doc/output/JSDOCS.md) [Developer Instructions](./DEVELOPMENT.md) - -# Beta 2.0.0 Documentation -[HTML](https://opensource.adobe.com/json-formula/doc/output/json-formula-specification-2.0.0-beta.1.html) -[PDF](https://opensource.adobe.com/json-formula/doc/output/json-formula-specification-2.0.0-beta.1.pdf) - diff --git a/doc/output/json-formula-specification-2.0.0.html b/doc/output/json-formula-specification-2.0.0.html new file mode 100644 index 00000000..35c7df89 --- /dev/null +++ b/doc/output/json-formula-specification-2.0.0.html @@ -0,0 +1,8278 @@ + + + + + + + + +json-formula Specification + + + + + +
+ +
+

Scope

+
+
+

This document is the specification for json-formula, an expression grammar that operates on JSON (JavaScript Object Notation) documents. The referenced JSON documents and JSON literals must conform to RFC 8259.

+
+
+

The grammar borrows from

+
+
+
    +
  • +

    OpenFormula for spreadsheet operators and function

    +
  • +
  • +

    JMESPath for JSON query semantics

    +
  • +
+
+
+

The intended audience are both end-users of json-formula as well as implementors; the contents are then both a user guide and a specification.

+
+
+
+
+

1. Notation

+
+
+

In the specification, examples are shown through the use of a search function. The syntax for this function is:

+
+
+
+
eval(<json-formula expr>, <JSON document>) -> <return value>
+
+
+
+

For simplicity, the json-formula expression and the JSON document are not quoted. For example:

+
+
+
+
eval(foo, {"foo": "bar"}) -> "bar"
+
+
+
+

The result of applying a json-formula expression against a JSON document will result in valid JSON, provided there are no errors during the evaluation process.

+
+
+
+
+

2. Data Types

+
+
+

json-formula supports all the JSON types:

+
+
+
    +
  • +

    number: All numbers are internally represented as double-precision floating-point

    +
  • +
  • +

    string

    +
  • +
  • +

    boolean: true or false

    +
  • +
  • +

    array: an ordered, sequence of values

    +
  • +
  • +

    object: an unordered collection of key value pairs

    +
  • +
  • +

    null

    +
  • +
+
+
+

There is an additional type that is not a JSON type that’s used in +json-formula functions:

+
+
+
    +
  • +

    expression: A string prefixed with an ampersand (&) character

    +
  • +
+
+
+

This specification uses the term "scalar" to refer to any value that is not an array, object or expression. Scalars include numbers, strings, booleans, and null values.

+
+
+

2.1. Type Coercion

+
+

If the supplied data is not correct for the execution context, json-formula will attempt to coerce the data to the correct type. Coercion will occur in these contexts:

+
+
+
    +
  • +

    Operands of the concatenation operator (&) shall be coerced to a string, except when an operand is an array. Arrays shall be coerced to an array of strings.

    +
  • +
  • +

    Operands of numeric operators (+, -, *, /) shall be coerced to numbers except when the operand is an array. Arrays shall be coerced to an array of numbers.

    +
  • +
  • +

    Operands of the union operator (~) shall be coerced to an array

    +
  • +
  • +

    The left-hand operand of ordering comparison operators (>, >=, <, <=) must be a string or number. Any other type shall be coerced to a number.

    +
  • +
  • +

    If the operands of an ordering comparison are different, they shall both be coerced to a number

    +
  • +
  • +

    Parameters to functions shall be coerced when there is a single viable coercion available. For example, if a null value is provided to a function that accepts a number or string, then coercion shall not happen, since a null value can be coerced to both types. Conversely if a string is provided to a function that accepts a number or array of numbers, then the string shall be coerced to a number, since there is no supported coercion to convert it to an array of numbers.

    +
  • +
+
+
+

The equality and inequality operators (=, ==, !=, <>) do not perform type coercion. If operands are different types, the values are considered not equal.

+
+
+

If an ordering comparison requires coercion, and the coercion is not possible (including the case where a string cannot be coerced to a number), the comparison will return false. e.g., {a: 12} < 12 and "12a" < 13 will each return false.

+
+
+

In all cases except ordering comparison, if the coercion is not possible, a TypeError error shall be raised.

+
+

Examples

+
+
+
    eval("abc" & 123, {}) -> "abc123"
+    eval("123" * 2, {}) -> 246
+    eval([1,2,3] ~ 4, {}) -> [1,2,3,4]
+    eval(123 < "124", {}) -> true
+    eval("23" > 111, {}) -> false
+    eval(avgA(["2", "3", "4"]), {}) -> 3
+    eval(1 == "1", {}) -> false
+
+
+
+
+

2.2. Type Coercion Rules

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Provided TypeExpected TypeResult

number

string

number converted to a string, following the JavaScript toString() rules.

boolean

string

"true" or "false"

array

string

Not supported

object

string

Not supported

null

string

"" (empty string)

string

number

Parse the string to a number. An empty string converts to zero. If the string is not a well-formed number, the coercion will fail.

boolean

number

true → 1 false → 0

array

number

Not supported

object

number

Not supported

null

number

0

number

array

create a single-element array with the number

string

array

create a single-element array with the string

boolean

array

create a single-element array with the boolean

object

array

Not supported

null

array

Not supported

number

object

Not supported

string

object

Not supported

boolean

object

Not supported

array

object

Not supported. Use: fromEntries(entries(array))

null

object

Not supported

number

boolean

zero is false, all other numbers are true

string

boolean

Empty string is false, populated strings are true

array

boolean

Empty array is false, populated arrays are true

object

boolean

Empty object is false, populated objects are true

null

boolean

false

+
+

An array may be coerced to another type of array as long as there is a supported coercion for the array content. For example, just as a string can be coerced to a number, an array of strings may be coerced to an array of numbers.

+
+
+

Note that while strings, numbers and booleans may be coerced to arrays, they may not be coerced to a different type within that array. For example, a number cannot be coerced to an array of strings — even though a number can be coerced to a string, and a string can be coerced to an array of strings.

+
+

Examples

+
+
+
    eval("\"$123.00\" + 1", {}) -> TypeError
+    eval("truth is " & `true`, {}) -> "truth is true"
+    eval(2 + `true`, {}) -> 3
+    eval(minA(["20", "30"]), {}) -> 20
+
+
+
+
+

2.3. Date and Time Values

+
+

In order to support date and time functions, json-formula represents date and time values as numbers where:

+
+
+
    +
  • +

    The integral portion of the number represents the number of days since the epoch: January 1, 1970, UTC

    +
  • +
  • +

    The fractional portion of the number represents the fractional portion of the day

    +
  • +
  • +

    The date/time value is offset from the current time zone to UTC

    +
  • +
  • +

    The current time zone is determined by the host operating system

    +
  • +
+
+
+

The preferred ways to create a date/time value are by using one of these functions:

+
+
+ +
+
+

Functions that operate on a date/time value will convert the date/time value back to the local time zone.

+
+

Examples

+
+
+
    eval(datetime(1970,1,2,0,0,0) - datetime(1970,1,1,0,0,0), {}) -> 1
+    eval(datetime(2010,1,21,12,0,0) |
+      {month: month(@), day: day(@), hour: hour(@)}, {}) ->
+        {"month": 1, "day": 21, "hour": 12}
+
+
+
+
+

2.4. Integers

+
+

Some functions and operators accept numeric parameters that are expected to be integers. In these contexts, if a non-numeric or non-integer value is provided, it will be coerced to a number and then truncated. The specific truncation behaviour is to remove any fractional value without rounding.

+
+
+
+

2.5. Floating Point Precision

+
+

Numbers are represented in double-precision floating-point format. As with any system that uses this level of precision, results of expressions may be off by a tiny fraction. e.g. +10 * 1.44 → 14.399999999999999

+
+
+

Authors should mitigate this behavior:

+
+
+
    +
  • +

    When comparing fractional results, do not compare for exact equality. Instead, compare within a range. e.g.: instead of: a == b, use: abs(a-b) < 0.000001

    +
  • +
  • +

    leverage the built-in functions that manipulate fractional values:

    +
    + +
    +
  • +
+
+
+
+
+
+

3. Errors

+
+
+

Errors may be raised during the json-formula evaluation process. +The following errors are defined:

+
+
+
    +
  • +

    EvaluationError is raised when an unexpected runtime condition occurs. For example, divide by zero.

    +
  • +
  • +

    FunctionError is raised when an unknown function is encountered or when a function receives invalid arguments.

    +
  • +
  • +

    SyntaxError is raised when the supplied expression does not conform to the json-formula grammar.

    +
  • +
  • +

    TypeError is raised when coercion is required for the current evaluation context, but the coercion is not possible.

    +
  • +
+
+
+
+
+

4. Grammar

+
+
+

The grammar is specified using Antlr. For a machine-readable version of the grammar, see the grammar.g4 file in the source repository.

+
+
+
+
grammar JsonFormula;
+
+formula : expression EOF ;
+
+expression
+  : '(' expression ')' 
+  | expression bracketExpression 
+  | bracketExpression 
+  | objectExpression 
+  | expression '.' chainedExpression 
+  | '!' expression 
+  | '-' expression 
+  | expression ('*' | '/') expression	
+  | expression ('+' | '-' | '~') expression	
+  | expression '&' expression	
+  | expression COMPARATOR expression 
+  | expression '&&' expression 
+  | expression '||' expression 
+  | expression '|' expression 
+  | identifier 
+  | wildcard 
+  | arrayExpression 
+  | JSON_LITERAL 
+  | functionExpression 
+  | STRING 
+  | (REAL_OR_EXPONENT_NUMBER | INT) 
+  | currentNode 
+  ;
+
+chainedExpression
+  : identifier
+  | arrayExpression
+  | objectExpression
+  | functionExpression
+  | wildcard
+  ;
+
+wildcard : '*' ;
+
+arrayExpression : '[' expression (',' expression)* ']' ;
+
+objectExpression
+  : '{' keyvalExpr (',' keyvalExpr)* '}'  
+  ;
+
+keyvalExpr : identifier ':' expression ;
+
+bracketExpression
+  : '[' '*' ']' 
+  | '[' slice ']' 
+  | '[' ']' 
+  | '[?' expression ']' 
+  | '[' signedInt ']' 
+  ;
+
+slice : start=signedInt? ':' stop=signedInt? (':' step=signedInt?)? ;
+
+COMPARATOR
+  : '<'
+  | '<='
+  | '=='
+  | '='
+  | '>='
+  | '>'
+  | '!='
+  | '<>'
+  ;
+
+functionExpression
+  : NAME '(' functionArg (',' functionArg)* ')'
+  | NAME '(' ')'
+  ;
+
+functionArg
+  : expression
+  | expressionType
+  ;
+
+currentNode : '@' ;
+
+expressionType : '&' expression ;
+
+identifier
+  : NAME
+  | QUOTED_NAME
+  ;
+
+signedInt
+  : '-'? INT+
+  ;
+
+NAME : [a-zA-Z_$] [a-zA-Z0-9_$]* ;
+
+QUOTED_NAME : '\'' (ESC | ~ ['\\])* '\'';
+
+JSON_LITERAL
+  : '`' (ESC | ~ [\\`]+)* '`'
+  ;
+
+STRING : '"' (ESC | ~["\\])* '"' ;
+
+fragment ESC : '\\' (UNICODE | [bfnrt\\`'"/]);
+
+fragment UNICODE
+  : 'u' HEX HEX HEX HEX
+  ;
+
+fragment HEX
+  : [0-9a-fA-F]
+  ;
+
+REAL_OR_EXPONENT_NUMBER
+  : INT? '.' [0-9] + EXP?
+  | INT EXP
+  ;
+
+INT
+  : [0-9]+
+  ;
+
+fragment EXP
+  : [Ee] [+\-]? INT
+  ;
+
+WS
+  : [ \t\n\r] + -> skip
+  ;
+
+
+
+

4.1. Operator Precedence

+
+

The antlr grammar defines operator precedence by the order of expressions in the grammar. These are the operators listed from strongest to weakest binding:

+
+
+
    +
  • +

    Parenthesis ()

    +
  • +
  • +

    Bracket Expression […​]

    +
  • +
  • +

    Braces {}

    +
  • +
  • +

    Dot . (chained expressions)

    +
  • +
  • +

    Flatten: []

    +
  • +
  • +

    Unary not !, unary minus: -

    +
  • +
  • +

    multiply: *, divide: /

    +
  • +
  • +

    add: +, subtract: -, union: ~

    +
  • +
  • +

    concatenate: &

    +
  • +
  • +

    Comparison operators: =, ==, >, <, >=, <=, !=, <>

    +
  • +
  • +

    and: &&

    +
  • +
  • +

    or: ||

    +
  • +
  • +

    pipe: |

    +
  • +
+
+
+
+
+
+

5. Literals

+
+
+

5.1. JSON Literals

+
+
+
  JSON_LITERAL: '`' (ESC | ~ [\\`]+)* '`';
+
+
+
+

A JSON literal expression allows arbitrary JSON objects to be +specified anywhere an expression is permitted. Implementations should +use a JSON parser to parse these literals. Note that the backtick character +( ` ) character must be escaped in a JSON literal which means +implementations need to handle this case before passing the resulting string to +a JSON parser.

+
+

Examples

+
+
+
  eval(`"foo"`, {}) -> "foo"
+  eval(`"foo\`bar"`, {}) -> "foo`bar"
+  eval(`[1, 2]`, {}) -> [1, 2]
+  eval(`true`, {}) -> true
+  eval(`{"a": "b"}`.a, {}) -> "b"
+  eval({first: a, type: `"mytype"`}, {"a": "b", "c": "d"})
+       -> {"first": "b", "type": "mytype"}
+
+
+
+
+

5.2. String Literals

+
+
+
STRING : '"' (ESC | ~["\\])* '"' ;
+
+fragment ESC : '\\' (UNICODE | [bfnrt\\`'"/]);
+
+fragment UNICODE
+  : 'u' HEX HEX HEX HEX
+  ;
+
+fragment HEX
+  : [0-9a-fA-F]
+  ;
+
+
+
+

A STRING literal is a value enclosed in double quotes and supports the same character escape sequences as strings in JSON, as encoded by the ESC fragment. +e.g., a character 'A' could be specified as the unicode sequence: \u0041.

+
+
+

A string literal can also be expressed as a JSON literal. For example, the following expressions both +evaluate to the same value: "foo"

+
+
+
+
    eval(`"foo"`, {}) -> "foo"
+    eval("foo", {}) -> "foo"
+
+
+
+
+

5.3. Number literals

+
+
+
numberLiteral = REAL_OR_EXPONENT_NUMBER | INT
+
+REAL_OR_EXPONENT_NUMBER
+  : INT? '.' [0-9] + EXP?
+  | INT EXP
+  ;
+
+INT
+  : [0-9]+
+  ;
+
+fragment EXP
+  : [Ee] [+\-]? INT
+  ;
+
+
+
+

Number literals follow the same syntax rules as numeric values in JSON with three exceptions:

+
+
+
    +
  1. +

    Number literals may omit a leading zero before the decimal point. For example, .123 is not valid JSON, but is allowed as a number literal.

    +
  2. +
  3. +

    Number literals may include leading zeros ahead of the integral part of the number. For example, 0123 is not valid JSON, but is allowed as a number literal.

    +
  4. +
  5. +

    The grammar construction for a number literal does not include a minus sign. Literal expressions are made negative by prefixing them with a unary minus.

    +
  6. +
+
+
+

Note that number literals (and JSON numbers) allow scientific notation.

+
+

Examples

+
+
+
  eval(44, {}) -> 44
+  eval([12, 13], {}) -> [12, 13]
+  eval({a: 12, b: 13}, {}) -> {"a": 12, "b": 13}
+  eval(foo | [1], {"foo": [3,4,5]}) -> 4
+  eval(foo | @[-1], {"foo": [3,4,5]}) -> 5
+  eval(foo | [1, 2], {"foo": [3,4,5]}) -> [1, 2]
+  eval(6 / 3, {}) -> 2
+  eval(1e2, {}) -> 100
+
+
+
+
+
+
+

6. Identifiers

+
+
+
+
identifier
+  : NAME
+  | QUOTED_NAME
+  ;
+
+NAME : [a-zA-Z_$] [a-zA-Z0-9_$]* ;
+
+QUOTED_NAME : '\'' (ESC | ~ ['\\])* '\'';
+
+
+
+

An identifier is the most basic expression and can be used to extract a +single element from a JSON document. The return value for an identifier is the value associated with the identifier. If the identifier does not exist in the JSON document, then a null value is returned.

+
+
+

Using the NAME token grammar rule, identifiers can be one or more characters, +and must start with a character in the range: A-Za-z_$.

+
+
+

When an identifier has a +character sequence that does not match a NAME token, an identifier shall follow the QUOTED_NAME token rule where an identifier is specified with a single quote ('), followed by +any number of characters, followed by another single quote. Any valid string can be placed between single quotes, including JSON escape sequences.

+
+

Examples

+
+
+
   eval(foo, {"foo": "value"}) -> "value"
+   eval(bar, {"foo": "value"}) -> null
+   eval(foo, {"foo": [0, 1, 2]}) -> [0, 1, 2]
+   eval('with space', {"with space": "value"}) -> "value"
+   eval('special chars: !@#"', {"special chars: !@#": "value"}) -> "value"
+   eval('quote\'char', {"quote'char": "value"}) -> "value"
+   eval('\u2713', {"\u2713": "value"}) -> "value"
+
+
+
+
+
+

7. Operators

+
+
+

7.1. Comparison Operators

+
+

The following comparison operators are supported:

+
+
+
    +
  • +

    = , ==: test for equality

    +
  • +
  • +

    !=, <>: test for inequality

    +
  • +
  • +

    <: less than

    +
  • +
  • +

    <=: less than or equal to

    +
  • +
  • +

    >: greater than

    +
  • +
  • +

    >=: greater than or equal to

    +
  • +
+
+
+

7.1.1. Equality Operators

+
+

Two representations of the equality and inequality operators are supported: = and == are equivalent in functionality. Both variations are supported in order to provide familiarity to users with experience with similar grammars. Similarly, != and <> function identically. Note that there is no ambiguity with the = operator, since json-formula does not have an assignment operator.

+
+
+
    +
  • +

    A string is equal to another string if they they have the exact same sequence +of code points

    +
  • +
  • +

    number values are compared for an exact match. When comparing fractional values, authors should take into account floating point precision considerations.

    +
  • +
  • +

    The literal values true/false/null are equal only to their +own literal values

    +
  • +
  • +

    Two JSON objects are equal if they have the same set of +keys and values. Two JSON objects x and y, are consider equal if they have the same number of key/value pairs and if, for each key value +pair (i, j) in x, there exists an equivalent pair (i, j) in y

    +
  • +
  • +

    Two JSON arrays are equal if they have equal elements in the same order. Two arrays x and y are considered equal if they have the same length and, for each i from 0 until length(x), x[i] == y[i]

    +
  • +
  • +

    The comparison of array and objects is a deep comparison. That is, where nested arrays or objects are found, the nested elements will included in the comparison.

    +
  • +
+
+
+
+

7.1.2. Ordering Operators

+
+

Ordering comparisons follow these rules:

+
+
+
    +
  • +

    If both operands are numbers, a numeric comparison is performed

    +
  • +
  • +

    If both operands are strings, they are compared as strings, based on the values of the Unicode code points they contain

    +
  • +
  • +

    If operands are mixed types, type coercion to number is applied before performing the comparison

    +
  • +
+
+
+
+
+

7.2. Numeric Operators

+
+

The following operators work with numeric operands:

+
+
+
    +
  • +

    addition: +

    +
  • +
  • +

    subtraction: -

    +
  • +
  • +

    multiplication *

    +
  • +
  • +

    division: /

    +
  • +
+
+
+
+
  eval(left + right, {"left": 8, "right": 12 }) -> 20
+  eval(right - left - 10, {"left": 8, "right": 12 }) -> -6
+  eval(4 + 2 * 4, {}) -> 12
+  eval(10 / 2 * 3, {}) -> 15
+
+
+
+
+

7.3. Concatenation Operator

+
+

The concatenation operator (&) takes two string operands and combines them to form a single string.

+
+
+
+
  eval(left & value & right,
+    {"left": "[", "right": "]", "value": "abc" }) -> "[abc]"
+  eval(map(values, &"$" & @), {"values": [123.45, 44.32, 99.00] }) ->
+      ["$123.45", "$44.32", "$99"]
+
+
+
+
+

7.4. Array Operands

+
+

The numeric and concatenation operators (+, -, *, /, &) have special behavior when applied to arrays.

+
+
+
    +
  • +

    When both operands are arrays, a new array is returned where the elements are populated by applying the operator on each element of the left operand array with the corresponding element from the right operand array

    +
  • +
  • +

    If both operands are arrays and they do not have the same size, the shorter array is padded with null values

    +
  • +
  • +

    If one operand is an array and one is a scalar value, the scalar operand will be converted to an array by repeating the value to the same size array as the other operand

    +
  • +
+
+
+
+
  eval([1,2,3] + [2,3,4], {}) -> [3,5,7]
+  eval([1,2,3,4] * [1,2,3], {}) -> [1,4,9,0]
+  eval([1,2,3,4] & "%", {}) -> ["1%", "2%", "3%", "4%"]
+
+
+
+

7.4.1. Union Operator

+
+

The union operator (~) returns an array formed by concatenating the contents of two arrays.

+
+
+
+
  eval(a ~ b, {"a": [0,1,2], "b": [3,4,5]}) -> [0,1,2,3,4,5]
+  eval(a ~ b, {"a": [[0,1,2]], "b": [[3,4,5]]}) -> [[0,1,2],[3,4,5]]
+  eval(a[] ~ b[], {"a": [[0,1,2]], "b": [[3,4,5]]}) -> [0,1,2,3,4,5]
+  eval(a ~ 10, {"a": [0,1,2]}) -> [0,1,2,10]
+  eval(a ~ `null`, {"a": [0,1,2]}) -> [0,1,2,null]
+
+
+
+
+
+

7.5. Boolean Operators

+
+

7.5.1. Or Operator

+
+

The OR operator (||) will evaluate to either the left operand or the right +operand. If the left operand can be coerced to a true value, it is used +as the return value. If the left operand cannot be coerced to a true value, then the right operand is used as the return value. +If the left operand is a truth-like value, then the right operand is not evaluated. For example, the expression: if() will result in a FunctionError (missing arguments), but the expression true() || if() will not result in a FunctionError because the right operand is not evaluated.

+
+
+

The following conditions cannot be coerced to true:

+
+
+
    +
  • +

    Empty array: []

    +
  • +
  • +

    Empty object: {}

    +
  • +
  • +

    Empty string: ""

    +
  • +
  • +

    False boolean: false

    +
  • +
  • +

    Null value: null

    +
  • +
  • +

    zero value: 0

    +
  • +
+
+
Examples
+
+
+
  eval(foo || bar, {"foo": "foo-value"}) -> "foo-value"
+  eval(foo || bar, {"bar": "bar-value"}) -> "bar-value"
+  eval(foo || bar, {"foo": "foo-value", "bar": "bar-value"}) -> "foo-value"
+  eval(foo || bar, {"baz": "baz-value"}) -> null
+  eval(foo || bar || baz, {"baz": "baz-value"}) -> "baz-value"
+  eval(override || myarray[-1], {"myarray": ["one", "two"]}) -> "two"
+  eval(override || myarray[-1], {"myarray": ["one", "two"], "override": "yes"})
+       -> "yes"
+
+
+
+
+

7.5.2. And Operator

+
+

The AND operator (&&) will evaluate to either the left operand or the right +operand. If the left operand is a truth-like value, +then the right operand is returned. Otherwise the left operand is returned. This reduces to the +expected truth table:

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LHSRHSResult

True

True

True

True

False

False

False

True

False

False

False

False

+
+

This is the standard truth table for a +logical conjunction.

+
+
+

If the left operand is not a truth-like value, then the right operand is not evaluated. For example, the expression: true() && if() will result in a FunctionError (missing arguments), but the expression false() && if() will not result in an error because the right operand is not evaluated.

+
+
Examples
+
+
+
  eval(True && False, {"True": true, "False": false}) -> false
+  eval(Number && EmptyList, {"Number": 5, "EmptyList": []}) -> []
+  eval(foo[?a == `1` && b == `2`],
+         {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]}) -> [{"a": 1, "b": 2}]
+
+
+
+
+
+

7.6. Unary Operators

+
+

7.6.1. Not Operator

+
+

A unary NOT operator (!) is a boolean operator that negates the result of an expression. If the expression +results in a truth-like value, NOT operator will change this value to +false. If the expression results in a false-like value, a +NOT operator will change the value to true.

+
+
Examples
+
+
+
  eval(!True, {"True": true}) -> false
+  eval(!False, {"False": false}) -> true
+  eval(!Number, {"Number": 5}) -> false
+  eval(!EmptyList, {"EmptyList": []}) -> true
+
+
+
+
+

7.6.2. Minus Operator

+
+

A unary Minus operator (-) is a numeric operator that negates the value of an operand.

+
+
Examples
+
+
+
  eval(-11, {}) -> -11
+  eval(-n, {"n": 5, "nn": -10}) -> -5
+  eval(-nn, {"n": 5, "nn": -10}) -> 10
+  eval(--n, {"n": 5, "nn": -10}) -> 5
+
+
+
+
+
+
+
+

8. Expressions

+
+
+

8.1. Chained Expressions

+
+
+
expression: expression '.' chainedExpression
+
+chainedExpression
+  : identifier
+  | arrayExpression
+  | objectExpression
+  | functionExpression
+  | wildcard
+  ;
+
+wildcard : '*' ;
+
+
+
+

A chained expression is a combination of two expressions separated by the dot (.) char. +A chained expression is evaluated as follows:

+
+
+
    +
  • +

    Evaluate the expression on the left against the source JSON document

    +
  • +
  • +

    Evaluate the expression on the right against the result of the left expression +evaluation

    +
  • +
+
+
+

In pseudo-code

+
+
+
+
  left-evaluation = eval(left-expression, original-json-document)
+  result = eval(right-expression, left-evaluation)
+
+
+
+

A chained expression is itself an expression, so there can be multiple levels of +chained expressions: grandparent.parent.child.

+
+

Examples

+
+

Given a JSON document: {"foo": {"bar": "baz"}}, and a json-formula expression: +foo.bar, the evaluation process would be

+
+
+
+
  left-evaluation = eval(foo, {"foo": {"bar": "baz"}}) -> {"bar": "baz"}
+  result = eval(bar, {"bar": "baz"}) -> "baz"
+
+
+
+

The final result in this example is "baz".

+
+
+

Additional examples

+
+
+
+
   eval(foo.bar, {"foo": {"bar": "value"}}) -> "value"
+   eval(foo.'bar', {"foo": {"bar": "value"}}) -> "value"
+   eval(foo.bar, {"foo": {"baz": "value"}}) -> null
+   eval(foo.bar.baz, {"foo": {"bar": {"baz": "value"}}}) -> "value"
+
+
+
+
+

8.2. Bracket Expressions

+
+
+
expression: expression bracketExpression
+
+bracketExpression
+  : '[' '*' ']'
+  | '[?' expression ']'
+  | '[' signedInt ']'
+  | '[' slice ']'
+  | '[' ']'
+  ;
+
+signedInt
+  : '-'? INT+
+  ;
+
+
+
+

From the bracketExpression construction, the bracketed contents provide access to the elements in an array.

+
+
+
    +
  • +

    The wildcard: ('[' '*' ']') variation is discussed in the Wildcard Expressions section

    +
  • +
  • +

    The filtering: ('[?' expression ']') variation is discussed in the Filter Expressions section

    +
  • +
+
+
+

8.2.1. Index Expressions

+
+

When brackets enclose a signed integer ('[' signedInt ']'), the integer value is used to index into an array. +Indexing is 0 based where an index of 0 refers to the first element of the array. A negative index indicates that indexing is relative to the end of the array, specifically:

+
+
+
+
  negative-index == (length of array) + negative-index
+
+
+
+

Given an array of length N, an index of -1 would be equal to a positive +index of N - 1, which is the last element of the array. +An index value is outside the bounds of the array when the value is greater than or equal to the length of the array or less than the negative length of the array. +If an index is outside the bounds of the array then a value of null is returned.

+
+
Examples
+
+
+
  eval(a[1], {a: [5,6,7,8,9]}) -> 6
+  eval(a[-2], {a: [5,6,7,8,9]}) -> 8
+  eval([0], ["first", "second", "third"]) -> "first"
+  eval([-1], ["first", "second", "third"]) -> "third"
+  eval([100], ["first", "second", "third"]) -> null
+  eval(foo[0], {"foo": ["first", "second", "third"]}) -> "first"
+  eval(foo[100], {"foo": ["first", "second", "third"]}) -> null
+  eval(foo[0][0], {"foo": [[0, 1], [1, 2]]}) -> 0
+
+
+
+
+

8.2.2. Slices

+
+
+
  slice : start=signedInt? ':' stop=signedInt? (':' step=signedInt?)? ;
+
+
+
+

A slice expression allows you to select a contiguous subset of an array. A +slice has a start, stop, and step value. The general form of a +slice is [start:stop:step]. Each component of the slice is optional and can +be omitted, but there must be at least one colon (:) character.

+
+
+
+
+

Slices in json-formula have the same semantics as python slices. If you’re +familiar with python slices, you’re familiar with json-formula slices.

+
+
+
+
+

Given a start, stop, and step value, the sub elements in an array +are extracted as follows:

+
+
+
    +
  • +

    The first element in the extracted array is the index denoted by start.

    +
  • +
  • +

    The last element in the extracted array is the index denoted by stop - 1.

    +
  • +
  • +

    The step value determines the amount by which the index increases or decreases. The default step value is 1. For example, a step value of 2 will return every second value from the array. If step is negative, slicing is performed in reverse — from the last (stop) element to the start.

    +
  • +
+
+
+

Slice expressions adhere to the following rules:

+
+
+
    +
  • +

    If a negative start position is given, it is calculated as the total length +of the array plus the given start position.

    +
  • +
  • +

    If no start position is given, it is assumed to be 0 if the given step is +greater than 0 or the end of the array if the given step is less than 0.

    +
  • +
  • +

    If a negative stop position is given, it is calculated as the total length +of the array plus the given stop position.

    +
  • +
  • +

    If no stop position is given and the given step is greater than 0 then the stop is assumed to be the length of the array.

    +
  • +
  • +

    If no stop position is given and the given step is less than 0, then the stop is assumed to be negative (length+1).

    +
  • +
  • +

    If the given step is omitted, it is assumed to be 1.

    +
  • +
  • +

    If the given step is 0, an EvaluationError error must be raised.

    +
  • +
  • +

    If the element being sliced is not an array, the result is null.

    +
  • +
  • +

    If the element being sliced is an array and yields no results, the result +must be an empty array.

    +
  • +
+
+

Examples

+
+
+
  eval([0:4:1], [0, 1, 2, 3]) -> [0, 1, 2, 3]
+  eval([0:4], [0, 1, 2, 3]) -> [0, 1, 2, 3]
+  eval([0:3], [0, 1, 2, 3]) -> [0, 1, 2]
+  eval([:2], [0, 1, 2, 3]) -> [0, 1]
+  eval([::2], [0, 1, 2, 3]) -> [0, 2]
+  eval([::-1], [0, 1, 2, 3]) -> [3, 2, 1, 0]
+  eval([-2:], [0, 1, 2, 3]) -> [2, 3]
+
+
+
+
+

8.2.3. Flatten Operator

+
+

When the character sequence [] is provided as a bracket specifier, then +a flattening operation occurs on the current result. The flattening operator +will merge one level of sub-arrays in the current result into a single array. The flattening +operator follows these processing steps:

+
+
+
    +
  • +

    Create an empty result array

    +
  • +
  • +

    Iterate over the elements of the current result

    +
  • +
  • +

    If the current element is not an array, add to the end of the result array

    +
  • +
  • +

    If the current element is an array, add each element of the current element +to the end of the result array

    +
  • +
  • +

    The result array is returned as a projection

    +
  • +
+
+
+

Once the flattening operation has been performed, subsequent operations +are projected onto the flattened array.

+
+
+

A bracketed wildcard ([*]) and flatten ([]) behave similarly in that they produce a projection from an array. The only difference is that a bracketed wildcard preserves the original array structure while flatten collapses one level of array structure.

+
+

Examples

+
+
+
  eval(foo[], {"foo": [[0, 1], [1, 2], 3]}) -> [0,1,1,2,3]
+  eval(foo[], {"foo": [[0, 1], [1, 2], [3,[4,5]]]}) -> [0,1,1,2,3,[4,5]]
+  eval(foo[][], {"foo": [[0, 1], [1, 2], [3,[4,5]]]}) -> [0,1,1,2,3,4,5]
+
+
+
+
+
+

8.3. Projections

+
+

Projections allow you to apply an expression to a collection of elements. Projections are created when any form of a Bracket Expression transforms a source array or when a wildcard is applied to an object:

+
+
+

Given the source JSON:

+
+
+
+
{
+  "items": [
+    {
+      "desc": "pens",
+      "price": 3.23
+    },
+    {
+      "desc": "pencils",
+      "price": 1.34
+    },
+    {
+      "desc": "staplers",
+      "price": 10.79
+    }
+  ]
+}
+
+
+
+

These expressions will create a projection:

+
+
+
    +
  • +

    items[*]

    +
  • +
  • +

    items[]

    +
  • +
  • +

    items[0:2]

    +
  • +
  • +

    items[?expr]

    +
  • +
  • +

    items[0].*

    +
  • +
+
+
+

When a chained expression or bracket expression is applied to a projection, their behavior is changed so that the expression is applied to each element of the projection, rather than the underlying array itself.

+
+

Examples

+
+
+
  eval(items[*].desc, items) -> ["pens", "pencils", "staplers"]
+  eval(items[*].desc.upper(@), items) -> ["PENS", "PENCILS", "STAPLERS"]
+  eval(items[].*, items) -> [
+                                ["pens", 3.23],
+                                ["pencils", 1.34],
+                                ["staplers", 10.79]
+                              ]
+  eval(items[0:2].price * 2, items) -> [6.46, 2.68]
+  eval(items[?price < 3], items) -> [{"desc": "pencils", "price": 1.34}]
+
+
+
+

A pipe expression will stop the current projection and process it as a normal array.

+
+
+

For example, if you wanted to sum the price values, this expression: items[*].price.sum(@) will sum each individual price, returning: [3.23,1.34,10.79]. Whereas using a pipe operator will sum the array: items[*].price | sum(@) → 15.36.

+
+
+
+

8.4. Paren Expressions

+
+
+
  parenExpression = '(' expression ')'
+
+
+
+

A parenExpression allows a user to override the precedence order of +an expression
+e.g. (a || b) && c

+
+

Examples

+
+
+
  eval(foo[?(a == 1 || b == 2) && c == 5],
+         {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]}) -> []
+
+
+
+
+

8.5. Array Expression

+
+
+
    arrayExpression : '[' expression (',' expression)* ']' ;
+
+
+
+

An array expression is used to extract a subset of elements from the JSON document into an array. +Within the start and closing +brackets are one or more expressions separated by a comma. Each +expression will be evaluated against the JSON document, and each result will be added to the array

+
+
+

An arrayExpression with N expressions will result in an array of length N. Given an array +expression [expr-1,expr-2,…​,expr-n], the evaluated expression will return +[evaluate(expr-1), evaluate(expr-2), …​, evaluate(expr-n)].

+
+
+

Given an array expression: [n, "doubled", n * 2] and the +data {"n": 4}, the expression is evaluated as follows:

+
+
+
    +
  1. +

    An empty array is created: []

    +
  2. +
  3. +

    The expression n is evaluated against the source document and the result (4) is appended to the array

    +
  4. +
  5. +

    The literal expression "doubled" is appended to the array

    +
  6. +
  7. +

    The expression n * 2 is evaluated against the source document and the result (8) is appended to the array

    +
  8. +
+
+
+

The final result will be: [4, "doubled", 8].

+
+

Examples

+
+
+
  eval([foo,bar], {"foo": "a", "bar": "b", "baz": "c"}) -> ["a", "b"]
+  eval([foo,bar[0]], {"foo": "a", "bar": ["b"], "baz": "c"}) -> ["a", "b"]
+  eval([foo,bar.baz], {"foo": "a", "bar": {"baz": "b"}}) -> ["a", "b"]
+  eval([foo,baz], {"foo": "a", "bar": "b"}) -> ["a", null]
+
+
+
+

The grammar contains one ambiguity: a bracket with a single signed digit e.g., [0] can be interpreted as a flatten operation or an arrayExpression with the number zero. To resolve this ambiguity, the grammar sets a precedence order so that [-?[0-9]] is treated as a an index expression. To explicitly express an array with one element, use a JSON literal: `[0]`

+
+
+
+

8.6. Object Expression

+
+
+
    objectExpression = "{" ( keyvalExpr ( "," keyvalExpr )*)? "}"
+    keyvalExpr = identifier ":" expression
+
+
+
+

An object expression is used to extract a subset of elements from the JSON document into an object. +An objectExpression requires key names to be provided, as +specified in the keyvalExpr rule. Given the following rule

+
+
+
+
    keyvalExpr = identifier ":" expression
+
+
+
+

The identifier is used as the key name and the result of evaluating the +expression is the value associated with the identifier key.

+
+
+

Each keyvalExpr within the objectExpression will correspond to a +single key value pair in the created object. If a key is specified more than once, the last value will be used. +Consistent with an arrayExpression, an objectExpression may not be empty. To create an empty object, use a JSON literal: {} .

+
+

Examples

+
+

Given an object expression {foo: one.two, bar: bar} and the +data {"bar": "bar", {"one": {"two": "one-two"}}}, the expression is +evaluated as follows:

+
+
+
    +
  1. +

    An object is created: {}

    +
  2. +
  3. +

    A key foo is created whose value is the result of evaluating one.two +against the provided JSON document: {"foo": evaluate(one.two, <data>)}

    +
  4. +
  5. +

    A key bar is created whose value is the result of evaluating the +expression bar against the provided JSON document. If key bar already exists, it is replaced.

    +
  6. +
+
+
+

The final result will be: {"foo": "one-two", "bar": "bar"}.

+
+
+

Additional examples:

+
+
+
+
  eval({foo: foo, bar: bar}, {"foo": "a", "bar": "b", "baz": "c"})
+                -> {"foo": "a", "bar": "b"}
+  eval({foo: foo, firstbar: bar[0]}, {"foo": "a", "bar": ["b"]})
+                -> {"foo": "a", "firstbar": "b"}
+  eval({foo: foo, 'bar.baz': bar.baz}, {"foo": "a", "bar": {"baz": "b"}})
+                -> {"foo": "a", "bar.baz": "b"}
+  eval({foo: foo, baz: baz}, {"foo": "a", "bar": "b"})
+                -> {"foo": "a", "baz": null}
+  eval({foo: foo, foo: 42}, {"foo": "a", "bar": "b"})
+                -> {"foo": 42}
+
+
+
+
+

8.7. Wildcard Expressions

+
+

There are two forms of wildcard expression:

+
+
+
    +
  1. +

    [*] from the bracketExpression construction:

    +
    +
    +
    bracketExpression
    +  : '[' '*' ']'
    +  | '[' slice ']'
    +  | '[' ']'
    +  | '[?' expression ']'
    +  | '[' expression ']'
    +  ;
    +
    +
    +
  2. +
  3. +

    .* from the chainedExpression construction:

    +
  4. +
+
+
+
+
expression : expression '.' chainedExpression
+
+chainedExpression
+  : identifier
+  | arrayExpression
+  | objectExpression
+  | functionExpression
+  | wildcard
+  ;
+
+wildcard : '*' ;
+
+
+
+

The [*] syntax (referred to as an array wildcard expression) may be applied to arrays, and will return a projection with all +the elements of the source array. If an array +wildcard expression is applied to any other JSON type, a value of null is +returned.

+
+
+

The .* syntax (referred to as an object wildcard expression) may be applied to objects and will return an array +of the values from the object key/value pairs. +If an object wildcard expression is applied to any other JSON type, a value of +null is returned.

+
+
+

Note that JSON objects are explicitly defined as +unordered. Therefore an object wildcard expression can return the values +associated with the object in any order.

+
+

Examples

+
+
+
  eval([*].foo, [{"foo": 1}, {"foo": 2}, {"foo": 3}]) -> [1, 2, 3]
+  eval([*].foo, [{"foo": 1}, {"foo": 2}, {"bar": 3}]) -> [1, 2, null]
+  eval(*.foo, {"a": {"foo": 1}, "b": {"foo": 2}, "c": {"bar": 1}}) ->
+      [1, 2, null]
+
+
+
+
+

8.8. currentNode

+
+
+
currentNode : '@' ;
+
+
+
+

The currentNode token represents the node being +evaluated in the current context. The currentNode token is commonly used for:

+
+
+
    +
  • +

    Functions that require the current node as an argument

    +
  • +
  • +

    Filter Expressions that examine elements of an array

    +
  • +
  • +

    Access to the current context in projections.

    +
  • +
+
+
+

json-formula assumes that all expressions operate on the current node. Because of this, an +expression such as @.name would be equivalent to just name.

+
+
+

8.8.1. currentNode state

+
+

At the start of an expression, the value of the current node is the data +being evaluated by the json-formula expression. As an expression is evaluated, currentNode must change to reflect the node +being evaluated. When in a projection, the current node value must be changed +to the node being evaluated by the projection.

+
+

Examples

+
+
+
Given:
+{
+  "family": [
+    {"name": "frank", "age": 22},
+    {"name": "jane", "age": 23}
+  ]
+}
+
+eval(@.family[0].name, {...}) -> "frank"
+
+eval(family[].[left(@.name), age], {...}) ->
+   [["f", 22], ["j", 23]]
+
+eval(family[?@.age == 23], {...}) -> [{"name": "jane", "age": 23}]
+
+eval(family[?age == 23], {...}) -> [{"name": "jane", "age": 23}]
+
+eval(family[].name.proper(@), {...}) -> ["Frank", "Jane"]
+
+eval(family[].age | avg(@), {...}) -> 22.5
+
+
+
+
+
+

8.9. Filter Expressions

+
+
+
bracketExpression
+  : '[' '*' ']'
+  | '[' slice ']'
+  | '[' ']'
+  | '[?' expression ']'
+  | '[' expression ']'
+  ;
+
+
+
+

A filter expression is defined by a bracketExpression where the bracket contents are prefixed with a question mark character (?). +A filter expression provides a way to select array elements based on a +comparison to another expression. A filter expression is evaluated as follows:

+
+
+
    +
  • +

    For each element in an array evaluate the expression against the +element.

    +
  • +
  • +

    If the expression evaluates to a truth-like value, the item (in its +entirety) is added to the result array.

    +
  • +
  • +

    If the expression does not evaluate to a truth-like value it is excluded from the +result array.

    +
  • +
+
+
+

A filter expression may be applied to arrays. Attempting +to evaluate a filter expression against any other type will return null.

+
+

Examples

+
+
+
eval(
+  foo[?a < b],
+  {
+    "foo": [
+      {"a": "char", "b": "bar"},
+      {"a": 2, "b": 1},
+      {"a": 1, "b": 2},
+      {"a": false, "b": "1"},
+      {"a": 10, "b": "12"}
+    ]
+  })
+  ->
+  [ {"a": 1, "b": 2},
+    {"a": false, "b": "1"},
+    {"a": 10, "b": "12"} ]
+
+
+
+

The five elements in the foo array are evaluated against a < b:

+
+
+
    +
  • +

    The first element resolves to the comparison "char" < "bar", and because these types are string, the comparison of code points returns false, and the first element is excluded from the result array.

    +
  • +
  • +

    The second element resolves to 2 < 1, +which is false, so the second element is excluded from the result array.

    +
  • +
  • +

    The third expression resolves to 1 < 2 which evaluates to true, so the third element is included in the result array.

    +
  • +
  • +

    The fourth expression resolves to false < "1". Since the left hand operand is boolean, both operands are coerced to numbers and evaluated as: 0 < 1 and so the fourth element included in the result array.

    +
  • +
  • +

    The final expression resolves to 10 < "12". Since we have mixed operands, the operands are coerced to numbers and evaluated as: 10 < 12 and the last element is included in the result array.

    +
  • +
+
+

Examples

+
+
+
  eval(foo[?bar==10], {"foo": [{"bar": 1}, {"bar": 10}]}) -> [{"bar": 10}]
+  eval([?bar==10], [{"bar": 1}, {"bar": 10}]}) -> [{"bar": 10}]
+  eval(foo[?a==b], {"foo": [{"a": 1, "b": 2}, {"a": 2, "b": 2}]})
+       -> [{"a": 2, "b": 2}]
+
+
+
+
+

8.10. Pipe Expressions

+
+
+
    pipeExpression = expression '|' expression
+
+
+
+

A pipe expression combines two expressions, separated by the pipe (|) character. +It is similar to a chained expression with two distinctions:

+
+
+
    +
  1. +

    Any expression can be used on the right hand side. A chained expression +restricts the type of expression that can be used on the right hand side.

    +
  2. +
  3. +

    A pipe expression stops projections on the left hand side from +propagating to the right hand side. If the left expression creates a +projection, the right hand side will receive the array underlying the projection.

    +
  4. +
+
+
+

For example, given the following data

+
+
+
+
    {"foo": [{"bar": ["first1", "second1"]}, {"bar": ["first2", "second2"]}]}
+
+
+
+

The expression foo[*].bar gives the result of

+
+
+
+
    [
+        [
+            "first1",
+            "second1"
+        ],
+        [
+            "first2",
+            "second2"
+        ]
+    ]
+
+
+
+

The first part of the expression, foo[*], creates a projection. At this +point, the remaining expression, bar is projected onto each element of the +array created from foo[*]. If you project the [0] expression, you will +get the first element from each sub array. The expression foo[*].bar[0] +will return

+
+
+
+
    ["first1", "first2"]
+
+
+
+

If you instead wanted only the first sub array, ["first1", "second1"], you +can use a pipe expression.

+
+
+
+
    foo[*].bar[0] -> ["first1", "first2"]
+    foo[*].bar | [0] -> ["first1", "second1"]
+
+
+

Examples

+
+
+
   eval(foo | bar, {"foo": {"bar": "baz"}}) -> "baz"
+   eval(foo[*].bar | [0], {
+       "foo": [{"bar": ["first1", "second1"]},
+               {"bar": ["first2", "second2"]}]}) -> ["first1", "second1"]
+   eval(foo | [0], {"foo": [0, 1, 2]}) -> 0
+
+
+
+
+
+
+

9. Functions

+
+
+
+
functionExpression
+  : NAME '(' functionArg (',' functionArg)* ')'
+  | NAME '(' ')'
+  ;
+
+functionArg
+  : expression
+  | expressionType
+  ;
+
+expressionType : '&' expression ;
+
+
+
+

json-formula has a robust set of built-in functions. Each function has a signature +that defines the expected types of the input and the type of the returned +output.

+
+
+
+
    return_type function_name(type $argname)
+    return_type function_name2(type1|type2 $argname)
+
+
+
+

9.1. Function parameters

+
+

Functions support the set of standard json-formula data types. If the parameters cannot be coerced to match the types specified in the signature, a TypeError error occurs.

+
+
+

As a shorthand, the type any is used to indicate that the function argument can be +any of (array|object|number|string|boolean|null).

+
+
+

The expression type, (denoted by &expression), is used to specify an +expression that is not immediately evaluated. Instead, a reference to that +expression is provided to the function. The function can then apply the expression reference as needed. It is semantically similar +to an anonymous function. See the sortBy() function for an example of the expression type.

+
+
+

Function parameters can either have a specific arity or be variadic with a minimum +number of arguments. If a functionExpression is encountered where the +arity does not match, or the minimum number of arguments for a variadic function +is not provided, or too many arguments are provided, then a +FunctionError error is raised.

+
+
+

The result of the functionExpression is the result returned by the +function call. If a functionExpression is evaluated for a function that +does not exist, a FunctionError error is raised.

+
+
+

9.1.1. Array Parameters

+
+

Many functions that process scalar values also allow for the processing of arrays of values. For example, the round() function may be called to process a single value: round(1.2345, 2) or to process an array of values: round([1.2345, 2.3456], 2). The first call will return a single value, the second call will return an array of values. +When processing arrays of values, and where there is more than one parameter, each parameter is converted to an array so that the function processes each value in the set of arrays. From our example above, the call to round([1.2345, 2.3456], 2) would be processed as if it were round([1.2345, 2.3456], [2, 2]), and the result would be the same as: [round(1.2345, 2), round(2.3456, 2)].

+
+
+

Functions that accept array parameters will also accept nested arrays. Aggregating functions (min(), max(), avg(), sum(), etc.) will flatten nested arrays. e.g. avg([2.1, 3.1, [4.1, 5.1]]) will be processed as avg([2.1, 3.1, 4.1, 5.1]) and return 3.6.

+
+
+

Non-aggregating functions will return the same array hierarchy. e.g.

+
+
+

upper(["a", ["b"]]) ⇒ ["A", ["B"]] +round([2.12, 3.12, [4.12, 5.12]], 1) will be processed as round([2.12, 3.12, [4.12, 5.12]], [1, 1, [1, 1]]) and return [2.1, 3.1, [4.1, 5.1]]

+
+
+

These array balancing rules apply when any parameter is an array:

+
+
+
    +
  • +

    All parameters will be treated as arrays

    +
  • +
  • +

    Any scalar parameters will be converted to an array by repeating the scalar value to the length of the longest array

    +
  • +
  • +

    All array parameters will be padded to the length of the longest array by adding null values

    +
  • +
  • +

    The function will return an array which is the result of iterating over the elements of the arrays and applying the function logic on the values at the same index.

    +
  • +
+
+
+

With nested arrays:

+
+
+
    +
  • +

    Nested arrays will be flattened for aggregating functions

    +
  • +
  • +

    Non-aggregating functions will preserve the array hierarchy and will apply the balancing rules to each element of the nested arrays

    +
  • +
+
+
+
+
+

9.2. Function evaluation

+
+

Functions are evaluated in applicative order: +- Each argument must be an expression +- Each argument expression must be evaluated before evaluating the +function +- Each argument expression result must be coerced to the expected type +- If coercion is not possible, a TypeError error is raised +- The function is then called with the evaluated function arguments.

+
+
+

The one exception to this rule is the if(expr, result1, result2) function. In this case either the result1 expression or the result2 expression is evaluated, depending on the outcome of expr.

+
+
+

Consider this example using the abs() function. Given:

+
+
+
+
    {"foo": -1, "bar": "2"}
+
+
+
+

Evaluating abs(foo) works as follows:

+
+
+
    +
  1. +

    Evaluate the input argument against the current data:

    +
    +
    +
         eval(foo, {"foo": -1, "bar": "2"}) -> -1
    +
    +
    +
  2. +
  3. +

    Coerce the type of the resolved argument if needed. In this case -1 is of type number so no coercion is needed.

    +
  4. +
  5. +

    Validate the type of the coerced argument. In this case -1 is of type number so it passes the type check.

    +
  6. +
  7. +

    Call the function with the resolved argument:

    +
    +
    +
         abs(-1) -> 1
    +
    +
    +
  8. +
+
+
+

Below is the same steps for evaluating abs(bar):

+
+
+
    +
  1. +

    Evaluate the input argument against the current data:

    +
    +
    +
         eval(bar, {"foo": -1, "bar": "2"}) -> "2"
    +
    +
    +
  2. +
  3. +

    Attempt to coerce the result to the required number type. In this case, coerce "2" to 2.

    +
  4. +
  5. +

    Validate the type of the coerced argument. In this case 2 is of type number so it passes the type check.

    +
  6. +
  7. +

    Call the function with the resolved and coerced argument:

    +
    +
    +
         abs(2) -> 2
    +
    +
    +
  8. +
+
+
+

Function expressions are allowed as the child element of a chained expression. +The function is then evaluated in the context of the parent expression result. For example: [1,2,3].sum(@) → 6.

+
+
+

When the parent expression is a projection a chained function expression +will be applied to every element in the projection. For example, given the input +data of ["1", "2", "3", "notanumber", true], the following expression can +be used to convert all elements to numbers:

+
+
+
+
    eval([].toNumber(@), ["1", "2", "3", "notanumber", null, true]) -> [1,2,3,null,0,1]
+
+
+
+
+

9.3. Function Reference

+ +
+

9.3.1. abs

+
+

abs(value) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Find the absolute (non-negative) value of the provided +argument value.

+
+
Returns
+
+

number | Array.<number> - If value < 0, returns +-value, otherwise returns value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

value

number | Array.<number>

A numeric value

+
+
+
+
+

Example

+
+
+
+
abs(-1) // returns 1
+
+
+
+
+

9.3.2. acos

+
+

acos(cosine) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the inverse cosine (in radians) of a number.

+
+
Returns
+
+

number | Array.<number> - The inverse cosine angle in +radians between 0 and PI

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

cosine

number | Array.<number>

A number between -1 and 1, +inclusive, representing the angle’s cosine value.

+
+
+
+
+

Example

+
+
+
+
acos(0) => 1.5707963267948966
+
+
+
+
+

9.3.3. and

+
+

and(firstOperand, […additionalOperands]) ⇒ boolean

+
+
+
+
Description
+
+

Finds the logical AND result of all parameters. If the +parameters are not boolean they will be cast to +boolean. Note the related And Operator.

+
+
Returns
+
+

boolean - The logical result of applying AND to all +parameters

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

firstOperand

any

logical expression

[…additionalOperands]

any

any number of additional expressions

+
+
+
+
+

Example

+
+
+
+
and(10 > 8, length("foo") < 5) // returns true
+and(`null`, length("foo") < 5) // returns false
+
+
+
+
+

9.3.4. asin

+
+

asin(sine) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the inverse sine (in radians) of a number.

+
+
Returns
+
+

number | Array.<number> - The inverse sine angle in +radians between -PI/2 and PI/2

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

sine

number | Array.<number>

A number between -1 and 1, +inclusive, representing the angle’s sine value.

+
+
+
+
+

Example

+
+
+
+
Math.asin(0) => 0
+
+
+
+
+

9.3.5. atan2

+
+

atan2(y, x) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the angle in the plane (in radians) between the +positive x-axis and the ray from (0, 0) to the point (x, y)

+
+
Returns
+
+

number | Array.<number> - The angle in radians (between +-PI and PI), between the positive x-axis and the ray from (0, 0) to the +point (x, y).

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

y

number | Array.<number>

The y coordinate of the point

x

number | Array.<number>

The x coordinate of the point

+
+
+
+
+

Example

+
+
+
+
atan2(20,10) => 1.1071487177940904
+
+
+
+
+

9.3.6. avg

+
+

avg(elements) ⇒ number

+
+
+
+
Description
+
+

Finds the average of the elements in an array. Non-numeric +values (text, boolean, null, object) are ignored. If there are nested +arrays, they are flattened. If the array is empty, an evaluation error +is thrown

+
+
Returns
+
+

number - average value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

elements

Array.<any>

array of values

+
+
+
+
+

Example

+
+
+
+
avg([1, 2, 3]) // returns 2
+
+
+
+
+

9.3.7. avgA

+
+

avgA(elements) ⇒ number

+
+
+
+
Description
+
+

Finds the average of the elements in an array, converting +strings and booleans to number. If any conversions to number fail, a +type error is thrown. If there are nested arrays, they are flattened. If +the array is empty, an evaluation error is thrown

+
+
Returns
+
+

number - average value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

elements

Array.<number>

array of numeric values

+
+
+
+
+

Example

+
+
+
+
avgA([1, 2, "3", null()]) // returns 2
+
+
+
+
+

9.3.8. casefold

+
+

casefold(input) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Generates a lower-case string of the input string using +locale-specific mappings. e.g. Strings with German letter ß (eszett) can +be compared to "ss"

+
+
Returns
+
+

string | Array.<string> - A new string converted to +lower case

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

input

string | Array.<string>

string to casefold

+
+
+
+
+

Example

+
+
+
+
casefold("AbC") // returns "abc"
+
+
+
+
+

9.3.9. ceil

+
+

ceil(num) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Finds the next highest integer value of the argument num +by rounding up if necessary. i.e. ceil() rounds toward positive +infinity.

+
+
Returns
+
+

integer | Array.<integer> - The smallest integer +greater than or equal to num

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

numeric value

+
+
+
+
+

Example

+
+
+
+
ceil(10) // returns 10
+ceil(10.4) // return 11
+
+
+
+
+

9.3.10. codePoint

+
+

codePoint(str) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Retrieve the first code point from a string

+
+
Returns
+
+

integer | Array.<integer> - Unicode code point value. +If the input string is empty, returns null.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

str

string | Array.<string>

source string.

+
+
+
+
+

Example

+
+
+
+
codePoint("ABC") // 65
+
+
+
+
+

9.3.11. contains

+
+

contains(subject, search) ⇒ boolean

+
+
+
+
Description
+
+

Determines if the given subject contains search. If +subject is an array, this function returns true if one of the elements +in the array is equal to the search value. If subject is a string, +return true if the string contains the search value.

+
+
Returns
+
+

boolean - true if found

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

array | string

The element to be searched

search

any

element to find. If subject is an array, search for an +exact match for search in the array. If subject is a string, +search must also be a string.

+
+
+
+
+

Example

+
+
+
+
contains([1, 2, 3, 4], 2) // returns true
+contains([1, 2, 3, 4], -1) // returns false
+contains("Abcd", "d") // returns true
+contains("Abcd", "x") // returns false
+
+
+
+
+

9.3.12. cos

+
+

cos(angle) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the cosine (in radians) of a number.

+
+
Returns
+
+

number | Array.<number> - The cosine of the angle, +between -1 and 1, inclusive.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

angle

number | Array.<number>

A number representing an angle in +radians

+
+
+
+
+

Example

+
+
+
+
cos(1.0471975512) => 0.4999999999970535
+
+
+
+
+

9.3.13. datedif

+
+

datedif(start_date, end_date, unit) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Return difference between two date values. The measurement +of the difference is determined by the unit parameter. One of:

+
+
    +
  • +

    y the number of whole years between start_date and end_date

    +
  • +
  • +

    m the number of whole months between start_date and end_date.

    +
  • +
  • +

    d the number of days between start_date and end_date

    +
  • +
  • +

    ym the number of whole months between start_date and end_date +after subtracting whole years.

    +
  • +
  • +

    yd the number of days between start_date and end_date, assuming +start_date and end_date were no more than one year apart

    +
  • +
+
+
+
Returns
+
+

integer | Array.<integer> - The number of +days/months/years difference

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

start_date

number | Array.<number>

The starting +date/time value. Date/time values can be +generated using the datetime, toDate, +today, now and time functions.

end_date

number | Array.<number>

The end +date/time value – must be greater or equal to +start_date. If not, an error will be thrown.

unit

string | Array.<string>

Case-insensitive string +representing the unit of time to measure. An unrecognized unit will +result in an error.

+
+
+
+
+

Example

+
+
+
+
datedif(datetime(2001, 1, 1), datetime(2003, 1, 1), "y") // returns 2
+datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), "D") // returns 805
+// 805 days between June 1, 2001, and August 15, 2003
+datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), "YD") // returns 75
+// 75 days between June 1 and August 15, ignoring the years of the dates (75)
+
+
+
+
+

9.3.14. datetime

+
+

datetime(year, month, day, [hours], [minutes], [seconds], +[milliseconds]) ⇒ number

+
+
+
+
Description
+
+

Generate a date/time value from individual date/time +parts. If any of the units are greater than their normal range, the +overflow will be added to the next greater unit. e.g. specifying 25 +hours will increment the day value by 1. Similarly, negative values will +decrement the next greater unit. e.g. datetime(year, month, day - 30) +will return a date 30 days earlier.

+
+
Returns
+
+

number - A date/time value to be +used with other date/time functions

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

year

integer

The year to use for date construction. Values from 0 +to 99 map to the years 1900 to 1999. All other values are the actual +year

month

integer

The month: beginning with 1 for January to 12 for +December.

day

integer

The day of the month.

[hours]

integer

0

Integer value between 0 and 23 representing the +hour of the day.

[minutes]

integer

0

Integer value representing the minute segment of +a time.

[seconds]

integer

0

Integer value representing the second segment of +a time.

[milliseconds]

integer

0

Integer value representing the millisecond +segment of a time.

+
+
+
+
+

Example

+
+
+
+
datetime(2010, 10, 10) // returns representation of October 10, 2010
+datetime(2010, 2, 28) // returns representation of February 28, 2010
+datetime(2023,13,5) | year(@) & "/" & month(@) // returns 2024/1
+
+
+
+
+

9.3.15. day

+
+

day(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Finds the day of the month for a date value

+
+
Returns
+
+

integer | Array.<integer> - The day of the month +ranging from 1 to 31.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

date/time +value generated using the datetime, +toDate, today, now and +time functions.

+
+
+
+
+

Example

+
+
+
+
day(datetime(2008,5,23)) // returns 23
+
+
+
+
+

9.3.16. debug

+
+

debug(arg, [displayValue]) ⇒ any

+
+
+
+
Description
+
+

Debug a json-formula expression. The debug() function +allows users to inspect a sub-expression within a formula.

+
+
Returns
+
+

any - The value of the arg parameter

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

arg

any

The expression to return from debug() function, and the +default expression to be debugged. May be any type except an expression.

[displayValue]

any | expression

arg

Optionally override the +value to be debugged. displayValue may be an expression to be +evaluated with the context of arg.

+
+
+
+
+

Example

+
+
+
+
avg(([1,2,3] * [2,3,4]).debug(@)).round(@,3) // 6.667
+avg(debug([1,2,3] * [2,3,4],&"average of: " &toString(@))).round(@,3) // 6.667
+
+
+
+
+

9.3.17. deepScan

+
+

deepScan(object, name) ⇒ Array.<any>

+
+
+
+
Description
+
+

Performs a depth-first search of a nested hierarchy to +return an array of key values that match a name. The name can be +either a key into an object or an array index. This is similar to the +Descendant Accessor operator (..) from +E4X.

+
+
Returns
+
+

Array.<any> - The array of matched elements

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

object

object | array | null

The starting object or array +where we start the search

name

string | integer

The name (or index position) of the +elements to find. If name is a string, search for nested objects with +a matching key. If name is an integer, search for nested arrays with a +matching index.

+
+
+
+
+

Example

+
+
+
+
deepScan({a : {b1 : {c : 2}, b2 : {c : 3}}}, "c") // returns [2, 3]
+
+
+
+
+

9.3.18. endsWith

+
+

endsWith(subject, suffix) ⇒ boolean | Array.<boolean>

+
+
+
+
Description
+
+

Determines if the subject string ends with a specific +suffix

+
+
Returns
+
+

boolean | Array.<boolean> - true if the suffix value +is at the end of the subject

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

string | Array.<string>

source string in which to +search

suffix

string | Array.<string>

search string

+
+
+
+
+

Example

+
+
+
+
endsWith("Abcd", "d") // returns true
+endsWith("Abcd", "A") // returns false
+
+
+
+
+

9.3.19. entries

+
+

entries(obj) ⇒ Array.<any>

+
+
+
+
Description
+
+

Returns an array of [key, value] pairs from an object or +array. The fromEntries() function may be used to convert an array to +an object.

+
+
Returns
+
+

Array.<any> - an array of arrays where each child array has +two elements representing the key and value of a pair

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

obj

object | array

source object or array

+
+
+
+
+

Example

+
+
+
+
entries({a: 1, b: 2}) // returns [["a", 1], ["b", 2]]
+entries([4,5]) // returns [["0", 4],["1", 5]]
+
+
+
+
+

9.3.20. eomonth

+
+

eomonth(startDate, monthAdd) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Finds the date value of the end of a month, given +startDate plus monthAdd months

+
+
Returns
+
+

number | Array.<number> - the date of the last day of +the month

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

startDate

number | Array.<number>

The base date to start from. +Date/time values can be generated using the +datetime, toDate, today, +now and time functions.

monthAdd

integer | Array.<integer>

Number of months to add to +start date

+
+
+
+
+

Example

+
+
+
+
eomonth(datetime(2011, 1, 1), 1) | [month(@), day(@)] // returns [2, 28]
+eomonth(datetime(2011, 1, 1), -3) | [month(@), day(@)] // returns [10, 31]
+
+
+
+
+

9.3.21. exp

+
+

exp(x) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Finds e (the base of natural logarithms) raised to a +power. (i.e. e^x)

+
+
Returns
+
+

number | Array.<number> - e (the base of natural +logarithms) raised to power x

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

x

number | Array.<number>

A numeric expression representing the +power of e.

+
+
+
+
+

Example

+
+
+
+
exp(10) // returns 22026.465794806718
+
+
+
+
+

9.3.22. false

+
+

false() ⇒ boolean

+
+
+
+
Description
+
+

Return constant boolean false value. Expressions may also +use the JSON literal: `false`

+
+
Returns
+
+

boolean - constant boolean value false

+
+
+
+
+
+

9.3.23. find

+
+

find(findText, withinText, [start]) ⇒ integer | null | +Array.<integer>

+
+
+
+
Description
+
+

Finds and returns the index of query in text from a start +position

+
+
Returns
+
+

integer | null | Array.<integer> - The position +of the found string, null if not found.

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

findText

string | Array.<string>

string to search

withinText

string | Array.<string>

text to be searched

[start]

integer | Array.<integer>

0

zero-based position to +start searching. If specified, start must be greater than or equal to +0

+
+
+
+
+

Example

+
+
+
+
find("m", "abm") // returns 2
+find("M", "abMcdM", 3) // returns 5
+find("M", "ab") // returns `null`
+find("M", "abMcdM", 2) // returns 2
+
+
+
+
+

9.3.24. floor

+
+

floor(num) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Calculates the next lowest integer value of the argument +num by rounding down if necessary. i.e. floor() rounds toward negative +infinity.

+
+
Returns
+
+

integer | Array.<integer> - The largest integer smaller +than or equal to num

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

numeric value

+
+
+
+
+

Example

+
+
+
+
floor(10.4) // returns 10
+floor(10) // returns 10
+
+
+
+
+

9.3.25. fromCodePoint

+
+

fromCodePoint(codePoint) ⇒ string

+
+
+
+
Description
+
+

Create a string from a code point.

+
+
Returns
+
+

string - A string from the given code point(s)

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

codePoint

integer | Array.<integer>

An integer or array of +integers between 0 and 0x10FFFF (inclusive) representing Unicode code +point(s).

+
+
+
+
+

Example

+
+
+
+
fromCodePoint(65) // "A"
+fromCodePoint(65) == "\u0041" // true
+
+
+
+
+

9.3.26. fromEntries

+
+

fromEntries(pairs) ⇒ object

+
+
+
+
Description
+
+

Returns an object by transforming a list of key-value +pairs into an object. fromEntries() is the inverse operation of +entries(). If the nested arrays are not of the form: [key, value] +(where key is a string), an error will be thrown.

+
+
Returns
+
+

object - An object constructed from the provided key-value +pairs

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

pairs

Array.<any>

A nested array of key-value pairs to create the +object from The nested arrays must have exactly two values, where the +first value is a string. If a key is specified more than once, the last +occurrence will override any previous value.

+
+
+
+
+

Example

+
+
+
+
fromEntries([["a", 1], ["b", 2]]) // returns {a: 1, b: 2}
+
+
+
+
+

9.3.27. fround

+
+

fround(num) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the nearest 32-bit single precision float +representation of a number

+
+
Returns
+
+

number | Array.<number> - The rounded representation of +num

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

input to be rounded

+
+
+
+
+

Example

+
+
+
+
fround(2147483650.987) => 2147483648
+fround(100.44444444444444444444) => 100.44444274902344
+
+
+
+
+

9.3.28. hasProperty

+
+

hasProperty(subject, name) ⇒ boolean

+
+
+
+
Description
+
+

Determine if an object has a property or if an array index +is in range.

+
+
Returns
+
+

boolean - true if the element exists

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

object | array | null

source object or array. +When querying for hidden properties, subject +may be any data type.

name

string | integer

The name (or index position) of the +element to find. if subject is an array, name must be an integer; if +subject is an object, name must be a string.

+
+
+
+
+

Example

+
+
+
+
hasProperty({a: 1, b: 2}, "a") // returns true
+hasProperty(["apples", "oranges"], 3) // returns false
+hasProperty(`null`, "a") // returns false
+
+
+
+
+

9.3.29. hour

+
+

hour(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Extract the hour from a date/time +value

+
+
Returns
+
+

integer | Array.<integer> - value between 0 and 23

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

The datetime/time for which the +hour is to be returned. Date/time values can be generated using the +datetime, toDate, today, +now and time functions.

+
+
+
+
+

Example

+
+
+
+
hour(datetime(2008,5,23,12, 0, 0)) // returns 12
+hour(time(12, 0, 0)) // returns 12
+
+
+
+
+

9.3.30. if

+
+

if(condition, result1, result2) ⇒ any

+
+
+
+
Description
+
+

Return one of two values result1 or result2, depending +on the condition

+
+
Returns
+
+

any - either result1 or result2

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

condition

any

boolean result of a logical expression

result1

any

if condition is true

result2

any

if condition is false

+
+
+
+
+

Example

+
+
+
+
if(true(), 1, 2) // returns 1
+if(false(), 1, 2) // returns 2
+
+
+
+
+

9.3.31. join

+
+

join(array, glue) ⇒ string

+
+
+
+
Description
+
+

Combines all the elements from the provided array, joined +together using the glue argument as a separator between each array +element.

+
+
Returns
+
+

string - String representation of the array

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

array

Array.<any>

array of values that will be converted to strings +using toString()

glue

string

+
+
+
+
+

Example

+
+
+
+
join(["a", "b", "c"], ",") // returns "a,b,c"
+join(["apples", "bananas"], " and ") // returns "apples and bananas"
+join([1, 2, 3, null()], "|") // returns "1|2|3|null"
+
+
+
+
+

9.3.32. keys

+
+

keys(obj) ⇒ array

+
+
+
+
Description
+
+

Generates an array of the keys of the input object. If the +object is null, the value return an empty array

+
+
Returns
+
+

array - the array of all the key names

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

obj

object

the object to examine

+
+
+
+
+

Example

+
+
+
+
keys({a : 3, b : 4}) // returns ["a", "b"]
+
+
+
+
+

9.3.33. left

+
+

left(subject, [elements]) ⇒ string | array

+
+
+
+
Description
+
+

Return a substring from the start of a string or the +left-most elements of an array

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

subject

string | array

The source text/array of code +points/elements

[elements]

integer

1

number of elements to pick

+
+
+
+
+

Example

+
+
+
+
left("Sale Price", 4) // returns "Sale"
+left("Sweden") // returns "S"
+left([4, 5, 6], 2) // returns [4, 5]
+
+
+
+
+

9.3.34. length

+
+

length(subject) ⇒ integer

+
+
+
+
Description
+
+

Calculates the length of the input argument based on +types:

+
+
    +
  • +

    string: returns the number of unicode code points

    +
  • +
  • +

    array: returns the number of array elements

    +
  • +
  • +

    object: returns the number of key-value pairs

    +
  • +
+
+
+
Returns
+
+

integer - the length of the input subject

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

subject

string | array | object

subject whose length to +calculate

+
+
+
+
+

Example

+
+
+
+
length(`[]`) // returns 0
+length("") // returns 0
+length("abcd") // returns 4
+length([1, 2, 3, 4]) // returns 4
+length(`{}`) // returns 0
+length({a : 3, b : 4}) // returns 2
+
+
+
+
+

9.3.35. log

+
+

log(num) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the natural logarithm (base e) of a number

+
+
Returns
+
+

number | Array.<number> - The natural log value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

A number greater than zero

+
+
+
+
+

Example

+
+
+
+
log(10) // 2.302585092994046
+
+
+
+
+

9.3.36. log10

+
+

log10(num) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Compute the base 10 logarithm of a number.

+
+
Returns
+
+

number | Array.<number> - The base 10 log result

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

A number greater than or equal to +zero

+
+
+
+
+

Example

+
+
+
+
log10(100000) // 5
+
+
+
+
+

9.3.37. lower

+
+

lower(input) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Converts all the alphabetic code points in a string to +lowercase.

+
+
Returns
+
+

string | Array.<string> - the lower case value of the +input string

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

input

string | Array.<string>

input string

+
+
+
+
+

Example

+
+
+
+
lower("E. E. Cummings") // returns "e. e. cummings"
+
+
+
+
+

9.3.38. map

+
+

map(elements, expr) ⇒ array

+
+
+
+
Description
+
+

Apply an expression to every element in an array and +return the array of results. An input array of length N will return an +array of length N.

+
+
Returns
+
+

array - the mapped array

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

elements

array

array of elements to process

expr

expression

expression to evaluate

+
+
+
+
+

Example

+
+
+
+
map([1, 2, 3, 4], &(@ + 1)) // returns [2, 3, 4, 5]
+map(["doe", "nick", "chris"], &length(@)) // returns [3, 4, 5]
+
+
+
+
+

9.3.39. max

+
+

max(…collection) ⇒ number

+
+
+
+
Description
+
+

Calculates the largest value in the input numbers. Any +values that are not numbers (null, boolean, strings, objects) will be +ignored. If any parameters are arrays, the arrays will be flattened. If +no numbers are provided, the function will return zero.

+
+
Returns
+
+

number - the largest value found

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

…collection

array | any

values/array(s) in which the maximum +element is to be calculated

+
+
+
+
+

Example

+
+
+
+
max([1, 2, 3], [4, 5, 6]) // returns 6
+max([\"a\", \"a1\", \"b\"], null(), true())) // returns 0
+max(8, 10, 12, "14") // returns 12
+
+
+
+
+

9.3.40. maxA

+
+

maxA(…collection) ⇒ number

+
+
+
+
Description
+
+

Calculates the largest value in the input values, coercing +parameters to numbers. Null values are ignored. If any parameters cannot +be converted to a number, the function will fail with a type error. If +any parameters are arrays, the arrays will be flattened. If no numbers +are provided, the function will return zero.

+
+
Returns
+
+

number - the largest value found

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

…collection

any

values/array(s) in which the maximum element is to be +calculated

+
+
+
+
+

Example

+
+
+
+
maxA([1, 2, 3], [4, 5, 6]) // returns 6
+maxA(["a", "a1", "b", null()]) // error
+maxA(8, 10, 12, "14") // returns 14
+
+
+
+
+

9.3.41. merge

+
+

merge(…args) ⇒ object

+
+
+
+
Description
+
+

Accepts one or more objects, and returns a single object +with all objects merged. The first object is copied, and then and each +key value pair from each subsequent object are added to the first +object. Duplicate keys in subsequent objects will override those found +in earlier objects.

+
+
Returns
+
+

object - The combined object

+
+
Parameters
+
+ ++++ + + + + + + + + + + + + +
ParamType

…args

object

+
+
+
+
+

Example

+
+
+
+
merge({a: 1, b: 2}, {c : 3, d: 4}) // returns {a :1, b: 2, c: 3, d: 4}
+merge({a: 1, b: 2}, {a : 3, d: 4}) // returns {a :3, b: 2, d: 4}
+
+
+
+
+

9.3.42. mid

+
+

mid(subject, startPos, length) ⇒ string | array

+
+
+
+
Description
+
+

Extracts a substring from text, or a subset from an array.

+
+
Returns
+
+

string | array - The resulting substring or array +subset of elements

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

string | array

the text string or array of elements +from which to extract.

startPos

integer

the zero-based position of the first code point or +element to extract.

length

integer

The number of code points or elements to return from +the string or array. If greater then the length of subject the length +of the subject is used.

+
+
+
+
+

Example

+
+
+
+
mid("Fluid Flow", 0, 5) // returns "Fluid"
+mid("Fluid Flow", 6, 20) // returns "Flow"
+mid("Fluid Flow", 20, 5) // returns ""
+mid([0,1,2,3,4,5,6,7,8,9], 2, 3) // returns [2,3,4]
+
+
+
+
+

9.3.43. millisecond

+
+

millisecond(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Extract the milliseconds of the time value in a +date/time value.

+
+
Returns
+
+

integer | Array.<integer> - The number of milliseconds: +0 through 999

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

datetime/time for which the +millisecond is to be returned. Date/time values can be generated using +the datetime, toDate, today, +now and time functions.

+
+
+
+
+

Example

+
+
+
+
millisecond(datetime(2008, 5, 23, 12, 10, 53, 42)) // returns 42
+
+
+
+
+

9.3.44. min

+
+

min(…collection) ⇒ number

+
+
+
+
Description
+
+

Calculates the smallest value in the input numbers. Any +values that are not numbers (null, boolean, string, object) will be +ignored. If any parameters are arrays, the arrays will be flattened. If +no numbers are provided, the function will return zero.

+
+
Returns
+
+

number - the smallest value found

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

…collection

Array.<any> | any

Values/arrays to search for the +minimum value

+
+
+
+
+

Example

+
+
+
+
min([1, 2, 3], [4, 5, 6]) // returns 1
+min("4", 8, 10, 12, null()) // returns 8
+
+
+
+
+

9.3.45. minA

+
+

minA(…collection) ⇒ number

+
+
+
+
Description
+
+

Calculates the smallest value in the input values, +coercing parameters to numbers. Null values are ignored. If any +parameters cannot be converted to a number, the function will fail with +a type error. If any parameters are arrays, the arrays will be +flattened. If no numbers are provided, the function will return zero.

+
+
Returns
+
+

number - the largest value found

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

…collection

Array.<any> | any

values/array(s) in which the +maximum element is to be calculated

+
+
+
+
+

Example

+
+
+
+
minA([1, 2, 3], [4, 5, 6]) // returns 1
+minA("4", 8, 10, 12, null()) // returns 4
+
+
+
+
+

9.3.46. minute

+
+

minute(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Extract the minute (0 through 59) from a +date/time value

+
+
Returns
+
+

integer | Array.<integer> - Number of minutes in the +time portion of the date/time value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

A datetime/time value. Date/time +values can be generated using the datetime, +toDate, today, now and +time functions.

+
+
+
+
+

Example

+
+
+
+
minute(datetime(2008,5,23,12, 10, 0)) // returns 10
+minute(time(12, 10, 0)) // returns 10
+
+
+
+
+

9.3.47. mod

+
+

mod(dividend, divisor) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Return the remainder when one number is divided by another +number.

+
+
Returns
+
+

number | Array.<number> - Computes the remainder of +dividend/divisor. If dividend is negative, the result will also be +negative. If dividend is zero, an error is thrown.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

dividend

number | Array.<number>

The number for which to find +the remainder.

divisor

number | Array.<number>

The number by which to divide +number.

+
+
+
+
+

Example

+
+
+
+
mod(3, 2) // returns 1
+mod(-3, 2) // returns -1
+
+
+
+
+

9.3.48. month

+
+

month(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Finds the month of a date.

+
+
Returns
+
+

integer | Array.<integer> - The month number value, +ranging from 1 (January) to 12 (December)

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

source date/time value. Date/time values can be generated using the +datetime, toDate, today, +now and time functions.

+
+
+
+
+

Example

+
+
+
+
month(datetime(2008,5,23)) // returns 5
+
+
+
+
+

9.3.49. not

+
+

not(value) ⇒ boolean

+
+
+
+
Description
+
+

Compute logical NOT of a value. If the parameter is not +boolean it will be cast to boolean Note the +related unary NOT operator.

+
+
Returns
+
+

boolean - The logical NOT applied to the input parameter

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

value

any

any data type

+
+
+
+
+

Example

+
+
+
+
not(length("bar") > 0) // returns false
+not(false()) // returns true
+not("abcd") // returns false
+not("") // returns true
+
+
+
+
+

9.3.50. notNull

+
+

notNull(…argument) ⇒ any

+
+
+
+
Description
+
+

Finds the first argument that does not resolve to null. +This function accepts one or more arguments, and will evaluate them in +order until a non-null argument is encountered. If all arguments values +resolve to null, then return a null value.

+
+
Parameters
+
+ ++++ + + + + + + + + + + + + +
ParamType

…argument

any

+
+
+
+
+

Example

+
+
+
+
notNull(1, 2, 3, 4, `null`) // returns 1
+notNull(`null`, 2, 3, 4, `null`) // returns 2
+
+
+
+
+

9.3.51. now

+
+

now() ⇒ number

+
+
+
+
Description
+
+

Retrieve the current date/time.

+
+
Returns
+
+

number - representation of the current date/time value.

+
+
+
+
+
+

9.3.52. null

+
+

null() ⇒ boolean

+
+
+
+
Description
+
+

Return constant null value. Expressions may also use the +JSON literal: `null`

+
+
Returns
+
+

boolean - True

+
+
+
+
+
+

9.3.53. or

+
+

or(first, […operand]) ⇒ boolean

+
+
+
+
Description
+
+

Determines the logical OR result of a set of parameters. +If the parameters are not boolean they will be +cast to boolean. Note the related +Or Operator.

+
+
Returns
+
+

boolean - The logical result of applying OR to all parameters

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

first

any

logical expression

[…operand]

any

any number of additional expressions

+
+
+
+
+

Example

+
+
+
+
or((x / 2) == y, (y * 2) == x) // true
+
+
+
+
+

9.3.54. power

+
+

power(a, x) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Computes a raised to a power x. (a^x)

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

a

number | Array.<number>

The base number – can be any real +number.

x

number | Array.<number>

The exponent to which the base number +is raised.

+
+
+
+
+

Example

+
+
+
+
power(10, 2) // returns 100 (10 raised to power 2)
+
+
+
+
+

9.3.55. proper

+
+

proper(text) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Apply proper casing to a string. Proper casing is where +the first letter of each word is converted to an uppercase letter and +the rest of the letters in the word converted to lowercase. Words are +demarcated by whitespace, punctuation, or numbers. Specifically, any +character(s) matching the regular expression: [\s\d\p{P}]+.

+
+
Returns
+
+

string | Array.<string> - source string with proper +casing applied.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

text

string | Array.<string>

source string

+
+
+
+
+

Example

+
+
+
+
proper("this is a TITLE") // returns "This Is A Title"
+proper("2-way street") // returns "2-Way Street"
+proper("76BudGet") // returns "76Budget"
+
+
+
+
+

9.3.56. random

+
+

random() ⇒ number

+
+
+
+
Description
+
+

Generate a pseudo random number.

+
+
Returns
+
+

number - A value greater than or equal to zero, and less than +one.
+Example

+
+
+
+
+
+
random() // 0.022585461160693265
+
+
+
+
+

9.3.57. reduce

+
+

reduce(elements, expr, initialValue) ⇒ any

+
+
+
+
Description
+
+

Executes a user-supplied reducer expression on each +element of an array, in order, passing in the return value from the +expression from the preceding element. The final result of running the +reducer across all elements of the input array is a single value. The +expression can access the following properties of the current object:

+
+
    +
  • +

    accumulated: accumulated value based on the previous expression. For +the first array element use the initialValue parameter. If not +provided, then null

    +
  • +
  • +

    current: current element to process

    +
  • +
  • +

    index: index of the current element in the array

    +
  • +
  • +

    array: original array

    +
  • +
+
+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

elements

array

array of elements on which the expression will be +evaluated

expr

expression

reducer expression to be executed on each element

initialValue

any

the accumulated value to pass to the first array +element

+
+
+
+
+

Example

+
+
+
+
reduce([1, 2, 3], &(accumulated + current)) // returns 6
+// find maximum entry by age
+reduce(
+  [{age: 10, name: "Joe"},{age: 20, name: "John"}],
+  &max(@.accumulated.age, @.current.age), @[0].age)
+reduce([3, 3, 3], &accumulated * current, 1) // returns 27
+
+
+
+
+

9.3.58. register

+
+

register(functionName, expr) ⇒ Object

+
+
+
+
Description
+
+

Register a function. The registered function may take one +parameter. If more parameters are needed, combine them in an array or +object. A function may not be re-registered with a different definition. +Note that implementations are not required to provide register() in +order to be conformant. Built-in functions may not be overridden.

+
+
Returns
+
+

Object - returns an empty object

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

functionName

string

Name of the function to register. functionName +must begin with an underscore or uppercase letter and follow the regular +expression pattern: +^[_A-Z][_a-zA-Z0-9$]*$

expr

expression

Expression to execute with this function call

+
+
+
+
+

Example

+
+
+
+
register("_product", &@[0] * @[1]) // can now call: _product([2,21]) => returns 42
+register("_ltrim", &split(@,"").reduce(@, &accumulated & current | if(@ = " ", "", @), ""))
+// _ltrim("  abc  ") => returns "abc  "
+
+
+
+
+

9.3.59. registerWithParams

+
+

registerWithParams(functionName, expr) ⇒ Object

+
+
+
+
Description
+
+

Register a function that accepts multiple parameters. A +function may not be re-registered with a different definition. Note that +implementations are not required to provide registerWithParams() in +order to be conformant. Built-in functions may not be overridden.

+
+
Returns
+
+

Object - returns an empty object

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

functionName

string

Name of the function to register. functionName +must begin with an underscore or uppercase letter and follow the regular +expression pattern: +^[_A-Z][_a-zA-Z0-9$]*$

expr

expression

Expression to execute with this function call. +Parameters are passed as an array.

+
+
+
+
+

Example

+
+
+
+
registerWithParams("Product", &@[0] * @[1])
+// can now call: Product(2,21) => returns 42
+registerWithParams(
+  "Ltrim",
+  &split(@[0],"").reduce(@, &accumulated & current | if(@ = " ", "", @), "")
+ )
+// Ltrim("  abc  ") => returns "abc  "
+
+
+
+
+

9.3.60. replace

+
+

replace(subject, start, length, replacement) ⇒ string | array

+
+
+
+
Description
+
+

Generates text (or an array) where we substitute elements +at a given start position and length, with new text (or array elements).

+
+
Returns
+
+

string | array - the resulting text or array

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

string | array

original text or array

start

integer

zero-based index in the original text from where to +begin the replacement. Must be greater than or equal to 0.

length

integer

number of code points to be replaced. If start
+length is greater than the length of subject, all text past start +will be replaced.

replacement

any

Replacement to insert at the start index. If +subject is an array, and replacement is an array, the replacement +array elements will be inserted into the subject array. If subject +is an array and replacement is not an array, the replacement will be +inserted as a single element in subject If subject is a string, the +replacement will be coerced to a string.

+
+
+
+
+

Example

+
+
+
+
replace("abcdefghijk", 5, 5, "*") // returns abcde*k
+replace("2009",2,2,"10") // returns  2010
+replace("123456",0,3,"@") // returns @456
+replace(["blue","black","white","red"], 1, 2, ["green"]) // returns ["blue","green","red"]
+
+
+
+
+

9.3.61. rept

+
+

rept(text, count) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Return text repeated count times.

+
+
Returns
+
+

string | Array.<string> - Text generated from the +repeated text. if count is zero, returns an empty string.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

text

string | Array.<string>

text to repeat

count

integer | Array.<integer>

number of times to repeat the +text. Must be greater than or equal to 0.

+
+
+
+
+

Example

+
+
+
+
rept("x", 5) // returns "xxxxx"
+
+
+
+
+

9.3.62. reverse

+
+

reverse(subject) ⇒ array

+
+
+
+
Description
+
+

Reverses the order of an array or the order of code points +in a string

+
+
Returns
+
+

array - The resulting reversed array or string

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

subject

string | array

the source to be reversed

+
+
+
+
+

Example

+
+
+
+
reverse(["a", "b", "c"]) // returns ["c", "b", "a"]
+
+
+
+
+

9.3.63. right

+
+

right(subject, [elements]) ⇒ string | array

+
+
+
+
Description
+
+

Generates a string from the right-most code points of a +string or a subset of elements from the end of an array

+
+
Returns
+
+

string | array - The extracted substring or array +subset Returns null if the number of elements is less than 0

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

subject

string | array

The text/array containing the code +points/elements to extract

[elements]

integer

1

number of elements to pick

+
+
+
+
+

Example

+
+
+
+
right("Sale Price", 4) // returns "rice"
+right("Sweden") // returns "n"
+right([4, 5, 6], 2) // returns [5, 6]
+
+
+
+
+

9.3.64. round

+
+

round(num, [precision]) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Round a number to a specified precision:

+
+
    +
  • +

    If precision is greater than zero, round to the specified number of +decimal places.

    +
  • +
  • +

    If precision is 0, round to the nearest integer.

    +
  • +
  • +

    If precision is less than 0, round to the left of the decimal point.

    +
  • +
+
+
+
Returns
+
+

number | Array.<number> - rounded value. Rounding a +half value will round up.

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

num

number | Array.<number>

number to round

[precision]

integer | Array.<integer>

0

precision to use for +the rounding operation.

+
+
+
+
+

Example

+
+
+
+
round(2.15, 1) // returns 2.2
+round(626.3,-3) // returns 1000 (Rounds 626.3 to the nearest multiple of 1000)
+round(626.3, 0) // returns 626
+round(1.98,-1) // returns 0 (Rounds 1.98 to the nearest multiple of 10)
+round(-50.55,-2) // -100 (round -50.55 to the nearest multiple of 100)
+round(1.95583) // 2
+round(-1.5) // -1
+
+
+
+
+ +
+

search(findText, withinText, [startPos]) ⇒ array

+
+
+
+
Description
+
+

Perform a wildcard search. The search is case-sensitive +and supports two forms of wildcards: * finds a sequence of +code points and ? finds a single code point. To use * or +? or \ as text values, precede them with an escape +(\) character. Note that the wildcard search is not greedy. +e.g. search("a*b", "abb") will return [0, "ab"] Not +[0, "abb"]

+
+
Returns
+
+

array - returns an array with two values:

+
+
    +
  • +

    The start position of the found text and the text string that was +found.

    +
  • +
  • +

    If a match was not found, an empty array is returned.

    +
  • +
+
+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

findText

string | Array.<string>

the search string – which +may include wild cards.

withinText

string | Array.<string>

The string to search.

[startPos]

integer | Array.<integer>

0

The zero-based position +of withinText to start searching. A negative value is not allowed.

+
+
+
+
+

Example

+
+
+
+
search("a?c", "acabc") // returns [2, "abc"]
+
+
+
+
+

9.3.66. second

+
+

second(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Extract the seconds of the time value in a +date/time value.

+
+
Returns
+
+

integer | Array.<integer> - The number of seconds: 0 +through 59

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

datetime/time for which the second +is to be returned. Date/time values can be generated using the +datetime, toDate, today, +now and time functions.

+
+
+
+
+

Example

+
+
+
+
second(datetime(2008,5,23,12, 10, 53)) // returns 53
+second(time(12, 10, 53)) // returns 53
+
+
+
+
+

9.3.67. sign

+
+

sign(num) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Computes the sign of a number passed as argument.

+
+
Returns
+
+

number | Array.<number> - returns 1 or -1, indicating +the sign of num. If the num is 0, it will return 0.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

any number

+
+
+
+
+

Example

+
+
+
+
sign(5) // 1
+sign(-5) // -1
+sign(0) // 0
+
+
+
+
+

9.3.68. sin

+
+

sin(angle) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Computes the sine of a number in radians

+
+
Returns
+
+

number | Array.<number> - The sine of angle, between +-1 and 1, inclusive

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

angle

number | Array.<number>

A number representing an angle in +radians.

+
+
+
+
+

Example

+
+
+
+
sin(0) // 0
+sin(1) // 0.8414709848078965
+
+
+
+
+

9.3.69. sort

+
+

sort(list) ⇒ Array.<any>

+
+
+
+
Description
+
+

This function accepts an array values and returns an array +with the elements in sorted order. If there are mixed data types, the +values will be grouped in order: numbers, strings, booleans, nulls +String sorting is based on code points and is not locale-sensitive. If +the sort encounters any objects or arrays, it will throw an evaluation +error.

+
+
Returns
+
+

Array.<any> - The ordered result

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

list

Array.<any>

to be sorted

+
+
+
+
+

Example

+
+
+
+
sort([1, 2, 4, 3, 1]) // returns [1, 1, 2, 3, 4]
+sort(["20", 20, true(), "100", null(), 100]) // returns [20, 100, "100", "20", true, null]
+
+
+
+
+

9.3.70. sortBy

+
+

sortBy(elements, expr) ⇒ array

+
+
+
+
Description
+
+

Sort an array using an expression to find the sort key. +For each element in the array, the expression is applied and the +resulting value is used as the sort value. If the result of evaluating +the expression against the current array element results in type other +than a number or a string, a TypeError will occur.

+
+
Returns
+
+

array - The sorted array

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

elements

array

Array to be sorted

expr

expression

The comparison expression

+
+
+
+
+

Example

+
+
+
+
// returns ["e", "def", "abcd"]
+sortBy(["abcd", "e", "def"], &length(@))
+
+// returns [{year: 1910}, {year: 2010}, {year: 2020}]
+sortBy([{year: 2010}, {year: 2020}, {year: 1910}], &year)
+
+// returns [5, -10, -11, -15, 30]
+sortBy([-15, 30, -10, -11, 5], &abs(@))
+
+
+
+
+

9.3.71. split

+
+

split(string, separator) ⇒ Array.<string> | +Array.<Array.<string>>

+
+
+
+
Description
+
+

Split a string into an array, given a separator

+
+
Returns
+
+

Array.<string> | Array.<Array.<string>> - The array of +separated strings

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

string

string | Array.<string>

string to split

separator

string | Array.<string>

separator where the split(s) +should occur

+
+
+
+
+

Example

+
+
+
+
split("abcdef", "") // returns ["a", "b", "c", "d", "e", "f"]
+split("abcdef", "e") // returns ["abcd", "f"]
+
+
+
+
+

9.3.72. sqrt

+
+

sqrt(num) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Find the square root of a number

+
+
Returns
+
+

number | Array.<number> - The calculated square root +value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

num

number | Array.<number>

source number

+
+
+
+
+

Example

+
+
+
+
sqrt(4) // returns 2
+
+
+
+
+

9.3.73. startsWith

+
+

startsWith(subject, prefix) ⇒ boolean | Array.<boolean>

+
+
+
+
Description
+
+

Determine if a string starts with a prefix.

+
+
Returns
+
+

boolean | Array.<boolean> - true if prefix matches +the start of subject

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

string | Array.<string>

string to search

prefix

string | Array.<string>

prefix to search for

+
+
+
+
+

Example

+
+
+
+
startsWith("jack is at home", "jack") // returns true
+
+
+
+
+

9.3.74. stdev

+
+

stdev(values) ⇒ number

+
+
+
+
Description
+
+

Estimates standard deviation based on a sample. stdev +assumes that its arguments are a sample of the entire population. If +your data represents a entire population, then compute the standard +deviation using stdevp. Non-numeric values (text, boolean, +null etc) are ignored. If there are nested arrays, they are flattened.

+
+
Returns
+
+

number - +Standard deviation

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

values

Array.<any>

The array containing numbers comprising the +population. Array size must be greater than 1.

+
+
+
+
+

Example

+
+
+
+
stdev([1345, 1301, 1368]) // returns 34.044089061098404
+stdevp([1345, 1301, 1368]) // returns 27.797
+
+
+
+
+

9.3.75. stdevA

+
+

stdevA(numbers) ⇒ number

+
+
+
+
Description
+
+

Estimates standard deviation based on a sample. stdev +assumes that its arguments are a sample of the entire population. If +your data represents a entire population, then compute the standard +deviation using stdevpA. Nested arrays are flattened. Null values are +ignored. All other parameters are converted to number. If conversion to +number fails, a type error is thrown.

+
+
Returns
+
+

number - +Standard deviation

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

numbers

Array.<number>

The array of numbers comprising the +population. Array size must be greater than 1.

+
+
+
+
+

Example

+
+
+
+
stdevA([1345, "1301", 1368]) // returns 34.044089061098404
+stdevpA([1345, 1301, "1368"]) // returns 27.797
+
+
+
+
+

9.3.76. stdevp

+
+

stdevp(values) ⇒ number

+
+
+
+
Description
+
+

Calculates standard deviation based on the entire +population given as arguments. stdevp assumes that its arguments are +the entire population. If your data represents a sample of the +population, then compute the standard deviation using +stdev. Non-numeric values (text, boolean, null etc) are +ignored. If there are nested arrays, they are flattened.

+
+
Returns
+
+

number - Calculated standard deviation

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

values

Array.<any>

The array containing numbers comprising the +population. An empty array is not allowed.

+
+
+
+
+

Example

+
+
+
+
stdevp([1345, 1301, 1368]) // returns 27.797
+stdev([1345, 1301, 1368]) // returns 34.044
+
+
+
+
+

9.3.77. stdevp

+
+

stdevp(numbers) ⇒ number

+
+
+
+
Description
+
+

Calculates standard deviation based on the entire +population given as arguments. stdevpA assumes that its arguments are +the entire population. If your data represents a sample of the +population, then compute the standard deviation using +[_stdevA]. Nested arrays are flattened. Null values are +ignored. All other parameters are converted to number. If conversion to +number fails, a type error is thrown.

+
+
Returns
+
+

number - Calculated standard deviation

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

numbers

Array.<number>

The array of numbers comprising the +population. An empty array is not allowed.

+
+
+
+
+

Example

+
+
+
+
stdevpA([1345, "1301", 1368]) // returns 27.797
+stdevA([1345, 1301, "1368"]) // returns 34.044
+
+
+
+
+

9.3.78. substitute

+
+

substitute(text, old, new, [which]) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Generates a string from the input text, with text old +replaced by text new (when searching from the left). If there is no +match, or if old has length 0, text is returned unchanged. Note that +old and new may have different lengths.

+
+
Returns
+
+

string | Array.<string> - replaced string

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

text

string | Array.<string>

The text for which to substitute +code points.

old

string | Array.<string>

The text to replace.

new

string | Array.<string>

The text to replace old with. If +new is an empty string, then occurrences of old are removed from +text.

[which]

integer | Array.<integer>

The zero-based occurrence of +old text to replace with new text. If which parameter is omitted, +every occurrence of old is replaced with new.

+
+
+
+
+

Example

+
+
+
+
substitute("Sales Data", "Sales", "Cost") // returns "Cost Data"
+substitute("Quarter 1, 2001", "1", "2", 1)" // returns "Quarter 1, 2002"
+substitute("Quarter 1, 2011", "1", "2", 2)" // returns "Quarter 1, 2012"
+
+
+
+
+

9.3.79. sum

+
+

sum(collection) ⇒ number

+
+
+
+
Description
+
+

Calculates the sum of the provided array. An empty array +will produce a return value of 0. Any values that are not numbers (null, +boolean, strings, objects) will be ignored. If any parameters are +arrays, the arrays will be flattened.

+
+
Returns
+
+

number - The computed sum

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

collection

Array.<any>

array of values

+
+
+
+
+

Example

+
+
+
+
sum([1, 2, 3]) // returns 6
+
+
+
+
+

9.3.80. tan

+
+

tan(angle) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Computes the tangent of a number in radians

+
+
Returns
+
+

number | Array.<number> - The tangent of angle

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

angle

number | Array.<number>

A number representing an angle in +radians.

+
+
+
+
+

Example

+
+
+
+
tan(0) // 0
+tan(1) // 1.5574077246549023
+
+
+
+
+

9.3.81. time

+
+

time(hours, [minutes], [seconds]) ⇒ number

+
+
+
+
Description
+
+

Construct and returns a time +value. If any of the units are greater or less than their normal +range, the overflow/underflow will be added/subtracted from the next +greater unit.

+
+
Returns
+
+

number - Returns a date/time value representing the fraction +of the day consumed by the given time

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

hours

integer

Zero-based integer value between 0 and 23 +representing the hour of the day.

[minutes]

integer

0

Zero-based integer value representing the minute +segment of a time.

[seconds]

integer

0

Zero-based integer value representing the +seconds segment of a time.

+
+
+
+
+

Example

+
+
+
+
time(12, 0, 0) | [hour(@), minute(@), second(@)] // returns [12, 0, 0]
+
+
+
+
+

9.3.82. toArray

+
+

toArray(arg) ⇒ array

+
+
+
+
Description
+
+

Converts the provided argument to an array. The conversion +happens as per the following rules:

+
+
    +
  • +

    array - Returns the provided value.

    +
  • +
  • +

    number/string/object/boolean/null - Returns a one element array +containing the argument.

    +
  • +
+
+
+
Returns
+
+

array - The resulting array

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

arg

any

parameter to turn into an array

+
+
+
+
+

Example

+
+
+
+
toArray(1) // returns [1]
+toArray(null()) // returns [`null`]
+
+
+
+
+

9.3.83. toDate

+
+

toDate(ISOString) ⇒ number

+
+
+
+
Description
+
+

Converts the provided string to a date/time value.

+
+
Returns
+
+

number - The resulting date/time +number. If conversion fails, return null.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

ISOString

string

An +ISO8601 formatted +string. (limited to the RFC +3339 profile) If the string does not include a timezone offset (or +trailing `Z'), it will be assumed to be local time

+
+
+
+
+

Example

+
+
+
+
toDate("20231110T130000+04:00") // returns 19671.375
+toDate("2023-11-10T13:00:00+04:00") // returns 19671.375
+toDate("20231110") | year(@) & "/" & month(@) // returns "2023/11"
+
+
+
+
+

9.3.84. today

+
+

today() ⇒ number

+
+
+
+
Description
+
+

Returns a date/time value +representing the start of the current day. i.e. midnight

+
+
Returns
+
+

number - today at midnight

+
+
+
+
+
+

9.3.85. toNumber

+
+

toNumber(value, [base]) ⇒ number

+
+
+
+
Description
+
+

Converts the provided arg to a number. The conversions +follow the type coercion rules but will also: * +Convert non-numeric strings to zero * Convert arrays to arrays of +numbers

+
+
Returns
+
+

number - The resulting number. If conversion to number fails, +return null.

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

value

any | Array.<any>

to convert to number

[base]

integer | Array.<integer>

10

If the input arg is a +string, the base to use to convert to number. One of: 2, 8, 10, 16. +Defaults to 10.

+
+
+
+
+

Example

+
+
+
+
toNumber(1) // returns 1
+toNumber("10") // returns 10
+toNumber({a: 1}) // returns null
+toNumber(true()) // returns 1
+toNumber("10f") // returns null
+toNumber("FF", 16) // returns 255
+
+
+
+
+

9.3.86. toString

+
+

toString(arg, [indent]) ⇒ string

+
+
+
+
Description
+
+

Returns the argument converted to a string. If the +argument is a string, it will be returned unchanged. Otherwise, returns +the JSON encoded value of the argument.

+
+
Returns
+
+

string - The result string.

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

arg

any

Value to be converted to a string

[indent]

integer

0

Indentation to use when converting objects and +arrays to a JSON string

+
+
+
+
+

Example

+
+
+
+
toString(1) // returns "1"
+toString(true()) // returns "true"
+toString({sum: 12 + 13}) // "{"sum":25}"
+toString("hello") // returns "hello"
+
+
+
+
+

9.3.87. trim

+
+

trim(text) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Remove leading and trailing spaces (U+0020), and replace +all internal multiple spaces with a single space. Note that other +whitespace characters are left intact.

+
+
Returns
+
+

string | Array.<string> - trimmed string

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

text

string | Array.<string>

string to trim

+
+
+
+
+

Example

+
+
+
+
trim("   ab    c   ") // returns "ab c"
+
+
+
+
+

9.3.88. true

+
+

true() ⇒ boolean

+
+
+
+
Description
+
+

Return constant boolean true value. Expressions may also +use the JSON literal: `true`

+
+
Returns
+
+

boolean - True

+
+
+
+
+
+

9.3.89. trunc

+
+

trunc(numA, [numB]) ⇒ number | Array.<number>

+
+
+
+
Description
+
+

Truncates a number to an integer by removing the +fractional part of the number. i.e. it rounds towards zero.

+
+
Returns
+
+

number | Array.<number> - Truncated value

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

numA

number | Array.<number>

number to truncate

[numB]

integer | Array.<integer>

0

A number specifying the +number of decimal digits to preserve.

+
+
+
+
+

Example

+
+
+
+
trunc(8.9) // returns 8
+trunc(-8.9) // returns -8
+trunc(8.912, 2) // returns 8.91
+
+
+
+
+

9.3.90. type

+
+

type(subject) ⇒ string

+
+
+
+
Description
+
+

Finds the type name of the given subject argument as a +string value. The return value will be one of the following:

+
+
    +
  • +

    number

    +
  • +
  • +

    string

    +
  • +
  • +

    boolean

    +
  • +
  • +

    array

    +
  • +
  • +

    object

    +
  • +
  • +

    null

    +
  • +
+
+
+
Returns
+
+

string - The type name

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

subject

any

type to evaluate

+
+
+
+
+

Example

+
+
+
+
type(1) // returns "number"
+type("") // returns "string"
+
+
+
+
+

9.3.91. unique

+
+

unique(input) ⇒ array

+
+
+
+
Description
+
+

Find the set of unique elements within an array

+
+
Returns
+
+

array - array with duplicate elements removed

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

input

array

input array

+
+
+
+
+

Example

+
+
+
+
unique([1, 2, 3, 4, 1, 1, 2]) // returns [1, 2, 3, 4]
+
+
+
+
+

9.3.92. upper

+
+

upper(input) ⇒ string | Array.<string>

+
+
+
+
Description
+
+

Converts all the alphabetic code points in a string to +uppercase.

+
+
Returns
+
+

string | Array.<string> - the upper case value of the +input string

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

input

string | Array.<string>

input string

+
+
+
+
+

Example

+
+
+
+
upper("abcd") // returns "ABCD"
+
+
+
+
+

9.3.93. value

+
+

value(subject, index) ⇒ any

+
+
+
+
Description
+
+

Perform an indexed lookup on an object or array

+
+
Returns
+
+

any - the result of the lookup – or null if not found.

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + + + + + + +
ParamTypeDescription

subject

object | array | null

on which to perform the +lookup. When querying for hidden properties, +subject may be any data type.

index

string | integer

if subject is an object, index must +be a string indicating the key name to search for. If subject is an +array, then index must be an integer indicating the offset into the +array

+
+
+
+
+

Example

+
+
+
+
value({a: 1, b:2, c:3}, "a") // returns 1
+value([1, 2, 3, 4], 2) // returns 3
+
+
+
+
+

9.3.94. values

+
+

values(obj) ⇒ array

+
+
+
+
Description
+
+

Generates an array of the values of the provided object. +Note that because JSON objects are inherently unordered, the values +associated with the provided object are also unordered.

+
+
Returns
+
+

array - array of the values

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

obj

object

source object

+
+
+
+
+

Example

+
+
+
+
values({a : 3, b : 4}) // returns [3, 4]
+
+
+
+
+

9.3.95. weekday

+
+

weekday(date, [returnType]) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Extract the day of the week from a date. The specific +numbering of the day of week is controlled by the returnType +parameter:

+
+
    +
  • +

    1 : Sunday (1), Monday (2), …, Saturday (7)

    +
  • +
  • +

    2 : Monday (1), Tuesday (2), …, Sunday(7)

    +
  • +
  • +

    3 : Monday (0), Tuesday (1), …., Sunday(6)

    +
  • +
+
+
+
Returns
+
+

integer | Array.<integer> - day of the week

+
+
Parameters
+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDefaultDescription

date

number | Array.<number>

date/time value for which the day of the week is to be returned. +Date/time values can be generated using the datetime, +toDate, today, now and +time functions.

[returnType]

integer | Array.<integer>

1

Determines the +representation of the result. An unrecognized returnType will result in +a error.

+
+
+
+
+

Example

+
+
+
+
weekday(datetime(2006,5,21)) // 1
+weekday(datetime(2006,5,21), 2) // 7
+weekday(datetime(2006,5,21), 3) // 6
+
+
+
+
+

9.3.96. year

+
+

year(date) ⇒ integer | Array.<integer>

+
+
+
+
Description
+
+

Finds the year of a datetime value

+
+
Returns
+
+

integer | Array.<integer> - The year value

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

date

number | Array.<number>

input date/time value Date/time values can be generated using the +datetime, toDate, today, +now and time functions.

+
+
+
+
+

Example

+
+
+
+
year(datetime(2008,5,23)) // returns 2008
+
+
+
+
+

9.3.97. zip

+
+

zip(…arrays) ⇒ array

+
+
+
+
Description
+
+

Generates a convolved (zipped) array containing grouped +arrays of values from the array arguments from index 0, 1, 2, etc. This +function accepts a variable number of arguments. The length of the +returned array is equal to the length of the shortest array.

+
+
Returns
+
+

array - An array of arrays with elements zipped together

+
+
Parameters
+
+ +++++ + + + + + + + + + + + + + + +
ParamTypeDescription

…arrays

array

array of arrays to zip together

+
+
+
+
+

Example

+
+
+
+
zip([1, 2, 3], [4, 5, 6, 7]) // returns [[1, 4], [2, 5], [3, 6]]
+
+
+
+
+
+
+
+

10. Integrations

+
+
+

The json-formula API allows integrations to customize various json-formula behaviors.

+
+
+

10.1. Globals

+
+

By default, json-formula has one global symbol: @. A host may inject additional global identifiers. These identifiers must be prefixed with the dollar ($) symbol.

+
+

Examples

+
+

Given: a global symbol:

+
+
+
+
  {
+    "$days": [
+       "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
+    ]
+  }
+
+
+
+
+
    eval(value($days, weekday(datetime(date.year, date.month, date.day), 3)),
+    {
+      "date": {
+        "year": 2023,
+        "month": 9,
+        "day": 13
+      }
+    }) -> "Wednesday"
+
+
+
+
+

10.2. Specify locale

+
+

The default locale for json-formula is en-US. A host may specify an alternate locale. The locale setting affects only the behavior of the casefold() function.

+
+
+
+

10.3. Custom toNumber

+
+

In various contexts, json-formula converts values to numbers. +A host may provide its own toNumber() function that json-formula will use in place of the default functionality. For example, a custom toNumber() could make use of locale-specific date formats to attempt to convert a string to a date value, or could allow currency values e.g., "$123.45" to be converted to number.

+
+
+
+

10.4. Additional Functions

+
+

A host may provide its own set of functions to augment the base set provided by json-formula.

+
+
+
+

10.5. Hidden Properties

+
+

A host system may construct its source JSON data with complex properties that have nested structure that can be found through explicit navigation, but will not be found through normal tree searching. Here is an example of how this can be configured in JavaScript:

+
+
+
+
function createField(id, value) {
+  class Field {
+    valueOf() { return value; }
+
+    toString() { return value.toString(); }
+
+    toJSON() { return value; }
+  }
+  const f = new Field();
+  Object.defineProperty(f, '$id', { get: () -> id });
+  Object.defineProperty(f, '$value', { get: () -> value });
+
+  return f;
+}
+
+const json = {
+  "street": createField("abc123", "Maple Street"),
+  "city": createField("def456", "New York")
+}
+
+Given this configuration, these search results are possible:
+
+street -> "Maple Street"
+street.$value -> "Maple Street"
+street.$id -> "abc123"
+type(street) -> "string"
+keys(street) -> []
+
+
+
+
+

10.6. Tracking

+
+

A host system may want to track which properties are accessed during the evaluation of an expression. This can be done by providing a track function on the object being evaluated. The track function will be called with the object being evaluated and the key being accessed. Here is an example of how this can be configured in JavaScript:

+
+
+
+
properties[Symbol.for('track')] = (obj, key) => trackDependent(obj, key);
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/doc/output/json-formula-specification-2.0.0.pdf b/doc/output/json-formula-specification-2.0.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..204d8428b99f1e04ec848a65997a3485b85af761 GIT binary patch literal 1382935 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 CaR)q(^nl;Ek25CDwZ$wY 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 z

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%0DX)Kc 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�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 UJsJob?n9_f!-h?rW6 Date: Wed, 12 Nov 2025 18:20:31 -0500 Subject: [PATCH 2/3] documentation improvements --- dist/tutorial.js.map | 2 +- doc/output/JSDOCS.md | 128 +++++++++++++++--- .../json-formula-specification-2.0.0.html | 14 +- .../json-formula-specification-2.0.0.pdf | Bin 1382935 -> 1383241 bytes doc/spec.adoc | 12 +- npm-shrinkwrap.json | 116 ++++++++++------ package.json | 2 +- src/json-formula.js | 102 +++++++++++++- 8 files changed, 292 insertions(+), 84 deletions(-) diff --git a/dist/tutorial.js.map b/dist/tutorial.js.map index 44edf8ce..48551df2 100644 --- a/dist/tutorial.js.map +++ b/dist/tutorial.js.map @@ -1 +1 @@ -{"version":3,"file":"tutorial.js","mappings":"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","sources":["webpack://jsonFormula/webpack/bootstrap","webpack://jsonFormula/webpack/runtime/make namespace object","webpack://jsonFormula/./src/dataTypes.js","webpack://jsonFormula/./src/tokenDefinitions.js","webpack://jsonFormula/./src/errors.js","webpack://jsonFormula/./src/matchType.js","webpack://jsonFormula/./src/utils.js","webpack://jsonFormula/./src/TreeInterpreter.js","webpack://jsonFormula/./src/Lexer.js","webpack://jsonFormula/./src/Parser.js","webpack://jsonFormula/./src/functions.js","webpack://jsonFormula/./src/interpreter.js","webpack://jsonFormula/./src/json-formula.js","webpack://jsonFormula/./tutorial/Form.js","webpack://jsonFormula/./src/stringToNumber.js","webpack://jsonFormula/./tutorial/tutorial.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n// Type constants used to define functions.\nconst dataTypes = {\n TYPE_NUMBER: 0,\n TYPE_ANY: 1,\n TYPE_STRING: 2,\n TYPE_ARRAY: 3,\n TYPE_OBJECT: 4,\n TYPE_BOOLEAN: 5,\n TYPE_EXPREF: 6,\n TYPE_NULL: 7,\n TYPE_ARRAY_NUMBER: 8,\n TYPE_ARRAY_STRING: 9,\n TYPE_ARRAY_ARRAY: 10,\n TYPE_EMPTY_ARRAY: 11,\n};\n\nconst typeNameTable = {\n [dataTypes.TYPE_NUMBER]: 'number',\n [dataTypes.TYPE_ANY]: 'any',\n [dataTypes.TYPE_STRING]: 'string',\n [dataTypes.TYPE_ARRAY]: 'array',\n [dataTypes.TYPE_OBJECT]: 'object',\n [dataTypes.TYPE_BOOLEAN]: 'boolean',\n [dataTypes.TYPE_EXPREF]: 'expression',\n [dataTypes.TYPE_NULL]: 'null',\n [dataTypes.TYPE_ARRAY_NUMBER]: 'Array',\n [dataTypes.TYPE_ARRAY_STRING]: 'Array',\n [dataTypes.TYPE_ARRAY_ARRAY]: 'Array',\n [dataTypes.TYPE_EMPTY_ARRAY]: 'array',\n};\n\nexport { dataTypes, typeNameTable };\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nexport default {\n TOK_EOF: 'EOF',\n TOK_IDENTIFIER: 'Identifier',\n TOK_QUOTEDIDENTIFIER: 'QuotedIdentifier',\n TOK_RBRACKET: 'Rbracket',\n TOK_RPAREN: 'Rparen',\n TOK_COMMA: 'Comma',\n TOK_COLON: 'Colon',\n TOK_CONCATENATE: 'Concatenate',\n TOK_RBRACE: 'Rbrace',\n TOK_NUMBER: 'Number',\n TOK_CURRENT: 'Current',\n TOK_GLOBAL: 'Global',\n TOK_EXPREF: 'Expref',\n TOK_PIPE: 'Pipe',\n TOK_OR: 'Or',\n TOK_AND: 'And',\n TOK_ADD: 'Add',\n TOK_SUBTRACT: 'Subtract',\n TOK_UNARY_MINUS: 'UnaryMinus',\n TOK_MULTIPLY: 'Multiply',\n TOK_UNION: 'Union',\n TOK_DIVIDE: 'Divide',\n TOK_COMPARATOR: 'Comparator',\n TOK_FLATTEN: 'Flatten',\n TOK_STAR: 'Star',\n TOK_FILTER: 'Filter',\n TOK_DOT: 'Dot',\n TOK_NOT: 'Not',\n TOK_LBRACE: 'Lbrace',\n TOK_LBRACKET: 'Lbracket',\n TOK_LPAREN: 'Lparen',\n TOK_JSON: 'Literal',\n TOK_STRING: 'String',\n TOK_INT: 'Integer',\n};\n","/*\nCopyright 2023 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nexport function typeError(desc) {\n return new TypeError(desc);\n}\n\nexport function syntaxError(desc) {\n const e = new Error(desc);\n e.name = 'SyntaxError';\n return e;\n}\n\nexport function functionError(desc) {\n const e = new Error(desc);\n e.name = 'FunctionError';\n return e;\n}\n\nexport function evaluationError(desc) {\n const e = new Error(desc);\n e.name = 'EvaluationError';\n return e;\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport { dataTypes, typeNameTable } from './dataTypes.js';\nimport tokenDefinitions from './tokenDefinitions.js';\nimport { typeError } from './errors.js';\n// import { isClass } from './utils.js';\n\nconst {\n TYPE_NUMBER,\n TYPE_ANY,\n TYPE_STRING,\n TYPE_ARRAY,\n TYPE_OBJECT,\n TYPE_BOOLEAN,\n TYPE_EXPREF,\n TYPE_NULL,\n TYPE_ARRAY_NUMBER,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY_ARRAY,\n TYPE_EMPTY_ARRAY,\n} = dataTypes;\n\nconst {\n TOK_EXPREF,\n} = tokenDefinitions;\n\nfunction isArray(t) {\n return [\n TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING, TYPE_ARRAY_ARRAY, TYPE_EMPTY_ARRAY,\n ].includes(t);\n}\n\nexport function getType(inputObj) {\n function simpleType(obj) {\n if (obj === null) return TYPE_NULL;\n const t = typeof obj;\n if (t === 'string') return TYPE_STRING;\n if (t === 'number') return TYPE_NUMBER;\n if (t === 'boolean') return TYPE_BOOLEAN;\n if (Array.isArray(obj)) {\n if (obj.length === 0) return TYPE_EMPTY_ARRAY;\n if (obj.flat(Infinity).every(a => getType(a) === TYPE_NUMBER)) return TYPE_ARRAY_NUMBER;\n if (obj.flat(Infinity).every(a => getType(a) === TYPE_STRING)) return TYPE_ARRAY_STRING;\n if (obj.every(a => isArray(getType(a)))) return TYPE_ARRAY_ARRAY;\n return TYPE_ARRAY;\n }\n // Check if it's an expref. If it has, it's been\n // tagged with a jmespathType attr of 'Expref';\n if (obj.jmespathType === TOK_EXPREF) return TYPE_EXPREF;\n return TYPE_OBJECT;\n }\n let type = simpleType(inputObj);\n if (type !== TYPE_OBJECT) return type;\n // if inputObj is a class, then convert it to its base type via JSON\n const obj = JSON.parse(JSON.stringify(inputObj));\n type = simpleType(obj);\n return type;\n}\n\nexport function isArrayType(t) {\n return [\n TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING, TYPE_ARRAY_ARRAY, TYPE_EMPTY_ARRAY,\n ].includes(getType(t));\n}\n\nexport function getTypeName(arg) {\n return typeNameTable[getType(arg)];\n}\n\nfunction supportedConversion(from, to) {\n const pairs = {\n [TYPE_NUMBER]: [\n TYPE_STRING,\n TYPE_ARRAY,\n TYPE_ARRAY_NUMBER,\n TYPE_BOOLEAN,\n ],\n [TYPE_BOOLEAN]: [\n TYPE_STRING,\n TYPE_NUMBER,\n TYPE_ARRAY,\n ],\n [TYPE_ARRAY]: [TYPE_BOOLEAN, TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER],\n [TYPE_ARRAY_NUMBER]: [TYPE_BOOLEAN, TYPE_ARRAY_STRING, TYPE_ARRAY],\n [TYPE_ARRAY_STRING]: [TYPE_BOOLEAN, TYPE_ARRAY_NUMBER, TYPE_ARRAY],\n [TYPE_ARRAY_ARRAY]: [TYPE_BOOLEAN],\n [TYPE_EMPTY_ARRAY]: [TYPE_BOOLEAN],\n\n [TYPE_OBJECT]: [TYPE_BOOLEAN],\n [TYPE_NULL]: [\n TYPE_STRING,\n TYPE_NUMBER,\n TYPE_BOOLEAN,\n ],\n [TYPE_STRING]: [\n TYPE_NUMBER,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY,\n TYPE_BOOLEAN],\n };\n return pairs[from].includes(to);\n}\n\nexport function matchType(expectedList, argValue, context, toNumber, toString) {\n const actual = getType(argValue);\n if (argValue?.jmespathType === TOK_EXPREF && !expectedList.includes(TYPE_EXPREF)) {\n throw typeError(`${context} does not accept an expression reference argument.`);\n }\n const isObject = t => t === TYPE_OBJECT;\n const match = (expect, found) => expect === found\n || expect === TYPE_ANY\n || (expect === TYPE_ARRAY && isArray(found))\n || (isArray(expect) && found === TYPE_EMPTY_ARRAY);\n\n if (expectedList.some(type => match(type, actual))) return argValue;\n\n // if the function allows multiple types, we can't coerce the type and we need an exact match\n // Of the set of expected types, filter out the ones that can be coerced from the actual type\n const filteredList = expectedList.filter(t => supportedConversion(actual, t));\n if (filteredList.length === 0) {\n throw typeError(`${context} expected argument to be type ${typeNameTable[expectedList[0]]} but received type ${typeNameTable[actual]} instead.`);\n }\n const exactMatch = filteredList.length > 1;\n const expected = filteredList[0];\n let wrongType = false;\n\n // Can't coerce objects and arrays to any other type\n if (isArray(actual)) {\n if ([TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING].includes(expected)) {\n if (argValue.flat(Infinity).some(a => {\n const t = getType(a);\n // can't coerce arrays or objects to numbers or strings\n return isArray(t) || isObject(t);\n })) wrongType = true;\n }\n }\n // nothing coerces to an object\n if (exactMatch && expected === TYPE_OBJECT) wrongType = true;\n\n if (exactMatch) {\n throw typeError(`${context} cannot process type: ${typeNameTable[actual]}. Must be one of: ${expectedList.map(t => typeNameTable[t]).join(', ')}.`);\n }\n if (wrongType) {\n throw typeError(`${context} expected argument to be type ${typeNameTable[expected]} but received type ${typeNameTable[actual]} instead.`);\n }\n // Can't coerce Objects and arrays to anything other than boolean\n if (isObject(actual) && expected === TYPE_BOOLEAN) {\n return Object.keys(argValue).length === 0;\n }\n\n // no exact match, see if we can coerce an array type\n if (isArray(actual)) {\n const toArray = a => (Array.isArray(a) ? a : [a]);\n const coerceString = a => (Array.isArray(a) ? a.map(coerceString) : toString(a));\n const coerceNumber = a => (Array.isArray(a) ? a.map(coerceNumber) : toNumber(a));\n\n if (expected === TYPE_BOOLEAN) return argValue.length > 0;\n if (expected === TYPE_ARRAY_STRING) return argValue.map(coerceString);\n if (expected === TYPE_ARRAY_NUMBER) return argValue.map(coerceNumber);\n if (expected === TYPE_ARRAY_ARRAY) return argValue.map(toArray);\n }\n\n if (!isArray(actual) && !isObject(actual)) {\n if (expected === TYPE_ARRAY_STRING) return [toString(argValue)];\n if (expected === TYPE_ARRAY_NUMBER) return [toNumber(argValue)];\n if (expected === TYPE_ARRAY) return [argValue];\n if (expected === TYPE_NUMBER) return toNumber(argValue);\n if (expected === TYPE_STRING) return toString(argValue);\n if (expected === TYPE_BOOLEAN) return !!argValue;\n }\n\n throw typeError(`${context} expected argument to be type ${typeNameTable[expected]} but received type ${typeNameTable[actual]} instead.`);\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nexport function isArray(obj) {\n return Array.isArray(obj);\n}\n\nexport function isObject(obj) {\n if (obj !== null) {\n return Object.prototype.toString.call(obj) === '[object Object]';\n }\n return false;\n}\n\nexport function getValueOf(a) {\n if (a === null || a === undefined) return a;\n if (isArray(a)) {\n return a.map(i => getValueOf(i));\n }\n // if we have a child named 'valueOf' then we're an object,\n // and just return the object.\n if (typeof (a.valueOf) !== 'function') return a;\n return a.valueOf();\n}\n\nexport function toBoolean(param) {\n if (param === null) return false;\n // in case it's an object with a valueOf defined\n const val = getValueOf(param);\n\n // empty arrays are false\n if (Array.isArray(val)) return val.length > 0;\n // empty objects are false\n if (isObject(val)) return Object.keys(val).length > 0;\n return !!val;\n}\n\nexport function strictDeepEqual(lhs, rhs) {\n const first = getValueOf(lhs);\n const second = getValueOf(rhs);\n // Check the scalar case first.\n if (first === second) {\n return true;\n }\n\n // Check if they are the same type.\n const firstType = Object.prototype.toString.call(first);\n if (firstType !== Object.prototype.toString.call(second)) {\n return false;\n }\n // We know that first and second have the same type so we can just check the\n // first type from now on.\n if (isArray(first) === true) {\n // Short circuit if they're not the same length;\n if (first.length !== second.length) return false;\n return first.every((f, i) => strictDeepEqual(f, second[i]));\n }\n if (isObject(first) === true) {\n if (Object.keys(first).length !== Object.keys(second).length) return false;\n // An object is equal if it has the same key/value pairs.\n // eslint-disable-next-line no-restricted-syntax\n for (const key in first) {\n if (hasOwnProperty.call(first, key)) {\n if (strictDeepEqual(first[key], second[key]) === false) return false;\n }\n }\n return true;\n }\n return false;\n}\n\nexport function getProperty(obj, key) {\n const desc = Object.getOwnPropertyDescriptor(obj, key);\n // if it's a regular enumerable property or if it's configured with a getter,\n // then return it.\n // if it's a built-in property such as length or toString etc. we'll want to ignore it.\n if (desc?.enumerable || !!desc?.get) {\n // for applications that want to track which properties are accessed, allow for a special\n // hook to callback and register this key/value accessor.\n obj[key]?.[Symbol.for('track')]?.(obj, key);\n return obj[key];\n }\n return undefined;\n}\n\nexport function debugAvailable(debug, obj, key, chainStart = null) {\n try {\n let available = [];\n if (isArray(obj) && obj.length > 0) {\n debug.push(`Failed to find: '${key}' on an array object.`);\n debug.push(`Did you mean to use a projection? e.g. ${chainStart || 'array'}[*].${key}`);\n return;\n }\n debug.push(`Failed to find: '${key}'`);\n if (obj !== null) {\n available = [...available, ...Object.entries(Object.getOwnPropertyDescriptors(obj, key))\n .filter(([k, desc]) => (desc?.enumerable || !!desc?.get) && !/^[0-9]+$/.test(k) && (!k.startsWith('$') || key.startsWith('$')))\n .map(([k]) => `'${k}'`)];\n }\n if (available.length) debug.push(`Available fields: ${available}`);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n}\n\nexport function isClass(obj) {\n if (obj === null) return false;\n if (Array.isArray(obj)) return false;\n return !['Object', 'Boolean', 'Number', 'String'].includes(obj.constructor.name);\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n matchType, getTypeName, getType, isArrayType,\n} from './matchType.js';\nimport { dataTypes } from './dataTypes.js';\nimport tokenDefinitions from './tokenDefinitions.js';\nimport {\n isArray, isObject, strictDeepEqual, getValueOf, getProperty, debugAvailable, toBoolean,\n} from './utils.js';\nimport { evaluationError, typeError } from './errors.js';\n\nconst {\n TOK_CURRENT,\n TOK_GLOBAL,\n TOK_EXPREF,\n TOK_PIPE,\n TOK_FLATTEN,\n} = tokenDefinitions;\n\nconst {\n TYPE_STRING,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY,\n TYPE_NUMBER,\n} = dataTypes;\n\nfunction objValues(obj) {\n return Object.values(obj);\n}\n\nfunction balanceArrayOperands(opLeft, opRight) {\n if (isArray(opLeft) && isArray(opRight)) {\n // balance the size of the arrays by padding with nulls\n const shorter = opLeft.length < opRight.length ? opLeft : opRight;\n const diff = Math.abs(opLeft.length - opRight.length);\n shorter.length += diff;\n shorter.fill(null, shorter.length - diff);\n }\n}\n\nexport default class TreeInterpreter {\n constructor(runtime, globals, toNumber, toString, debug, language) {\n this.runtime = runtime;\n this.globals = globals;\n this.toNumber = toNumber;\n this.toString = toString;\n this.debug = debug;\n this.language = language;\n this.visitFunctions = this.initVisitFunctions();\n // track the identifier name that started the chain\n // so that we can use it in debug hints\n this.debugChainStart = null;\n }\n\n search(node, value) {\n return this.visit(node, value);\n }\n\n field(node, value) {\n // we used to check isObject(value) here -- but it is possible for an array-based\n // object to have properties. So we'll allow the child check on objects and arrays.\n if (value !== null && (isObject(value) || isArray(value))) {\n const field = getProperty(value, node.name);\n if (field === undefined) {\n debugAvailable(this.debug, value, node.name, this.debugChainStart);\n return null;\n }\n return field;\n }\n debugAvailable(this.debug, value, node.name, this.debugChainStart);\n return null;\n }\n\n initVisitFunctions() {\n return {\n Identifier: this.field.bind(this),\n QuotedIdentifier: this.field.bind(this),\n ChainedExpression: (node, value) => {\n let result = this.visit(node.children[0], value);\n this.debugChainStart = node.children[0].name;\n for (let i = 1; i < node.children.length; i += 1) {\n result = this.visit(node.children[1], result);\n if (result === null) return null;\n }\n return result;\n },\n\n BracketExpression: (node, value) => {\n const left = this.visit(node.children[0], value);\n return this.visit(node.children[1], left);\n },\n\n Index: (node, value) => {\n if (isArray(value)) {\n let index = node.value.value;\n if (index < 0) {\n index = value.length + index;\n }\n const result = value[index];\n if (result === undefined) {\n this.debug.push(`Index: ${index} out of range for array size: ${value.length}`);\n return null;\n }\n return result;\n }\n this.debug.push('Left side of index expression must be an array');\n this.debug.push(`Did you intend a single-element array? if so, use a JSON literal: \\`[${node.value.value}]\\``);\n return null;\n },\n\n Slice: (node, value) => {\n if (!isArray(value)) {\n this.debug.push('Slices apply to arrays only');\n return null;\n }\n const sliceParams = node.children.map(param => (param === null ? null : param.value));\n const [start, stop, step] = this.computeSliceParams(value.length, sliceParams);\n const result = [];\n if (step > 0) {\n for (let i = start; i < stop; i += step) {\n result.push(value[i]);\n }\n } else {\n for (let i = start; i > stop; i += step) {\n result.push(value[i]);\n }\n }\n return result;\n },\n\n Projection: (node, value) => {\n // Evaluate left child.\n const base = this.visit(node.children[0], value);\n if (!isArray(base)) {\n if (node.debug === 'Wildcard') {\n this.debug.push('Bracketed wildcards apply to arrays only');\n }\n return null;\n }\n const collected = [];\n base.forEach(b => {\n const current = this.visit(node.children[1], b);\n collected.push(current);\n });\n return collected;\n },\n\n // wildcard: \".*\"\n ValueProjection: (node, value) => {\n // Evaluate left child.\n const projection = this.visit(node.children[0], value);\n if (!isObject(getValueOf(projection))) {\n this.debug.push('Chained wildcards apply to objects only');\n return null;\n }\n const collected = [];\n const values = objValues(projection);\n values.forEach(val => {\n const current = this.visit(node.children[1], val);\n collected.push(current);\n });\n return collected;\n },\n\n FilterProjection: (node, value) => {\n const base = this.visit(node.children[0], value);\n if (!isArray(base)) {\n this.debug.push('Filter expressions apply to arrays only');\n return null;\n }\n const filtered = base.filter(b => {\n const matched = this.visit(node.children[2], b);\n return toBoolean(matched);\n });\n\n const finalResults = [];\n filtered.forEach(f => {\n const current = this.visit(node.children[1], f);\n finalResults.push(current);\n });\n return finalResults;\n },\n\n Comparator: (node, value) => {\n let first = getValueOf(this.visit(node.children[0], value));\n let second = getValueOf(this.visit(node.children[1], value));\n\n if (node.value === '==') return strictDeepEqual(first, second);\n if (node.value === '!=') return !strictDeepEqual(first, second);\n if (isObject(first) || isArray(first)) {\n this.debug.push(`Cannot use comparators with ${getTypeName(first)}`);\n return false;\n }\n if (isObject(second) || isArray(second)) {\n this.debug.push(`Cannot use comparators with ${getTypeName(second)}`);\n return false;\n }\n const type1 = getType(first);\n const type2 = getType(second);\n // if either parameter is a number, we need to do a numeric comparison\n // javascript will compare this way automatically, but if we explicitly convert\n // to numbers, we will get debug warnings for non-numeric strings\n if (type1 === TYPE_NUMBER || type2 === TYPE_NUMBER) {\n // if toNumber fails, it will populate the debug array\n // with an appropriate warning\n try {\n first = this.toNumber(first);\n second = this.toNumber(second);\n if (first === null || second === null) return false;\n } catch (_e) {\n // failing to convert to a number for comparison is not an error\n // we just return false\n return false;\n }\n }\n if (node.value === '>') return first > second;\n if (node.value === '>=') return first >= second;\n if (node.value === '<') return first < second;\n // if (node.value === '<=)\n // must be LTE\n return first <= second;\n },\n\n [TOK_FLATTEN]: (node, value) => {\n const original = this.visit(node.children[0], value);\n if (!isArray(original)) {\n this.debug.push('Flatten expressions apply to arrays only. If you want an empty array, use a JSON literal: `[]`');\n return null;\n }\n const merged = [];\n original.forEach(current => {\n if (isArray(current)) {\n merged.push(...current);\n } else {\n merged.push(current);\n }\n });\n return merged;\n },\n\n Identity: (_node, value) => value,\n\n ArrayExpression: (node, value) => node.children.map(child => this.visit(child, value)),\n\n ObjectExpression: (node, value) => {\n // at one time we used to have this:\n // if (value === null) return null;\n // BUT then an expression such as:\n // values({a: 'aa'})\n // would return null if the document were `null`\n // Removing the check means that:\n // `null`.{a: 'aa'}\n // returns: {a: 'aa'}\n // which is a bit odd, but seems correct.\n const collected = {};\n node.children.forEach(child => {\n if (collected[child.name] !== undefined) this.debug.push(`Duplicate key: '${child.name}'`);\n collected[child.name] = this.visit(child.value, value);\n });\n return collected;\n },\n\n OrExpression: (node, value) => {\n let matched = this.visit(node.children[0], value);\n if (!toBoolean(matched)) matched = this.visit(node.children[1], value);\n return matched;\n },\n\n AndExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n\n if (!toBoolean(first)) return first;\n return this.visit(node.children[1], value);\n },\n\n AddExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '+');\n },\n\n ConcatenateExpression: (node, value) => {\n let first = this.visit(node.children[0], value);\n let second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n if (isArrayType(first)) {\n first = matchType([TYPE_ARRAY_STRING], first, 'concatenate', this.toNumber, this.toString);\n } else {\n first = matchType([TYPE_STRING], first, 'concatenate', this.toNumber, this.toString);\n }\n if (isArrayType(second)) {\n second = matchType([TYPE_ARRAY_STRING], second, 'concatenate', this.toNumber, this.toString);\n } else {\n second = matchType([TYPE_STRING], second, 'concatenate', this.toNumber, this.toString);\n }\n return this.applyOperator(first, second, '&');\n },\n\n UnionExpression: (node, value) => {\n let first = this.visit(node.children[0], value);\n if (first === null) first = [null];\n let second = this.visit(node.children[1], value);\n if (second === null) second = [null];\n first = matchType([TYPE_ARRAY], first, 'union', this.toNumber, this.toString);\n second = matchType([TYPE_ARRAY], second, 'union', this.toNumber, this.toString);\n return first.concat(second);\n },\n\n SubtractExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '-');\n },\n\n MultiplyExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '*');\n },\n\n DivideExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '/');\n },\n\n NotExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n return !toBoolean(first);\n },\n\n UnaryMinusExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const minus = first * -1;\n if (Number.isNaN(minus)) throw typeError(`Failed to convert \"${first}\" to number`);\n return minus;\n },\n\n String: node => node.value,\n\n Literal: node => node.value,\n\n Number: node => node.value,\n\n Integer: node => node.value,\n\n [TOK_PIPE]: (node, value) => {\n const left = this.visit(node.children[0], value);\n return this.visit(node.children[1], left);\n },\n\n [TOK_CURRENT]: (_node, value) => value,\n\n [TOK_GLOBAL]: node => {\n const result = this.globals[node.name];\n return result === undefined ? null : result;\n },\n\n Function: (node, value) => {\n // Special case for if()\n // we need to make sure the results are called only after the condition is evaluated\n // Otherwise we end up with both results invoked -- which could include side effects\n // For \"if\", the last parameter to callFunction is false (bResolved) to indicate there's\n // no point in validating the argument type.\n if (node.name === 'if') return this.runtime.callFunction(node.name, node.children, value, this, false);\n const resolvedArgs = node.children.map(child => this.visit(child, value));\n return this.runtime.callFunction(node.name, resolvedArgs, value, this);\n },\n\n ExpressionReference: node => {\n const [refNode] = node.children;\n // Tag the node with a specific attribute so the type\n // checker verify the type.\n refNode.jmespathType = TOK_EXPREF;\n return refNode;\n },\n };\n }\n\n visit(n, v = null) {\n const fn = n && this.visitFunctions[n.type];\n return fn(n, v);\n }\n\n // eslint-disable-next-line class-methods-use-this\n computeSliceParams(arrayLength, sliceParams) {\n function capSliceRange(arrayLen, actual, stp) {\n let actualValue = actual;\n if (actualValue < 0) {\n actualValue += arrayLen;\n if (actualValue < 0) {\n actualValue = stp < 0 ? -1 : 0;\n }\n } else if (actualValue >= arrayLen) {\n actualValue = stp < 0 ? arrayLen - 1 : arrayLen;\n }\n return actualValue;\n }\n\n let [start, stop, step] = sliceParams;\n if (step === null) {\n step = 1;\n } else if (step === 0) {\n throw evaluationError('Invalid slice, step cannot be 0');\n }\n const stepValueNegative = step < 0;\n\n if (start === null) {\n start = stepValueNegative ? arrayLength - 1 : 0;\n } else {\n start = capSliceRange(arrayLength, start, step);\n }\n\n if (stop === null) {\n stop = stepValueNegative ? -1 : arrayLength;\n } else {\n stop = capSliceRange(arrayLength, stop, step);\n }\n return [start, stop, step];\n }\n\n applyOperator(first, second, operator) {\n if (isArray(first) && isArray(second)) {\n const result = [];\n for (let i = 0; i < first.length; i += 1) {\n result.push(this.applyOperator(first[i], second[i], operator));\n }\n return result;\n }\n\n if (isArray(first)) return first.map(a => this.applyOperator(a, second, operator));\n if (isArray(second)) return second.map(a => this.applyOperator(first, a, operator));\n\n if (operator === '&') return first + second;\n if (operator === '*') return this.toNumber(first) * this.toNumber(second);\n const n1 = this.toNumber(first);\n const n2 = this.toNumber(second);\n if (operator === '+') return n1 + n2;\n if (operator === '-') return n1 - n2;\n // if (operator === '/') {\n // Must be division\n const result = n1 / n2;\n if (!Number.isFinite(result)) {\n throw evaluationError(`Division by zero ${first}/${second}`);\n }\n return result;\n }\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable no-underscore-dangle */\nimport tokenDefinitions from './tokenDefinitions.js';\nimport { syntaxError } from './errors.js';\n\nconst {\n TOK_IDENTIFIER,\n TOK_QUOTEDIDENTIFIER,\n TOK_RBRACKET,\n TOK_RPAREN,\n TOK_COMMA,\n TOK_COLON,\n TOK_CONCATENATE,\n TOK_RBRACE,\n TOK_NUMBER,\n TOK_CURRENT,\n TOK_GLOBAL,\n TOK_EXPREF,\n TOK_PIPE,\n TOK_OR,\n TOK_COMPARATOR,\n TOK_AND,\n TOK_ADD,\n TOK_SUBTRACT,\n TOK_UNARY_MINUS,\n TOK_DIVIDE,\n TOK_UNION,\n TOK_FLATTEN,\n TOK_STAR,\n TOK_FILTER,\n TOK_DOT,\n TOK_NOT,\n TOK_LBRACE,\n TOK_LBRACKET,\n TOK_LPAREN,\n TOK_JSON,\n TOK_STRING,\n TOK_INT,\n} = tokenDefinitions;\n\n// The \"&\", \"[\", \"<\", \">\" tokens\n// are not in basicToken because\n// there are two token variants\n// (\"&&\", \"[?\", \"<=\", \">=\"). This is specially handled\n// below.\n\nconst basicTokens = {\n '.': TOK_DOT,\n ',': TOK_COMMA,\n ':': TOK_COLON,\n '{': TOK_LBRACE,\n '}': TOK_RBRACE,\n ']': TOK_RBRACKET,\n '(': TOK_LPAREN,\n ')': TOK_RPAREN,\n '@': TOK_CURRENT,\n};\n\nconst globalStartToken = '$';\nconst operatorStartToken = {\n '<': true,\n '>': true,\n '=': true,\n '!': true,\n};\n\nconst skipChars = {\n ' ': true,\n '\\t': true,\n '\\n': true,\n};\n\nfunction isAlphaNum(ch) {\n return (ch >= 'a' && ch <= 'z')\n || (ch >= 'A' && ch <= 'Z')\n || (ch >= '0' && ch <= '9')\n || ch === '_';\n}\n\nfunction isIdentifier(stream, pos) {\n const ch = stream[pos];\n // $ is special -- it's allowed to be part of an identifier if it's the first character\n // return whether character 'isAlpha'\n return ch === '$'\n || (ch >= 'a' && ch <= 'z')\n || (ch >= 'A' && ch <= 'Z')\n || ch === '_';\n}\n\nexport default class Lexer {\n constructor(allowedGlobalNames = [], debug = []) {\n this._allowedGlobalNames = allowedGlobalNames;\n this.debug = debug;\n }\n\n tokenize(stream) {\n const tokens = [];\n this._current = 0;\n let start;\n let identifier;\n let token;\n while (this._current < stream.length) {\n const prev = tokens.length ? tokens.slice(-1)[0].type : null;\n\n if (this._isGlobal(prev, stream, this._current)) {\n tokens.push(this._consumeGlobal(stream));\n } else if (isIdentifier(stream, this._current)) {\n start = this._current;\n identifier = this._consumeUnquotedIdentifier(stream);\n tokens.push({\n type: TOK_IDENTIFIER,\n value: identifier,\n start,\n });\n } else if (this._isNumber(stream)) {\n token = this._consumeNumber(stream);\n tokens.push(token);\n } else if (basicTokens[stream[this._current]] !== undefined) {\n tokens.push({\n type: basicTokens[stream[this._current]],\n value: stream[this._current],\n start: this._current,\n });\n this._current += 1;\n } else if (stream[this._current] === '-' && ![TOK_GLOBAL, TOK_CURRENT, TOK_NUMBER, TOK_INT, TOK_RPAREN, TOK_IDENTIFIER, TOK_QUOTEDIDENTIFIER, TOK_RBRACKET, TOK_JSON, TOK_STRING].includes(prev)) {\n token = this._consumeUnaryMinus(stream);\n tokens.push(token);\n } else if (stream[this._current] === '[') {\n // No need to increment this._current. This happens\n // in _consumeLBracket\n token = this._consumeLBracket(stream);\n tokens.push(token);\n } else if (stream[this._current] === \"'\") {\n start = this._current;\n identifier = this._consumeQuotedIdentifier(stream);\n tokens.push({\n type: TOK_QUOTEDIDENTIFIER,\n value: identifier,\n start,\n });\n } else if (stream[this._current] === '\"') {\n start = this._current;\n identifier = this._consumeRawStringLiteral(stream);\n tokens.push({\n type: TOK_STRING,\n value: identifier,\n start,\n });\n } else if (stream[this._current] === '`') {\n start = this._current;\n const json = this._consumeJson(stream);\n tokens.push({\n type: TOK_JSON,\n value: json,\n start,\n });\n } else if (operatorStartToken[stream[this._current]] !== undefined) {\n tokens.push(this._consumeOperator(stream));\n } else if (skipChars[stream[this._current]] !== undefined) {\n // Ignore whitespace.\n this._current += 1;\n } else if (stream[this._current] === '&') {\n start = this._current;\n this._current += 1;\n if (stream[this._current] === '&') {\n this._current += 1;\n tokens.push({ type: TOK_AND, value: '&&', start });\n } else if (prev === TOK_COMMA || prev === TOK_LPAREN) {\n // based on previous token we'll know if this & is a JMESPath expression-type\n // or if it's a concatenation operator\n // if we're a function arg then it's an expression-type\n tokens.push({ type: TOK_EXPREF, value: '&', start });\n } else {\n tokens.push({ type: TOK_CONCATENATE, value: '&', start });\n }\n } else if (stream[this._current] === '~') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_UNION, value: '~', start });\n } else if (stream[this._current] === '+') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_ADD, value: '+', start });\n } else if (stream[this._current] === '-') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_SUBTRACT, value: '-', start });\n } else if (stream[this._current] === '*') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_STAR, value: '*', start });\n } else if (stream[this._current] === '/') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_DIVIDE, value: '/', start });\n } else if (stream[this._current] === '|') {\n start = this._current;\n this._current += 1;\n if (stream[this._current] === '|') {\n this._current += 1;\n tokens.push({ type: TOK_OR, value: '||', start });\n } else {\n tokens.push({ type: TOK_PIPE, value: '|', start });\n }\n } else {\n throw syntaxError(`Unknown character:${stream[this._current]}`);\n }\n }\n return tokens;\n }\n\n _consumeUnquotedIdentifier(stream) {\n const start = this._current;\n this._current += 1;\n while (\n this._current < stream.length\n && (stream[this._current] === '$' || isAlphaNum(stream[this._current]))\n ) {\n this._current += 1;\n }\n return stream.slice(start, this._current);\n }\n\n _consumeQuotedIdentifier(stream) {\n const start = this._current;\n this._current += 1;\n const maxLength = stream.length;\n let foundNonAlpha = !isIdentifier(stream, start + 1);\n while (stream[this._current] !== \"'\" && this._current < maxLength) {\n // You can escape a single quote and you can escape an escape.\n let current = this._current;\n if (!isAlphaNum(stream[current])) foundNonAlpha = true;\n if (stream[current] === '\\\\' && (stream[current + 1] === '\\\\'\n || stream[current + 1] === \"'\")) {\n current += 2;\n } else {\n current += 1;\n }\n this._current = current;\n }\n this._current += 1;\n const val = stream.slice(start, this._current);\n // Check for unnecessary single quotes.\n // json-formula uses single quotes to escape characters that don't belong in names.\n // e.g. \"purchase-order\".address\n // If we find a single-quoted entity with spaces or all legal characters, issue a warning\n try {\n if (!foundNonAlpha) {\n this.debug.push(`Suspicious quotes: ${val}`);\n this.debug.push(`Did you intend a literal? \"${val.replace(/'/g, '')}\"?`);\n }\n // eslint-disable-next-line no-empty\n } catch (e) { }\n // we want to do all the escape-processing that JSON does ...\n // except that JSON expects to escape double quotes, and our identifiers\n // escape single quotes.\n return JSON.parse(`\"${val.substring(1, val.length - 1).replace(/\\\\'/g, \"'\")}\"`);\n }\n\n _consumeRawStringLiteral(stream) {\n const start = this._current;\n this._current += 1;\n const maxLength = stream.length;\n while (stream[this._current] !== '\"' && this._current < maxLength) {\n // You can escape a double quote and you can escape an escape.\n let current = this._current;\n if (stream[current] === '\\\\' && (stream[current + 1] === '\\\\'\n || stream[current + 1] === '\"')) {\n current += 2;\n } else {\n current += 1;\n }\n this._current = current;\n }\n this._current += 1;\n const literal = stream.slice(start + 1, this._current - 1);\n if (this._current > maxLength) {\n throw syntaxError(`Unterminated string literal at ${start}, \"${literal}`);\n }\n try {\n return JSON.parse(`\"${literal}\"`);\n } catch (_e) {\n throw syntaxError(`Invalid string literal: ${literal}`);\n }\n }\n\n _isNumber(stream) {\n // if we see the first two characters are either a digit or radix, then we have a number\n let ch = stream[this._current];\n if (ch >= '0' && ch <= '9') return true;\n if (ch !== '.') return false;\n if (this._current === stream.length) return false;\n ch = stream[this._current + 1];\n return ch >= '0' && ch <= '9';\n }\n\n _consumeNumber(stream) {\n const start = this._current;\n const num = stream.slice(start);\n const match = num.match(/^[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?/);\n if (!match) throw syntaxError(`Invalid number: ${num}`);\n const n = match[0];\n this._current += n.length;\n let value;\n if (n.includes('.') || n.toLowerCase().includes('e')) {\n value = parseFloat(n);\n return { type: TOK_NUMBER, value, start };\n }\n value = parseInt(n, 10);\n return { type: TOK_INT, value, start };\n }\n\n _consumeUnaryMinus() {\n const start = this._current;\n this._current += 1;\n return { type: TOK_UNARY_MINUS, value: '-', start };\n }\n\n _consumeLBracket(stream) {\n const start = this._current;\n this._current += 1;\n if (stream[this._current] === '?') {\n this._current += 1;\n return { type: TOK_FILTER, value: '[?', start };\n }\n if (stream[this._current] === ']') {\n this._current += 1;\n return { type: TOK_FLATTEN, value: '[]', start };\n }\n return { type: TOK_LBRACKET, value: '[', start };\n }\n\n _isGlobal(prev, stream, pos) {\n // global tokens occur only at the start of an expression\n if (prev !== null && prev === TOK_DOT) return false;\n const ch = stream[pos];\n if (ch !== globalStartToken) return false;\n // $ is special -- it's allowed to be part of an identifier if it's the first character\n let i = pos + 1;\n while (i < stream.length && (stream[i] === '$' || isAlphaNum(stream[i]))) i += 1;\n const global = stream.slice(pos, i);\n return this._allowedGlobalNames.includes(global);\n }\n\n _consumeGlobal(stream) {\n const start = this._current;\n this._current += 1;\n while (this._current < stream.length\n && (stream[this._current] === '$' || isAlphaNum(stream[this._current]))) this._current += 1;\n const global = stream.slice(start, this._current);\n\n return { type: TOK_GLOBAL, name: global, start };\n }\n\n _consumeOperator(stream) {\n const start = this._current;\n const startingChar = stream[start];\n this._current += 1;\n if (startingChar === '!') {\n if (stream[this._current] === '=') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '!=', start };\n }\n return { type: TOK_NOT, value: '!', start };\n }\n if (startingChar === '<') {\n if (stream[this._current] === '=') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '<=', start };\n }\n if (stream[this._current] === '>') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '!=', start };\n }\n return { type: TOK_COMPARATOR, value: '<', start };\n }\n if (startingChar === '>') {\n if (stream[this._current] === '=') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '>=', start };\n }\n return { type: TOK_COMPARATOR, value: '>', start };\n }\n // startingChar is '='\n if (stream[this._current] === '=') {\n this._current += 1;\n }\n return { type: TOK_COMPARATOR, value: '==', start };\n }\n\n _consumeJson(stream) {\n this._current += 1;\n const start = this._current;\n const maxLength = stream.length;\n while (stream[this._current] !== '`' && this._current < maxLength) {\n let current = this._current;\n if (stream[current] === '\\\\' && stream[current + 1] === '`') {\n current += 2;\n } else {\n current += 1;\n }\n this._current = current;\n }\n let literalString = stream.slice(start, this._current).trimStart();\n literalString = literalString.replaceAll('\\\\`', '`');\n // +1 gets us to the ending \"`\", +1 to move on to the next char.\n this._current += 1;\n if (this._current > maxLength) {\n throw syntaxError(`Unterminated JSON literal at ${start}: \\`${literalString}`);\n }\n\n return JSON.parse(literalString);\n }\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport Lexer from './Lexer.js';\nimport tokenDefinitions from './tokenDefinitions.js';\nimport { syntaxError } from './errors.js';\n\n/* eslint-disable no-underscore-dangle */\nconst {\n TOK_JSON,\n TOK_COLON,\n TOK_EOF,\n TOK_IDENTIFIER,\n TOK_QUOTEDIDENTIFIER,\n TOK_RBRACKET,\n TOK_RPAREN,\n TOK_COMMA,\n TOK_CONCATENATE,\n TOK_RBRACE,\n TOK_NUMBER,\n TOK_CURRENT,\n TOK_GLOBAL,\n TOK_EXPREF,\n TOK_PIPE,\n TOK_OR,\n TOK_AND,\n TOK_ADD,\n TOK_SUBTRACT,\n TOK_UNARY_MINUS,\n TOK_MULTIPLY,\n TOK_DIVIDE,\n TOK_UNION,\n TOK_COMPARATOR,\n TOK_FLATTEN,\n TOK_STAR,\n TOK_FILTER,\n TOK_DOT,\n TOK_NOT,\n TOK_LBRACE,\n TOK_LBRACKET,\n TOK_LPAREN,\n TOK_STRING,\n TOK_INT,\n} = tokenDefinitions;\n\nconst bindingPower = {\n [TOK_EOF]: 0,\n [TOK_IDENTIFIER]: 0,\n [TOK_QUOTEDIDENTIFIER]: 0,\n [TOK_RBRACKET]: 0,\n [TOK_RPAREN]: 0,\n [TOK_COMMA]: 0,\n [TOK_RBRACE]: 0,\n [TOK_NUMBER]: 0,\n [TOK_INT]: 0,\n [TOK_CURRENT]: 0,\n [TOK_GLOBAL]: 0,\n [TOK_EXPREF]: 0,\n [TOK_PIPE]: 1,\n [TOK_OR]: 2,\n [TOK_AND]: 3,\n [TOK_COMPARATOR]: 4,\n [TOK_CONCATENATE]: 5,\n [TOK_ADD]: 6,\n [TOK_SUBTRACT]: 6,\n [TOK_UNION]: 6,\n [TOK_MULTIPLY]: 7,\n [TOK_DIVIDE]: 7,\n [TOK_NOT]: 8,\n [TOK_UNARY_MINUS]: 8,\n [TOK_FLATTEN]: 10,\n [TOK_STAR]: 20,\n [TOK_FILTER]: 21,\n [TOK_DOT]: 40,\n [TOK_LBRACE]: 50,\n [TOK_LBRACKET]: 55,\n [TOK_LPAREN]: 60,\n};\n\nexport default class Parser {\n constructor(allowedGlobalNames = []) {\n this._allowedGlobalNames = allowedGlobalNames;\n }\n\n parse(expression, debug) {\n this.debug = debug;\n this._loadTokens(expression);\n this.index = 0;\n const ast = this.expression(0);\n if (this._lookahead(0) !== TOK_EOF) {\n const t = this._lookaheadToken(0);\n throw syntaxError(`Unexpected token type: ${t.type}, value: ${t.value}`);\n }\n return ast;\n }\n\n _loadTokens(expression) {\n const lexer = new Lexer(this._allowedGlobalNames, this.debug);\n const tokens = lexer.tokenize(expression);\n tokens.push({ type: TOK_EOF, value: '', start: expression.length });\n this.tokens = tokens;\n }\n\n expression(rbp) {\n const leftToken = this._lookaheadToken(0);\n this._advance();\n let left = this.nud(leftToken);\n let currentToken = this._lookaheadToken(0, left);\n while (rbp < bindingPower[currentToken.type]) {\n this._advance();\n left = this.led(currentToken, left);\n currentToken = this._lookaheadToken(0, left);\n }\n return left;\n }\n\n _lookahead(number) {\n return this.tokens[this.index + number].type;\n }\n\n _lookaheadToken(number, previous = {}) {\n const next = this.tokens[this.index + number];\n // disambiguate multiply and star\n if (next.type === TOK_STAR) {\n if (![\n undefined,\n TOK_LBRACKET,\n TOK_DOT,\n TOK_PIPE,\n TOK_AND,\n TOK_OR,\n TOK_COMMA,\n TOK_NOT,\n TOK_MULTIPLY,\n TOK_ADD,\n TOK_SUBTRACT,\n TOK_DIVIDE,\n TOK_LPAREN,\n TOK_CONCATENATE,\n TOK_UNION,\n TOK_COMPARATOR].includes(previous.type)) {\n next.type = TOK_MULTIPLY;\n }\n }\n\n return next;\n }\n\n _advance() {\n this.index += 1;\n }\n\n _lookAheadIndex() {\n let idx = 0;\n if (this._lookahead(idx) === TOK_UNARY_MINUS) idx += 1;\n if (this._lookahead(idx) === TOK_INT) idx += 1;\n if (this._lookahead(idx) === TOK_RBRACKET\n || this._lookahead(idx) === TOK_COLON) return true;\n return false;\n }\n\n _getIndex() {\n return this.index;\n }\n\n _setIndex(index) {\n this.index = index;\n }\n\n // eslint-disable-next-line consistent-return\n nud(token) {\n let left;\n let right;\n let expression;\n let node;\n let args;\n switch (token.type) {\n case TOK_STRING:\n return { type: 'String', value: token.value };\n case TOK_JSON:\n return { type: 'Literal', value: token.value };\n case TOK_NUMBER:\n return { type: 'Number', value: token.value };\n case TOK_INT:\n return { type: 'Integer', value: token.value };\n case TOK_IDENTIFIER:\n return { type: 'Identifier', name: token.value };\n case TOK_QUOTEDIDENTIFIER:\n node = { type: 'QuotedIdentifier', name: token.value };\n return node;\n case TOK_NOT:\n right = this.expression(bindingPower.Not);\n return { type: 'NotExpression', children: [right] };\n case TOK_UNARY_MINUS:\n right = this.expression(bindingPower.UnaryMinus);\n return { type: 'UnaryMinusExpression', children: [right] };\n case TOK_STAR:\n left = { type: 'Identity' };\n if (this._lookahead(0) === TOK_RBRACKET) {\n // This can happen in a ArrayExpression,\n // [a, b, *]\n right = { type: 'Identity' };\n } else {\n right = this._parseProjectionRHS(bindingPower.Star);\n }\n return { type: 'ValueProjection', children: [left, right] };\n case TOK_FILTER:\n return this.led(token, { type: 'Identity' });\n case TOK_LBRACE:\n return this._parseObjectExpression();\n case TOK_FLATTEN:\n left = { type: TOK_FLATTEN, children: [{ type: 'Identity' }] };\n right = this._parseProjectionRHS(bindingPower.Flatten);\n return { type: 'Projection', children: [left, right] };\n case TOK_LBRACKET:\n if (this._lookAheadIndex()) {\n right = this._parseIndexExpression();\n return this._projectIfSlice({ type: 'Identity' }, right);\n }\n if (this._lookahead(0) === TOK_STAR && this._lookahead(1) === TOK_RBRACKET) {\n this._advance();\n this._advance();\n right = this._parseProjectionRHS(bindingPower.Star);\n return {\n type: 'Projection',\n children: [{ type: 'Identity' }, right],\n debug: 'Wildcard',\n };\n }\n return this._parseArrayExpression();\n\n case TOK_CURRENT:\n return { type: TOK_CURRENT };\n case TOK_GLOBAL:\n return { type: TOK_GLOBAL, name: token.name };\n case TOK_EXPREF:\n expression = this.expression(bindingPower.Expref);\n return { type: 'ExpressionReference', children: [expression] };\n case TOK_LPAREN:\n args = [];\n while (this._lookahead(0) !== TOK_RPAREN) {\n expression = this.expression(0);\n args.push(expression);\n }\n this._match(TOK_RPAREN);\n return args[0];\n default:\n this._errorToken(token);\n }\n }\n\n // eslint-disable-next-line consistent-return\n led(token, left) {\n let condition;\n let right;\n let name;\n let args;\n let node;\n let rbp;\n let leftNode;\n let rightNode;\n const tokenName = token.type;\n switch (tokenName) {\n case TOK_CONCATENATE:\n right = this.expression(bindingPower.Concatenate);\n return { type: 'ConcatenateExpression', children: [left, right] };\n case TOK_DOT:\n rbp = bindingPower.Dot;\n if (this._lookahead(0) !== TOK_STAR) {\n right = this._parseDotRHS(rbp);\n return { type: 'ChainedExpression', children: [left, right] };\n }\n // Creating a projection.\n this._advance();\n right = this._parseProjectionRHS(rbp);\n return { type: 'ValueProjection', children: [left, right] };\n case TOK_PIPE:\n right = this.expression(bindingPower.Pipe);\n return { type: TOK_PIPE, children: [left, right] };\n case TOK_OR:\n right = this.expression(bindingPower.Or);\n return { type: 'OrExpression', children: [left, right] };\n case TOK_AND:\n right = this.expression(bindingPower.And);\n return { type: 'AndExpression', children: [left, right] };\n case TOK_ADD:\n right = this.expression(bindingPower.Add);\n return { type: 'AddExpression', children: [left, right] };\n case TOK_SUBTRACT:\n right = this.expression(bindingPower.Subtract);\n return { type: 'SubtractExpression', children: [left, right] };\n case TOK_MULTIPLY:\n right = this.expression(bindingPower.Multiply);\n return { type: 'MultiplyExpression', children: [left, right] };\n case TOK_DIVIDE:\n right = this.expression(bindingPower.Divide);\n return { type: 'DivideExpression', children: [left, right] };\n case TOK_UNION:\n right = this.expression(bindingPower.Union);\n return { type: 'UnionExpression', children: [left, right] };\n case TOK_LPAREN:\n if (left.type !== TOK_IDENTIFIER) {\n throw syntaxError('Bad function syntax. Parenthesis must be preceded by an unquoted identifier');\n }\n name = left.name;\n args = this._parseFunctionArgs();\n node = { type: 'Function', name, children: args };\n return node;\n case TOK_FILTER:\n condition = this.expression(0);\n this._match(TOK_RBRACKET);\n right = this._parseProjectionRHS(bindingPower.Filter);\n return { type: 'FilterProjection', children: [left, right, condition] };\n case TOK_FLATTEN:\n leftNode = { type: TOK_FLATTEN, children: [left] };\n rightNode = this._parseProjectionRHS(bindingPower.Flatten);\n return { type: 'Projection', children: [leftNode, rightNode] };\n case TOK_COMPARATOR:\n return this._parseComparator(left, token);\n case TOK_LBRACKET:\n if (this._lookahead(0) === TOK_STAR\n && this._lookahead(1) === TOK_RBRACKET) {\n this._advance();\n this._advance();\n right = this._parseProjectionRHS(bindingPower.Star);\n return { type: 'Projection', children: [left, right], debug: 'Wildcard' };\n }\n right = this._parseIndexExpression();\n return this._projectIfSlice(left, right);\n default:\n this._errorToken(token);\n }\n }\n\n _match(tokenType) {\n const token = this._lookaheadToken(0);\n if (token.type === tokenType) {\n this._advance();\n return token;\n }\n throw syntaxError(`Expected ${tokenType}, got: ${token.type}`);\n }\n\n // eslint-disable-next-line class-methods-use-this\n _errorToken(token) {\n throw syntaxError(`Unexpected token (${\n token.type}): \"${\n token.value || token.name}\"`);\n }\n\n _parseFunctionArgs() {\n let firstExpression = true;\n const args = [];\n while (this._lookahead(0) !== TOK_RPAREN) {\n if (!firstExpression) {\n this._match(TOK_COMMA);\n }\n args.push(this.expression(0));\n firstExpression = false;\n }\n this._match(TOK_RPAREN);\n return args;\n }\n\n _parseSignedInt() {\n const first = this._lookaheadToken(0);\n if (first.type === TOK_UNARY_MINUS) {\n this._advance();\n const value = this._match(TOK_INT);\n return {\n type: 'SignedInt',\n value: -value.value,\n };\n }\n if (first.type !== TOK_INT) this._errorToken(first);\n this._advance();\n return {\n type: 'SignedInt',\n value: first.value,\n };\n }\n\n _parseIndexExpression() {\n const oldIndex = this._getIndex();\n if (this._lookahead(0) === TOK_COLON) {\n return this._parseSliceExpression();\n }\n // look ahead of the first expression to determine the type\n const first = this._parseSignedInt();\n const token = this._lookahead(0);\n if (token === TOK_COLON) {\n // now that we know the type revert back to the old position and parse\n this._setIndex(oldIndex);\n return this._parseSliceExpression();\n }\n this._match(TOK_RBRACKET);\n return {\n type: 'Index',\n value: first,\n };\n }\n\n _projectIfSlice(left, right) {\n const indexExpr = { type: 'BracketExpression', children: [left, right] };\n if (right.type === 'Slice') {\n return {\n type: 'Projection',\n children: [indexExpr, this._parseProjectionRHS(bindingPower.Star)],\n };\n }\n return indexExpr;\n }\n\n _parseSliceExpression() {\n // [start:end:step] where each part is optional, as well as the last\n // colon.\n const parts = [null, null, null];\n let index = 0;\n let currentToken = this._lookahead(0);\n while (currentToken !== TOK_RBRACKET && index < 3) {\n if (currentToken === TOK_COLON && index < 2) { // there can't be more than 2 colons\n index += 1;\n this._advance();\n } else {\n parts[index] = this._parseSignedInt();\n // check next token to be either colon or rbracket\n const t = this._lookahead(0);\n if (t !== TOK_COLON && t !== TOK_RBRACKET) {\n throw syntaxError(`Unexpected token: ${\n t.value}(${t.type})`);\n }\n }\n currentToken = this._lookahead(0);\n }\n this._match(TOK_RBRACKET);\n return {\n type: 'Slice',\n children: parts,\n };\n }\n\n _parseComparator(left, comparator) {\n const right = this.expression(bindingPower[comparator.type]);\n return { type: 'Comparator', value: comparator.value, children: [left, right] };\n }\n\n _parseDotRHS(rbp) {\n const lookahead = this._lookahead(0);\n const exprTokens = [TOK_IDENTIFIER, TOK_QUOTEDIDENTIFIER, TOK_STAR];\n if (exprTokens.indexOf(lookahead) >= 0) {\n return this.expression(rbp);\n }\n if (lookahead === TOK_LBRACKET) {\n this._match(TOK_LBRACKET);\n return this._parseArrayExpression();\n }\n if (lookahead === TOK_LBRACE) {\n this._match(TOK_LBRACE);\n return this._parseObjectExpression();\n }\n throw syntaxError('Expecting one of: \"*\", \"[\", \"{\", name or quoted name after a dot');\n }\n\n _parseProjectionRHS(rbp) {\n let right;\n const next = this._lookaheadToken(0, { type: TOK_STAR });\n if (bindingPower[next.type] <= bindingPower[TOK_FLATTEN]) {\n right = { type: 'Identity' };\n } else if (next.type === TOK_LBRACKET) {\n right = this.expression(rbp);\n } else if (next.type === TOK_FILTER) {\n right = this.expression(rbp);\n } else if (next.type === TOK_DOT) {\n this._match(TOK_DOT);\n right = this._parseDotRHS(rbp);\n } else {\n throw syntaxError(`Unexpected token: ${next.value}(${next.type})`);\n }\n return right;\n }\n\n _parseArrayExpression() {\n const expressions = [];\n while (this._lookahead(0) !== TOK_RBRACKET) {\n const expression = this.expression(0);\n expressions.push(expression);\n if (this._lookahead(0) === TOK_COMMA) {\n this._match(TOK_COMMA);\n if (this._lookahead(0) === TOK_RBRACKET) {\n throw syntaxError('Unexpected token Rbracket');\n }\n }\n }\n this._match(TOK_RBRACKET);\n return { type: 'ArrayExpression', children: expressions };\n }\n\n _parseObjectExpression() {\n const pairs = [];\n const identifierTypes = [TOK_IDENTIFIER, TOK_QUOTEDIDENTIFIER];\n let keyToken; let keyName; let value; let\n node;\n if (this._lookahead(0) === TOK_RBRACE) {\n this.debug.push('To create an empty object, use a JSON literal: `{}`');\n throw syntaxError('An empty object expression is not allowed');\n }\n for (;;) {\n keyToken = this._lookaheadToken(0);\n if (identifierTypes.indexOf(keyToken.type) < 0) {\n throw syntaxError(`Expecting an identifier token, got: ${\n keyToken.type}`);\n }\n keyName = keyToken.value;\n this._advance();\n this._match(TOK_COLON);\n value = this.expression(0);\n node = { type: 'KeyValuePair', name: keyName, value };\n pairs.push(node);\n if (this._lookahead(0) === TOK_COMMA) {\n this._match(TOK_COMMA);\n } else if (this._lookahead(0) === TOK_RBRACE) {\n this._match(TOK_RBRACE);\n break;\n }\n }\n return { type: 'ObjectExpression', children: pairs };\n }\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable no-underscore-dangle */\nimport { dataTypes, typeNameTable } from './dataTypes.js';\nimport {\n getProperty, debugAvailable, toBoolean, strictDeepEqual,\n} from './utils.js';\nimport { evaluationError, functionError, typeError } from './errors.js';\n\nfunction round(num, digits) {\n const precision = 10 ** digits;\n return Math.round(num * precision) / precision;\n}\n\nconst MS_IN_DAY = 24 * 60 * 60 * 1000;\n\nfunction getDateObj(dateNum) {\n return new Date(Math.round(dateNum * MS_IN_DAY));\n}\n\nfunction getDateNum(dateObj) {\n return dateObj / MS_IN_DAY;\n}\n\nfunction validNumber(n, context) {\n if (Number.isNaN(n) || !Number.isFinite(n)) {\n throw evaluationError(`Call to \"${context}()\" resulted in an invalid number`);\n }\n return n;\n}\n\nexport default function functions(\n runtime,\n isObject,\n toNumber,\n getType,\n isArrayType,\n valueOf,\n toString,\n debug,\n) {\n const {\n TYPE_NUMBER,\n TYPE_ANY,\n TYPE_STRING,\n TYPE_ARRAY,\n TYPE_OBJECT,\n TYPE_BOOLEAN,\n TYPE_EXPREF,\n TYPE_NULL,\n TYPE_ARRAY_NUMBER,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY_ARRAY,\n } = dataTypes;\n\n function toInteger(num) {\n let n = valueOf(num);\n // functions that require an integer parameter will have declared\n // the parameters as a number, so any strings will have already been\n // converted to number before the function call.\n // However, a few functions accept a string | integer. Attempt to convert\n // to integer in these cases, but failure isn't an error.\n if (getType(n) === TYPE_STRING) n = toNumber(n);\n n = Math.trunc(num);\n if (Number.isNaN(n)) return num;\n return n;\n }\n\n function toJSON(arg, indent) {\n const value = valueOf(arg);\n if (getType(value) === TYPE_STRING) {\n return arg;\n }\n const offset = indent ? toInteger(indent) : 0;\n return JSON.stringify(value, null, offset);\n }\n\n function balanceArrays(listOfArrays) {\n const maxLen = Math.max(...listOfArrays.map(a => (Array.isArray(a) ? a.length : 0)));\n const allArrays = listOfArrays.map(a => {\n if (Array.isArray(a)) {\n return a.concat(Array(maxLen - a.length).fill(null));\n }\n return Array(maxLen).fill(a);\n });\n // convolve allArrays\n const arrays = [];\n for (let i = 0; i < maxLen; i += 1) {\n const row = [];\n for (let j = 0; j < allArrays.length; j += 1) {\n row.push(allArrays[j][i]);\n }\n arrays.push(row);\n }\n return arrays;\n }\n\n function evaluate(args, fn) {\n if (args.some(Array.isArray)) {\n return balanceArrays(args).map(a => evaluate(a, fn));\n }\n return fn(...args);\n }\n\n function datedifFn(date1Arg, date2Arg, unitArg) {\n const unit = toString(unitArg).toLowerCase();\n const date1 = getDateObj(date1Arg);\n const date2 = getDateObj(date2Arg);\n if (date2 === date1) return 0;\n if (date2 < date1) throw functionError('end_date must be >= start_date in datedif()');\n\n if (unit === 'd') return Math.floor(getDateNum(date2 - date1));\n const yearDiff = date2.getFullYear() - date1.getFullYear();\n let monthDiff = date2.getMonth() - date1.getMonth();\n const dayDiff = date2.getDate() - date1.getDate();\n\n if (unit === 'y') {\n let y = yearDiff;\n if (monthDiff < 0) y -= 1;\n if (monthDiff === 0 && dayDiff < 0) y -= 1;\n return y;\n }\n if (unit === 'm') {\n return yearDiff * 12 + monthDiff + (dayDiff < 0 ? -1 : 0);\n }\n if (unit === 'ym') {\n if (dayDiff < 0) monthDiff -= 1;\n if (monthDiff <= 0 && yearDiff > 0) return 12 + monthDiff;\n return monthDiff;\n }\n if (unit === 'yd') {\n if (dayDiff < 0) monthDiff -= 1;\n if (monthDiff < 0) date2.setFullYear(date1.getFullYear() + 1);\n else date2.setFullYear(date1.getFullYear());\n return Math.floor(getDateNum(date2 - date1));\n }\n throw functionError(`Unrecognized unit parameter \"${unit}\" for datedif()`);\n }\n\n function endsWithFn(searchArg, suffixArg) {\n const searchStr = valueOf(searchArg);\n const suffix = valueOf(suffixArg);\n // make sure the comparison is based on code points\n const search = Array.from(searchStr).reverse();\n const ending = Array.from(suffix).reverse();\n return ending.every((c, i) => c === search[i]);\n }\n\n function eomonthFn(dateArg, monthsArg) {\n const jsDate = getDateObj(dateArg);\n const months = toInteger(monthsArg);\n // We can give the constructor a month value > 11 and it will increment the years\n // Since day is 1-based, giving zero will yield the last day of the previous month\n const newDate = new Date(jsDate.getFullYear(), jsDate.getMonth() + months + 1, 0);\n return getDateNum(newDate);\n }\n\n function findFn(queryArg, textArg, offsetArg) {\n const query = Array.from(toString(queryArg));\n const text = Array.from(toString(textArg));\n const offset = toInteger(offsetArg);\n if (offset < 0) throw evaluationError('find() start position must be >= 0');\n if (query.length === 0) {\n // allow an empty string to be found at any position -- including the end\n if (offset > text.length) return null;\n return offset;\n }\n for (let i = offset; i < text.length; i += 1) {\n if (text.slice(i, i + query.length).every((c, j) => c === query[j])) {\n return i;\n }\n }\n return null;\n }\n\n function properFn(arg) {\n const capitalize = word => `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}`;\n const original = toString(arg);\n // split the string by whitespace, punctuation, and numbers\n const wordParts = original.match(/[\\s\\d\\p{P}]+|[^\\s\\d\\p{P}]+/gu);\n if (wordParts !== null) return wordParts.map(w => capitalize(w)).join('');\n return capitalize(original);\n }\n\n function reptFn(textArg, countArg) {\n const text = toString(textArg);\n const count = toInteger(countArg);\n if (count < 0) throw evaluationError('rept() count must be greater than or equal to 0');\n return text.repeat(count);\n }\n\n function searchFn(findTextString, withinTextString, startPosInt = 0) {\n const findText = toString(findTextString);\n const withinText = toString(withinTextString);\n const startPos = toInteger(startPosInt);\n if (startPos < 0) throw functionError('search() startPos must be greater than or equal to 0');\n if (findText === null || withinText === null || withinText.length === 0) return [];\n\n // Process as an array of code points\n // Find escapes and wildcards\n const globString = Array.from(findText).reduce((acc, cur) => {\n if (acc.escape) return { escape: false, result: acc.result.concat(cur) };\n if (cur === '\\\\') return { escape: true, result: acc.result };\n if (cur === '?') return { escape: false, result: acc.result.concat('dot') };\n if (cur === '*') {\n // consecutive * are treated as a single *\n if (acc.result.slice(-1).pop() === 'star') return acc;\n return { escape: false, result: acc.result.concat('star') };\n }\n return { escape: false, result: acc.result.concat(cur) };\n }, { escape: false, result: [] }).result;\n\n const testMatch = (array, glob, match) => {\n // we've consumed the entire glob, so we're done\n if (glob.length === 0) return match;\n // we've consumed the entire array, but there's still glob left -- no match\n if (array.length === 0) return null;\n const testChar = array[0];\n let [globChar, ...nextGlob] = glob;\n const isStar = globChar === 'star';\n if (isStar) {\n // '*' is at the end of the match -- so we're done matching\n if (glob.length === 1) return match;\n // we'll check for a match past the * and if not found, we'll process the *\n [globChar, ...nextGlob] = glob.slice(1);\n }\n if (testChar === globChar || globChar === 'dot') {\n return testMatch(array.slice(1), nextGlob, match.concat(testChar));\n }\n // no match, so consume wildcard *\n if (isStar) return testMatch(array.slice(1), glob, match.concat(testChar));\n\n return null;\n };\n // process code points\n const within = Array.from(withinText);\n for (let i = startPos; i < within.length; i += 1) {\n const result = testMatch(within.slice(i), globString, []);\n if (result !== null) return [i, result.join('')];\n }\n return [];\n }\n\n function splitFn(strArg, separatorArg) {\n const str = toString(strArg);\n const separator = toString(separatorArg);\n // for empty separator, return an array of code points\n return separator.length === 0 ? Array.from(str) : str.split(separator);\n }\n\n function startsWithFn(subjectString, prefixString) {\n const subject = Array.from(toString(subjectString));\n const prefix = Array.from(toString(prefixString));\n if (prefix.length > subject.length) return false;\n for (let i = 0; i < prefix.length; i += 1) {\n if (prefix[i] !== subject[i]) return false;\n }\n return true;\n }\n\n function substituteFn(source, oldString, replacementString, nearest) {\n const src = Array.from(toString(source));\n const old = Array.from(toString(oldString));\n const replacement = Array.from(toString(replacementString));\n\n if (old.length === 0) return source;\n\n // no third parameter? replace all instances\n let replaceAll = true;\n let whch = 0;\n if (nearest > -1) {\n replaceAll = false;\n whch = nearest + 1;\n }\n\n let found = 0;\n const result = [];\n // find the instances to replace\n for (let j = 0; j < src.length;) {\n const match = old.every((c, i) => src[j + i] === c);\n if (match) found += 1;\n if (match && (replaceAll || found === whch)) {\n result.push(...replacement);\n j += old.length;\n } else {\n result.push(src[j]);\n j += 1;\n }\n }\n return result.join('');\n }\n\n function truncFn(number, d) {\n const digits = toInteger(d);\n\n const method = number >= 0 ? Math.floor : Math.ceil;\n return method(number * 10 ** digits) / 10 ** digits;\n }\n\n function weekdayFn(date, type) {\n const jsDate = getDateObj(date);\n const day = jsDate.getDay();\n // day is in range [0-7) with 0 mapping to sunday\n switch (toInteger(type)) {\n case 1:\n // range = [1, 7], sunday = 1\n return day + 1;\n case 2:\n // range = [1, 7] sunday = 7\n return ((day + 6) % 7) + 1;\n case 3:\n // range = [0, 6] sunday = 6\n return (day + 6) % 7;\n default:\n throw functionError(`Unsupported returnType: \"${type}\" for weekday()`);\n }\n }\n\n const functionMap = {\n // name: [function, ]\n // The can be:\n //\n // {\n // args: [[type1, type2], [type1, type2]],\n // variadic: true|false\n // }\n //\n // Each arg in the arg list is a list of valid types\n // (if the function is overloaded and supports multiple\n // types. If the type is \"any\" then no type checking\n // occurs on the argument. Variadic is optional\n // and if not provided is assumed to be false.\n /**\n * Find the absolute (non-negative) value of the provided argument `value`.\n * @param {number|number[]} value A numeric value\n * @return {number|number[]} If `value < 0`, returns `-value`, otherwise returns `value`\n * @function abs\n * @example\n * abs(-1) // returns 1\n */\n abs: {\n _func: args => evaluate(args, Math.abs),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n /**\n * Compute the inverse cosine (in radians) of a number.\n * @param {number|number[]} cosine A number between -1 and 1, inclusive,\n * representing the angle's cosine value.\n * @return {number|number[]} The inverse cosine angle in radians between 0 and PI\n * @function acos\n * @example\n * acos(0) => 1.5707963267948966\n */\n acos: {\n _func: args => evaluate(args, n => validNumber(Math.acos(n), 'acos')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Finds the logical AND result of all parameters.\n * If the parameters are not boolean they will be <<_type_coercion_rules,cast to boolean>>.\n * Note the related <<_and_operator, And Operator>>.\n * @param {any} firstOperand logical expression\n * @param {...any} [additionalOperands] any number of additional expressions\n * @returns {boolean} The logical result of applying AND to all parameters\n * @example\n * and(10 > 8, length(\"foo\") < 5) // returns true\n * and(`null`, length(\"foo\") < 5) // returns false\n * @function and\n */\n and: {\n _func: resolvedArgs => {\n let result = toBoolean(valueOf(resolvedArgs[0]));\n resolvedArgs.slice(1).forEach(arg => {\n result = result && toBoolean(valueOf(arg));\n });\n return result;\n },\n _signature: [{ types: [TYPE_ANY], variadic: true }],\n },\n\n /**\n * Compute the inverse sine (in radians) of a number.\n * @param {number|number[]} sine A number between -1 and 1, inclusive,\n * representing the angle's sine value.\n * @return {number|number[]} The inverse sine angle in radians between -PI/2 and PI/2\n * @function asin\n * @example\n * Math.asin(0) => 0\n */\n asin: {\n _func: args => evaluate(args, n => validNumber(Math.asin(n), 'asin')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Compute the angle in the plane (in radians) between the positive\n * x-axis and the ray from (0, 0) to the point (x, y)\n * @param {number|number[]} y The y coordinate of the point\n * @param {number|number[]} x The x coordinate of the point\n * @return {number|number[]} The angle in radians (between -PI and PI),\n * between the positive x-axis and the ray from (0, 0) to the point (x, y).\n * @function atan2\n * @example\n * atan2(20,10) => 1.1071487177940904\n */\n atan2: {\n _func: args => evaluate(args, Math.atan2),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Finds the average of the elements in an array.\n * Non-numeric values (text, boolean, null, object) are ignored.\n * If there are nested arrays, they are flattened.\n * If the array is empty, an evaluation error is thrown\n * @param {any[]} elements array of values\n * @return {number} average value\n * @function avg\n * @example\n * avg([1, 2, 3]) // returns 2\n */\n avg: {\n _func: resolvedArgs => {\n let sum = 0;\n const filtered = resolvedArgs\n .flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER);\n\n if (filtered.length === 0) throw evaluationError('avg() requires at least one argument');\n filtered.forEach(a => {\n sum += a;\n });\n return sum / filtered.length;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Finds the average of the elements in an array, converting strings and booleans to number.\n * If any conversions to number fail, a type error is thrown.\n * If there are nested arrays, they are flattened.\n * If the array is empty, an evaluation error is thrown\n * @param {number[]} elements array of numeric values\n * @return {number} average value\n * @function avgA\n * @example\n * avgA([1, 2, \"3\", null()]) // returns 2\n */\n avgA: {\n _func: resolvedArgs => {\n let sum = 0;\n let filtered;\n try {\n filtered = resolvedArgs\n .flat(Infinity)\n .filter(a => getType(a) !== TYPE_NULL)\n .map(toNumber);\n } catch (_e) {\n throw typeError('avgA() received non-numeric parameters');\n }\n if (filtered.length === 0) throw evaluationError('avg() requires at least one argument');\n filtered.forEach(a => {\n sum += a;\n });\n return sum / filtered.length;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Generates a lower-case string of the `input` string using locale-specific mappings.\n * e.g. Strings with German letter ß (eszett) can be compared to \"ss\"\n * @param {string|string[]} input string to casefold\n * @returns {string|string[]} A new string converted to lower case\n * @function casefold\n * @example\n * casefold(\"AbC\") // returns \"abc\"\n */\n casefold: {\n _func: (args, _data, interpreter) => evaluate(args, s => toString(s)\n .toLocaleUpperCase(interpreter.language)\n .toLocaleLowerCase(interpreter.language)),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Finds the next highest integer value of the argument `num` by rounding up if necessary.\n * i.e. ceil() rounds toward positive infinity.\n * @param {number|number[]} num numeric value\n * @return {integer|integer[]} The smallest integer greater than or equal to num\n * @function ceil\n * @example\n * ceil(10) // returns 10\n * ceil(10.4) // return 11\n\n */\n ceil: {\n _func: args => evaluate(args, Math.ceil),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n /**\n * Retrieve the first code point from a string\n * @param {string|string[]} str source string.\n * @return {integer|integer[]} Unicode code point value.\n * If the input string is empty, returns `null`.\n * @function codePoint\n * @example\n * codePoint(\"ABC\") // 65\n */\n codePoint: {\n _func: args => evaluate(args, arg => {\n const text = toString(arg);\n return text.length === 0 ? null : text.codePointAt(0);\n }),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Determines if the given `subject` contains `search`.\n * If `subject` is an array, this function returns true if one of the elements\n * in the array is equal to the `search` value. If `subject`\n * is a string, return true if the string contains the\n * `search` value.\n * @param {array|string} subject The element to be searched\n * @param {any} search element to find.\n * If `subject` is an array, search for an exact match for `search` in the array.\n * If `subject` is a string, `search` must also be a string.\n * @return {boolean} true if found\n * @function contains\n * @example\n * contains([1, 2, 3, 4], 2) // returns true\n * contains([1, 2, 3, 4], -1) // returns false\n * contains(\"Abcd\", \"d\") // returns true\n * contains(\"Abcd\", \"x\") // returns false\n\n */\n contains: {\n _func: resolvedArgs => {\n const subject = valueOf(resolvedArgs[0]);\n const search = valueOf(resolvedArgs[1]);\n if (isArrayType(resolvedArgs[0])) {\n return subject.some(s => strictDeepEqual(s, search));\n }\n const source = Array.from(subject);\n if (getType(search) !== TYPE_STRING) {\n throw typeError('contains() requires a string search value for string subjects');\n }\n if (search === '') return true;\n const searchLen = Array.from(search).length;\n for (let i = 0; i < source.length; i += 1) {\n if (source.slice(i, i + searchLen).join('') === search) return true;\n }\n return false;\n },\n _signature: [{ types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_ANY] }],\n },\n /**\n * Compute the cosine (in radians) of a number.\n * @param {number|number[]} angle A number representing an angle in radians\n * @return {number|number[]} The cosine of the angle, between -1 and 1, inclusive.\n * @function cos\n * @example\n * cos(1.0471975512) => 0.4999999999970535\n */\n cos: {\n _func: args => evaluate(args, Math.cos),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Return difference between two date values.\n * The measurement of the difference is determined by the `unit` parameter. One of:\n *\n * * `y` the number of whole years between `start_date` and `end_date`\n * * `m` the number of whole months between `start_date` and `end_date`.\n * * `d` the number of days between `start_date` and `end_date`\n * * `ym` the number of whole months between `start_date` and `end_date`\n * after subtracting whole years.\n * * `yd` the number of days between `start_date` and `end_date`, assuming `start_date`\n * and `end_date` were no more than one year apart\n * @param {number|number[]} start_date The starting <<_date_and_time_values, date/time value>>.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @param {number|number[]} end_date The end <<_date_and_time_values, date/time value>> -- must\n * be greater or equal to start_date. If not, an error will be thrown.\n * @param {string|string[]} unit Case-insensitive string representing the unit of\n * time to measure. An unrecognized unit will result in an error.\n * @returns {integer|integer[]} The number of days/months/years difference\n * @function datedif\n * @example\n * datedif(datetime(2001, 1, 1), datetime(2003, 1, 1), \"y\") // returns 2\n * datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), \"D\") // returns 805\n * // 805 days between June 1, 2001, and August 15, 2003\n * datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), \"YD\") // returns 75\n * // 75 days between June 1 and August 15, ignoring the years of the dates (75)\n */\n datedif: {\n _func: args => evaluate(args, datedifFn),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Generate a date/time value from individual date/time parts.\n * If any of the units are greater than their normal range,\n * the overflow will be added to the next greater unit.\n * e.g. specifying 25 hours will increment the day value by 1.\n * Similarly,\n * negative values will decrement the next greater unit.\n * e.g. datetime(year, month, day - 30) will return a date 30 days earlier.\n * @param {integer} year The year to use for date construction.\n * Values from 0 to 99 map to the years 1900 to 1999. All other values are the actual year\n * @param {integer} month The month: beginning with 1 for\n * January to 12 for December.\n * @param {integer} day The day of the month.\n * @param {integer} [hours=0] Integer value between 0 and 23 representing the hour of the day.\n * @param {integer} [minutes=0] Integer value representing the minute segment of a time.\n * @param {integer} [seconds=0] Integer value representing the second segment of a time.\n * @param {integer} [milliseconds=0] Integer value representing the\n * millisecond segment of a time.\n * @returns {number} A <<_date_and_time_values, date/time value>>\n * to be used with other date/time functions\n * @function datetime\n * @example\n * datetime(2010, 10, 10) // returns representation of October 10, 2010\n * datetime(2010, 2, 28) // returns representation of February 28, 2010\n * datetime(2023,13,5) | year(@) & \"/\" & month(@) // returns 2024/1\n */\n datetime: {\n _func: args => {\n const year = toInteger(args[0]);\n const month = toInteger(args[1]) - 1; // javascript months start from 0\n const day = toInteger(args[2]);\n const hours = args.length > 3 ? toInteger(args[3]) : 0;\n const minutes = args.length > 4 ? toInteger(args[4]) : 0;\n const seconds = args.length > 5 ? toInteger(args[5]) : 0;\n const ms = args.length > 6 ? toInteger(args[6]) : 0;\n\n const baseDate = new Date(year, month, day, hours, minutes, seconds, ms);\n\n return getDateNum(baseDate);\n },\n _signature: [\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Finds the day of the month for a date value\n * @param {number|number[]} date <<_date_and_time_values, date/time value>> generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The day of the month ranging from 1 to 31.\n * @function day\n * @example\n * day(datetime(2008,5,23)) // returns 23\n */\n day: {\n _func: args => evaluate(args, a => getDateObj(a).getDate()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Debug a json-formula expression.\n * The `debug()` function allows users to inspect a sub-expression within a formula.\n * @param {any} arg The expression to return from `debug()` function,\n * and the default expression to be debugged. May be any type except an expression.\n * @param {any|expression} [displayValue=arg] Optionally override the value to be debugged.\n * `displayValue` may be an expression to\n * be evaluated with the context of `arg`.\n * @returns {any} The value of the `arg` parameter\n * @function debug\n * @example\n * avg(([1,2,3] * [2,3,4]).debug(@)).round(@,3) // 6.667\n * avg(debug([1,2,3] * [2,3,4],&\"average of: \" &toString(@))).round(@,3) // 6.667\n */\n debug: {\n _func: resolvedArgs => {\n const arg = resolvedArgs[0];\n if (resolvedArgs.length > 1) {\n if (getType(resolvedArgs[1]) === TYPE_EXPREF) {\n debug.push(runtime.interpreter.visit(resolvedArgs[1], arg));\n } else {\n debug.push(resolvedArgs[1]);\n }\n } else {\n debug.push(toJSON(resolvedArgs[0]));\n }\n return arg;\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_ANY, TYPE_EXPREF], optional: true },\n ],\n },\n\n /**\n * Performs a depth-first search of a nested hierarchy to\n * return an array of key values that match a `name`.\n * The name can be either a key into an object or an array index.\n * This is similar to the Descendant Accessor operator (`..`) from [E4X](https://ecma-international.org/publications-and-standards/standards/ecma-357/).\n * @param {object|array|null} object The starting object or array where we start the search\n * @param {string|integer} name The name (or index position) of the elements to find.\n * If `name` is a string, search for nested objects with a matching key.\n * If `name` is an integer, search for nested arrays with a matching index.\n * @returns {any[]} The array of matched elements\n * @function deepScan\n * @example\n * deepScan({a : {b1 : {c : 2}, b2 : {c : 3}}}, \"c\") // returns [2, 3]\n */\n deepScan: {\n _func: resolvedArgs => {\n const [source, n] = resolvedArgs;\n const [name, checkArrays] = getType(n) === TYPE_NUMBER\n ? [toInteger(n), true] : [toString(n), false];\n const items = [];\n function scan(node) {\n if (node === null) return;\n if (isArrayType(node)) {\n if (checkArrays && node[name] !== undefined) items.push(node[name]);\n node.forEach(scan);\n } else if (isObject(node)) {\n Object.entries(node).forEach(([k, v]) => {\n if (!checkArrays && k === name) items.push(v);\n scan(v);\n });\n }\n }\n scan(source);\n return items;\n },\n _signature: [\n { types: [TYPE_OBJECT, TYPE_ARRAY, TYPE_NULL] },\n { types: [TYPE_STRING, TYPE_NUMBER] },\n ],\n },\n\n /**\n * Determines if the `subject` string ends with a specific `suffix`\n * @param {string|string[]} subject source string in which to search\n * @param {string|string[]} suffix search string\n * @return {boolean|boolean[]} true if the `suffix` value is at the end of the `subject`\n * @function endsWith\n * @example\n * endsWith(\"Abcd\", \"d\") // returns true\n * endsWith(\"Abcd\", \"A\") // returns false\n */\n endsWith: {\n _func: args => evaluate(args, endsWithFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Returns an array of `[key, value]` pairs from an object or array.\n * The `fromEntries()` function may be used to convert an array to an object.\n * @param {object|array} obj source object or array\n * @returns {any[]} an array of arrays where each child array has two elements\n * representing the key and value of a pair\n * @function entries\n * @example\n * entries({a: 1, b: 2}) // returns [[\"a\", 1], [\"b\", 2]]\n * entries([4,5]) // returns [[\"0\", 4],[\"1\", 5]]\n */\n entries: {\n _func: args => {\n const obj = valueOf(args[0]);\n return Object.entries(obj);\n },\n _signature: [\n {\n types: [\n TYPE_ARRAY,\n TYPE_OBJECT,\n ],\n },\n ],\n },\n\n /**\n * Finds the date value of the end of a month, given `startDate` plus `monthAdd` months\n * @param {number|number[]} startDate The base date to start from.\n * <<_date_and_time_values, Date/time values>> can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @param {integer|integer[]} monthAdd Number of months to add to start date\n * @return {number|number[]} the date of the last day of the month\n * @function eomonth\n * @example\n * eomonth(datetime(2011, 1, 1), 1) | [month(@), day(@)] // returns [2, 28]\n * eomonth(datetime(2011, 1, 1), -3) | [month(@), day(@)] // returns [10, 31]\n */\n eomonth: {\n _func: args => evaluate(args, eomonthFn),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Finds e (the base of natural logarithms) raised to a power. (i.e. e^x)\n * @param {number|number[]} x A numeric expression representing the power of e.\n * @returns {number|number[]} e (the base of natural logarithms) raised to power x\n * @function exp\n * @example\n * exp(10) // returns 22026.465794806718\n */\n exp: {\n _func: args => evaluate(args, Math.exp),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Return constant boolean false value.\n * Expressions may also use the JSON literal: `` `false` ``\n * @returns {boolean} constant boolean value `false`\n * @function false\n */\n false: {\n _func: () => false,\n _signature: [],\n },\n\n /**\n * Finds and returns the index of query in text from a start position\n * @param {string|string[]} findText string to search\n * @param {string|string[]} withinText text to be searched\n * @param {integer|integer[]} [start=0] zero-based position to start searching.\n * If specified, `start` must be greater than or equal to 0\n * @returns {integer|null|integer[]} The position of the found string, null if not found.\n * @function find\n * @example\n * find(\"m\", \"abm\") // returns 2\n * find(\"M\", \"abMcdM\", 3) // returns 5\n * find(\"M\", \"ab\") // returns `null`\n * find(\"M\", \"abMcdM\", 2) // returns 2\n */\n find: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 3) args.push(0);\n return evaluate(args, findFn);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Calculates the next lowest integer value of the argument `num` by rounding down if necessary.\n * i.e. floor() rounds toward negative infinity.\n * @param {number|number[]} num numeric value\n * @return {integer|integer[]} The largest integer smaller than or equal to num\n * @function floor\n * @example\n * floor(10.4) // returns 10\n * floor(10) // returns 10\n */\n floor: {\n _func: args => evaluate(args, Math.floor),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Create a string from a code point.\n * @param {integer|integer[]} codePoint An integer or array of integers\n * between 0 and 0x10FFFF (inclusive) representing Unicode code point(s).\n * @return {string} A string from the given code point(s)\n * @function fromCodePoint\n * @example\n * fromCodePoint(65) // \"A\"\n * fromCodePoint(65) == \"\\u0041\" // true\n */\n fromCodePoint: {\n _func: args => {\n try {\n const points = Array.isArray(args[0]) ? args[0] : [args[0]];\n return String.fromCodePoint(...points.map(toInteger));\n } catch (e) {\n throw evaluationError(`Invalid code point: \"${args[0]}\"`);\n }\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Returns an object by transforming a list of key-value `pairs` into an object.\n * `fromEntries()` is the inverse operation of `entries()`.\n * If the nested arrays are not of the form: `[key, value]`\n * (where key is a string), an error will be thrown.\n * @param {any[]} pairs A nested array of key-value pairs to create the object from\n * The nested arrays must have exactly two values, where the first value is a string.\n * If a key is specified more than once, the last occurrence will override any previous value.\n * @returns {object} An object constructed from the provided key-value pairs\n * @function fromEntries\n * @example\n * fromEntries([[\"a\", 1], [\"b\", 2]]) // returns {a: 1, b: 2}\n */\n fromEntries: {\n _func: args => {\n const array = args[0];\n // validate beyond the TYPE_ARRAY_ARRAY check\n if (!array.every(a => {\n if (!Array.isArray(a)) return false;\n if (a.length !== 2) return false;\n if (getType(a[0]) !== TYPE_STRING) return false;\n return true;\n })) {\n throw typeError('fromEntries() requires an array of key value pairs');\n }\n return Object.fromEntries(array);\n },\n _signature: [\n { types: [TYPE_ARRAY_ARRAY, TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Compute the nearest 32-bit single precision float representation of a number\n * @param {number|number[]} num input to be rounded\n * @return {number|number[]} The rounded representation of `num`\n * @function fround\n * @example\n * fround(2147483650.987) => 2147483648\n * fround(100.44444444444444444444) => 100.44444274902344\n */\n fround: {\n _func: args => evaluate(args, Math.fround),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Determine if an object has a property or if an array index is in range.\n * @param {object|array|null} subject source object or array.\n * When querying for <<_hidden_properties,hidden properties>>, `subject` may be any data type.\n * @param {string|integer} name The name (or index position) of the element to find.\n * if `subject` is an array, `name` must be an integer;\n * if `subject` is an object, `name` must be a string.\n * @returns {boolean} true if the element exists\n * @function hasProperty\n * @example\n * hasProperty({a: 1, b: 2}, \"a\") // returns true\n * hasProperty([\"apples\", \"oranges\"], 3) // returns false\n * hasProperty(`null`, \"a\") // returns false\n */\n hasProperty: {\n _func: args => {\n let key = args[1];\n const keyType = getType(key);\n\n // if the object/array has a getter for this property then don't validate types\n if (args[0] !== null && Object.getOwnPropertyDescriptor(args[0], key)?.get) return true;\n const obj = valueOf(args[0]);\n if (obj === null) return false;\n const isArray = isArrayType(obj);\n if (!(isArray || getType(obj) === TYPE_OBJECT)) {\n throw typeError('First parameter to hasProperty() must be either an object or array.');\n }\n\n if (isArray) {\n if (keyType !== TYPE_NUMBER) throw TypeError('hasProperty(): Array index must be an integer');\n key = toInteger(key);\n } else if (keyType !== TYPE_STRING) throw TypeError('hasProperty(): Object key must be a string');\n const result = getProperty(obj, key);\n return result !== undefined;\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_STRING, TYPE_NUMBER] },\n ],\n },\n /**\n * Extract the hour from a <<_date_and_time_values, date/time value>>\n * @param {number|number[]} date The datetime/time for which the hour is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} value between 0 and 23\n * @function hour\n * @example\n * hour(datetime(2008,5,23,12, 0, 0)) // returns 12\n * hour(time(12, 0, 0)) // returns 12\n */\n hour: {\n _func: args => evaluate(args, a => getDateObj(a).getHours()),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Return one of two values `result1` or `result2`, depending on the `condition`\n * @param {any} condition boolean result of a logical expression\n * @param {any} result1 if condition is true\n * @param {any} result2 if condition is false\n * @return {any} either result1 or result2\n * @function if\n\n * @example\n * if(true(), 1, 2) // returns 1\n * if(false(), 1, 2) // returns 2\n */\n if: {\n _func: (unresolvedArgs, data, interpreter) => {\n const conditionNode = unresolvedArgs[0];\n const leftBranchNode = unresolvedArgs[1];\n const rightBranchNode = unresolvedArgs[2];\n unresolvedArgs\n .forEach(arg => {\n if (arg.type === 'ExpressionReference') {\n throw typeError('\"if()\" does not accept an expression reference argument.');\n }\n });\n\n const condition = interpreter.visit(conditionNode, data);\n if (toBoolean(valueOf(condition))) {\n return interpreter.visit(leftBranchNode, data);\n }\n return interpreter.visit(rightBranchNode, data);\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_ANY] },\n { types: [TYPE_ANY] }],\n },\n\n /**\n * Combines all the elements from the provided\n * array, joined together using the `glue` argument as a separator between each array element.\n * @param {any[]} array array of values that will be converted to strings using `toString()`\n * @param {string} glue\n * @return {string} String representation of the array\n * @function join\n * @example\n * join([\"a\", \"b\", \"c\"], \",\") // returns \"a,b,c\"\n * join([\"apples\", \"bananas\"], \" and \") // returns \"apples and bananas\"\n * join([1, 2, 3, null()], \"|\") // returns \"1|2|3|null\"\n */\n join: {\n _func: resolvedArgs => {\n const listJoin = resolvedArgs[0];\n const joinChar = resolvedArgs[1];\n return listJoin.map(a => toJSON(a)).join(joinChar);\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n { types: [TYPE_STRING] },\n ],\n },\n\n /**\n * Generates an array of the keys of the input object. If the\n * object is null, the value return an empty array\n * @param {object} obj the object to examine\n * @return {array} the array of all the key names\n * @function keys\n * @example\n * keys({a : 3, b : 4}) // returns [\"a\", \"b\"]\n */\n keys: {\n _func: resolvedArgs => Object.keys(resolvedArgs[0]),\n _signature: [{ types: [TYPE_OBJECT] }],\n },\n /**\n * Return a substring from the start of a string or the left-most elements of an array\n * @param {string|array} subject The source text/array of code points/elements\n * @param {integer} [elements=1] number of elements to pick\n * @return {string|array}\n * @function left\n * @example\n * left(\"Sale Price\", 4) // returns \"Sale\"\n * left(\"Sweden\") // returns \"S\"\n * left([4, 5, 6], 2) // returns [4, 5]\n */\n left: {\n _func: args => {\n const numEntries = args.length > 1 ? toInteger(args[1]) : 1;\n if (numEntries < 0) throw evaluationError('left() requires a non-negative number of elements');\n if (isArrayType(args[0])) return args[0].slice(0, numEntries);\n const text = Array.from(toString(args[0]));\n return text.slice(0, numEntries).join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Calculates the length of the input argument based on types:\n *\n * * string: returns the number of unicode code points\n * * array: returns the number of array elements\n * * object: returns the number of key-value pairs\n * @param {string | array | object} subject subject whose length to calculate\n * @return {integer} the length of the input subject\n * @function length\n * @example\n * length(`[]`) // returns 0\n * length(\"\") // returns 0\n * length(\"abcd\") // returns 4\n * length([1, 2, 3, 4]) // returns 4\n * length(`{}`) // returns 0\n * length({a : 3, b : 4}) // returns 2\n */\n length: {\n _func: resolvedArgs => {\n const arg = valueOf(resolvedArgs[0]);\n if (isObject(arg)) return Object.keys(arg).length;\n // Array.from splits a string into code points\n // If we didn't do this, then String.length would return the number of UTF-16 code units\n return isArrayType(arg) ? arg.length : Array.from(toString(arg)).length;\n },\n _signature: [{ types: [TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT] }],\n },\n\n /**\n * Compute the natural logarithm (base e) of a number\n * @param {number|number[]} num A number greater than zero\n * @return {number|number[]} The natural log value\n * @function log\n * @example\n * log(10) // 2.302585092994046\n */\n log: {\n _func: args => evaluate(args, a => validNumber(Math.log(a), 'log')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Compute the base 10 logarithm of a number.\n * @param {number|number[]} num A number greater than or equal to zero\n * @return {number|number[]} The base 10 log result\n * @function log10\n * @example\n * log10(100000) // 5\n */\n log10: {\n _func: args => evaluate(args, a => validNumber(Math.log10(a), 'log10')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Converts all the alphabetic code points in a string to lowercase.\n * @param {string|string[]} input input string\n * @returns {string|string[]} the lower case value of the input string\n * @function lower\n * @example\n * lower(\"E. E. Cummings\") // returns \"e. e. cummings\"\n */\n lower: {\n _func: args => evaluate(args, a => toString(a).toLowerCase()),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Apply an expression to every element in an array and return the array of results.\n * An input array of length N will return an array of length N.\n * @param {array} elements array of elements to process\n * @param {expression} expr expression to evaluate\n * @return {array} the mapped array\n * @function map\n * @example\n * map([1, 2, 3, 4], &(@ + 1)) // returns [2, 3, 4, 5]\n * map([\"doe\", \"nick\", \"chris\"], &length(@)) // returns [3, 4, 5]\n */\n map: {\n _func: resolvedArgs => {\n const exprefNode = resolvedArgs[1];\n return resolvedArgs[0].map(arg => runtime.interpreter.visit(exprefNode, arg));\n },\n _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],\n },\n\n /**\n * Calculates the largest value in the input numbers.\n * Any values that are not numbers (null, boolean, strings, objects) will be ignored.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(array|any)} collection values/array(s) in which the maximum\n * element is to be calculated\n * @return {number} the largest value found\n * @function max\n * @example\n * max([1, 2, 3], [4, 5, 6]) // returns 6\n * max([\\\"a\\\", \\\"a1\\\", \\\"b\\\"], null(), true())) // returns 0\n * max(8, 10, 12, \"14\") // returns 12\n */\n max: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => typeof valueOf(a) === 'number');\n\n if (array.length === 0) return 0;\n\n return Math.max(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Calculates the largest value in the input values, coercing parameters to numbers.\n * Null values are ignored.\n * If any parameters cannot be converted to a number,\n * the function will fail with a type error.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(any)} collection values/array(s) in which the maximum\n * element is to be calculated\n * @return {number} the largest value found\n * @function maxA\n * @example\n * maxA([1, 2, 3], [4, 5, 6]) // returns 6\n * maxA([\"a\", \"a1\", \"b\", null()]) // error\n * maxA(8, 10, 12, \"14\") // returns 14\n */\n maxA: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => valueOf(a) !== null)\n .map(toNumber);\n\n if (array.find(a => a === null)) {\n throw evaluationError('maxA() received non-numeric parameters');\n }\n if (array.length === 0) return 0;\n\n return Math.max(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Accepts one or more objects, and returns a single object with\n * all objects merged.\n * The first object is copied, and then\n * and each key value pair from each subsequent object\n * are added to the first object. Duplicate keys in subsequent objects will\n * override those found in earlier objects.\n * @param {...object} args\n * @return {object} The combined object\n * @function merge\n * @example\n * merge({a: 1, b: 2}, {c : 3, d: 4}) // returns {a :1, b: 2, c: 3, d: 4}\n * merge({a: 1, b: 2}, {a : 3, d: 4}) // returns {a :3, b: 2, d: 4}\n */\n merge: {\n _func: resolvedArgs => {\n const merged = {};\n resolvedArgs.forEach(current => {\n if (current === null) return;\n Object.entries(current || {}).forEach(([key, value]) => {\n merged[key] = value;\n });\n });\n return merged;\n },\n _signature: [{ types: [TYPE_OBJECT, TYPE_NULL], variadic: true }],\n },\n\n /**\n * Extracts a substring from text, or a subset from an array.\n * @param {string|array} subject the text string or array of elements from which to extract.\n * @param {integer} startPos the zero-based position of the first code point\n * or element to extract.\n * @param {integer} length The number of code points or elements to return from the\n * string or array.\n * If greater then the length of `subject` the length of the subject is used.\n * @return {string|array} The resulting substring or array subset of elements\n * @function mid\n * @example\n * mid(\"Fluid Flow\", 0, 5) // returns \"Fluid\"\n * mid(\"Fluid Flow\", 6, 20) // returns \"Flow\"\n * mid(\"Fluid Flow\", 20, 5) // returns \"\"\n * mid([0,1,2,3,4,5,6,7,8,9], 2, 3) // returns [2,3,4]\n */\n mid: {\n _func: args => {\n const startPos = toInteger(args[1]);\n const numEntries = toInteger(args[2]);\n if (startPos < 0) throw evaluationError('mid() requires a non-negative start position');\n if (numEntries < 0) throw evaluationError('mid() requires a non-negative length parameter');\n if (isArrayType(args[0])) {\n return args[0].slice(startPos, startPos + numEntries);\n }\n const text = Array.from(toString(args[0]));\n return text.slice(startPos, startPos + numEntries).join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n ],\n },\n\n /**\n * Extract the milliseconds of the time value in a <<_date_and_time_values, date/time value>>.\n * @param {number|number[]} date datetime/time for which the millisecond is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The number of milliseconds: 0 through 999\n * @function millisecond\n * @example\n * millisecond(datetime(2008, 5, 23, 12, 10, 53, 42)) // returns 42\n */\n millisecond: {\n _func: args => evaluate(args, a => getDateObj(a).getMilliseconds()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Calculates the smallest value in the input numbers.\n * Any values that are not numbers (null, boolean, string, object) will be ignored.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(any[]|any)} collection\n * Values/arrays to search for the minimum value\n * @return {number} the smallest value found\n * @function min\n * @example\n * min([1, 2, 3], [4, 5, 6]) // returns 1\n * min(\"4\", 8, 10, 12, null()) // returns 8\n */\n min: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => typeof valueOf(a) === 'number');\n if (array.length === 0) return 0;\n\n return Math.min(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Calculates the smallest value in the input values, coercing parameters to numbers.\n * Null values are ignored.\n * If any parameters cannot be converted to a number,\n * the function will fail with a type error.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(any[]|any)} collection values/array(s) in which the maximum\n * element is to be calculated\n * @return {number} the largest value found\n * @function minA\n * @example\n * minA([1, 2, 3], [4, 5, 6]) // returns 1\n * minA(\"4\", 8, 10, 12, null()) // returns 4\n */\n minA: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => valueOf(a) !== null)\n .map(toNumber);\n\n if (array.find(a => a === null)) {\n throw evaluationError('minA() received non-numeric parameters');\n }\n if (array.length === 0) return 0;\n\n return Math.min(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Extract the minute (0 through 59) from a <<_date_and_time_values, date/time value>>\n * @param {number|number[]} date A datetime/time value.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} Number of minutes in the time portion of the date/time value\n * @function minute\n * @example\n * minute(datetime(2008,5,23,12, 10, 0)) // returns 10\n * minute(time(12, 10, 0)) // returns 10\n */\n minute: {\n _func: args => evaluate(args, a => getDateObj(a).getMinutes()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Return the remainder when one number is divided by another number.\n * @param {number|number[]} dividend The number for which to find the remainder.\n * @param {number|number[]} divisor The number by which to divide number.\n * @return {number|number[]} Computes the remainder of `dividend`/`divisor`.\n * If `dividend` is negative, the result will also be negative.\n * If `dividend` is zero, an error is thrown.\n * @function mod\n * @example\n * mod(3, 2) // returns 1\n * mod(-3, 2) // returns -1\n */\n mod: {\n _func: args => evaluate(args, (a, b) => {\n const result = a % b;\n if (Number.isNaN(result)) throw evaluationError(`Bad parameter for mod: '${a} % ${b}'`);\n return result;\n }),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Finds the month of a date.\n * @param {number|number[]} date source <<_date_and_time_values, date/time value>>.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The month number value, ranging from 1 (January) to 12 (December)\n * @function month\n * @example\n * month(datetime(2008,5,23)) // returns 5\n */\n month: {\n // javascript months start from 0\n _func: args => evaluate(args, a => getDateObj(a).getMonth() + 1),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Compute logical NOT of a value. If the parameter is not boolean\n * it will be <<_type_coercion_rules,cast to boolean>>\n * Note the related <<_not_operator, unary NOT operator>>.\n * @param {any} value - any data type\n * @returns {boolean} The logical NOT applied to the input parameter\n * @example\n * not(length(\"bar\") > 0) // returns false\n * not(false()) // returns true\n * not(\"abcd\") // returns false\n * not(\"\") // returns true\n * @function not\n */\n not: {\n _func: resolveArgs => !toBoolean(valueOf(resolveArgs[0])),\n _signature: [{ types: [TYPE_ANY] }],\n },\n\n /**\n * Finds the first argument that does not resolve to `null`.\n * This function accepts one or more arguments, and will evaluate\n * them in order until a non-null argument is encountered. If all\n * arguments values resolve to null, then return a null value.\n * @param {...any} argument\n * @return {any}\n * @function notNull\n * @example\n * notNull(1, 2, 3, 4, `null`) // returns 1\n * notNull(`null`, 2, 3, 4, `null`) // returns 2\n */\n notNull: {\n _func: resolvedArgs => {\n const result = resolvedArgs.find(arg => getType(arg) !== TYPE_NULL);\n return result === undefined ? null : result;\n },\n _signature: [{ types: [TYPE_ANY], variadic: true }],\n },\n /**\n * Retrieve the current date/time.\n * @return {number} representation of the <<_date_and_time_values, current date/time value>>.\n * @function now\n */\n now: {\n _func: () => getDateNum(Date.now()),\n _signature: [],\n },\n\n /**\n * Return constant null value.\n * Expressions may also use the JSON literal: `` `null` ``\n * @returns {boolean} True\n * @function null\n */\n null: {\n _func: () => null,\n _signature: [],\n },\n\n /**\n * Determines the logical OR result of a set of parameters.\n * If the parameters are not boolean they will be <<_type_coercion_rules,cast to\n * boolean>>.\n * Note the related <<_or_operator, Or Operator>>.\n * @param {any} first logical expression\n * @param {...any} [operand] any number of additional expressions\n * @returns {boolean} The logical result of applying OR to all parameters\n * @example\n * or((x / 2) == y, (y * 2) == x) // true\n * @function or\n */\n or: {\n _func: resolvedArgs => {\n let result = toBoolean(valueOf(resolvedArgs[0]));\n resolvedArgs.slice(1).forEach(arg => {\n result = result || toBoolean(valueOf(arg));\n });\n return result;\n },\n _signature: [{ types: [TYPE_ANY], variadic: true }],\n },\n\n /**\n * Computes `a` raised to a power `x`. (a^x)\n * @param {number|number[]} a The base number -- can be any real number.\n * @param {number|number[]} x The exponent to which the base number is raised.\n * @return {number|number[]}\n * @function power\n * @example\n * power(10, 2) // returns 100 (10 raised to power 2)\n */\n power: {\n _func: args => evaluate(args, (a, b) => validNumber(a ** b, 'power')),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Apply proper casing to a string. Proper casing is where the first letter of each\n * word is converted to an\n * uppercase letter and the rest of the letters in the word converted to lowercase.\n * Words are demarcated by whitespace, punctuation, or numbers.\n * Specifically, any character(s) matching the regular expression: `[\\s\\d\\p{P}]+`.\n * @param {string|string[]} text source string\n * @returns {string|string[]} source string with proper casing applied.\n * @function proper\n * @example\n * proper(\"this is a TITLE\") // returns \"This Is A Title\"\n * proper(\"2-way street\") // returns \"2-Way Street\"\n * proper(\"76BudGet\") // returns \"76Budget\"\n */\n proper: {\n _func: args => evaluate(args, properFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Generate a pseudo random number.\n * @returns {number} A value greater than or equal to zero, and less than one.\n * @function random\n * @example\n * random() // 0.022585461160693265\n */\n random: {\n _func: () => Math.random(),\n _signature: [],\n },\n /**\n * Executes a user-supplied reducer expression on each element of an\n * array, in order, passing in the return value from the expression from the preceding element.\n * The final result of running the reducer across all elements of the input array is a\n * single value.\n * The expression can access the following properties of the current object:\n *\n * * accumulated: accumulated value based on the previous expression.\n * For the first array element use the `initialValue` parameter. If not provided, then `null`\n * * current: current element to process\n * * index: index of the current element in the array\n * * array: original array\n * @param {array} elements array of elements on which the expression will be evaluated\n * @param {expression} expr reducer expression to be executed on each element\n * @param {any} initialValue the accumulated value to pass to the first array element\n * @return {any}\n * @function reduce\n * @example\n * reduce([1, 2, 3], &(accumulated + current)) // returns 6\n * // find maximum entry by age\n * reduce(\n * [{age: 10, name: \"Joe\"},{age: 20, name: \"John\"}],\n * &max(@.accumulated.age, @.current.age), @[0].age)\n * reduce([3, 3, 3], &accumulated * current, 1) // returns 27\n */\n reduce: {\n _func: resolvedArgs => {\n const exprefNode = resolvedArgs[1];\n return resolvedArgs[0].reduce(\n (accumulated, current, index, array) => runtime.interpreter.visit(exprefNode, {\n accumulated, current, index, array,\n }),\n resolvedArgs.length === 3 ? resolvedArgs[2] : null,\n );\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n { types: [TYPE_EXPREF] },\n { types: [TYPE_ANY], optional: true },\n ],\n },\n\n /**\n * Register a function. The registered function may take one parameter.\n * If more parameters are needed, combine them in an array or object.\n * A function may not be re-registered with a different definition.\n * Note that implementations are not required to provide `register()` in order to be conformant.\n * Built-in functions may not be overridden.\n * @param {string} functionName Name of the function to register.\n * `functionName` must begin with an underscore or uppercase letter and follow the regular\n * expression pattern:\n * `{caret}{startsb}_A-Z{endsb}{startsb}_a-zA-Z0-9${endsb}{asterisk}$`\n * @param {expression} expr Expression to execute with this function call\n * @return {{}} returns an empty object\n * @function register\n * @example\n * register(\"_product\", &@[0] * @[1]) // can now call: _product([2,21]) => returns 42\n * register(\"_ltrim\", &split(@,\"\").reduce(@, &accumulated & current | if(@ = \" \", \"\", @), \"\"))\n * // _ltrim(\" abc \") => returns \"abc \"\n */\n register: {\n _func: resolvedArgs => {\n const functionName = resolvedArgs[0];\n const exprefNode = resolvedArgs[1];\n\n if (!/^[_A-Z][_a-zA-Z0-9$]*$/.test(functionName)) throw functionError(`Invalid function name: \"${functionName}\"`);\n if (functionMap[functionName]\n && functionMap[functionName]._exprefNode.value !== exprefNode.value) {\n // custom functions can be re-registered as long as the expression is the same\n throw functionError(`Cannot override function: \"${functionName}\" with a different definition`);\n }\n functionMap[functionName] = {\n _func: args => runtime.interpreter.visit(exprefNode, ...args),\n _signature: [{ types: [TYPE_ANY], optional: true }],\n _exprefNode: exprefNode,\n };\n return {};\n },\n _signature: [\n { types: [TYPE_STRING] },\n { types: [TYPE_EXPREF] },\n ],\n },\n\n /**\n * Register a function that accepts multiple parameters.\n * A function may not be re-registered with a different definition.\n * Note that implementations are not required to provide `registerWithParams()`\n * in order to be conformant.\n * Built-in functions may not be overridden.\n * @param {string} functionName Name of the function to register.\n * `functionName` must begin with an underscore or uppercase letter and follow the regular\n * expression pattern:\n * `{caret}{startsb}_A-Z{endsb}{startsb}_a-zA-Z0-9${endsb}{asterisk}$`\n * @param {expression} expr Expression to execute with this function call.\n * Parameters are passed as an array.\n * @return {{}} returns an empty object\n * @function registerWithParams\n * @example\n * registerWithParams(\"Product\", &@[0] * @[1])\n * // can now call: Product(2,21) => returns 42\n * registerWithParams(\n * \"Ltrim\",\n * &split(@[0],\"\").reduce(@, &accumulated & current | if(@ = \" \", \"\", @), \"\")\n * )\n * // Ltrim(\" abc \") => returns \"abc \"\n */\n registerWithParams: {\n _func: resolvedArgs => {\n const functionName = resolvedArgs[0];\n const exprefNode = resolvedArgs[1];\n\n if (!/^[_A-Z][_a-zA-Z0-9$]*$/.test(functionName)) throw functionError(`Invalid function name: \"${functionName}\"`);\n if (functionMap[functionName]\n && functionMap[functionName]._exprefNode.value !== exprefNode.value) {\n // custom functions can be re-registered as long as the expression is the same\n throw functionError(`Cannot override function: \"${functionName}\" with a different definition`);\n }\n functionMap[functionName] = {\n _func: args => runtime.interpreter.visit(exprefNode, args),\n _signature: [{ types: [TYPE_ANY], optional: true, variadic: true }],\n _exprefNode: exprefNode,\n };\n return {};\n },\n _signature: [\n { types: [TYPE_STRING] },\n { types: [TYPE_EXPREF] },\n ],\n },\n\n /**\n * Generates text (or an array) where we substitute elements at a given start position and\n * length, with new text (or array elements).\n * @param {string|array} subject original text or array\n * @param {integer} start zero-based index in the original text\n * from where to begin the replacement. Must be greater than or equal to 0.\n * @param {integer} length number of code points to be replaced.\n * If `start` + `length` is greater than the length of `subject`,\n * all text past `start` will be replaced.\n * @param {any} replacement Replacement to insert at the start index.\n * If `subject` is an array, and `replacement` is an array, the `replacement` array\n * elements will be inserted into the `subject` array.\n * If `subject` is an array and replacement is not an array, the `replacement` will be\n * inserted as a single element in `subject`\n * If `subject` is a string, the `replacement` will be coerced to a string.\n * @returns {string|array} the resulting text or array\n * @function replace\n * @example\n * replace(\"abcdefghijk\", 5, 5, \"*\") // returns abcde*k\n * replace(\"2009\",2,2,\"10\") // returns 2010\n * replace(\"123456\",0,3,\"@\") // returns @456\n * replace([\"blue\",\"black\",\"white\",\"red\"], 1, 2, [\"green\"]) // returns [\"blue\",\"green\",\"red\"]\n */\n replace: {\n _func: args => {\n const startPos = toInteger(args[1]);\n const numElements = toInteger(args[2]);\n if (startPos < 0) throw evaluationError('replace() start position must be greater than or equal to 0');\n if (numElements < 0) throw evaluationError('replace() length must be greater than or equal to 0');\n if (isArrayType(args[0])) {\n const sourceArray = valueOf(args[0]);\n let replacement = valueOf(args[3]);\n if (!isArrayType(replacement)) replacement = [replacement];\n sourceArray.splice(startPos, numElements, ...replacement);\n return sourceArray;\n }\n const subject = Array.from(toString(args[0]));\n if (isArrayType(args[3]) || getType(args[3]) === TYPE_OBJECT) throw typeError('replace() replacement must not be an array or object');\n const newText = toString(args[3]);\n\n subject.splice(startPos, numElements, newText);\n return subject.join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_ANY] },\n ],\n },\n\n /**\n * Return text repeated `count` times.\n * @param {string|string[]} text text to repeat\n * @param {integer|integer[]} count number of times to repeat the text.\n * Must be greater than or equal to 0.\n * @returns {string|string[]} Text generated from the repeated text.\n * if `count` is zero, returns an empty string.\n * @function rept\n * @example\n * rept(\"x\", 5) // returns \"xxxxx\"\n */\n rept: {\n _func: args => evaluate(args, reptFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Reverses the order of an array or the order of code points in a string\n * @param {string|array} subject the source to be reversed\n * @return {array} The resulting reversed array or string\n * @function reverse\n * @example\n * reverse([\"a\", \"b\", \"c\"]) // returns [\"c\", \"b\", \"a\"]\n */\n reverse: {\n _func: resolvedArgs => {\n const originalStr = valueOf(resolvedArgs[0]);\n const typeName = getType(originalStr);\n if (typeName === TYPE_STRING) {\n return Array.from(originalStr).reverse().join('');\n }\n const reversedArray = resolvedArgs[0].slice(0);\n return reversedArray.reverse();\n },\n _signature: [{ types: [TYPE_STRING, TYPE_ARRAY] }],\n },\n\n /**\n * Generates a string from the right-most code points of a string or\n * a subset of elements from the end of an array\n * @param {string|array} subject The text/array containing the code points/elements to extract\n * @param {integer} [elements=1] number of elements to pick\n * @return {string|array} The extracted substring or array subset\n * Returns null if the number of elements is less than 0\n * @function right\n * @example\n * right(\"Sale Price\", 4) // returns \"rice\"\n * right(\"Sweden\") // returns \"n\"\n * right([4, 5, 6], 2) // returns [5, 6]\n */\n right: {\n _func: args => {\n const numEntries = args.length > 1 ? toInteger(args[1]) : 1;\n if (numEntries < 0) throw evaluationError('right() count must be greater than or equal to 0');\n if (args[0] instanceof Array) {\n if (numEntries === 0) return [];\n return args[0].slice(numEntries * -1);\n }\n if (numEntries === 0) return '';\n const text = Array.from(toString(args[0]));\n return text.slice(numEntries * -1).join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Round a number to a specified precision:\n *\n * * If `precision` is greater than zero, round to the specified number of decimal places.\n * * If `precision` is 0, round to the nearest integer.\n * * If `precision` is less than 0, round to the left of the decimal point.\n * @param {number|number[]} num number to round\n * @param {integer|integer[]} [precision=0] precision to use for the rounding operation.\n * @returns {number|number[]} rounded value. Rounding a half value will round up.\n * @function round\n * @example\n * round(2.15, 1) // returns 2.2\n * round(626.3,-3) // returns 1000 (Rounds 626.3 to the nearest multiple of 1000)\n * round(626.3, 0) // returns 626\n * round(1.98,-1) // returns 0 (Rounds 1.98 to the nearest multiple of 10)\n * round(-50.55,-2) // -100 (round -50.55 to the nearest multiple of 100)\n * round(1.95583) // 2\n * round(-1.5) // -1\n */\n round: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2)args.push(0);\n return evaluate(args, (a, n) => {\n const digits = toInteger(n);\n return round(a, digits);\n });\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Perform a wildcard search. The search is case-sensitive and supports two forms of wildcards:\n * `{asterisk}` finds a sequence of code points and `?` finds a single code point.\n * To use `{asterisk}` or `?` or `{backslash}` as text values,\n * precede them with an escape (`{backslash}`) character.\n * Note that the wildcard search is not greedy.\n * e.g. `search(\"a{asterisk}b\", \"abb\")` will return `[0, \"ab\"]` Not `[0, \"abb\"]`\n * @param {string|string[]} findText the search string -- which may include wild cards.\n * @param {string|string[]} withinText The string to search.\n * @param {integer|integer[]} [startPos=0] The zero-based position of withinText\n * to start searching.\n * A negative value is not allowed.\n * @returns {array} returns an array with two values:\n *\n * * The start position of the found text and the text string that was found.\n * * If a match was not found, an empty array is returned.\n * @function search\n * @example\n * search(\"a?c\", \"acabc\") // returns [2, \"abc\"]\n */\n search: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2) args.push(0);\n return evaluate(args, searchFn);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n\n },\n\n /**\n * Extract the seconds of the time value in a <<_date_and_time_values, date/time value>>.\n * @param {number|number[]} date datetime/time for which the second is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The number of seconds: 0 through 59\n * @function second\n * @example\n * second(datetime(2008,5,23,12, 10, 53)) // returns 53\n * second(time(12, 10, 53)) // returns 53\n */\n second: {\n _func: args => evaluate(args, a => getDateObj(a).getSeconds()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Computes the sign of a number passed as argument.\n * @param {number|number[]} num any number\n * @return {number|number[]} returns 1 or -1, indicating the sign of `num`.\n * If the `num` is 0, it will return 0.\n * @function sign\n * @example\n * sign(5) // 1\n * sign(-5) // -1\n * sign(0) // 0\n */\n sign: {\n _func: args => evaluate(args, Math.sign),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Computes the sine of a number in radians\n * @param {number|number[]} angle A number representing an angle in radians.\n * @return {number|number[]} The sine of `angle`, between -1 and 1, inclusive\n * @function sin\n * @example\n * sin(0) // 0\n * sin(1) // 0.8414709848078965\n */\n sin: {\n _func: args => evaluate(args, Math.sin),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * This function accepts an array values and returns an\n * array with the elements in sorted order.\n * If there are mixed data types, the values will be grouped in order:\n * numbers, strings, booleans, nulls\n * String sorting is based on code points and is not locale-sensitive.\n * If the sort encounters any objects or arrays, it will throw an evaluation error.\n * @param {any[]} list to be sorted\n * @return {any[]} The ordered result\n * @function sort\n * @example\n * sort([1, 2, 4, 3, 1]) // returns [1, 1, 2, 3, 4]\n * sort([\"20\", 20, true(), \"100\", null(), 100]) // returns [20, 100, \"100\", \"20\", true, null]\n */\n sort: {\n _func: resolvedArgs => {\n /*\n numbers sort first\n strings sort second\n Booleans sort third\n nulls sort last\n */\n const typeVals = resolvedArgs[0].map(value => {\n const type = getType(value);\n if (![TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN, TYPE_NULL].includes(type)) {\n throw evaluationError('Bad datatype for sort');\n }\n return { type, value };\n });\n\n const sortFunction = (a, b) => {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n };\n\n const sorted = typeVals\n .filter(v => v.type === TYPE_NUMBER)\n .map(v => v.value)\n .sort(sortFunction);\n\n sorted.push(\n ...typeVals\n .filter(v => v.type === TYPE_STRING)\n .map(v => v.value)\n .sort(),\n );\n\n sorted.push(...typeVals.filter(v => v.type === TYPE_BOOLEAN).map(v => v.value));\n sorted.push(...typeVals.filter(v => v.type === TYPE_NULL).map(v => v.value));\n return sorted;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Sort an array using an expression to find the sort key. For each element\n * in the array, the expression is applied and the resulting\n * value is used as the sort value. If the result of\n * evaluating the expression against the current array element results in type\n * other than a number or a string, a <<_errors, TypeError>> will occur.\n * @param {array} elements Array to be sorted\n * @param {expression} expr The comparison expression\n * @return {array} The sorted array\n * @function sortBy\n * @example\n * // returns [\"e\", \"def\", \"abcd\"]\n * sortBy([\"abcd\", \"e\", \"def\"], &length(@))\n *\n * // returns [{year: 1910}, {year: 2010}, {year: 2020}]\n * sortBy([{year: 2010}, {year: 2020}, {year: 1910}], &year)\n *\n * // returns [5, -10, -11, -15, 30]\n * sortBy([-15, 30, -10, -11, 5], &abs(@))\n */\n sortBy: {\n _func: resolvedArgs => {\n const sortedArray = resolvedArgs[0].slice(0);\n if (sortedArray.length === 0) {\n return sortedArray;\n }\n const exprefNode = resolvedArgs[1];\n const requiredType = getType(\n runtime.interpreter.visit(exprefNode, sortedArray[0]),\n );\n if (![TYPE_NUMBER, TYPE_STRING].includes(requiredType)) {\n throw typeError('Bad data type for sortBy()');\n }\n // In order to get a stable sort out of an unstable\n // sort algorithm, we decorate/sort/undecorate (DSU)\n // by creating a new list of [index, element] pairs.\n // In the cmp function, if the evaluated elements are\n // equal, then the index will be used as the tiebreaker.\n // After the decorated list has been sorted, it will be\n // undecorated to extract the original elements.\n const decorated = [];\n for (let i = 0; i < sortedArray.length; i += 1) {\n decorated.push([i, sortedArray[i]]);\n }\n decorated.sort((a, b) => {\n const exprA = runtime.interpreter.visit(exprefNode, a[1]);\n const typeA = getType(exprA);\n const exprB = runtime.interpreter.visit(exprefNode, b[1]);\n const typeB = getType(exprB);\n if (typeA !== requiredType) {\n throw typeError(`sortBy expected ${typeNameTable[requiredType]}, received ${typeNameTable[typeA]}`);\n } else if (typeB !== requiredType) {\n throw typeError(`sortyBy expected ${typeNameTable[requiredType]}, received ${typeNameTable[typeB]}`);\n }\n if (exprA > exprB) return 1;\n if (exprA < exprB) return -1;\n // If they\"re equal compare the items by their\n // order to maintain relative order of equal keys\n // (i.e. to get a stable sort).\n return a[0] - b[0];\n });\n // Undecorate: extract out the original list elements.\n for (let j = 0; j < decorated.length; j += 1) {\n [, sortedArray[j]] = decorated[j];\n }\n return sortedArray;\n },\n _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],\n },\n\n /**\n * Split a string into an array, given a separator\n * @param {string|string[]} string string to split\n * @param {string|string[]} separator separator where the split(s) should occur\n * @return {string[]|string[][]} The array of separated strings\n * @function split\n * @example\n * split(\"abcdef\", \"\") // returns [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]\n * split(\"abcdef\", \"e\") // returns [\"abcd\", \"f\"]\n */\n split: {\n _func: args => evaluate(args, splitFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Find the square root of a number\n * @param {number|number[]} num source number\n * @return {number|number[]} The calculated square root value\n * @function sqrt\n * @example\n * sqrt(4) // returns 2\n */\n sqrt: {\n _func: args => evaluate(args, arg => validNumber(Math.sqrt(arg), 'sqrt')),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Determine if a string starts with a prefix.\n * @param {string|string[]} subject string to search\n * @param {string|string[]} prefix prefix to search for\n * @return {boolean|boolean[]} true if `prefix` matches the start of `subject`\n * @function startsWith\n * @example\n * startsWith(\"jack is at home\", \"jack\") // returns true\n */\n startsWith: {\n _func: args => evaluate(args, startsWithFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n /**\n * Estimates standard deviation based on a sample.\n * `stdev` assumes that its arguments are a sample of the entire population.\n * If your data represents a entire population,\n * then compute the standard deviation using [stdevp]{@link stdevp}.\n * Non-numeric values (text, boolean, null etc) are ignored.\n * If there are nested arrays, they are flattened.\n * @param {any[]} values The array containing numbers comprising the population.\n * Array size must be greater than 1.\n * @returns {number} [Standard deviation](https://en.wikipedia.org/wiki/Standard_deviation)\n * @function stdev\n * @example\n * stdev([1345, 1301, 1368]) // returns 34.044089061098404\n * stdevp([1345, 1301, 1368]) // returns 27.797\n */\n stdev: {\n _func: args => {\n const values = args.flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER);\n\n if (values.length <= 1) throw evaluationError('stdev() must have at least two values');\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const sumSquare = values.reduce((a, b) => a + b * b, 0);\n const result = Math.sqrt((sumSquare - values.length * mean * mean) / (values.length - 1));\n return validNumber(result, 'stdev');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Estimates standard deviation based on a sample.\n * `stdev` assumes that its arguments are a sample of the entire population.\n * If your data represents a entire population,\n * then compute the standard deviation using [stdevpA]{@link stdevpA}.\n * Nested arrays are flattened.\n * Null values are ignored. All other parameters are converted to number.\n * If conversion to number fails, a type error is thrown.\n * @param {number[]} numbers The array of numbers comprising the population.\n * Array size must be greater than 1.\n * @returns {number} [Standard deviation](https://en.wikipedia.org/wiki/Standard_deviation)\n * @function stdevA\n * @example\n * stdevA([1345, \"1301\", 1368]) // returns 34.044089061098404\n * stdevpA([1345, 1301, \"1368\"]) // returns 27.797\n */\n stdevA: {\n _func: args => {\n let values;\n try {\n values = args.flat(Infinity)\n .filter(a => getType(a) !== TYPE_NULL)\n .map(toNumber);\n } catch (_e) {\n throw evaluationError('stdevA() received non-numeric parameters');\n }\n\n if (values.length <= 1) throw evaluationError('stdevA() must have at least two values');\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const sumSquare = values.reduce((a, b) => a + b * b, 0);\n const result = Math.sqrt((sumSquare - values.length * mean * mean) / (values.length - 1));\n return validNumber(result, 'stdevA');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Calculates standard deviation based on the entire population given as arguments.\n * `stdevp` assumes that its arguments are the entire population.\n * If your data represents a sample of the population,\n * then compute the standard deviation using [stdev]{@link stdev}.\n * Non-numeric values (text, boolean, null etc) are ignored.\n * If there are nested arrays, they are flattened.\n * @param {any[]} values The array containing numbers comprising the population.\n * An empty array is not allowed.\n * @returns {number} Calculated standard deviation\n * @function stdevp\n * @example\n * stdevp([1345, 1301, 1368]) // returns 27.797\n * stdev([1345, 1301, 1368]) // returns 34.044\n */\n stdevp: {\n _func: args => {\n const values = args[0]\n .flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER);\n\n if (values.length === 0) throw evaluationError('stdevp() must have at least one value');\n\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const meanSumSquare = values.reduce((a, b) => a + b * b, 0) / values.length;\n const result = Math.sqrt(meanSumSquare - mean * mean);\n return validNumber(result, 'stdevp');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Calculates standard deviation based on the entire population given as arguments.\n * `stdevpA` assumes that its arguments are the entire population.\n * If your data represents a sample of the population,\n * then compute the standard deviation using [stdevA]{@link stdevA}.\n * Nested arrays are flattened.\n * Null values are ignored. All other parameters are converted to number.\n * If conversion to number fails, a type error is thrown.\n * @param {number[]} numbers The array of numbers comprising the population.\n * An empty array is not allowed.\n * @returns {number} Calculated standard deviation\n * @function stdevp\n * @example\n * stdevpA([1345, \"1301\", 1368]) // returns 27.797\n * stdevA([1345, 1301, \"1368\"]) // returns 34.044\n */\n stdevpA: {\n _func: args => {\n const values = args[0]\n .flat(Infinity)\n .filter(a => getType(a) !== TYPE_NULL)\n .map(toNumber);\n\n if (values.length === 0) throw evaluationError('stdevp() must have at least one value');\n\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const meanSumSquare = values.reduce((a, b) => a + b * b, 0) / values.length;\n const result = Math.sqrt(meanSumSquare - mean * mean);\n return validNumber(result, 'stdevp');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Generates a string from the input `text`,\n * with text `old` replaced by text `new` (when searching from the left).\n * If there is no match, or if `old` has length 0, `text` is returned unchanged.\n * Note that `old` and `new` may have different lengths.\n * @param {string|string[]} text The text for which to substitute code points.\n * @param {string|string[]} old The text to replace.\n * @param {string|string[]} new The text to replace `old` with.\n * If `new` is an empty string, then occurrences of `old` are removed from `text`.\n * @param {integer|integer[]} [which]\n * The zero-based occurrence of `old` text to replace with `new` text.\n * If `which` parameter is omitted, every occurrence of `old` is replaced with `new`.\n * @returns {string|string[]} replaced string\n * @function substitute\n * @example\n * substitute(\"Sales Data\", \"Sales\", \"Cost\") // returns \"Cost Data\"\n * substitute(\"Quarter 1, 2001\", \"1\", \"2\", 1)\" // returns \"Quarter 1, 2002\"\n * substitute(\"Quarter 1, 2011\", \"1\", \"2\", 2)\" // returns \"Quarter 1, 2012\"\n */\n substitute: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n let n;\n if (args.length > 3) {\n if (Array.isArray(args[3])) {\n n = args[3].map(toInteger);\n if (n.find(o => o < 0) !== undefined) throw evaluationError('substitute() which parameter must be greater than or equal to 0');\n } else {\n n = toInteger(args[3]);\n if (n < 0) throw evaluationError('substitute() which parameter must be greater than or equal to 0');\n }\n args[3] = n;\n }\n return evaluate(args, substituteFn);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Calculates the sum of the provided array.\n * An empty array will produce a return value of 0.\n * Any values that are not numbers (null, boolean, strings, objects) will be ignored.\n * If any parameters are arrays, the arrays will be flattened.\n * @param {any[]} collection array of values\n * @return {number} The computed sum\n * @function sum\n * @example\n * sum([1, 2, 3]) // returns 6\n */\n sum: {\n _func: resolvedArgs => {\n let sum = 0;\n resolvedArgs[0]\n .flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER)\n .forEach(arg => {\n sum += arg * 1;\n });\n\n return sum;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Computes the tangent of a number in radians\n * @param {number|number[]} angle A number representing an angle in radians.\n * @return {number|number[]} The tangent of `angle`\n * @function tan\n * @example\n * tan(0) // 0\n * tan(1) // 1.5574077246549023\n */\n tan: {\n _func: args => evaluate(args, Math.tan),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Construct and returns a <<_date_and_time_values, time value>>.\n * If any of the units are greater or less than their normal range,\n * the overflow/underflow will be added/subtracted from the next greater unit.\n * @param {integer} hours Zero-based integer value between 0 and 23 representing\n * the hour of the day.\n * @param {integer} [minutes=0] Zero-based integer value representing\n * the minute segment of a time.\n * @param {integer} [seconds=0] Zero-based integer value representing the seconds\n * segment of a time.\n * @return {number} Returns a date/time value representing the fraction\n * of the day consumed by the given time\n * @function time\n * @example\n * time(12, 0, 0) | [hour(@), minute(@), second(@)] // returns [12, 0, 0]\n */\n time: {\n _func: args => {\n const hours = toInteger(args[0]);\n const minutes = args.length > 1 ? toInteger(args[1]) : 0;\n const seconds = args.length > 2 ? toInteger(args[2]) : 0;\n // Since time values are interchangeable with date and datetime values, it\"s consistent\n // to create them at the epoch\n const epochTime = new Date(1970, 0, 1, hours, minutes, seconds);\n return getDateNum(epochTime);\n },\n _signature: [\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Converts the provided argument to an array.\n * The conversion happens as per the following rules:\n *\n * * array - Returns the provided value.\n * * number/string/object/boolean/null - Returns a one element array containing the argument.\n * @param {any} arg parameter to turn into an array\n * @return {array} The resulting array\n * @function toArray\n * @example\n * toArray(1) // returns [1]\n * toArray(null()) // returns [`null`]\n */\n toArray: {\n _func: resolvedArgs => (isArrayType(resolvedArgs[0]) ? resolvedArgs[0] : [resolvedArgs[0]]),\n _signature: [{ types: [TYPE_ANY] }],\n },\n\n /**\n * Converts the provided string to a date/time value.\n *\n * @param {string} ISOString An [ISO8601 formatted string]{@link https://www.iso.org/iso-8601-date-and-time-format.html}.\n * (limited to the [RFC 3339]{@link https://www.rfc-editor.org/rfc/rfc3339} profile)\n * If the string does not include a timezone offset (or trailing 'Z'),\n * it will be assumed to be local time\n * @return {number} The resulting <<_date_and_time_values, date/time number>>.\n * If conversion fails, return null.\n * @function toDate\n * @example\n * toDate(\"20231110T130000+04:00\") // returns 19671.375\n * toDate(\"2023-11-10T13:00:00+04:00\") // returns 19671.375\n * toDate(\"20231110\") | year(@) & \"/\" & month(@) // returns \"2023/11\"\n */\n toDate: {\n _func: resolvedArgs => {\n // expand compact notation so that the Date() constructor will\n // accept the value\n const iso = toString(resolvedArgs[0])\n .replace(/(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)/, '$1-$2-$3')\n .replace(/T(\\d\\d)(\\d\\d)(\\d\\d)/, 'T$1:$2:$3');\n const dateparts = iso.split(/[\\D,zZ]+/);\n let d;\n if (dateparts.length <= 3) {\n if (dateparts.length < 3 || dateparts.find(x => x === '') === '') {\n debug.push(`Failed to convert \"${resolvedArgs[0]}\" to a date`);\n return null;\n }\n }\n if (dateparts.length < 7) {\n // no timezone component, so assume local time\n // The date constructor always parses an ISO string as\n // UTC -- with or without a trailing 'z'\n // But if there's no timezone component, it needs to be local time\n\n const range = [99999, 12, 31, 23, 59, 59, 999];\n // check that the date parts are in range\n for (let i = 0; i < dateparts.length; i += 1) {\n if (dateparts[i] > range[i]) {\n debug.push(`Failed to convert \"${resolvedArgs[0]}\" to a date`);\n return null;\n }\n }\n // account for zero-based date month parts\n d = new Date(...dateparts.map((x, i) => (i === 1 ? x - 1 : x * 1)));\n } else {\n d = new Date(iso);\n }\n if (d instanceof Date && Number.isFinite(d.getTime())) return getDateNum(d);\n debug.push(`Failed to convert \"${resolvedArgs[0]}\" to a date`);\n\n return null;\n },\n _signature: [{ types: [TYPE_STRING] }],\n },\n\n /**\n * Returns a <<_date_and_time_values, date/time>> value representing\n * the start of the current day. i.e. midnight\n * @return {number} today at midnight\n * @function today\n */\n today: {\n _func: () => {\n const now = new Date(Date.now());\n // We used to take the floor() to truncate h/m/s from Date.now(), but that would return\n // today at UTC time. We want today in local time.\n // i.e. UTC time could be a day ahead or behind\n // But note that means that the result is not an integer.\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n return getDateNum(today);\n },\n _signature: [],\n },\n\n /**\n * Converts the provided arg to a number.\n * The conversions follow the <<_type_coercion_rules,type coercion rules>> but will also:\n * * Convert non-numeric strings to zero\n * * Convert arrays to arrays of numbers\n *\n * @param {any|any[]} value to convert to number\n * @param {integer|integer[]} [base=10] If the input `arg` is a string,\n * the base to use to convert to number.\n * One of: 2, 8, 10, 16. Defaults to 10.\n * @return {number} The resulting number. If conversion to number fails, return null.\n * @function toNumber\n * @example\n * toNumber(1) // returns 1\n * toNumber(\"10\") // returns 10\n * toNumber({a: 1}) // returns null\n * toNumber(true()) // returns 1\n * toNumber(\"10f\") // returns null\n * toNumber(\"FF\", 16) // returns 255\n */\n toNumber: {\n _func: resolvedArgs => {\n const toNumberFn = (value, base) => {\n const num = valueOf(value);\n if (getType(num) === TYPE_STRING && base !== 10) {\n let digitCheck;\n if (base === 2) digitCheck = /^\\s*(\\+|-)?[01.]+\\s*$/;\n else if (base === 8) digitCheck = /^\\s*(\\+|-)?[0-7.]+\\s*$/;\n else if (base === 16) digitCheck = /^\\s*(\\+|-)?[0-9A-Fa-f.]+\\s*$/;\n else throw evaluationError(`Invalid base: \"${base}\" for toNumber()`);\n\n if (num === '') return 0;\n if (!digitCheck.test(num)) {\n debug.push(`Failed to convert \"${num}\" base \"${base}\" to number`);\n return null;\n }\n const parts = num.split('.').map(p => p.trim());\n\n let decimal = 0;\n if (parts.length > 1) {\n decimal = parseInt(parts[1], base) * base ** -parts[1].length;\n }\n\n const result = parseInt(parts[0], base) + decimal;\n if (parts.length > 2 || Number.isNaN(result)) {\n debug.push(`Failed to convert \"${num}\" base \"${base}\" to number`);\n return null;\n }\n return result;\n }\n try {\n return toNumber(num);\n } catch (e) {\n const errorString = arg => {\n const v = toJSON(arg);\n return v.length > 50 ? `${v.substring(0, 20)} ...` : v;\n };\n\n debug.push(`Failed to convert \"${errorString(num)}\" to number`);\n return null;\n }\n };\n let base = 10;\n if (resolvedArgs.length > 1) {\n base = Array.isArray(resolvedArgs[1])\n ? resolvedArgs.map(toInteger)\n : toInteger(resolvedArgs[1]);\n }\n return evaluate([resolvedArgs[0], base], toNumberFn);\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Returns the argument converted to a string.\n * If the argument is a string, it will be returned unchanged.\n * Otherwise, returns the JSON encoded value of the argument.\n * @param {any} arg Value to be converted to a string\n * @param {integer} [indent=0] Indentation to use when converting\n * objects and arrays to a JSON string\n * @return {string} The result string.\n * @function toString\n * @example\n * toString(1) // returns \"1\"\n * toString(true()) // returns \"true\"\n * toString({sum: 12 + 13}) // \"{\"sum\":25}\"\n * toString(\"hello\") // returns \"hello\"\n */\n toString: {\n _func: resolvedArgs => toJSON(resolvedArgs[0], resolvedArgs.length > 1 ? resolvedArgs[1] : 0),\n _signature: [{ types: [TYPE_ANY] }, { types: [TYPE_NUMBER], optional: true }],\n },\n\n /**\n * Remove leading and trailing spaces (U+0020), and replace all internal multiple spaces\n * with a single space. Note that other whitespace characters are left intact.\n * @param {string|string[]} text string to trim\n * @return {string|string[]} trimmed string\n * @function trim\n * @example\n * trim(\" ab c \") // returns \"ab c\"\n */\n trim: {\n _func: args => evaluate(args, s => toString(s).split(' ').filter(x => x).join(' ')),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Return constant boolean true value.\n * Expressions may also use the JSON literal: `` `true` ``\n * @returns {boolean} True\n * @function true\n */\n true: {\n _func: () => true,\n _signature: [],\n },\n\n /**\n * Truncates a number to an integer by removing the fractional part of the number.\n * i.e. it rounds towards zero.\n * @param {number|number[]} numA number to truncate\n * @param {integer|integer[]} [numB=0]\n * A number specifying the number of decimal digits to preserve.\n * @return {number|number[]} Truncated value\n * @function trunc\n * @example\n * trunc(8.9) // returns 8\n * trunc(-8.9) // returns -8\n * trunc(8.912, 2) // returns 8.91\n */\n trunc: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2) args.push(0);\n return evaluate(args, truncFn);\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Finds the type name of the given `subject` argument as a string value.\n * The return value will be one of the following:\n *\n * * number\n * * string\n * * boolean\n * * array\n * * object\n * * null\n * @param {any} subject type to evaluate\n * @return {string} The type name\n *\n * @function type\n * @example\n * type(1) // returns \"number\"\n * type(\"\") // returns \"string\"\n */\n type: {\n _func: resolvedArgs => ({\n [TYPE_NUMBER]: 'number',\n [TYPE_STRING]: 'string',\n [TYPE_ARRAY]: 'array',\n [TYPE_ARRAY_NUMBER]: 'array',\n [TYPE_ARRAY_STRING]: 'array',\n [TYPE_ARRAY_ARRAY]: 'array',\n [TYPE_OBJECT]: 'object',\n [TYPE_BOOLEAN]: 'boolean',\n [TYPE_EXPREF]: 'expref',\n [TYPE_NULL]: 'null',\n }[getType(resolvedArgs[0])]),\n _signature: [{ types: [TYPE_ANY] }],\n },\n\n /**\n * Find the set of unique elements within an array\n * @param {array} input input array\n * @return {array} array with duplicate elements removed\n * @function unique\n * @example\n * unique([1, 2, 3, 4, 1, 1, 2]) // returns [1, 2, 3, 4]\n */\n unique: {\n _func: args => {\n // create an array of values for searching. That way if the array elements are\n // represented by class objects with a valueOf(), we'll locate them in the valueArray\n // but return the original class object.\n const valueArray = args[0].map(a => valueOf(a));\n return args[0]\n .filter(\n (v, index) => valueArray.findIndex(\n lookup => strictDeepEqual(lookup, valueOf(v)),\n ) === index,\n );\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Converts all the alphabetic code points in a string to uppercase.\n * @param {string|string[]} input input string\n * @returns {string|string[]} the upper case value of the input string\n * @function upper\n * @example\n * upper(\"abcd\") // returns \"ABCD\"\n */\n upper: {\n _func: args => evaluate(args, a => toString(a).toUpperCase()),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Perform an indexed lookup on an object or array\n * @param {object | array | null} subject on which to perform the lookup.\n * When querying for <<_hidden_properties,hidden properties>>, `subject` may be any data type.\n * @param {string | integer} index if `subject` is an object, `index` must be a string\n * indicating the key name to search for.\n * If `subject` is an array, then index must be an integer indicating the offset into the array\n * @returns {any} the result of the lookup -- or `null` if not found.\n * @function value\n * @example\n * value({a: 1, b:2, c:3}, \"a\") // returns 1\n * value([1, 2, 3, 4], 2) // returns 3\n */\n value: {\n _func: args => {\n const indexType = getType(args[1]);\n let index = args[1];\n const subjectArray = isArrayType(args[0]);\n // if the object/array has a getter for this property then don't validate types\n // just return the value.\n if (args[0] !== null && Object.getOwnPropertyDescriptor(args[0], index)?.get) {\n return getProperty(args[0], index);\n }\n const obj = valueOf(args[0]);\n if (obj === null) return null;\n if (!(getType(obj) === TYPE_OBJECT || subjectArray)) {\n throw typeError('First parameter to value() must be one of: object, array, null.');\n }\n if (subjectArray) {\n if (indexType !== TYPE_NUMBER) throw typeError('value() requires an integer index for arrays');\n index = toInteger(index);\n } else if (indexType !== TYPE_STRING) {\n throw typeError('value() requires a string index for objects');\n }\n const result = getProperty(args[0], index);\n if (result === undefined) {\n if (subjectArray) {\n debug.push(\n `Index: ${index} out of range for array size: ${obj.length}`,\n );\n } else debugAvailable(debug, obj, index);\n return null;\n }\n return result;\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_STRING, TYPE_NUMBER] },\n ],\n },\n\n /**\n * Generates an array of the values of the provided object.\n * Note that because JSON objects are\n * inherently unordered, the values associated with the provided object are\n * also unordered.\n * @param {object} obj source object\n * @return {array} array of the values\n * @function values\n * @example\n * values({a : 3, b : 4}) // returns [3, 4]\n */\n values: {\n _func: resolvedArgs => Object.values(resolvedArgs[0]),\n _signature: [{ types: [TYPE_OBJECT] }],\n },\n\n /**\n * Extract the day of the week from a date.\n * The specific numbering of the day of week is controlled by the `returnType` parameter:\n *\n * * 1 : Sunday (1), Monday (2), ..., Saturday (7)\n * * 2 : Monday (1), Tuesday (2), ..., Sunday(7)\n * * 3 : Monday (0), Tuesday (1), ...., Sunday(6)\n * @param {number|number[]} date <<_date_and_time_values, date/time value>> for\n * which the day of the week is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @param {integer|integer[]} [returnType=1] Determines the\n * representation of the result.\n * An unrecognized returnType will result in a error.\n * @returns {integer|integer[]} day of the week\n * @function weekday\n * @example\n * weekday(datetime(2006,5,21)) // 1\n * weekday(datetime(2006,5,21), 2) // 7\n * weekday(datetime(2006,5,21), 3) // 6\n */\n weekday: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2) args.push(1);\n return evaluate(args, weekdayFn);\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Finds the year of a datetime value\n * @param {number|number[]} date input <<_date_and_time_values, date/time value>>\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The year value\n * @function year\n * @example\n * year(datetime(2008,5,23)) // returns 2008\n */\n year: {\n _func: args => evaluate(args, a => getDateObj(a).getFullYear()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Generates a convolved (zipped) array containing grouped arrays of values from\n * the array arguments from index 0, 1, 2, etc.\n * This function accepts a variable number of arguments.\n * The length of the returned array is equal to the length of the shortest array.\n * @param {...array} arrays array of arrays to zip together\n * @return {array} An array of arrays with elements zipped together\n * @function zip\n * @example\n * zip([1, 2, 3], [4, 5, 6, 7]) // returns [[1, 4], [2, 5], [3, 6]]\n */\n zip: {\n _func: args => {\n const count = args.reduce((min, current) => Math.min(min, current.length), args[0].length);\n const result = new Array(count);\n for (let i = 0; i < count; i += 1) {\n result[i] = [];\n args.forEach(a => {\n result[i].push(a[i]);\n });\n }\n return result;\n },\n _signature: [{ types: [TYPE_ARRAY], variadic: true }],\n },\n };\n return functionMap;\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable max-classes-per-file */\n/* eslint-disable no-underscore-dangle */\nimport TreeInterpreter from './TreeInterpreter.js';\nimport Parser from './Parser.js';\nimport { dataTypes } from './dataTypes.js';\nimport { matchType, getType, isArrayType } from './matchType.js';\nimport functions from './functions.js';\nimport {\n isObject, strictDeepEqual, getValueOf,\n} from './utils.js';\nimport {\n evaluationError, typeError, functionError,\n} from './errors.js';\n\n// Type constants used to define functions.\nconst { TYPE_OBJECT } = dataTypes;\n\nfunction getToNumber(stringToNumber) {\n return value => {\n const n = getValueOf(value); // in case it's an object that implements valueOf()\n if (n === null) return 0;\n if (n instanceof Array) {\n throw typeError('Failed to convert array to number');\n }\n const type = typeof n;\n if (type === 'number') return n;\n if (type === 'string') return stringToNumber(n);\n if (type === 'boolean') return n ? 1 : 0;\n throw typeError('Failed to convert object to number');\n };\n}\nfunction toString(a) {\n if (a === null || a === undefined) return '';\n const type = getType(a);\n if (isArrayType(type)) {\n throw typeError('Failed to convert array to string');\n }\n if (type === TYPE_OBJECT) {\n throw typeError('Failed to convert object to string');\n }\n return a.toString();\n}\n\nconst defaultStringToNumber = (str => {\n const n = +str;\n return Number.isNaN(n) ? 0 : n;\n});\n\nclass Runtime {\n constructor(debug, toNumber, customFunctions = {}) {\n this.strictDeepEqual = strictDeepEqual;\n this.toNumber = toNumber;\n this.functionTable = functions(\n this,\n isObject,\n toNumber,\n getType,\n isArrayType,\n getValueOf,\n toString,\n debug,\n );\n\n Object.entries(customFunctions).forEach(([fname, func]) => {\n // Provide the runtime to custom functions so that\n // they can implement lambda functions\n // eslint-disable-next-line no-param-reassign\n func._runtime = this;\n this.functionTable[fname] = func;\n });\n }\n\n // eslint-disable-next-line class-methods-use-this\n _validateArgs(argName, args, signature, bResolved) {\n // Validating the args requires validating\n // the correct arity and the correct type of each arg.\n // If the last argument is declared as variadic, then we need\n // a minimum number of args to be required. Otherwise it has to\n // be an exact amount.\n if (signature.length === 0 && args.length > 0) {\n throw functionError(`${argName}() does not accept parameters`);\n }\n\n if (signature.length === 0) {\n return;\n }\n let pluralized;\n const argsNeeded = signature.filter(arg => !arg.optional).length;\n const lastArg = signature[signature.length - 1];\n if (lastArg.variadic) {\n if (args.length < signature.length && !lastArg.optional) {\n pluralized = signature.length === 1 ? ' argument' : ' arguments';\n throw functionError(`${argName}() takes at least ${signature.length}${pluralized\n } but received ${args.length}`);\n }\n } else if (args.length < argsNeeded || args.length > signature.length) {\n pluralized = signature.length === 1 ? ' argument' : ' arguments';\n throw functionError(`${argName}() takes ${signature.length}${pluralized\n } but received ${args.length}`);\n }\n // if the arguments are unresolved, there's no point in validating types\n if (!bResolved) return;\n let currentSpec;\n const limit = signature[signature.length - 1].variadic ? args.length\n : Math.min(signature.length, args.length);\n\n for (let i = 0; i < limit; i += 1) {\n currentSpec = i > signature.length - 1 ? signature[signature.length - 1].types\n : signature[i].types;\n // eslint-disable-next-line no-param-reassign\n args[i] = matchType(currentSpec, args[i], argName, this.toNumber, toString);\n }\n }\n\n callFunction(name, resolvedArgs, data, interpreter, bResolved = true) {\n // this check will weed out 'valueOf', 'toString' etc\n if (!Object.prototype.hasOwnProperty.call(this.functionTable, name)) {\n throw functionError(`No such function: ${name}()`);\n }\n\n const functionEntry = this.functionTable[name];\n this._validateArgs(name, resolvedArgs, functionEntry._signature, bResolved);\n return functionEntry._func.call(this, resolvedArgs, data, interpreter);\n }\n}\n\nexport default class Formula {\n constructor(debug, customFunctions, stringToNumberFn) {\n this.debug = debug;\n this.toNumber = getToNumber(stringToNumberFn || defaultStringToNumber);\n this.runtime = new Runtime(debug, this.toNumber, customFunctions);\n }\n\n compile(stream, allowedGlobalNames = []) {\n const parser = new Parser(allowedGlobalNames);\n return parser.parse(stream, this.debug);\n }\n\n search(node, data, globals = {}, language = 'en-US') {\n // This needs to be improved. Both the interpreter and runtime depend on\n // each other. The runtime needs the interpreter to support exprefs.\n // There's likely a clean way to avoid the cyclic dependency.\n this.runtime.interpreter = new TreeInterpreter(\n this.runtime,\n globals,\n this.toNumber,\n toString,\n this.debug,\n language,\n );\n\n try {\n return this.runtime.interpreter.search(node, data);\n } catch (e) {\n this.debug.push(e.message || e.toString());\n if (e.name === 'Error') throw evaluationError(e.message || e.toString());\n throw e;\n }\n }\n}\n","/*\nCopyright 2021 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport Formula from './interpreter.js';\n\nexport { dataTypes } from './dataTypes.js';\n\n/**\n * Class represents an instance of a JsonFormula Expression that can be executed later on with\n * multiple instances of JSON Data. The instance of the class has a search\n * function that can be used to evaluate the expression on a json payload.\n */\nclass JsonFormula {\n /**\n * @param {object} [customFunctions={}] custom functions needed by a hosting application.\n * @param {function} [stringToNumber='null'] A function that converts string values to numbers.\n * Can be used to convert currencies/dates to numbers\n * @param {string} [language=en-US]\n * @param {array} [debug=[]] will be populated with any errors/warnings\n */\n constructor(\n customFunctions = {},\n stringToNumber = null,\n debug = [],\n ) {\n this.customFunctions = { ...customFunctions };\n this.stringToNumber = stringToNumber;\n this.debug = debug;\n this.formula = new Formula(debug, customFunctions, stringToNumber);\n }\n\n /**\n * Evaluates the JsonFormula on a particular json payload and return the result\n * @param {object|array} json the json data on which the expression needs to be evaluated\n * @param {object} [globals={}] global objects that can be accessed via custom functions.\n * @returns {*} the result of the expression being evaluated\n */\n search(expression, json, globals = {}, language = 'en-US') {\n const ast = this.compile(expression, Object.keys(globals));\n return this.run(ast, json, language, globals);\n }\n\n /**\n * Execute a previously compiled expression against a json object and return the result\n * @param {object} ast The abstract syntax tree returned from compile()\n * @param {object|array} json the json data on which the expression needs to be evaluated\n * @param globals {*} set of objects available in global scope\n * @returns {*} the result of the expression being evaluated\n */\n run(ast, json, language, globals) {\n return this.formula.search(\n ast,\n json,\n globals,\n language,\n );\n }\n\n /**\n * Creates a compiled expression that can be executed later on with some data.\n * @param {string} expression the expression to evaluate\n * @param {string[]} [allowedGlobalNames=[]] A list of names of the global variables\n * being used in the expression.\n * @param {array} [debug=[]] will be populated with any errors/warnings\n */\n compile(expression, allowedGlobalNames = []) {\n this.debug.length = 0;\n return this.formula.compile(expression, allowedGlobalNames);\n }\n}\n\n/**\n * Compile and execute a json-formula expression.\n * If executing the same expression multiple times, it is more efficient to create a\n * class instance of {JsonFormula} and call the search method multiple times.\n* @param {object|array} json the json data on which the expression needs to be evaluated\n* @param {object} globals global objects that can be accessed via custom functions.\n* @param {string} expression the expression to evaluate\n* @param {object} [customFunctions={}] custom functions needed by a hosting application.\n* @param {function} [stringToNumber='null'] A function that converts string values to numbers.\n* Can be used to convert currencies/dates to numbers\n* @param {string} [language=en-US]\n* @param {array} [debug=[]] will be populated with any errors/warnings\n* @returns {*} the result of the expression being evaluated\n */\n\nexport function jsonFormula(\n json,\n globals,\n expression,\n customFunctions = {},\n stringToNumber = null,\n debug = [],\n language = 'en-US',\n) {\n return new JsonFormula(customFunctions, stringToNumber, debug)\n .search(expression, json, globals, language);\n}\n\nexport default JsonFormula;\n","/*\nCopyright 2021 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable no-param-reassign */\n/* eslint-disable max-classes-per-file */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable no-underscore-dangle */\n/*\n Field class allows objects to evaluate correctly according to context.\n - if used in an expression, will return a value or string.\n - for JSON.stringify() returns a scalar\n - BUT also allows explicit access to properties. e.g. field.required, field.name etc.\n\n Should allow us to eliminate getFieldProperty()\n */\nclass ArrayClass extends Array {}\nclass ObjectClass {}\n\nfunction createField(name, value, readonly = false, required = true) {\n class Field extends ObjectClass {\n valueOf() { return value; }\n\n toString() { return value.toString(); }\n\n toJSON() { return value; }\n }\n const f = new Field();\n Object.defineProperty(f, '$name', { get: () => name });\n Object.defineProperty(f, '$value', { get: () => value });\n Object.defineProperty(f, '$readonly', { get: () => readonly });\n Object.defineProperty(f, '$required', { get: () => required });\n\n return f;\n}\n\nfunction createFieldset(fsname, isObj, fields, children) {\n class FieldsetObj extends ObjectClass {\n _add(k, v) {\n this[k] = v;\n children.push(v);\n }\n }\n class FieldsetArray extends ArrayClass {\n _add(k, v) {\n this[k] = v;\n children.push(v);\n }\n }\n const fieldset = isObj ? new FieldsetObj() : new FieldsetArray();\n Object.defineProperty(fieldset, '$name', { get: () => fsname });\n Object.defineProperty(fieldset, '$fields', { get: () => fields });\n Object.defineProperty(fieldset, '$value', { get: () => fieldset.valueOf() });\n\n return fieldset;\n}\n\nfunction createFields(parent, childref, child) {\n const result = [];\n if (child instanceof Array) {\n // parent._add(childref, createFieldset(childref, false));\n parent._add(childref, createFieldset(childref, false, result, []));\n child.forEach((item, index) => {\n const fields = createFields(parent[childref], index, item);\n result.push(...fields);\n });\n } else if (child !== null && typeof child === 'object') {\n parent._add(childref, createFieldset(childref, true, result, []));\n Object.keys(child).forEach(k => {\n const fields = createFields(parent[childref], k, child[k]);\n result.push(...fields);\n });\n } else {\n const field = createField(childref, child);\n parent._add(childref, field);\n result.push(field);\n }\n return result;\n}\n\nexport default function createForm(dataRoot) {\n // if it's not an object or array (a scalar) then don't bother trying to create a form\n if (dataRoot === null || typeof dataRoot !== 'object') return dataRoot;\n\n const allFields = [];\n const form = createFieldset('', !Array.isArray(dataRoot), allFields, []);\n Object.entries(dataRoot).forEach(([k, v]) => {\n allFields.push(...createFields(form, k, v));\n });\n return form;\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { typeError } from './errors.js';\n\nexport default function stringToNumber(n) {\n if (!/^\\s*(-|\\+)?(\\d*)(\\.\\d+)?(e(\\+|-)?\\d+)?\\s*$/i.test(n)) throw typeError(`Failed to convert \"${n}\" to number`);\n const ret = +n;\n if (Number.isNaN(ret)) {\n throw typeError(`Failed to convert \"${n}\" to number`);\n }\n return ret;\n}\n","/*\nCopyright 2021 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* global window, document */\nimport Formula from '../src/json-formula.js';\nimport createForm from './Form.js';\nimport stringToNumber from '../src/stringToNumber.js';\n\nwindow.addEventListener('load', () => {\n const dataElement = document.getElementById('data');\n const expression = document.getElementById('expression');\n const result = document.getElementById('result');\n const debug = document.getElementById('debug');\n const debugInfo = [];\n // keep one instance active for the entire session so that any registered\n // functions are retained\n const formula = new Formula({}, stringToNumber, debugInfo);\n const defaultData = `{\n \"address\": {\n \"street\": \"12 Oak St\",\n \"city\": \"San Jose\",\n \"state\": \"CA\",\n \"country\": \"USA\",\n \"phone\": \"1234561234\"\n },\n \"items\": [\n {\n \"desc\": \"pens\",\n \"quantity\": 2,\n \"price\": 3.23\n },\n {\n \"desc\": \"pencils\",\n \"quantity\": 3,\n \"price\": 1.34\n }\n ],\n \"tax\": 1.13\n }`;\n\n const params = new URLSearchParams(document.location.search);\n if (params.has('sample')) {\n const sampleJSON = JSON.parse(atob(params.get('sample')));\n if (sampleJSON.data) dataElement.value = JSON.stringify(sampleJSON.data, null, 2);\n if (sampleJSON.expression) expression.value = sampleJSON.expression;\n if (sampleJSON.description) {\n document.getElementById('description-row').style.display = 'table-row';\n document.getElementById('description').innerText = sampleJSON.description;\n }\n Array.from(document.getElementsByClassName('controls')).forEach(c => c.classList.add('hidden'));\n } else {\n const d = window.localStorage.getItem('data');\n if (d) dataElement.value = d;\n else dataElement.value = defaultData;\n const exp = window.localStorage.getItem('expression');\n if (exp) expression.value = exp;\n else expression.value = 'sum(items[*].price * items[*].quantity)';\n }\n\n function run() {\n // save for next time...\n window.localStorage.setItem('data', dataElement.value);\n window.localStorage.setItem('expression', expression.value);\n const input = expression.value;\n const useFields = document.getElementById('use-fields').checked;\n let jsonData;\n try {\n jsonData = JSON.parse(dataElement.value);\n if (useFields) {\n jsonData = createForm(jsonData);\n }\n } catch (e) {\n result.value = e.toString();\n return;\n }\n\n try {\n const jsonResult = formula.search(input, jsonData, {});\n debug.innerHTML = debugInfo.join('\\n');\n let r = jsonResult;\n if (jsonResult !== null && jsonResult !== undefined) {\n r = jsonResult.valueOf.call(jsonResult);\n }\n if (typeof r === 'object') {\n result.value = JSON.stringify(r, null, 2);\n } else {\n result.value = r;\n }\n } catch (e) {\n result.value = e.toString();\n debug.innerHTML = debugInfo.join('\\n');\n }\n }\n\n dataElement.addEventListener('blur', run);\n expression.addEventListener('blur', run);\n document.getElementById('data-reset').addEventListener(\n 'click',\n () => {\n dataElement.value = defaultData;\n if (params.has('sample')) {\n expression.value = 'sum(items[*].price * items[*].quantity)';\n document.getElementById('description-row').style.display = 'none';\n Array.from(document.getElementsByClassName('controls')).forEach(c => c.classList.remove('hidden'));\n window.history.pushState({}, document.title, '/');\n run();\n }\n },\n );\n document.getElementById('canned').addEventListener('change', e => {\n expression.value = e.target.value;\n run();\n });\n run();\n\n fetch('../antlr/JsonFormula.g4').then(r => {\n r.text().then(g4 => {\n // remove comments and processing directives.\n const strippedGrammar = g4\n .replace(/[\\s\\S.]*grammar/m, 'grammar')\n .replace(/#.*/g, '');\n document.getElementById('grammar-out').innerHTML = strippedGrammar;\n });\n });\n});\n"],"names":["__webpack_require__","exports","Symbol","toStringTag","Object","defineProperty","value","dataTypes","TYPE_NUMBER","TYPE_ANY","TYPE_STRING","TYPE_ARRAY","TYPE_OBJECT","TYPE_BOOLEAN","TYPE_EXPREF","TYPE_NULL","TYPE_ARRAY_NUMBER","TYPE_ARRAY_STRING","TYPE_ARRAY_ARRAY","TYPE_EMPTY_ARRAY","typeNameTable","TOK_EOF","TOK_IDENTIFIER","TOK_QUOTEDIDENTIFIER","TOK_RBRACKET","TOK_RPAREN","TOK_COMMA","TOK_COLON","TOK_CONCATENATE","TOK_RBRACE","TOK_NUMBER","TOK_CURRENT","TOK_GLOBAL","TOK_EXPREF","TOK_PIPE","TOK_OR","TOK_AND","TOK_ADD","TOK_SUBTRACT","TOK_UNARY_MINUS","TOK_MULTIPLY","TOK_UNION","TOK_DIVIDE","TOK_COMPARATOR","TOK_FLATTEN","TOK_STAR","TOK_FILTER","TOK_DOT","TOK_NOT","TOK_LBRACE","TOK_LBRACKET","TOK_LPAREN","TOK_JSON","TOK_STRING","TOK_INT","typeError","desc","TypeError","syntaxError","e","Error","name","functionError","evaluationError","tokenDefinitions","isArray","t","includes","getType","inputObj","simpleType","obj","Array","length","flat","Infinity","every","a","jmespathType","type","JSON","parse","stringify","isArrayType","getTypeName","arg","matchType","expectedList","argValue","context","toNumber","toString","actual","isObject","some","match","expect","found","filteredList","filter","supportedConversion","to","exactMatch","expected","wrongType","map","join","keys","toArray","coerceString","coerceNumber","prototype","call","getValueOf","i","valueOf","toBoolean","param","val","strictDeepEqual","lhs","rhs","first","second","f","key","hasOwnProperty","getProperty","getOwnPropertyDescriptor","enumerable","get","for","debugAvailable","debug","chainStart","available","push","entries","getOwnPropertyDescriptors","k","test","startsWith","balanceArrayOperands","opLeft","opRight","shorter","diff","Math","abs","fill","TreeInterpreter","constructor","runtime","globals","language","this","visitFunctions","initVisitFunctions","debugChainStart","search","node","visit","field","undefined","Identifier","bind","QuotedIdentifier","ChainedExpression","result","children","BracketExpression","left","Index","index","Slice","sliceParams","start","stop","step","computeSliceParams","Projection","base","collected","forEach","b","current","ValueProjection","projection","values","FilterProjection","filtered","finalResults","Comparator","type1","type2","_e","original","merged","Identity","_node","ArrayExpression","child","ObjectExpression","OrExpression","matched","AndExpression","AddExpression","applyOperator","ConcatenateExpression","UnionExpression","concat","SubtractExpression","MultiplyExpression","DivideExpression","NotExpression","UnaryMinusExpression","minus","Number","isNaN","String","Literal","Integer","Function","callFunction","resolvedArgs","ExpressionReference","refNode","n","v","arrayLength","capSliceRange","arrayLen","stp","actualValue","stepValueNegative","operator","n1","n2","isFinite","basicTokens","operatorStartToken","skipChars","isAlphaNum","ch","isIdentifier","stream","pos","Lexer","allowedGlobalNames","_allowedGlobalNames","tokenize","tokens","identifier","token","_current","prev","slice","_isGlobal","_consumeGlobal","_consumeUnquotedIdentifier","_isNumber","_consumeNumber","_consumeLBracket","_consumeQuotedIdentifier","_consumeRawStringLiteral","json","_consumeJson","_consumeOperator","_consumeUnaryMinus","maxLength","foundNonAlpha","replace","substring","literal","num","toLowerCase","parseFloat","parseInt","global","startingChar","literalString","trimStart","replaceAll","bindingPower","Parser","expression","_loadTokens","ast","_lookahead","_lookaheadToken","rbp","leftToken","_advance","nud","currentToken","led","number","previous","next","_lookAheadIndex","idx","_getIndex","_setIndex","right","args","Not","UnaryMinus","_parseProjectionRHS","Star","_parseObjectExpression","Flatten","_parseIndexExpression","_projectIfSlice","_parseArrayExpression","Expref","_match","_errorToken","condition","leftNode","rightNode","Concatenate","Dot","_parseDotRHS","Pipe","Or","And","Add","Subtract","Multiply","Divide","Union","_parseFunctionArgs","Filter","_parseComparator","tokenType","firstExpression","_parseSignedInt","oldIndex","_parseSliceExpression","indexExpr","parts","comparator","lookahead","indexOf","expressions","pairs","identifierTypes","keyToken","keyName","MS_IN_DAY","getDateObj","dateNum","Date","round","getDateNum","dateObj","validNumber","defaultStringToNumber","str","Runtime","customFunctions","functionTable","toInteger","trunc","toJSON","indent","offset","evaluate","fn","listOfArrays","maxLen","max","allArrays","arrays","row","j","balanceArrays","datedifFn","date1Arg","date2Arg","unitArg","unit","date1","date2","floor","yearDiff","getFullYear","monthDiff","getMonth","dayDiff","getDate","y","setFullYear","endsWithFn","searchArg","suffixArg","searchStr","suffix","from","reverse","c","eomonthFn","dateArg","monthsArg","jsDate","months","findFn","queryArg","textArg","offsetArg","query","text","properFn","capitalize","word","charAt","toUpperCase","wordParts","w","reptFn","countArg","count","repeat","searchFn","findTextString","withinTextString","startPosInt","findText","withinText","startPos","globString","reduce","acc","cur","escape","pop","testMatch","array","glob","testChar","globChar","nextGlob","isStar","within","splitFn","strArg","separatorArg","separator","split","startsWithFn","subjectString","prefixString","subject","prefix","substituteFn","source","oldString","replacementString","nearest","src","old","replacement","whch","truncFn","d","digits","ceil","weekdayFn","date","day","getDay","functionMap","_func","_signature","types","acos","and","variadic","asin","atan2","avg","sum","avgA","casefold","_data","interpreter","s","toLocaleUpperCase","toLocaleLowerCase","codePoint","codePointAt","contains","searchLen","cos","datedif","datetime","year","month","hours","minutes","seconds","ms","optional","deepScan","checkArrays","items","scan","endsWith","eomonth","exp","false","find","fromCodePoint","points","fromEntries","fround","hasProperty","keyType","hour","getHours","if","unresolvedArgs","data","conditionNode","leftBranchNode","rightBranchNode","listJoin","joinChar","numEntries","log","log10","lower","exprefNode","maxA","merge","mid","millisecond","getMilliseconds","min","minA","minute","getMinutes","mod","not","resolveArgs","notNull","now","null","or","power","proper","random","accumulated","register","functionName","_exprefNode","registerWithParams","numElements","sourceArray","splice","newText","rept","originalStr","precision","getSeconds","sign","sin","sort","typeVals","sorted","sortFunction","sortBy","sortedArray","requiredType","decorated","exprA","typeA","exprB","typeB","sqrt","stdev","mean","sumSquare","stdevA","stdevp","meanSumSquare","stdevpA","substitute","o","tan","time","toDate","iso","dateparts","x","range","getTime","today","toNumberFn","digitCheck","p","trim","decimal","errorString","true","unique","valueArray","findIndex","lookup","upper","indexType","subjectArray","weekday","zip","functions","fname","func","_runtime","_validateArgs","argName","signature","bResolved","pluralized","argsNeeded","lastArg","currentSpec","limit","functionEntry","Formula","stringToNumberFn","stringToNumber","getToNumber","compile","message","formula","run","ArrayClass","ObjectClass","createFieldset","fsname","isObj","fields","fieldset","_add","createFields","parent","childref","item","readonly","required","createField","ret","window","addEventListener","dataElement","document","getElementById","debugInfo","defaultData","params","URLSearchParams","location","has","sampleJSON","atob","description","style","display","innerText","getElementsByClassName","classList","add","localStorage","getItem","setItem","input","useFields","checked","jsonData","dataRoot","allFields","form","createForm","jsonResult","innerHTML","r","remove","history","pushState","title","target","fetch","then","g4","strippedGrammar"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"tutorial.js","mappings":"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","sources":["webpack://jsonFormula/webpack/bootstrap","webpack://jsonFormula/webpack/runtime/make namespace object","webpack://jsonFormula/./src/dataTypes.js","webpack://jsonFormula/./src/tokenDefinitions.js","webpack://jsonFormula/./src/errors.js","webpack://jsonFormula/./src/matchType.js","webpack://jsonFormula/./src/utils.js","webpack://jsonFormula/./src/TreeInterpreter.js","webpack://jsonFormula/./src/Lexer.js","webpack://jsonFormula/./src/Parser.js","webpack://jsonFormula/./src/functions.js","webpack://jsonFormula/./src/interpreter.js","webpack://jsonFormula/./src/json-formula.js","webpack://jsonFormula/./tutorial/Form.js","webpack://jsonFormula/./src/stringToNumber.js","webpack://jsonFormula/./tutorial/tutorial.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n// Type constants used to define functions.\nconst dataTypes = {\n TYPE_NUMBER: 0,\n TYPE_ANY: 1,\n TYPE_STRING: 2,\n TYPE_ARRAY: 3,\n TYPE_OBJECT: 4,\n TYPE_BOOLEAN: 5,\n TYPE_EXPREF: 6,\n TYPE_NULL: 7,\n TYPE_ARRAY_NUMBER: 8,\n TYPE_ARRAY_STRING: 9,\n TYPE_ARRAY_ARRAY: 10,\n TYPE_EMPTY_ARRAY: 11,\n};\n\nconst typeNameTable = {\n [dataTypes.TYPE_NUMBER]: 'number',\n [dataTypes.TYPE_ANY]: 'any',\n [dataTypes.TYPE_STRING]: 'string',\n [dataTypes.TYPE_ARRAY]: 'array',\n [dataTypes.TYPE_OBJECT]: 'object',\n [dataTypes.TYPE_BOOLEAN]: 'boolean',\n [dataTypes.TYPE_EXPREF]: 'expression',\n [dataTypes.TYPE_NULL]: 'null',\n [dataTypes.TYPE_ARRAY_NUMBER]: 'Array',\n [dataTypes.TYPE_ARRAY_STRING]: 'Array',\n [dataTypes.TYPE_ARRAY_ARRAY]: 'Array',\n [dataTypes.TYPE_EMPTY_ARRAY]: 'array',\n};\n\nexport { dataTypes, typeNameTable };\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nexport default {\n TOK_EOF: 'EOF',\n TOK_IDENTIFIER: 'Identifier',\n TOK_QUOTEDIDENTIFIER: 'QuotedIdentifier',\n TOK_RBRACKET: 'Rbracket',\n TOK_RPAREN: 'Rparen',\n TOK_COMMA: 'Comma',\n TOK_COLON: 'Colon',\n TOK_CONCATENATE: 'Concatenate',\n TOK_RBRACE: 'Rbrace',\n TOK_NUMBER: 'Number',\n TOK_CURRENT: 'Current',\n TOK_GLOBAL: 'Global',\n TOK_EXPREF: 'Expref',\n TOK_PIPE: 'Pipe',\n TOK_OR: 'Or',\n TOK_AND: 'And',\n TOK_ADD: 'Add',\n TOK_SUBTRACT: 'Subtract',\n TOK_UNARY_MINUS: 'UnaryMinus',\n TOK_MULTIPLY: 'Multiply',\n TOK_UNION: 'Union',\n TOK_DIVIDE: 'Divide',\n TOK_COMPARATOR: 'Comparator',\n TOK_FLATTEN: 'Flatten',\n TOK_STAR: 'Star',\n TOK_FILTER: 'Filter',\n TOK_DOT: 'Dot',\n TOK_NOT: 'Not',\n TOK_LBRACE: 'Lbrace',\n TOK_LBRACKET: 'Lbracket',\n TOK_LPAREN: 'Lparen',\n TOK_JSON: 'Literal',\n TOK_STRING: 'String',\n TOK_INT: 'Integer',\n};\n","/*\nCopyright 2023 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nexport function typeError(desc) {\n return new TypeError(desc);\n}\n\nexport function syntaxError(desc) {\n const e = new Error(desc);\n e.name = 'SyntaxError';\n return e;\n}\n\nexport function functionError(desc) {\n const e = new Error(desc);\n e.name = 'FunctionError';\n return e;\n}\n\nexport function evaluationError(desc) {\n const e = new Error(desc);\n e.name = 'EvaluationError';\n return e;\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport { dataTypes, typeNameTable } from './dataTypes.js';\nimport tokenDefinitions from './tokenDefinitions.js';\nimport { typeError } from './errors.js';\n// import { isClass } from './utils.js';\n\nconst {\n TYPE_NUMBER,\n TYPE_ANY,\n TYPE_STRING,\n TYPE_ARRAY,\n TYPE_OBJECT,\n TYPE_BOOLEAN,\n TYPE_EXPREF,\n TYPE_NULL,\n TYPE_ARRAY_NUMBER,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY_ARRAY,\n TYPE_EMPTY_ARRAY,\n} = dataTypes;\n\nconst {\n TOK_EXPREF,\n} = tokenDefinitions;\n\nfunction isArray(t) {\n return [\n TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING, TYPE_ARRAY_ARRAY, TYPE_EMPTY_ARRAY,\n ].includes(t);\n}\n\nexport function getType(inputObj) {\n function simpleType(obj) {\n if (obj === null) return TYPE_NULL;\n const t = typeof obj;\n if (t === 'string') return TYPE_STRING;\n if (t === 'number') return TYPE_NUMBER;\n if (t === 'boolean') return TYPE_BOOLEAN;\n if (Array.isArray(obj)) {\n if (obj.length === 0) return TYPE_EMPTY_ARRAY;\n if (obj.flat(Infinity).every(a => getType(a) === TYPE_NUMBER)) return TYPE_ARRAY_NUMBER;\n if (obj.flat(Infinity).every(a => getType(a) === TYPE_STRING)) return TYPE_ARRAY_STRING;\n if (obj.every(a => isArray(getType(a)))) return TYPE_ARRAY_ARRAY;\n return TYPE_ARRAY;\n }\n // Check if it's an expref. If it has, it's been\n // tagged with a jmespathType attr of 'Expref';\n if (obj.jmespathType === TOK_EXPREF) return TYPE_EXPREF;\n return TYPE_OBJECT;\n }\n let type = simpleType(inputObj);\n if (type !== TYPE_OBJECT) return type;\n // if inputObj is a class, then convert it to its base type via JSON\n const obj = JSON.parse(JSON.stringify(inputObj));\n type = simpleType(obj);\n return type;\n}\n\nexport function isArrayType(t) {\n return [\n TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING, TYPE_ARRAY_ARRAY, TYPE_EMPTY_ARRAY,\n ].includes(getType(t));\n}\n\nexport function getTypeName(arg) {\n return typeNameTable[getType(arg)];\n}\n\nfunction supportedConversion(from, to) {\n const pairs = {\n [TYPE_NUMBER]: [\n TYPE_STRING,\n TYPE_ARRAY,\n TYPE_ARRAY_NUMBER,\n TYPE_BOOLEAN,\n ],\n [TYPE_BOOLEAN]: [\n TYPE_STRING,\n TYPE_NUMBER,\n TYPE_ARRAY,\n ],\n [TYPE_ARRAY]: [TYPE_BOOLEAN, TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER],\n [TYPE_ARRAY_NUMBER]: [TYPE_BOOLEAN, TYPE_ARRAY_STRING, TYPE_ARRAY],\n [TYPE_ARRAY_STRING]: [TYPE_BOOLEAN, TYPE_ARRAY_NUMBER, TYPE_ARRAY],\n [TYPE_ARRAY_ARRAY]: [TYPE_BOOLEAN],\n [TYPE_EMPTY_ARRAY]: [TYPE_BOOLEAN],\n\n [TYPE_OBJECT]: [TYPE_BOOLEAN],\n [TYPE_NULL]: [\n TYPE_STRING,\n TYPE_NUMBER,\n TYPE_BOOLEAN,\n ],\n [TYPE_STRING]: [\n TYPE_NUMBER,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY,\n TYPE_BOOLEAN],\n };\n return pairs[from].includes(to);\n}\n\nexport function matchType(expectedList, argValue, context, toNumber, toString) {\n const actual = getType(argValue);\n if (argValue?.jmespathType === TOK_EXPREF && !expectedList.includes(TYPE_EXPREF)) {\n throw typeError(`${context} does not accept an expression reference argument.`);\n }\n const isObject = t => t === TYPE_OBJECT;\n const match = (expect, found) => expect === found\n || expect === TYPE_ANY\n || (expect === TYPE_ARRAY && isArray(found))\n || (isArray(expect) && found === TYPE_EMPTY_ARRAY);\n\n if (expectedList.some(type => match(type, actual))) return argValue;\n\n // if the function allows multiple types, we can't coerce the type and we need an exact match\n // Of the set of expected types, filter out the ones that can be coerced from the actual type\n const filteredList = expectedList.filter(t => supportedConversion(actual, t));\n if (filteredList.length === 0) {\n throw typeError(`${context} expected argument to be type ${typeNameTable[expectedList[0]]} but received type ${typeNameTable[actual]} instead.`);\n }\n const exactMatch = filteredList.length > 1;\n const expected = filteredList[0];\n let wrongType = false;\n\n // Can't coerce objects and arrays to any other type\n if (isArray(actual)) {\n if ([TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING].includes(expected)) {\n if (argValue.flat(Infinity).some(a => {\n const t = getType(a);\n // can't coerce arrays or objects to numbers or strings\n return isArray(t) || isObject(t);\n })) wrongType = true;\n }\n }\n // nothing coerces to an object\n if (exactMatch && expected === TYPE_OBJECT) wrongType = true;\n\n if (exactMatch) {\n throw typeError(`${context} cannot process type: ${typeNameTable[actual]}. Must be one of: ${expectedList.map(t => typeNameTable[t]).join(', ')}.`);\n }\n if (wrongType) {\n throw typeError(`${context} expected argument to be type ${typeNameTable[expected]} but received type ${typeNameTable[actual]} instead.`);\n }\n // Can't coerce Objects and arrays to anything other than boolean\n if (isObject(actual) && expected === TYPE_BOOLEAN) {\n return Object.keys(argValue).length === 0;\n }\n\n // no exact match, see if we can coerce an array type\n if (isArray(actual)) {\n const toArray = a => (Array.isArray(a) ? a : [a]);\n const coerceString = a => (Array.isArray(a) ? a.map(coerceString) : toString(a));\n const coerceNumber = a => (Array.isArray(a) ? a.map(coerceNumber) : toNumber(a));\n\n if (expected === TYPE_BOOLEAN) return argValue.length > 0;\n if (expected === TYPE_ARRAY_STRING) return argValue.map(coerceString);\n if (expected === TYPE_ARRAY_NUMBER) return argValue.map(coerceNumber);\n if (expected === TYPE_ARRAY_ARRAY) return argValue.map(toArray);\n }\n\n if (!isArray(actual) && !isObject(actual)) {\n if (expected === TYPE_ARRAY_STRING) return [toString(argValue)];\n if (expected === TYPE_ARRAY_NUMBER) return [toNumber(argValue)];\n if (expected === TYPE_ARRAY) return [argValue];\n if (expected === TYPE_NUMBER) return toNumber(argValue);\n if (expected === TYPE_STRING) return toString(argValue);\n if (expected === TYPE_BOOLEAN) return !!argValue;\n }\n\n throw typeError(`${context} expected argument to be type ${typeNameTable[expected]} but received type ${typeNameTable[actual]} instead.`);\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nexport function isArray(obj) {\n return Array.isArray(obj);\n}\n\nexport function isObject(obj) {\n if (obj !== null) {\n return Object.prototype.toString.call(obj) === '[object Object]';\n }\n return false;\n}\n\nexport function getValueOf(a) {\n if (a === null || a === undefined) return a;\n if (isArray(a)) {\n return a.map(i => getValueOf(i));\n }\n // if we have a child named 'valueOf' then we're an object,\n // and just return the object.\n if (typeof (a.valueOf) !== 'function') return a;\n return a.valueOf();\n}\n\nexport function toBoolean(param) {\n if (param === null) return false;\n // in case it's an object with a valueOf defined\n const val = getValueOf(param);\n\n // empty arrays are false\n if (Array.isArray(val)) return val.length > 0;\n // empty objects are false\n if (isObject(val)) return Object.keys(val).length > 0;\n return !!val;\n}\n\nexport function strictDeepEqual(lhs, rhs) {\n const first = getValueOf(lhs);\n const second = getValueOf(rhs);\n // Check the scalar case first.\n if (first === second) {\n return true;\n }\n\n // Check if they are the same type.\n const firstType = Object.prototype.toString.call(first);\n if (firstType !== Object.prototype.toString.call(second)) {\n return false;\n }\n // We know that first and second have the same type so we can just check the\n // first type from now on.\n if (isArray(first) === true) {\n // Short circuit if they're not the same length;\n if (first.length !== second.length) return false;\n return first.every((f, i) => strictDeepEqual(f, second[i]));\n }\n if (isObject(first) === true) {\n if (Object.keys(first).length !== Object.keys(second).length) return false;\n // An object is equal if it has the same key/value pairs.\n // eslint-disable-next-line no-restricted-syntax\n for (const key in first) {\n if (hasOwnProperty.call(first, key)) {\n if (strictDeepEqual(first[key], second[key]) === false) return false;\n }\n }\n return true;\n }\n return false;\n}\n\nexport function getProperty(obj, key) {\n const desc = Object.getOwnPropertyDescriptor(obj, key);\n // if it's a regular enumerable property or if it's configured with a getter,\n // then return it.\n // if it's a built-in property such as length or toString etc. we'll want to ignore it.\n if (desc?.enumerable || !!desc?.get) {\n // for applications that want to track which properties are accessed, allow for a special\n // hook to callback and register this key/value accessor.\n obj[key]?.[Symbol.for('track')]?.(obj, key);\n return obj[key];\n }\n return undefined;\n}\n\nexport function debugAvailable(debug, obj, key, chainStart = null) {\n try {\n let available = [];\n if (isArray(obj) && obj.length > 0) {\n debug.push(`Failed to find: '${key}' on an array object.`);\n debug.push(`Did you mean to use a projection? e.g. ${chainStart || 'array'}[*].${key}`);\n return;\n }\n debug.push(`Failed to find: '${key}'`);\n if (obj !== null) {\n available = [...available, ...Object.entries(Object.getOwnPropertyDescriptors(obj, key))\n .filter(([k, desc]) => (desc?.enumerable || !!desc?.get) && !/^[0-9]+$/.test(k) && (!k.startsWith('$') || key.startsWith('$')))\n .map(([k]) => `'${k}'`)];\n }\n if (available.length) debug.push(`Available fields: ${available}`);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n}\n\nexport function isClass(obj) {\n if (obj === null) return false;\n if (Array.isArray(obj)) return false;\n return !['Object', 'Boolean', 'Number', 'String'].includes(obj.constructor.name);\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n matchType, getTypeName, getType, isArrayType,\n} from './matchType.js';\nimport { dataTypes } from './dataTypes.js';\nimport tokenDefinitions from './tokenDefinitions.js';\nimport {\n isArray, isObject, strictDeepEqual, getValueOf, getProperty, debugAvailable, toBoolean,\n} from './utils.js';\nimport { evaluationError, typeError } from './errors.js';\n\nconst {\n TOK_CURRENT,\n TOK_GLOBAL,\n TOK_EXPREF,\n TOK_PIPE,\n TOK_FLATTEN,\n} = tokenDefinitions;\n\nconst {\n TYPE_STRING,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY,\n TYPE_NUMBER,\n} = dataTypes;\n\nfunction objValues(obj) {\n return Object.values(obj);\n}\n\nfunction balanceArrayOperands(opLeft, opRight) {\n if (isArray(opLeft) && isArray(opRight)) {\n // balance the size of the arrays by padding with nulls\n const shorter = opLeft.length < opRight.length ? opLeft : opRight;\n const diff = Math.abs(opLeft.length - opRight.length);\n shorter.length += diff;\n shorter.fill(null, shorter.length - diff);\n }\n}\n\nexport default class TreeInterpreter {\n constructor(runtime, globals, toNumber, toString, debug, language) {\n this.runtime = runtime;\n this.globals = globals;\n this.toNumber = toNumber;\n this.toString = toString;\n this.debug = debug;\n this.language = language;\n this.visitFunctions = this.initVisitFunctions();\n // track the identifier name that started the chain\n // so that we can use it in debug hints\n this.debugChainStart = null;\n }\n\n search(node, value) {\n return this.visit(node, value);\n }\n\n field(node, value) {\n // we used to check isObject(value) here -- but it is possible for an array-based\n // object to have properties. So we'll allow the child check on objects and arrays.\n if (value !== null && (isObject(value) || isArray(value))) {\n const field = getProperty(value, node.name);\n if (field === undefined) {\n debugAvailable(this.debug, value, node.name, this.debugChainStart);\n return null;\n }\n return field;\n }\n debugAvailable(this.debug, value, node.name, this.debugChainStart);\n return null;\n }\n\n initVisitFunctions() {\n return {\n Identifier: this.field.bind(this),\n QuotedIdentifier: this.field.bind(this),\n ChainedExpression: (node, value) => {\n let result = this.visit(node.children[0], value);\n this.debugChainStart = node.children[0].name;\n for (let i = 1; i < node.children.length; i += 1) {\n result = this.visit(node.children[1], result);\n if (result === null) return null;\n }\n return result;\n },\n\n BracketExpression: (node, value) => {\n const left = this.visit(node.children[0], value);\n return this.visit(node.children[1], left);\n },\n\n Index: (node, value) => {\n if (isArray(value)) {\n let index = node.value.value;\n if (index < 0) {\n index = value.length + index;\n }\n const result = value[index];\n if (result === undefined) {\n this.debug.push(`Index: ${index} out of range for array size: ${value.length}`);\n return null;\n }\n return result;\n }\n this.debug.push('Left side of index expression must be an array');\n this.debug.push(`Did you intend a single-element array? if so, use a JSON literal: \\`[${node.value.value}]\\``);\n return null;\n },\n\n Slice: (node, value) => {\n if (!isArray(value)) {\n this.debug.push('Slices apply to arrays only');\n return null;\n }\n const sliceParams = node.children.map(param => (param === null ? null : param.value));\n const [start, stop, step] = this.computeSliceParams(value.length, sliceParams);\n const result = [];\n if (step > 0) {\n for (let i = start; i < stop; i += step) {\n result.push(value[i]);\n }\n } else {\n for (let i = start; i > stop; i += step) {\n result.push(value[i]);\n }\n }\n return result;\n },\n\n Projection: (node, value) => {\n // Evaluate left child.\n const base = this.visit(node.children[0], value);\n if (!isArray(base)) {\n if (node.debug === 'Wildcard') {\n this.debug.push('Bracketed wildcards apply to arrays only');\n }\n return null;\n }\n const collected = [];\n base.forEach(b => {\n const current = this.visit(node.children[1], b);\n collected.push(current);\n });\n return collected;\n },\n\n // wildcard: \".*\"\n ValueProjection: (node, value) => {\n // Evaluate left child.\n const projection = this.visit(node.children[0], value);\n if (!isObject(getValueOf(projection))) {\n this.debug.push('Chained wildcards apply to objects only');\n return null;\n }\n const collected = [];\n const values = objValues(projection);\n values.forEach(val => {\n const current = this.visit(node.children[1], val);\n collected.push(current);\n });\n return collected;\n },\n\n FilterProjection: (node, value) => {\n const base = this.visit(node.children[0], value);\n if (!isArray(base)) {\n this.debug.push('Filter expressions apply to arrays only');\n return null;\n }\n const filtered = base.filter(b => {\n const matched = this.visit(node.children[2], b);\n return toBoolean(matched);\n });\n\n const finalResults = [];\n filtered.forEach(f => {\n const current = this.visit(node.children[1], f);\n finalResults.push(current);\n });\n return finalResults;\n },\n\n Comparator: (node, value) => {\n let first = getValueOf(this.visit(node.children[0], value));\n let second = getValueOf(this.visit(node.children[1], value));\n\n if (node.value === '==') return strictDeepEqual(first, second);\n if (node.value === '!=') return !strictDeepEqual(first, second);\n if (isObject(first) || isArray(first)) {\n this.debug.push(`Cannot use comparators with ${getTypeName(first)}`);\n return false;\n }\n if (isObject(second) || isArray(second)) {\n this.debug.push(`Cannot use comparators with ${getTypeName(second)}`);\n return false;\n }\n const type1 = getType(first);\n const type2 = getType(second);\n // if either parameter is a number, we need to do a numeric comparison\n // javascript will compare this way automatically, but if we explicitly convert\n // to numbers, we will get debug warnings for non-numeric strings\n if (type1 === TYPE_NUMBER || type2 === TYPE_NUMBER) {\n // if toNumber fails, it will populate the debug array\n // with an appropriate warning\n try {\n first = this.toNumber(first);\n second = this.toNumber(second);\n if (first === null || second === null) return false;\n } catch (_e) {\n // failing to convert to a number for comparison is not an error\n // we just return false\n return false;\n }\n }\n if (node.value === '>') return first > second;\n if (node.value === '>=') return first >= second;\n if (node.value === '<') return first < second;\n // if (node.value === '<=)\n // must be LTE\n return first <= second;\n },\n\n [TOK_FLATTEN]: (node, value) => {\n const original = this.visit(node.children[0], value);\n if (!isArray(original)) {\n this.debug.push('Flatten expressions apply to arrays only. If you want an empty array, use a JSON literal: `[]`');\n return null;\n }\n const merged = [];\n original.forEach(current => {\n if (isArray(current)) {\n merged.push(...current);\n } else {\n merged.push(current);\n }\n });\n return merged;\n },\n\n Identity: (_node, value) => value,\n\n ArrayExpression: (node, value) => node.children.map(child => this.visit(child, value)),\n\n ObjectExpression: (node, value) => {\n // at one time we used to have this:\n // if (value === null) return null;\n // BUT then an expression such as:\n // values({a: 'aa'})\n // would return null if the document were `null`\n // Removing the check means that:\n // `null`.{a: 'aa'}\n // returns: {a: 'aa'}\n // which is a bit odd, but seems correct.\n const collected = {};\n node.children.forEach(child => {\n if (collected[child.name] !== undefined) this.debug.push(`Duplicate key: '${child.name}'`);\n collected[child.name] = this.visit(child.value, value);\n });\n return collected;\n },\n\n OrExpression: (node, value) => {\n let matched = this.visit(node.children[0], value);\n if (!toBoolean(matched)) matched = this.visit(node.children[1], value);\n return matched;\n },\n\n AndExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n\n if (!toBoolean(first)) return first;\n return this.visit(node.children[1], value);\n },\n\n AddExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '+');\n },\n\n ConcatenateExpression: (node, value) => {\n let first = this.visit(node.children[0], value);\n let second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n if (isArrayType(first)) {\n first = matchType([TYPE_ARRAY_STRING], first, 'concatenate', this.toNumber, this.toString);\n } else {\n first = matchType([TYPE_STRING], first, 'concatenate', this.toNumber, this.toString);\n }\n if (isArrayType(second)) {\n second = matchType([TYPE_ARRAY_STRING], second, 'concatenate', this.toNumber, this.toString);\n } else {\n second = matchType([TYPE_STRING], second, 'concatenate', this.toNumber, this.toString);\n }\n return this.applyOperator(first, second, '&');\n },\n\n UnionExpression: (node, value) => {\n let first = this.visit(node.children[0], value);\n if (first === null) first = [null];\n let second = this.visit(node.children[1], value);\n if (second === null) second = [null];\n first = matchType([TYPE_ARRAY], first, 'union', this.toNumber, this.toString);\n second = matchType([TYPE_ARRAY], second, 'union', this.toNumber, this.toString);\n return first.concat(second);\n },\n\n SubtractExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '-');\n },\n\n MultiplyExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '*');\n },\n\n DivideExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const second = this.visit(node.children[1], value);\n balanceArrayOperands(first, second);\n return this.applyOperator(first, second, '/');\n },\n\n NotExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n return !toBoolean(first);\n },\n\n UnaryMinusExpression: (node, value) => {\n const first = this.visit(node.children[0], value);\n const minus = first * -1;\n if (Number.isNaN(minus)) throw typeError(`Failed to convert \"${first}\" to number`);\n return minus;\n },\n\n String: node => node.value,\n\n Literal: node => node.value,\n\n Number: node => node.value,\n\n Integer: node => node.value,\n\n [TOK_PIPE]: (node, value) => {\n const left = this.visit(node.children[0], value);\n return this.visit(node.children[1], left);\n },\n\n [TOK_CURRENT]: (_node, value) => value,\n\n [TOK_GLOBAL]: node => {\n const result = this.globals[node.name];\n return result === undefined ? null : result;\n },\n\n Function: (node, value) => {\n // Special case for if()\n // we need to make sure the results are called only after the condition is evaluated\n // Otherwise we end up with both results invoked -- which could include side effects\n // For \"if\", the last parameter to callFunction is false (bResolved) to indicate there's\n // no point in validating the argument type.\n if (node.name === 'if') return this.runtime.callFunction(node.name, node.children, value, this, false);\n const resolvedArgs = node.children.map(child => this.visit(child, value));\n return this.runtime.callFunction(node.name, resolvedArgs, value, this);\n },\n\n ExpressionReference: node => {\n const [refNode] = node.children;\n // Tag the node with a specific attribute so the type\n // checker verify the type.\n refNode.jmespathType = TOK_EXPREF;\n return refNode;\n },\n };\n }\n\n visit(n, v = null) {\n const fn = n && this.visitFunctions[n.type];\n return fn(n, v);\n }\n\n // eslint-disable-next-line class-methods-use-this\n computeSliceParams(arrayLength, sliceParams) {\n function capSliceRange(arrayLen, actual, stp) {\n let actualValue = actual;\n if (actualValue < 0) {\n actualValue += arrayLen;\n if (actualValue < 0) {\n actualValue = stp < 0 ? -1 : 0;\n }\n } else if (actualValue >= arrayLen) {\n actualValue = stp < 0 ? arrayLen - 1 : arrayLen;\n }\n return actualValue;\n }\n\n let [start, stop, step] = sliceParams;\n if (step === null) {\n step = 1;\n } else if (step === 0) {\n throw evaluationError('Invalid slice, step cannot be 0');\n }\n const stepValueNegative = step < 0;\n\n if (start === null) {\n start = stepValueNegative ? arrayLength - 1 : 0;\n } else {\n start = capSliceRange(arrayLength, start, step);\n }\n\n if (stop === null) {\n stop = stepValueNegative ? -1 : arrayLength;\n } else {\n stop = capSliceRange(arrayLength, stop, step);\n }\n return [start, stop, step];\n }\n\n applyOperator(first, second, operator) {\n if (isArray(first) && isArray(second)) {\n const result = [];\n for (let i = 0; i < first.length; i += 1) {\n result.push(this.applyOperator(first[i], second[i], operator));\n }\n return result;\n }\n\n if (isArray(first)) return first.map(a => this.applyOperator(a, second, operator));\n if (isArray(second)) return second.map(a => this.applyOperator(first, a, operator));\n\n if (operator === '&') return first + second;\n if (operator === '*') return this.toNumber(first) * this.toNumber(second);\n const n1 = this.toNumber(first);\n const n2 = this.toNumber(second);\n if (operator === '+') return n1 + n2;\n if (operator === '-') return n1 - n2;\n // if (operator === '/') {\n // Must be division\n const result = n1 / n2;\n if (!Number.isFinite(result)) {\n throw evaluationError(`Division by zero ${first}/${second}`);\n }\n return result;\n }\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable no-underscore-dangle */\nimport tokenDefinitions from './tokenDefinitions.js';\nimport { syntaxError } from './errors.js';\n\nconst {\n TOK_IDENTIFIER,\n TOK_QUOTEDIDENTIFIER,\n TOK_RBRACKET,\n TOK_RPAREN,\n TOK_COMMA,\n TOK_COLON,\n TOK_CONCATENATE,\n TOK_RBRACE,\n TOK_NUMBER,\n TOK_CURRENT,\n TOK_GLOBAL,\n TOK_EXPREF,\n TOK_PIPE,\n TOK_OR,\n TOK_COMPARATOR,\n TOK_AND,\n TOK_ADD,\n TOK_SUBTRACT,\n TOK_UNARY_MINUS,\n TOK_DIVIDE,\n TOK_UNION,\n TOK_FLATTEN,\n TOK_STAR,\n TOK_FILTER,\n TOK_DOT,\n TOK_NOT,\n TOK_LBRACE,\n TOK_LBRACKET,\n TOK_LPAREN,\n TOK_JSON,\n TOK_STRING,\n TOK_INT,\n} = tokenDefinitions;\n\n// The \"&\", \"[\", \"<\", \">\" tokens\n// are not in basicToken because\n// there are two token variants\n// (\"&&\", \"[?\", \"<=\", \">=\"). This is specially handled\n// below.\n\nconst basicTokens = {\n '.': TOK_DOT,\n ',': TOK_COMMA,\n ':': TOK_COLON,\n '{': TOK_LBRACE,\n '}': TOK_RBRACE,\n ']': TOK_RBRACKET,\n '(': TOK_LPAREN,\n ')': TOK_RPAREN,\n '@': TOK_CURRENT,\n};\n\nconst globalStartToken = '$';\nconst operatorStartToken = {\n '<': true,\n '>': true,\n '=': true,\n '!': true,\n};\n\nconst skipChars = {\n ' ': true,\n '\\t': true,\n '\\n': true,\n};\n\nfunction isAlphaNum(ch) {\n return (ch >= 'a' && ch <= 'z')\n || (ch >= 'A' && ch <= 'Z')\n || (ch >= '0' && ch <= '9')\n || ch === '_';\n}\n\nfunction isIdentifier(stream, pos) {\n const ch = stream[pos];\n // $ is special -- it's allowed to be part of an identifier if it's the first character\n // return whether character 'isAlpha'\n return ch === '$'\n || (ch >= 'a' && ch <= 'z')\n || (ch >= 'A' && ch <= 'Z')\n || ch === '_';\n}\n\nexport default class Lexer {\n constructor(allowedGlobalNames = [], debug = []) {\n this._allowedGlobalNames = allowedGlobalNames;\n this.debug = debug;\n }\n\n tokenize(stream) {\n const tokens = [];\n this._current = 0;\n let start;\n let identifier;\n let token;\n while (this._current < stream.length) {\n const prev = tokens.length ? tokens.slice(-1)[0].type : null;\n\n if (this._isGlobal(prev, stream, this._current)) {\n tokens.push(this._consumeGlobal(stream));\n } else if (isIdentifier(stream, this._current)) {\n start = this._current;\n identifier = this._consumeUnquotedIdentifier(stream);\n tokens.push({\n type: TOK_IDENTIFIER,\n value: identifier,\n start,\n });\n } else if (this._isNumber(stream)) {\n token = this._consumeNumber(stream);\n tokens.push(token);\n } else if (basicTokens[stream[this._current]] !== undefined) {\n tokens.push({\n type: basicTokens[stream[this._current]],\n value: stream[this._current],\n start: this._current,\n });\n this._current += 1;\n } else if (stream[this._current] === '-' && ![TOK_GLOBAL, TOK_CURRENT, TOK_NUMBER, TOK_INT, TOK_RPAREN, TOK_IDENTIFIER, TOK_QUOTEDIDENTIFIER, TOK_RBRACKET, TOK_JSON, TOK_STRING].includes(prev)) {\n token = this._consumeUnaryMinus(stream);\n tokens.push(token);\n } else if (stream[this._current] === '[') {\n // No need to increment this._current. This happens\n // in _consumeLBracket\n token = this._consumeLBracket(stream);\n tokens.push(token);\n } else if (stream[this._current] === \"'\") {\n start = this._current;\n identifier = this._consumeQuotedIdentifier(stream);\n tokens.push({\n type: TOK_QUOTEDIDENTIFIER,\n value: identifier,\n start,\n });\n } else if (stream[this._current] === '\"') {\n start = this._current;\n identifier = this._consumeRawStringLiteral(stream);\n tokens.push({\n type: TOK_STRING,\n value: identifier,\n start,\n });\n } else if (stream[this._current] === '`') {\n start = this._current;\n const json = this._consumeJson(stream);\n tokens.push({\n type: TOK_JSON,\n value: json,\n start,\n });\n } else if (operatorStartToken[stream[this._current]] !== undefined) {\n tokens.push(this._consumeOperator(stream));\n } else if (skipChars[stream[this._current]] !== undefined) {\n // Ignore whitespace.\n this._current += 1;\n } else if (stream[this._current] === '&') {\n start = this._current;\n this._current += 1;\n if (stream[this._current] === '&') {\n this._current += 1;\n tokens.push({ type: TOK_AND, value: '&&', start });\n } else if (prev === TOK_COMMA || prev === TOK_LPAREN) {\n // based on previous token we'll know if this & is a JMESPath expression-type\n // or if it's a concatenation operator\n // if we're a function arg then it's an expression-type\n tokens.push({ type: TOK_EXPREF, value: '&', start });\n } else {\n tokens.push({ type: TOK_CONCATENATE, value: '&', start });\n }\n } else if (stream[this._current] === '~') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_UNION, value: '~', start });\n } else if (stream[this._current] === '+') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_ADD, value: '+', start });\n } else if (stream[this._current] === '-') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_SUBTRACT, value: '-', start });\n } else if (stream[this._current] === '*') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_STAR, value: '*', start });\n } else if (stream[this._current] === '/') {\n start = this._current;\n this._current += 1;\n tokens.push({ type: TOK_DIVIDE, value: '/', start });\n } else if (stream[this._current] === '|') {\n start = this._current;\n this._current += 1;\n if (stream[this._current] === '|') {\n this._current += 1;\n tokens.push({ type: TOK_OR, value: '||', start });\n } else {\n tokens.push({ type: TOK_PIPE, value: '|', start });\n }\n } else {\n throw syntaxError(`Unknown character:${stream[this._current]}`);\n }\n }\n return tokens;\n }\n\n _consumeUnquotedIdentifier(stream) {\n const start = this._current;\n this._current += 1;\n while (\n this._current < stream.length\n && (stream[this._current] === '$' || isAlphaNum(stream[this._current]))\n ) {\n this._current += 1;\n }\n return stream.slice(start, this._current);\n }\n\n _consumeQuotedIdentifier(stream) {\n const start = this._current;\n this._current += 1;\n const maxLength = stream.length;\n let foundNonAlpha = !isIdentifier(stream, start + 1);\n while (stream[this._current] !== \"'\" && this._current < maxLength) {\n // You can escape a single quote and you can escape an escape.\n let current = this._current;\n if (!isAlphaNum(stream[current])) foundNonAlpha = true;\n if (stream[current] === '\\\\' && (stream[current + 1] === '\\\\'\n || stream[current + 1] === \"'\")) {\n current += 2;\n } else {\n current += 1;\n }\n this._current = current;\n }\n this._current += 1;\n const val = stream.slice(start, this._current);\n // Check for unnecessary single quotes.\n // json-formula uses single quotes to escape characters that don't belong in names.\n // e.g. \"purchase-order\".address\n // If we find a single-quoted entity with spaces or all legal characters, issue a warning\n try {\n if (!foundNonAlpha) {\n this.debug.push(`Suspicious quotes: ${val}`);\n this.debug.push(`Did you intend a literal? \"${val.replace(/'/g, '')}\"?`);\n }\n // eslint-disable-next-line no-empty\n } catch (e) { }\n // we want to do all the escape-processing that JSON does ...\n // except that JSON expects to escape double quotes, and our identifiers\n // escape single quotes.\n return JSON.parse(`\"${val.substring(1, val.length - 1).replace(/\\\\'/g, \"'\")}\"`);\n }\n\n _consumeRawStringLiteral(stream) {\n const start = this._current;\n this._current += 1;\n const maxLength = stream.length;\n while (stream[this._current] !== '\"' && this._current < maxLength) {\n // You can escape a double quote and you can escape an escape.\n let current = this._current;\n if (stream[current] === '\\\\' && (stream[current + 1] === '\\\\'\n || stream[current + 1] === '\"')) {\n current += 2;\n } else {\n current += 1;\n }\n this._current = current;\n }\n this._current += 1;\n const literal = stream.slice(start + 1, this._current - 1);\n if (this._current > maxLength) {\n throw syntaxError(`Unterminated string literal at ${start}, \"${literal}`);\n }\n try {\n return JSON.parse(`\"${literal}\"`);\n } catch (_e) {\n throw syntaxError(`Invalid string literal: ${literal}`);\n }\n }\n\n _isNumber(stream) {\n // if we see the first two characters are either a digit or radix, then we have a number\n let ch = stream[this._current];\n if (ch >= '0' && ch <= '9') return true;\n if (ch !== '.') return false;\n if (this._current === stream.length) return false;\n ch = stream[this._current + 1];\n return ch >= '0' && ch <= '9';\n }\n\n _consumeNumber(stream) {\n const start = this._current;\n const num = stream.slice(start);\n const match = num.match(/^[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?/);\n if (!match) throw syntaxError(`Invalid number: ${num}`);\n const n = match[0];\n this._current += n.length;\n let value;\n if (n.includes('.') || n.toLowerCase().includes('e')) {\n value = parseFloat(n);\n return { type: TOK_NUMBER, value, start };\n }\n value = parseInt(n, 10);\n return { type: TOK_INT, value, start };\n }\n\n _consumeUnaryMinus() {\n const start = this._current;\n this._current += 1;\n return { type: TOK_UNARY_MINUS, value: '-', start };\n }\n\n _consumeLBracket(stream) {\n const start = this._current;\n this._current += 1;\n if (stream[this._current] === '?') {\n this._current += 1;\n return { type: TOK_FILTER, value: '[?', start };\n }\n if (stream[this._current] === ']') {\n this._current += 1;\n return { type: TOK_FLATTEN, value: '[]', start };\n }\n return { type: TOK_LBRACKET, value: '[', start };\n }\n\n _isGlobal(prev, stream, pos) {\n // global tokens occur only at the start of an expression\n if (prev !== null && prev === TOK_DOT) return false;\n const ch = stream[pos];\n if (ch !== globalStartToken) return false;\n // $ is special -- it's allowed to be part of an identifier if it's the first character\n let i = pos + 1;\n while (i < stream.length && (stream[i] === '$' || isAlphaNum(stream[i]))) i += 1;\n const global = stream.slice(pos, i);\n return this._allowedGlobalNames.includes(global);\n }\n\n _consumeGlobal(stream) {\n const start = this._current;\n this._current += 1;\n while (this._current < stream.length\n && (stream[this._current] === '$' || isAlphaNum(stream[this._current]))) this._current += 1;\n const global = stream.slice(start, this._current);\n\n return { type: TOK_GLOBAL, name: global, start };\n }\n\n _consumeOperator(stream) {\n const start = this._current;\n const startingChar = stream[start];\n this._current += 1;\n if (startingChar === '!') {\n if (stream[this._current] === '=') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '!=', start };\n }\n return { type: TOK_NOT, value: '!', start };\n }\n if (startingChar === '<') {\n if (stream[this._current] === '=') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '<=', start };\n }\n if (stream[this._current] === '>') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '!=', start };\n }\n return { type: TOK_COMPARATOR, value: '<', start };\n }\n if (startingChar === '>') {\n if (stream[this._current] === '=') {\n this._current += 1;\n return { type: TOK_COMPARATOR, value: '>=', start };\n }\n return { type: TOK_COMPARATOR, value: '>', start };\n }\n // startingChar is '='\n if (stream[this._current] === '=') {\n this._current += 1;\n }\n return { type: TOK_COMPARATOR, value: '==', start };\n }\n\n _consumeJson(stream) {\n this._current += 1;\n const start = this._current;\n const maxLength = stream.length;\n while (stream[this._current] !== '`' && this._current < maxLength) {\n let current = this._current;\n if (stream[current] === '\\\\' && stream[current + 1] === '`') {\n current += 2;\n } else {\n current += 1;\n }\n this._current = current;\n }\n let literalString = stream.slice(start, this._current).trimStart();\n literalString = literalString.replaceAll('\\\\`', '`');\n // +1 gets us to the ending \"`\", +1 to move on to the next char.\n this._current += 1;\n if (this._current > maxLength) {\n throw syntaxError(`Unterminated JSON literal at ${start}: \\`${literalString}`);\n }\n\n return JSON.parse(literalString);\n }\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport Lexer from './Lexer.js';\nimport tokenDefinitions from './tokenDefinitions.js';\nimport { syntaxError } from './errors.js';\n\n/* eslint-disable no-underscore-dangle */\nconst {\n TOK_JSON,\n TOK_COLON,\n TOK_EOF,\n TOK_IDENTIFIER,\n TOK_QUOTEDIDENTIFIER,\n TOK_RBRACKET,\n TOK_RPAREN,\n TOK_COMMA,\n TOK_CONCATENATE,\n TOK_RBRACE,\n TOK_NUMBER,\n TOK_CURRENT,\n TOK_GLOBAL,\n TOK_EXPREF,\n TOK_PIPE,\n TOK_OR,\n TOK_AND,\n TOK_ADD,\n TOK_SUBTRACT,\n TOK_UNARY_MINUS,\n TOK_MULTIPLY,\n TOK_DIVIDE,\n TOK_UNION,\n TOK_COMPARATOR,\n TOK_FLATTEN,\n TOK_STAR,\n TOK_FILTER,\n TOK_DOT,\n TOK_NOT,\n TOK_LBRACE,\n TOK_LBRACKET,\n TOK_LPAREN,\n TOK_STRING,\n TOK_INT,\n} = tokenDefinitions;\n\nconst bindingPower = {\n [TOK_EOF]: 0,\n [TOK_IDENTIFIER]: 0,\n [TOK_QUOTEDIDENTIFIER]: 0,\n [TOK_RBRACKET]: 0,\n [TOK_RPAREN]: 0,\n [TOK_COMMA]: 0,\n [TOK_RBRACE]: 0,\n [TOK_NUMBER]: 0,\n [TOK_INT]: 0,\n [TOK_CURRENT]: 0,\n [TOK_GLOBAL]: 0,\n [TOK_EXPREF]: 0,\n [TOK_PIPE]: 1,\n [TOK_OR]: 2,\n [TOK_AND]: 3,\n [TOK_COMPARATOR]: 4,\n [TOK_CONCATENATE]: 5,\n [TOK_ADD]: 6,\n [TOK_SUBTRACT]: 6,\n [TOK_UNION]: 6,\n [TOK_MULTIPLY]: 7,\n [TOK_DIVIDE]: 7,\n [TOK_NOT]: 8,\n [TOK_UNARY_MINUS]: 8,\n [TOK_FLATTEN]: 10,\n [TOK_STAR]: 20,\n [TOK_FILTER]: 21,\n [TOK_DOT]: 40,\n [TOK_LBRACE]: 50,\n [TOK_LBRACKET]: 55,\n [TOK_LPAREN]: 60,\n};\n\nexport default class Parser {\n constructor(allowedGlobalNames = []) {\n this._allowedGlobalNames = allowedGlobalNames;\n }\n\n parse(expression, debug) {\n this.debug = debug;\n this._loadTokens(expression);\n this.index = 0;\n const ast = this.expression(0);\n if (this._lookahead(0) !== TOK_EOF) {\n const t = this._lookaheadToken(0);\n throw syntaxError(`Unexpected token type: ${t.type}, value: ${t.value}`);\n }\n return ast;\n }\n\n _loadTokens(expression) {\n const lexer = new Lexer(this._allowedGlobalNames, this.debug);\n const tokens = lexer.tokenize(expression);\n tokens.push({ type: TOK_EOF, value: '', start: expression.length });\n this.tokens = tokens;\n }\n\n expression(rbp) {\n const leftToken = this._lookaheadToken(0);\n this._advance();\n let left = this.nud(leftToken);\n let currentToken = this._lookaheadToken(0, left);\n while (rbp < bindingPower[currentToken.type]) {\n this._advance();\n left = this.led(currentToken, left);\n currentToken = this._lookaheadToken(0, left);\n }\n return left;\n }\n\n _lookahead(number) {\n return this.tokens[this.index + number].type;\n }\n\n _lookaheadToken(number, previous = {}) {\n const next = this.tokens[this.index + number];\n // disambiguate multiply and star\n if (next.type === TOK_STAR) {\n if (![\n undefined,\n TOK_LBRACKET,\n TOK_DOT,\n TOK_PIPE,\n TOK_AND,\n TOK_OR,\n TOK_COMMA,\n TOK_NOT,\n TOK_MULTIPLY,\n TOK_ADD,\n TOK_SUBTRACT,\n TOK_DIVIDE,\n TOK_LPAREN,\n TOK_CONCATENATE,\n TOK_UNION,\n TOK_COMPARATOR].includes(previous.type)) {\n next.type = TOK_MULTIPLY;\n }\n }\n\n return next;\n }\n\n _advance() {\n this.index += 1;\n }\n\n _lookAheadIndex() {\n let idx = 0;\n if (this._lookahead(idx) === TOK_UNARY_MINUS) idx += 1;\n if (this._lookahead(idx) === TOK_INT) idx += 1;\n if (this._lookahead(idx) === TOK_RBRACKET\n || this._lookahead(idx) === TOK_COLON) return true;\n return false;\n }\n\n _getIndex() {\n return this.index;\n }\n\n _setIndex(index) {\n this.index = index;\n }\n\n // eslint-disable-next-line consistent-return\n nud(token) {\n let left;\n let right;\n let expression;\n let node;\n let args;\n switch (token.type) {\n case TOK_STRING:\n return { type: 'String', value: token.value };\n case TOK_JSON:\n return { type: 'Literal', value: token.value };\n case TOK_NUMBER:\n return { type: 'Number', value: token.value };\n case TOK_INT:\n return { type: 'Integer', value: token.value };\n case TOK_IDENTIFIER:\n return { type: 'Identifier', name: token.value };\n case TOK_QUOTEDIDENTIFIER:\n node = { type: 'QuotedIdentifier', name: token.value };\n return node;\n case TOK_NOT:\n right = this.expression(bindingPower.Not);\n return { type: 'NotExpression', children: [right] };\n case TOK_UNARY_MINUS:\n right = this.expression(bindingPower.UnaryMinus);\n return { type: 'UnaryMinusExpression', children: [right] };\n case TOK_STAR:\n left = { type: 'Identity' };\n if (this._lookahead(0) === TOK_RBRACKET) {\n // This can happen in a ArrayExpression,\n // [a, b, *]\n right = { type: 'Identity' };\n } else {\n right = this._parseProjectionRHS(bindingPower.Star);\n }\n return { type: 'ValueProjection', children: [left, right] };\n case TOK_FILTER:\n return this.led(token, { type: 'Identity' });\n case TOK_LBRACE:\n return this._parseObjectExpression();\n case TOK_FLATTEN:\n left = { type: TOK_FLATTEN, children: [{ type: 'Identity' }] };\n right = this._parseProjectionRHS(bindingPower.Flatten);\n return { type: 'Projection', children: [left, right] };\n case TOK_LBRACKET:\n if (this._lookAheadIndex()) {\n right = this._parseIndexExpression();\n return this._projectIfSlice({ type: 'Identity' }, right);\n }\n if (this._lookahead(0) === TOK_STAR && this._lookahead(1) === TOK_RBRACKET) {\n this._advance();\n this._advance();\n right = this._parseProjectionRHS(bindingPower.Star);\n return {\n type: 'Projection',\n children: [{ type: 'Identity' }, right],\n debug: 'Wildcard',\n };\n }\n return this._parseArrayExpression();\n\n case TOK_CURRENT:\n return { type: TOK_CURRENT };\n case TOK_GLOBAL:\n return { type: TOK_GLOBAL, name: token.name };\n case TOK_EXPREF:\n expression = this.expression(bindingPower.Expref);\n return { type: 'ExpressionReference', children: [expression] };\n case TOK_LPAREN:\n args = [];\n while (this._lookahead(0) !== TOK_RPAREN) {\n expression = this.expression(0);\n args.push(expression);\n }\n this._match(TOK_RPAREN);\n return args[0];\n default:\n this._errorToken(token);\n }\n }\n\n // eslint-disable-next-line consistent-return\n led(token, left) {\n let condition;\n let right;\n let name;\n let args;\n let node;\n let rbp;\n let leftNode;\n let rightNode;\n const tokenName = token.type;\n switch (tokenName) {\n case TOK_CONCATENATE:\n right = this.expression(bindingPower.Concatenate);\n return { type: 'ConcatenateExpression', children: [left, right] };\n case TOK_DOT:\n rbp = bindingPower.Dot;\n if (this._lookahead(0) !== TOK_STAR) {\n right = this._parseDotRHS(rbp);\n return { type: 'ChainedExpression', children: [left, right] };\n }\n // Creating a projection.\n this._advance();\n right = this._parseProjectionRHS(rbp);\n return { type: 'ValueProjection', children: [left, right] };\n case TOK_PIPE:\n right = this.expression(bindingPower.Pipe);\n return { type: TOK_PIPE, children: [left, right] };\n case TOK_OR:\n right = this.expression(bindingPower.Or);\n return { type: 'OrExpression', children: [left, right] };\n case TOK_AND:\n right = this.expression(bindingPower.And);\n return { type: 'AndExpression', children: [left, right] };\n case TOK_ADD:\n right = this.expression(bindingPower.Add);\n return { type: 'AddExpression', children: [left, right] };\n case TOK_SUBTRACT:\n right = this.expression(bindingPower.Subtract);\n return { type: 'SubtractExpression', children: [left, right] };\n case TOK_MULTIPLY:\n right = this.expression(bindingPower.Multiply);\n return { type: 'MultiplyExpression', children: [left, right] };\n case TOK_DIVIDE:\n right = this.expression(bindingPower.Divide);\n return { type: 'DivideExpression', children: [left, right] };\n case TOK_UNION:\n right = this.expression(bindingPower.Union);\n return { type: 'UnionExpression', children: [left, right] };\n case TOK_LPAREN:\n if (left.type !== TOK_IDENTIFIER) {\n throw syntaxError('Bad function syntax. Parenthesis must be preceded by an unquoted identifier');\n }\n name = left.name;\n args = this._parseFunctionArgs();\n node = { type: 'Function', name, children: args };\n return node;\n case TOK_FILTER:\n condition = this.expression(0);\n this._match(TOK_RBRACKET);\n right = this._parseProjectionRHS(bindingPower.Filter);\n return { type: 'FilterProjection', children: [left, right, condition] };\n case TOK_FLATTEN:\n leftNode = { type: TOK_FLATTEN, children: [left] };\n rightNode = this._parseProjectionRHS(bindingPower.Flatten);\n return { type: 'Projection', children: [leftNode, rightNode] };\n case TOK_COMPARATOR:\n return this._parseComparator(left, token);\n case TOK_LBRACKET:\n if (this._lookahead(0) === TOK_STAR\n && this._lookahead(1) === TOK_RBRACKET) {\n this._advance();\n this._advance();\n right = this._parseProjectionRHS(bindingPower.Star);\n return { type: 'Projection', children: [left, right], debug: 'Wildcard' };\n }\n right = this._parseIndexExpression();\n return this._projectIfSlice(left, right);\n default:\n this._errorToken(token);\n }\n }\n\n _match(tokenType) {\n const token = this._lookaheadToken(0);\n if (token.type === tokenType) {\n this._advance();\n return token;\n }\n throw syntaxError(`Expected ${tokenType}, got: ${token.type}`);\n }\n\n // eslint-disable-next-line class-methods-use-this\n _errorToken(token) {\n throw syntaxError(`Unexpected token (${\n token.type}): \"${\n token.value || token.name}\"`);\n }\n\n _parseFunctionArgs() {\n let firstExpression = true;\n const args = [];\n while (this._lookahead(0) !== TOK_RPAREN) {\n if (!firstExpression) {\n this._match(TOK_COMMA);\n }\n args.push(this.expression(0));\n firstExpression = false;\n }\n this._match(TOK_RPAREN);\n return args;\n }\n\n _parseSignedInt() {\n const first = this._lookaheadToken(0);\n if (first.type === TOK_UNARY_MINUS) {\n this._advance();\n const value = this._match(TOK_INT);\n return {\n type: 'SignedInt',\n value: -value.value,\n };\n }\n if (first.type !== TOK_INT) this._errorToken(first);\n this._advance();\n return {\n type: 'SignedInt',\n value: first.value,\n };\n }\n\n _parseIndexExpression() {\n const oldIndex = this._getIndex();\n if (this._lookahead(0) === TOK_COLON) {\n return this._parseSliceExpression();\n }\n // look ahead of the first expression to determine the type\n const first = this._parseSignedInt();\n const token = this._lookahead(0);\n if (token === TOK_COLON) {\n // now that we know the type revert back to the old position and parse\n this._setIndex(oldIndex);\n return this._parseSliceExpression();\n }\n this._match(TOK_RBRACKET);\n return {\n type: 'Index',\n value: first,\n };\n }\n\n _projectIfSlice(left, right) {\n const indexExpr = { type: 'BracketExpression', children: [left, right] };\n if (right.type === 'Slice') {\n return {\n type: 'Projection',\n children: [indexExpr, this._parseProjectionRHS(bindingPower.Star)],\n };\n }\n return indexExpr;\n }\n\n _parseSliceExpression() {\n // [start:end:step] where each part is optional, as well as the last\n // colon.\n const parts = [null, null, null];\n let index = 0;\n let currentToken = this._lookahead(0);\n while (currentToken !== TOK_RBRACKET && index < 3) {\n if (currentToken === TOK_COLON && index < 2) { // there can't be more than 2 colons\n index += 1;\n this._advance();\n } else {\n parts[index] = this._parseSignedInt();\n // check next token to be either colon or rbracket\n const t = this._lookahead(0);\n if (t !== TOK_COLON && t !== TOK_RBRACKET) {\n throw syntaxError(`Unexpected token: ${\n t.value}(${t.type})`);\n }\n }\n currentToken = this._lookahead(0);\n }\n this._match(TOK_RBRACKET);\n return {\n type: 'Slice',\n children: parts,\n };\n }\n\n _parseComparator(left, comparator) {\n const right = this.expression(bindingPower[comparator.type]);\n return { type: 'Comparator', value: comparator.value, children: [left, right] };\n }\n\n _parseDotRHS(rbp) {\n const lookahead = this._lookahead(0);\n const exprTokens = [TOK_IDENTIFIER, TOK_QUOTEDIDENTIFIER, TOK_STAR];\n if (exprTokens.indexOf(lookahead) >= 0) {\n return this.expression(rbp);\n }\n if (lookahead === TOK_LBRACKET) {\n this._match(TOK_LBRACKET);\n return this._parseArrayExpression();\n }\n if (lookahead === TOK_LBRACE) {\n this._match(TOK_LBRACE);\n return this._parseObjectExpression();\n }\n throw syntaxError('Expecting one of: \"*\", \"[\", \"{\", name or quoted name after a dot');\n }\n\n _parseProjectionRHS(rbp) {\n let right;\n const next = this._lookaheadToken(0, { type: TOK_STAR });\n if (bindingPower[next.type] <= bindingPower[TOK_FLATTEN]) {\n right = { type: 'Identity' };\n } else if (next.type === TOK_LBRACKET) {\n right = this.expression(rbp);\n } else if (next.type === TOK_FILTER) {\n right = this.expression(rbp);\n } else if (next.type === TOK_DOT) {\n this._match(TOK_DOT);\n right = this._parseDotRHS(rbp);\n } else {\n throw syntaxError(`Unexpected token: ${next.value}(${next.type})`);\n }\n return right;\n }\n\n _parseArrayExpression() {\n const expressions = [];\n while (this._lookahead(0) !== TOK_RBRACKET) {\n const expression = this.expression(0);\n expressions.push(expression);\n if (this._lookahead(0) === TOK_COMMA) {\n this._match(TOK_COMMA);\n if (this._lookahead(0) === TOK_RBRACKET) {\n throw syntaxError('Unexpected token Rbracket');\n }\n }\n }\n this._match(TOK_RBRACKET);\n return { type: 'ArrayExpression', children: expressions };\n }\n\n _parseObjectExpression() {\n const pairs = [];\n const identifierTypes = [TOK_IDENTIFIER, TOK_QUOTEDIDENTIFIER];\n let keyToken; let keyName; let value; let\n node;\n if (this._lookahead(0) === TOK_RBRACE) {\n this.debug.push('To create an empty object, use a JSON literal: `{}`');\n throw syntaxError('An empty object expression is not allowed');\n }\n for (;;) {\n keyToken = this._lookaheadToken(0);\n if (identifierTypes.indexOf(keyToken.type) < 0) {\n throw syntaxError(`Expecting an identifier token, got: ${\n keyToken.type}`);\n }\n keyName = keyToken.value;\n this._advance();\n this._match(TOK_COLON);\n value = this.expression(0);\n node = { type: 'KeyValuePair', name: keyName, value };\n pairs.push(node);\n if (this._lookahead(0) === TOK_COMMA) {\n this._match(TOK_COMMA);\n } else if (this._lookahead(0) === TOK_RBRACE) {\n this._match(TOK_RBRACE);\n break;\n }\n }\n return { type: 'ObjectExpression', children: pairs };\n }\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable no-underscore-dangle */\nimport { dataTypes, typeNameTable } from './dataTypes.js';\nimport {\n getProperty, debugAvailable, toBoolean, strictDeepEqual,\n} from './utils.js';\nimport { evaluationError, functionError, typeError } from './errors.js';\n\nfunction round(num, digits) {\n const precision = 10 ** digits;\n return Math.round(num * precision) / precision;\n}\n\nconst MS_IN_DAY = 24 * 60 * 60 * 1000;\n\nfunction getDateObj(dateNum) {\n return new Date(Math.round(dateNum * MS_IN_DAY));\n}\n\nfunction getDateNum(dateObj) {\n return dateObj / MS_IN_DAY;\n}\n\nfunction validNumber(n, context) {\n if (Number.isNaN(n) || !Number.isFinite(n)) {\n throw evaluationError(`Call to \"${context}()\" resulted in an invalid number`);\n }\n return n;\n}\n\nexport default function functions(\n runtime,\n isObject,\n toNumber,\n getType,\n isArrayType,\n valueOf,\n toString,\n debug,\n) {\n const {\n TYPE_NUMBER,\n TYPE_ANY,\n TYPE_STRING,\n TYPE_ARRAY,\n TYPE_OBJECT,\n TYPE_BOOLEAN,\n TYPE_EXPREF,\n TYPE_NULL,\n TYPE_ARRAY_NUMBER,\n TYPE_ARRAY_STRING,\n TYPE_ARRAY_ARRAY,\n } = dataTypes;\n\n function toInteger(num) {\n let n = valueOf(num);\n // functions that require an integer parameter will have declared\n // the parameters as a number, so any strings will have already been\n // converted to number before the function call.\n // However, a few functions accept a string | integer. Attempt to convert\n // to integer in these cases, but failure isn't an error.\n if (getType(n) === TYPE_STRING) n = toNumber(n);\n n = Math.trunc(num);\n if (Number.isNaN(n)) return num;\n return n;\n }\n\n function toJSON(arg, indent) {\n const value = valueOf(arg);\n if (getType(value) === TYPE_STRING) {\n return arg;\n }\n const offset = indent ? toInteger(indent) : 0;\n return JSON.stringify(value, null, offset);\n }\n\n function balanceArrays(listOfArrays) {\n const maxLen = Math.max(...listOfArrays.map(a => (Array.isArray(a) ? a.length : 0)));\n const allArrays = listOfArrays.map(a => {\n if (Array.isArray(a)) {\n return a.concat(Array(maxLen - a.length).fill(null));\n }\n return Array(maxLen).fill(a);\n });\n // convolve allArrays\n const arrays = [];\n for (let i = 0; i < maxLen; i += 1) {\n const row = [];\n for (let j = 0; j < allArrays.length; j += 1) {\n row.push(allArrays[j][i]);\n }\n arrays.push(row);\n }\n return arrays;\n }\n\n function evaluate(args, fn) {\n if (args.some(Array.isArray)) {\n return balanceArrays(args).map(a => evaluate(a, fn));\n }\n return fn(...args);\n }\n\n function datedifFn(date1Arg, date2Arg, unitArg) {\n const unit = toString(unitArg).toLowerCase();\n const date1 = getDateObj(date1Arg);\n const date2 = getDateObj(date2Arg);\n if (date2 === date1) return 0;\n if (date2 < date1) throw functionError('end_date must be >= start_date in datedif()');\n\n if (unit === 'd') return Math.floor(getDateNum(date2 - date1));\n const yearDiff = date2.getFullYear() - date1.getFullYear();\n let monthDiff = date2.getMonth() - date1.getMonth();\n const dayDiff = date2.getDate() - date1.getDate();\n\n if (unit === 'y') {\n let y = yearDiff;\n if (monthDiff < 0) y -= 1;\n if (monthDiff === 0 && dayDiff < 0) y -= 1;\n return y;\n }\n if (unit === 'm') {\n return yearDiff * 12 + monthDiff + (dayDiff < 0 ? -1 : 0);\n }\n if (unit === 'ym') {\n if (dayDiff < 0) monthDiff -= 1;\n if (monthDiff <= 0 && yearDiff > 0) return 12 + monthDiff;\n return monthDiff;\n }\n if (unit === 'yd') {\n if (dayDiff < 0) monthDiff -= 1;\n if (monthDiff < 0) date2.setFullYear(date1.getFullYear() + 1);\n else date2.setFullYear(date1.getFullYear());\n return Math.floor(getDateNum(date2 - date1));\n }\n throw functionError(`Unrecognized unit parameter \"${unit}\" for datedif()`);\n }\n\n function endsWithFn(searchArg, suffixArg) {\n const searchStr = valueOf(searchArg);\n const suffix = valueOf(suffixArg);\n // make sure the comparison is based on code points\n const search = Array.from(searchStr).reverse();\n const ending = Array.from(suffix).reverse();\n return ending.every((c, i) => c === search[i]);\n }\n\n function eomonthFn(dateArg, monthsArg) {\n const jsDate = getDateObj(dateArg);\n const months = toInteger(monthsArg);\n // We can give the constructor a month value > 11 and it will increment the years\n // Since day is 1-based, giving zero will yield the last day of the previous month\n const newDate = new Date(jsDate.getFullYear(), jsDate.getMonth() + months + 1, 0);\n return getDateNum(newDate);\n }\n\n function findFn(queryArg, textArg, offsetArg) {\n const query = Array.from(toString(queryArg));\n const text = Array.from(toString(textArg));\n const offset = toInteger(offsetArg);\n if (offset < 0) throw evaluationError('find() start position must be >= 0');\n if (query.length === 0) {\n // allow an empty string to be found at any position -- including the end\n if (offset > text.length) return null;\n return offset;\n }\n for (let i = offset; i < text.length; i += 1) {\n if (text.slice(i, i + query.length).every((c, j) => c === query[j])) {\n return i;\n }\n }\n return null;\n }\n\n function properFn(arg) {\n const capitalize = word => `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}`;\n const original = toString(arg);\n // split the string by whitespace, punctuation, and numbers\n const wordParts = original.match(/[\\s\\d\\p{P}]+|[^\\s\\d\\p{P}]+/gu);\n if (wordParts !== null) return wordParts.map(w => capitalize(w)).join('');\n return capitalize(original);\n }\n\n function reptFn(textArg, countArg) {\n const text = toString(textArg);\n const count = toInteger(countArg);\n if (count < 0) throw evaluationError('rept() count must be greater than or equal to 0');\n return text.repeat(count);\n }\n\n function searchFn(findTextString, withinTextString, startPosInt = 0) {\n const findText = toString(findTextString);\n const withinText = toString(withinTextString);\n const startPos = toInteger(startPosInt);\n if (startPos < 0) throw functionError('search() startPos must be greater than or equal to 0');\n if (findText === null || withinText === null || withinText.length === 0) return [];\n\n // Process as an array of code points\n // Find escapes and wildcards\n const globString = Array.from(findText).reduce((acc, cur) => {\n if (acc.escape) return { escape: false, result: acc.result.concat(cur) };\n if (cur === '\\\\') return { escape: true, result: acc.result };\n if (cur === '?') return { escape: false, result: acc.result.concat('dot') };\n if (cur === '*') {\n // consecutive * are treated as a single *\n if (acc.result.slice(-1).pop() === 'star') return acc;\n return { escape: false, result: acc.result.concat('star') };\n }\n return { escape: false, result: acc.result.concat(cur) };\n }, { escape: false, result: [] }).result;\n\n const testMatch = (array, glob, match) => {\n // we've consumed the entire glob, so we're done\n if (glob.length === 0) return match;\n // we've consumed the entire array, but there's still glob left -- no match\n if (array.length === 0) return null;\n const testChar = array[0];\n let [globChar, ...nextGlob] = glob;\n const isStar = globChar === 'star';\n if (isStar) {\n // '*' is at the end of the match -- so we're done matching\n if (glob.length === 1) return match;\n // we'll check for a match past the * and if not found, we'll process the *\n [globChar, ...nextGlob] = glob.slice(1);\n }\n if (testChar === globChar || globChar === 'dot') {\n return testMatch(array.slice(1), nextGlob, match.concat(testChar));\n }\n // no match, so consume wildcard *\n if (isStar) return testMatch(array.slice(1), glob, match.concat(testChar));\n\n return null;\n };\n // process code points\n const within = Array.from(withinText);\n for (let i = startPos; i < within.length; i += 1) {\n const result = testMatch(within.slice(i), globString, []);\n if (result !== null) return [i, result.join('')];\n }\n return [];\n }\n\n function splitFn(strArg, separatorArg) {\n const str = toString(strArg);\n const separator = toString(separatorArg);\n // for empty separator, return an array of code points\n return separator.length === 0 ? Array.from(str) : str.split(separator);\n }\n\n function startsWithFn(subjectString, prefixString) {\n const subject = Array.from(toString(subjectString));\n const prefix = Array.from(toString(prefixString));\n if (prefix.length > subject.length) return false;\n for (let i = 0; i < prefix.length; i += 1) {\n if (prefix[i] !== subject[i]) return false;\n }\n return true;\n }\n\n function substituteFn(source, oldString, replacementString, nearest) {\n const src = Array.from(toString(source));\n const old = Array.from(toString(oldString));\n const replacement = Array.from(toString(replacementString));\n\n if (old.length === 0) return source;\n\n // no third parameter? replace all instances\n let replaceAll = true;\n let whch = 0;\n if (nearest > -1) {\n replaceAll = false;\n whch = nearest + 1;\n }\n\n let found = 0;\n const result = [];\n // find the instances to replace\n for (let j = 0; j < src.length;) {\n const match = old.every((c, i) => src[j + i] === c);\n if (match) found += 1;\n if (match && (replaceAll || found === whch)) {\n result.push(...replacement);\n j += old.length;\n } else {\n result.push(src[j]);\n j += 1;\n }\n }\n return result.join('');\n }\n\n function truncFn(number, d) {\n const digits = toInteger(d);\n\n const method = number >= 0 ? Math.floor : Math.ceil;\n return method(number * 10 ** digits) / 10 ** digits;\n }\n\n function weekdayFn(date, type) {\n const jsDate = getDateObj(date);\n const day = jsDate.getDay();\n // day is in range [0-7) with 0 mapping to sunday\n switch (toInteger(type)) {\n case 1:\n // range = [1, 7], sunday = 1\n return day + 1;\n case 2:\n // range = [1, 7] sunday = 7\n return ((day + 6) % 7) + 1;\n case 3:\n // range = [0, 6] sunday = 6\n return (day + 6) % 7;\n default:\n throw functionError(`Unsupported returnType: \"${type}\" for weekday()`);\n }\n }\n\n const functionMap = {\n // name: [function, ]\n // The can be:\n //\n // {\n // args: [[type1, type2], [type1, type2]],\n // variadic: true|false\n // }\n //\n // Each arg in the arg list is a list of valid types\n // (if the function is overloaded and supports multiple\n // types. If the type is \"any\" then no type checking\n // occurs on the argument. Variadic is optional\n // and if not provided is assumed to be false.\n /**\n * Find the absolute (non-negative) value of the provided argument `value`.\n * @param {number|number[]} value A numeric value\n * @return {number|number[]} If `value < 0`, returns `-value`, otherwise returns `value`\n * @function abs\n * @example\n * abs(-1) // returns 1\n */\n abs: {\n _func: args => evaluate(args, Math.abs),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n /**\n * Compute the inverse cosine (in radians) of a number.\n * @param {number|number[]} cosine A number between -1 and 1, inclusive,\n * representing the angle's cosine value.\n * @return {number|number[]} The inverse cosine angle in radians between 0 and PI\n * @function acos\n * @example\n * acos(0) => 1.5707963267948966\n */\n acos: {\n _func: args => evaluate(args, n => validNumber(Math.acos(n), 'acos')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Finds the logical AND result of all parameters.\n * If the parameters are not boolean they will be <<_type_coercion_rules,cast to boolean>>.\n * Note the related <<_and_operator, And Operator>>.\n * @param {any} firstOperand logical expression\n * @param {...any} [additionalOperands] any number of additional expressions\n * @returns {boolean} The logical result of applying AND to all parameters\n * @example\n * and(10 > 8, length(\"foo\") < 5) // returns true\n * and(`null`, length(\"foo\") < 5) // returns false\n * @function and\n */\n and: {\n _func: resolvedArgs => {\n let result = toBoolean(valueOf(resolvedArgs[0]));\n resolvedArgs.slice(1).forEach(arg => {\n result = result && toBoolean(valueOf(arg));\n });\n return result;\n },\n _signature: [{ types: [TYPE_ANY], variadic: true }],\n },\n\n /**\n * Compute the inverse sine (in radians) of a number.\n * @param {number|number[]} sine A number between -1 and 1, inclusive,\n * representing the angle's sine value.\n * @return {number|number[]} The inverse sine angle in radians between -PI/2 and PI/2\n * @function asin\n * @example\n * Math.asin(0) => 0\n */\n asin: {\n _func: args => evaluate(args, n => validNumber(Math.asin(n), 'asin')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Compute the angle in the plane (in radians) between the positive\n * x-axis and the ray from (0, 0) to the point (x, y)\n * @param {number|number[]} y The y coordinate of the point\n * @param {number|number[]} x The x coordinate of the point\n * @return {number|number[]} The angle in radians (between -PI and PI),\n * between the positive x-axis and the ray from (0, 0) to the point (x, y).\n * @function atan2\n * @example\n * atan2(20,10) => 1.1071487177940904\n */\n atan2: {\n _func: args => evaluate(args, Math.atan2),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Finds the average of the elements in an array.\n * Non-numeric values (text, boolean, null, object) are ignored.\n * If there are nested arrays, they are flattened.\n * If the array is empty, an evaluation error is thrown\n * @param {any[]} elements array of values\n * @return {number} average value\n * @function avg\n * @example\n * avg([1, 2, 3]) // returns 2\n */\n avg: {\n _func: resolvedArgs => {\n let sum = 0;\n const filtered = resolvedArgs\n .flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER);\n\n if (filtered.length === 0) throw evaluationError('avg() requires at least one argument');\n filtered.forEach(a => {\n sum += a;\n });\n return sum / filtered.length;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Finds the average of the elements in an array, converting strings and booleans to number.\n * If any conversions to number fail, a type error is thrown.\n * If there are nested arrays, they are flattened.\n * If the array is empty, an evaluation error is thrown\n * @param {number[]} elements array of numeric values\n * @return {number} average value\n * @function avgA\n * @example\n * avgA([1, 2, \"3\", null()]) // returns 2\n */\n avgA: {\n _func: resolvedArgs => {\n let sum = 0;\n let filtered;\n try {\n filtered = resolvedArgs\n .flat(Infinity)\n .filter(a => getType(a) !== TYPE_NULL)\n .map(toNumber);\n } catch (_e) {\n throw typeError('avgA() received non-numeric parameters');\n }\n if (filtered.length === 0) throw evaluationError('avg() requires at least one argument');\n filtered.forEach(a => {\n sum += a;\n });\n return sum / filtered.length;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Generates a lower-case string of the `input` string using locale-specific mappings.\n * e.g. Strings with German letter ß (eszett) can be compared to \"ss\"\n * @param {string|string[]} input string to casefold\n * @returns {string|string[]} A new string converted to lower case\n * @function casefold\n * @example\n * casefold(\"AbC\") // returns \"abc\"\n */\n casefold: {\n _func: (args, _data, interpreter) => evaluate(args, s => toString(s)\n .toLocaleUpperCase(interpreter.language)\n .toLocaleLowerCase(interpreter.language)),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Finds the next highest integer value of the argument `num` by rounding up if necessary.\n * i.e. ceil() rounds toward positive infinity.\n * @param {number|number[]} num numeric value\n * @return {integer|integer[]} The smallest integer greater than or equal to num\n * @function ceil\n * @example\n * ceil(10) // returns 10\n * ceil(10.4) // return 11\n\n */\n ceil: {\n _func: args => evaluate(args, Math.ceil),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n /**\n * Retrieve the first code point from a string\n * @param {string|string[]} str source string.\n * @return {integer|integer[]} Unicode code point value.\n * If the input string is empty, returns `null`.\n * @function codePoint\n * @example\n * codePoint(\"ABC\") // 65\n */\n codePoint: {\n _func: args => evaluate(args, arg => {\n const text = toString(arg);\n return text.length === 0 ? null : text.codePointAt(0);\n }),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Determines if the given `subject` contains `search`.\n * If `subject` is an array, this function returns true if one of the elements\n * in the array is equal to the `search` value. If `subject`\n * is a string, return true if the string contains the\n * `search` value.\n * @param {array|string} subject The element to be searched\n * @param {any} search element to find.\n * If `subject` is an array, search for an exact match for `search` in the array.\n * If `subject` is a string, `search` must also be a string.\n * @return {boolean} true if found\n * @function contains\n * @example\n * contains([1, 2, 3, 4], 2) // returns true\n * contains([1, 2, 3, 4], -1) // returns false\n * contains(\"Abcd\", \"d\") // returns true\n * contains(\"Abcd\", \"x\") // returns false\n\n */\n contains: {\n _func: resolvedArgs => {\n const subject = valueOf(resolvedArgs[0]);\n const search = valueOf(resolvedArgs[1]);\n if (isArrayType(resolvedArgs[0])) {\n return subject.some(s => strictDeepEqual(s, search));\n }\n const source = Array.from(subject);\n if (getType(search) !== TYPE_STRING) {\n throw typeError('contains() requires a string search value for string subjects');\n }\n if (search === '') return true;\n const searchLen = Array.from(search).length;\n for (let i = 0; i < source.length; i += 1) {\n if (source.slice(i, i + searchLen).join('') === search) return true;\n }\n return false;\n },\n _signature: [{ types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_ANY] }],\n },\n /**\n * Compute the cosine (in radians) of a number.\n * @param {number|number[]} angle A number representing an angle in radians\n * @return {number|number[]} The cosine of the angle, between -1 and 1, inclusive.\n * @function cos\n * @example\n * cos(1.0471975512) => 0.4999999999970535\n */\n cos: {\n _func: args => evaluate(args, Math.cos),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Return difference between two date values.\n * The measurement of the difference is determined by the `unit` parameter. One of:\n *\n * * `y` the number of whole years between `start_date` and `end_date`\n * * `m` the number of whole months between `start_date` and `end_date`.\n * * `d` the number of days between `start_date` and `end_date`\n * * `ym` the number of whole months between `start_date` and `end_date`\n * after subtracting whole years.\n * * `yd` the number of days between `start_date` and `end_date`, assuming `start_date`\n * and `end_date` were no more than one year apart\n * @param {number|number[]} start_date The starting <<_date_and_time_values, date/time value>>.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @param {number|number[]} end_date The end <<_date_and_time_values, date/time value>> -- must\n * be greater or equal to start_date. If not, an error will be thrown.\n * @param {string|string[]} unit Case-insensitive string representing the unit of\n * time to measure. An unrecognized unit will result in an error.\n * @returns {integer|integer[]} The number of days/months/years difference\n * @function datedif\n * @example\n * datedif(datetime(2001, 1, 1), datetime(2003, 1, 1), \"y\") // returns 2\n * datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), \"D\") // returns 805\n * // 805 days between June 1, 2001, and August 15, 2003\n * datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), \"YD\") // returns 75\n * // 75 days between June 1 and August 15, ignoring the years of the dates (75)\n */\n datedif: {\n _func: args => evaluate(args, datedifFn),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Generate a date/time value from individual date/time parts.\n * If any of the units are greater than their normal range,\n * the overflow will be added to the next greater unit.\n * e.g. specifying 25 hours will increment the day value by 1.\n * Similarly,\n * negative values will decrement the next greater unit.\n * e.g. datetime(year, month, day - 30) will return a date 30 days earlier.\n * @param {integer} year The year to use for date construction.\n * Values from 0 to 99 map to the years 1900 to 1999. All other values are the actual year\n * @param {integer} month The month: beginning with 1 for\n * January to 12 for December.\n * @param {integer} day The day of the month.\n * @param {integer} [hours=0] Integer value between 0 and 23 representing the hour of the day.\n * @param {integer} [minutes=0] Integer value representing the minute segment of a time.\n * @param {integer} [seconds=0] Integer value representing the second segment of a time.\n * @param {integer} [milliseconds=0] Integer value representing the\n * millisecond segment of a time.\n * @returns {number} A <<_date_and_time_values, date/time value>>\n * to be used with other date/time functions\n * @function datetime\n * @example\n * datetime(2010, 10, 10) // returns representation of October 10, 2010\n * datetime(2010, 2, 28) // returns representation of February 28, 2010\n * datetime(2023,13,5) | year(@) & \"/\" & month(@) // returns 2024/1\n */\n datetime: {\n _func: args => {\n const year = toInteger(args[0]);\n const month = toInteger(args[1]) - 1; // javascript months start from 0\n const day = toInteger(args[2]);\n const hours = args.length > 3 ? toInteger(args[3]) : 0;\n const minutes = args.length > 4 ? toInteger(args[4]) : 0;\n const seconds = args.length > 5 ? toInteger(args[5]) : 0;\n const ms = args.length > 6 ? toInteger(args[6]) : 0;\n\n const baseDate = new Date(year, month, day, hours, minutes, seconds, ms);\n\n return getDateNum(baseDate);\n },\n _signature: [\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Finds the day of the month for a date value\n * @param {number|number[]} date <<_date_and_time_values, date/time value>> generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The day of the month ranging from 1 to 31.\n * @function day\n * @example\n * day(datetime(2008,5,23)) // returns 23\n */\n day: {\n _func: args => evaluate(args, a => getDateObj(a).getDate()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Debug a json-formula expression.\n * The `debug()` function allows users to inspect a sub-expression within a formula.\n * @param {any} arg The expression to return from `debug()` function,\n * and the default expression to be debugged. May be any type except an expression.\n * @param {any|expression} [displayValue=arg] Optionally override the value to be debugged.\n * `displayValue` may be an expression to\n * be evaluated with the context of `arg`.\n * @returns {any} The value of the `arg` parameter\n * @function debug\n * @example\n * avg(([1,2,3] * [2,3,4]).debug(@)).round(@,3) // 6.667\n * avg(debug([1,2,3] * [2,3,4],&\"average of: \" &toString(@))).round(@,3) // 6.667\n */\n debug: {\n _func: resolvedArgs => {\n const arg = resolvedArgs[0];\n if (resolvedArgs.length > 1) {\n if (getType(resolvedArgs[1]) === TYPE_EXPREF) {\n debug.push(runtime.interpreter.visit(resolvedArgs[1], arg));\n } else {\n debug.push(resolvedArgs[1]);\n }\n } else {\n debug.push(toJSON(resolvedArgs[0]));\n }\n return arg;\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_ANY, TYPE_EXPREF], optional: true },\n ],\n },\n\n /**\n * Performs a depth-first search of a nested hierarchy to\n * return an array of key values that match a `name`.\n * The name can be either a key into an object or an array index.\n * This is similar to the Descendant Accessor operator (`..`) from [E4X](https://ecma-international.org/publications-and-standards/standards/ecma-357/).\n * @param {object|array|null} object The starting object or array where we start the search\n * @param {string|integer} name The name (or index position) of the elements to find.\n * If `name` is a string, search for nested objects with a matching key.\n * If `name` is an integer, search for nested arrays with a matching index.\n * @returns {any[]} The array of matched elements\n * @function deepScan\n * @example\n * deepScan({a : {b1 : {c : 2}, b2 : {c : 3}}}, \"c\") // returns [2, 3]\n */\n deepScan: {\n _func: resolvedArgs => {\n const [source, n] = resolvedArgs;\n const [name, checkArrays] = getType(n) === TYPE_NUMBER\n ? [toInteger(n), true] : [toString(n), false];\n const items = [];\n function scan(node) {\n if (node === null) return;\n if (isArrayType(node)) {\n if (checkArrays && node[name] !== undefined) items.push(node[name]);\n node.forEach(scan);\n } else if (isObject(node)) {\n Object.entries(node).forEach(([k, v]) => {\n if (!checkArrays && k === name) items.push(v);\n scan(v);\n });\n }\n }\n scan(source);\n return items;\n },\n _signature: [\n { types: [TYPE_OBJECT, TYPE_ARRAY, TYPE_NULL] },\n { types: [TYPE_STRING, TYPE_NUMBER] },\n ],\n },\n\n /**\n * Determines if the `subject` string ends with a specific `suffix`\n * @param {string|string[]} subject source string in which to search\n * @param {string|string[]} suffix search string\n * @return {boolean|boolean[]} true if the `suffix` value is at the end of the `subject`\n * @function endsWith\n * @example\n * endsWith(\"Abcd\", \"d\") // returns true\n * endsWith(\"Abcd\", \"A\") // returns false\n */\n endsWith: {\n _func: args => evaluate(args, endsWithFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Returns an array of `[key, value]` pairs from an object or array.\n * The `fromEntries()` function may be used to convert an array to an object.\n * @param {object|array} obj source object or array\n * @returns {any[]} an array of arrays where each child array has two elements\n * representing the key and value of a pair\n * @function entries\n * @example\n * entries({a: 1, b: 2}) // returns [[\"a\", 1], [\"b\", 2]]\n * entries([4,5]) // returns [[\"0\", 4],[\"1\", 5]]\n */\n entries: {\n _func: args => {\n const obj = valueOf(args[0]);\n return Object.entries(obj);\n },\n _signature: [\n {\n types: [\n TYPE_ARRAY,\n TYPE_OBJECT,\n ],\n },\n ],\n },\n\n /**\n * Finds the date value of the end of a month, given `startDate` plus `monthAdd` months\n * @param {number|number[]} startDate The base date to start from.\n * <<_date_and_time_values, Date/time values>> can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @param {integer|integer[]} monthAdd Number of months to add to start date\n * @return {number|number[]} the date of the last day of the month\n * @function eomonth\n * @example\n * eomonth(datetime(2011, 1, 1), 1) | [month(@), day(@)] // returns [2, 28]\n * eomonth(datetime(2011, 1, 1), -3) | [month(@), day(@)] // returns [10, 31]\n */\n eomonth: {\n _func: args => evaluate(args, eomonthFn),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Finds e (the base of natural logarithms) raised to a power. (i.e. e^x)\n * @param {number|number[]} x A numeric expression representing the power of e.\n * @returns {number|number[]} e (the base of natural logarithms) raised to power x\n * @function exp\n * @example\n * exp(10) // returns 22026.465794806718\n */\n exp: {\n _func: args => evaluate(args, Math.exp),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Return constant boolean false value.\n * Expressions may also use the JSON literal: `` `false` ``\n * @returns {boolean} constant boolean value `false`\n * @function false\n */\n false: {\n _func: () => false,\n _signature: [],\n },\n\n /**\n * Finds and returns the index of query in text from a start position\n * @param {string|string[]} findText string to search\n * @param {string|string[]} withinText text to be searched\n * @param {integer|integer[]} [start=0] zero-based position to start searching.\n * If specified, `start` must be greater than or equal to 0\n * @returns {integer|null|integer[]} The position of the found string, null if not found.\n * @function find\n * @example\n * find(\"m\", \"abm\") // returns 2\n * find(\"M\", \"abMcdM\", 3) // returns 5\n * find(\"M\", \"ab\") // returns `null`\n * find(\"M\", \"abMcdM\", 2) // returns 2\n */\n find: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 3) args.push(0);\n return evaluate(args, findFn);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Calculates the next lowest integer value of the argument `num` by rounding down if necessary.\n * i.e. floor() rounds toward negative infinity.\n * @param {number|number[]} num numeric value\n * @return {integer|integer[]} The largest integer smaller than or equal to num\n * @function floor\n * @example\n * floor(10.4) // returns 10\n * floor(10) // returns 10\n */\n floor: {\n _func: args => evaluate(args, Math.floor),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Create a string from a code point.\n * @param {integer|integer[]} codePoint An integer or array of integers\n * between 0 and 0x10FFFF (inclusive) representing Unicode code point(s).\n * @return {string} A string from the given code point(s)\n * @function fromCodePoint\n * @example\n * fromCodePoint(65) // \"A\"\n * fromCodePoint(65) == \"\\u0041\" // true\n */\n fromCodePoint: {\n _func: args => {\n try {\n const points = Array.isArray(args[0]) ? args[0] : [args[0]];\n return String.fromCodePoint(...points.map(toInteger));\n } catch (e) {\n throw evaluationError(`Invalid code point: \"${args[0]}\"`);\n }\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Returns an object by transforming a list of key-value `pairs` into an object.\n * `fromEntries()` is the inverse operation of `entries()`.\n * If the nested arrays are not of the form: `[key, value]`\n * (where key is a string), an error will be thrown.\n * @param {any[]} pairs A nested array of key-value pairs to create the object from\n * The nested arrays must have exactly two values, where the first value is a string.\n * If a key is specified more than once, the last occurrence will override any previous value.\n * @returns {object} An object constructed from the provided key-value pairs\n * @function fromEntries\n * @example\n * fromEntries([[\"a\", 1], [\"b\", 2]]) // returns {a: 1, b: 2}\n */\n fromEntries: {\n _func: args => {\n const array = args[0];\n // validate beyond the TYPE_ARRAY_ARRAY check\n if (!array.every(a => {\n if (!Array.isArray(a)) return false;\n if (a.length !== 2) return false;\n if (getType(a[0]) !== TYPE_STRING) return false;\n return true;\n })) {\n throw typeError('fromEntries() requires an array of key value pairs');\n }\n return Object.fromEntries(array);\n },\n _signature: [\n { types: [TYPE_ARRAY_ARRAY, TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Compute the nearest 32-bit single precision float representation of a number\n * @param {number|number[]} num input to be rounded\n * @return {number|number[]} The rounded representation of `num`\n * @function fround\n * @example\n * fround(2147483650.987) => 2147483648\n * fround(100.44444444444444444444) => 100.44444274902344\n */\n fround: {\n _func: args => evaluate(args, Math.fround),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Determine if an object has a property or if an array index is in range.\n * @param {object|array|null} subject source object or array.\n * When querying for <<_hidden_properties,hidden properties>>, `subject` may be any data type.\n * @param {string|integer} name The name (or index position) of the element to find.\n * if `subject` is an array, `name` must be an integer;\n * if `subject` is an object, `name` must be a string.\n * @returns {boolean} true if the element exists\n * @function hasProperty\n * @example\n * hasProperty({a: 1, b: 2}, \"a\") // returns true\n * hasProperty([\"apples\", \"oranges\"], 3) // returns false\n * hasProperty(`null`, \"a\") // returns false\n */\n hasProperty: {\n _func: args => {\n let key = args[1];\n const keyType = getType(key);\n\n // if the object/array has a getter for this property then don't validate types\n if (args[0] !== null && Object.getOwnPropertyDescriptor(args[0], key)?.get) return true;\n const obj = valueOf(args[0]);\n if (obj === null) return false;\n const isArray = isArrayType(obj);\n if (!(isArray || getType(obj) === TYPE_OBJECT)) {\n throw typeError('First parameter to hasProperty() must be either an object or array.');\n }\n\n if (isArray) {\n if (keyType !== TYPE_NUMBER) throw TypeError('hasProperty(): Array index must be an integer');\n key = toInteger(key);\n } else if (keyType !== TYPE_STRING) throw TypeError('hasProperty(): Object key must be a string');\n const result = getProperty(obj, key);\n return result !== undefined;\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_STRING, TYPE_NUMBER] },\n ],\n },\n /**\n * Extract the hour from a <<_date_and_time_values, date/time value>>\n * @param {number|number[]} date The datetime/time for which the hour is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} value between 0 and 23\n * @function hour\n * @example\n * hour(datetime(2008,5,23,12, 0, 0)) // returns 12\n * hour(time(12, 0, 0)) // returns 12\n */\n hour: {\n _func: args => evaluate(args, a => getDateObj(a).getHours()),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Return one of two values `result1` or `result2`, depending on the `condition`\n * @param {any} condition boolean result of a logical expression\n * @param {any} result1 if condition is true\n * @param {any} result2 if condition is false\n * @return {any} either result1 or result2\n * @function if\n\n * @example\n * if(true(), 1, 2) // returns 1\n * if(false(), 1, 2) // returns 2\n */\n if: {\n _func: (unresolvedArgs, data, interpreter) => {\n const conditionNode = unresolvedArgs[0];\n const leftBranchNode = unresolvedArgs[1];\n const rightBranchNode = unresolvedArgs[2];\n unresolvedArgs\n .forEach(arg => {\n if (arg.type === 'ExpressionReference') {\n throw typeError('\"if()\" does not accept an expression reference argument.');\n }\n });\n\n const condition = interpreter.visit(conditionNode, data);\n if (toBoolean(valueOf(condition))) {\n return interpreter.visit(leftBranchNode, data);\n }\n return interpreter.visit(rightBranchNode, data);\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_ANY] },\n { types: [TYPE_ANY] }],\n },\n\n /**\n * Combines all the elements from the provided\n * array, joined together using the `glue` argument as a separator between each array element.\n * @param {any[]} array array of values that will be converted to strings using `toString()`\n * @param {string} glue\n * @return {string} String representation of the array\n * @function join\n * @example\n * join([\"a\", \"b\", \"c\"], \",\") // returns \"a,b,c\"\n * join([\"apples\", \"bananas\"], \" and \") // returns \"apples and bananas\"\n * join([1, 2, 3, null()], \"|\") // returns \"1|2|3|null\"\n */\n join: {\n _func: resolvedArgs => {\n const listJoin = resolvedArgs[0];\n const joinChar = resolvedArgs[1];\n return listJoin.map(a => toJSON(a)).join(joinChar);\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n { types: [TYPE_STRING] },\n ],\n },\n\n /**\n * Generates an array of the keys of the input object. If the\n * object is null, the value return an empty array\n * @param {object} obj the object to examine\n * @return {array} the array of all the key names\n * @function keys\n * @example\n * keys({a : 3, b : 4}) // returns [\"a\", \"b\"]\n */\n keys: {\n _func: resolvedArgs => Object.keys(resolvedArgs[0]),\n _signature: [{ types: [TYPE_OBJECT] }],\n },\n /**\n * Return a substring from the start of a string or the left-most elements of an array\n * @param {string|array} subject The source text/array of code points/elements\n * @param {integer} [elements=1] number of elements to pick\n * @return {string|array}\n * @function left\n * @example\n * left(\"Sale Price\", 4) // returns \"Sale\"\n * left(\"Sweden\") // returns \"S\"\n * left([4, 5, 6], 2) // returns [4, 5]\n */\n left: {\n _func: args => {\n const numEntries = args.length > 1 ? toInteger(args[1]) : 1;\n if (numEntries < 0) throw evaluationError('left() requires a non-negative number of elements');\n if (isArrayType(args[0])) return args[0].slice(0, numEntries);\n const text = Array.from(toString(args[0]));\n return text.slice(0, numEntries).join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Calculates the length of the input argument based on types:\n *\n * * string: returns the number of unicode code points\n * * array: returns the number of array elements\n * * object: returns the number of key-value pairs\n * @param {string | array | object} subject subject whose length to calculate\n * @return {integer} the length of the input subject\n * @function length\n * @example\n * length(`[]`) // returns 0\n * length(\"\") // returns 0\n * length(\"abcd\") // returns 4\n * length([1, 2, 3, 4]) // returns 4\n * length(`{}`) // returns 0\n * length({a : 3, b : 4}) // returns 2\n */\n length: {\n _func: resolvedArgs => {\n const arg = valueOf(resolvedArgs[0]);\n if (isObject(arg)) return Object.keys(arg).length;\n // Array.from splits a string into code points\n // If we didn't do this, then String.length would return the number of UTF-16 code units\n return isArrayType(arg) ? arg.length : Array.from(toString(arg)).length;\n },\n _signature: [{ types: [TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT] }],\n },\n\n /**\n * Compute the natural logarithm (base e) of a number\n * @param {number|number[]} num A number greater than zero\n * @return {number|number[]} The natural log value\n * @function log\n * @example\n * log(10) // 2.302585092994046\n */\n log: {\n _func: args => evaluate(args, a => validNumber(Math.log(a), 'log')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Compute the base 10 logarithm of a number.\n * @param {number|number[]} num A number greater than or equal to zero\n * @return {number|number[]} The base 10 log result\n * @function log10\n * @example\n * log10(100000) // 5\n */\n log10: {\n _func: args => evaluate(args, a => validNumber(Math.log10(a), 'log10')),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Converts all the alphabetic code points in a string to lowercase.\n * @param {string|string[]} input input string\n * @returns {string|string[]} the lower case value of the input string\n * @function lower\n * @example\n * lower(\"E. E. Cummings\") // returns \"e. e. cummings\"\n */\n lower: {\n _func: args => evaluate(args, a => toString(a).toLowerCase()),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Apply an expression to every element in an array and return the array of results.\n * An input array of length N will return an array of length N.\n * @param {array} elements array of elements to process\n * @param {expression} expr expression to evaluate\n * @return {array} the mapped array\n * @function map\n * @example\n * map([1, 2, 3, 4], &(@ + 1)) // returns [2, 3, 4, 5]\n * map([\"doe\", \"nick\", \"chris\"], &length(@)) // returns [3, 4, 5]\n */\n map: {\n _func: resolvedArgs => {\n const exprefNode = resolvedArgs[1];\n return resolvedArgs[0].map(arg => runtime.interpreter.visit(exprefNode, arg));\n },\n _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],\n },\n\n /**\n * Calculates the largest value in the input numbers.\n * Any values that are not numbers (null, boolean, strings, objects) will be ignored.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(array|any)} collection values/array(s) in which the maximum\n * element is to be calculated\n * @return {number} the largest value found\n * @function max\n * @example\n * max([1, 2, 3], [4, 5, 6]) // returns 6\n * max([\\\"a\\\", \\\"a1\\\", \\\"b\\\"], null(), true())) // returns 0\n * max(8, 10, 12, \"14\") // returns 12\n */\n max: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => typeof valueOf(a) === 'number');\n\n if (array.length === 0) return 0;\n\n return Math.max(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Calculates the largest value in the input values, coercing parameters to numbers.\n * Null values are ignored.\n * If any parameters cannot be converted to a number,\n * the function will fail with a type error.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(any)} collection values/array(s) in which the maximum\n * element is to be calculated\n * @return {number} the largest value found\n * @function maxA\n * @example\n * maxA([1, 2, 3], [4, 5, 6]) // returns 6\n * maxA([\"a\", \"a1\", \"b\", null()]) // error\n * maxA(8, 10, 12, \"14\") // returns 14\n */\n maxA: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => valueOf(a) !== null)\n .map(toNumber);\n\n if (array.find(a => a === null)) {\n throw evaluationError('maxA() received non-numeric parameters');\n }\n if (array.length === 0) return 0;\n\n return Math.max(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Accepts one or more objects, and returns a single object with\n * all objects merged.\n * The first object is copied, and then\n * and each key value pair from each subsequent object\n * are added to the first object. Duplicate keys in subsequent objects will\n * override those found in earlier objects.\n * @param {...object} args\n * @return {object} The combined object\n * @function merge\n * @example\n * merge({a: 1, b: 2}, {c : 3, d: 4}) // returns {a :1, b: 2, c: 3, d: 4}\n * merge({a: 1, b: 2}, {a : 3, d: 4}) // returns {a :3, b: 2, d: 4}\n */\n merge: {\n _func: resolvedArgs => {\n const merged = {};\n resolvedArgs.forEach(current => {\n if (current === null) return;\n Object.entries(current || {}).forEach(([key, value]) => {\n merged[key] = value;\n });\n });\n return merged;\n },\n _signature: [{ types: [TYPE_OBJECT, TYPE_NULL], variadic: true }],\n },\n\n /**\n * Extracts a substring from text, or a subset from an array.\n * @param {string|array} subject the text string or array of elements from which to extract.\n * @param {integer} startPos the zero-based position of the first code point\n * or element to extract.\n * @param {integer} length The number of code points or elements to return from the\n * string or array.\n * If greater then the length of `subject` the length of the subject is used.\n * @return {string|array} The resulting substring or array subset of elements\n * @function mid\n * @example\n * mid(\"Fluid Flow\", 0, 5) // returns \"Fluid\"\n * mid(\"Fluid Flow\", 6, 20) // returns \"Flow\"\n * mid(\"Fluid Flow\", 20, 5) // returns \"\"\n * mid([0,1,2,3,4,5,6,7,8,9], 2, 3) // returns [2,3,4]\n */\n mid: {\n _func: args => {\n const startPos = toInteger(args[1]);\n const numEntries = toInteger(args[2]);\n if (startPos < 0) throw evaluationError('mid() requires a non-negative start position');\n if (numEntries < 0) throw evaluationError('mid() requires a non-negative length parameter');\n if (isArrayType(args[0])) {\n return args[0].slice(startPos, startPos + numEntries);\n }\n const text = Array.from(toString(args[0]));\n return text.slice(startPos, startPos + numEntries).join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n ],\n },\n\n /**\n * Extract the milliseconds of the time value in a <<_date_and_time_values, date/time value>>.\n * @param {number|number[]} date datetime/time for which the millisecond is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The number of milliseconds: 0 through 999\n * @function millisecond\n * @example\n * millisecond(datetime(2008, 5, 23, 12, 10, 53, 42)) // returns 42\n */\n millisecond: {\n _func: args => evaluate(args, a => getDateObj(a).getMilliseconds()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Calculates the smallest value in the input numbers.\n * Any values that are not numbers (null, boolean, string, object) will be ignored.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(any[]|any)} collection\n * Values/arrays to search for the minimum value\n * @return {number} the smallest value found\n * @function min\n * @example\n * min([1, 2, 3], [4, 5, 6]) // returns 1\n * min(\"4\", 8, 10, 12, null()) // returns 8\n */\n min: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => typeof valueOf(a) === 'number');\n if (array.length === 0) return 0;\n\n return Math.min(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Calculates the smallest value in the input values, coercing parameters to numbers.\n * Null values are ignored.\n * If any parameters cannot be converted to a number,\n * the function will fail with a type error.\n * If any parameters are arrays, the arrays will be flattened.\n * If no numbers are provided, the function will return zero.\n * @param {...(any[]|any)} collection values/array(s) in which the maximum\n * element is to be calculated\n * @return {number} the largest value found\n * @function minA\n * @example\n * minA([1, 2, 3], [4, 5, 6]) // returns 1\n * minA(\"4\", 8, 10, 12, null()) // returns 4\n */\n minA: {\n _func: args => {\n // flatten the args into a single array\n const array = args\n .flat(Infinity)\n .filter(a => valueOf(a) !== null)\n .map(toNumber);\n\n if (array.find(a => a === null)) {\n throw evaluationError('minA() received non-numeric parameters');\n }\n if (array.length === 0) return 0;\n\n return Math.min(...array);\n },\n _signature: [{\n types: [TYPE_ARRAY, TYPE_ANY],\n variadic: true,\n }],\n },\n\n /**\n * Extract the minute (0 through 59) from a <<_date_and_time_values, date/time value>>\n * @param {number|number[]} date A datetime/time value.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} Number of minutes in the time portion of the date/time value\n * @function minute\n * @example\n * minute(datetime(2008,5,23,12, 10, 0)) // returns 10\n * minute(time(12, 10, 0)) // returns 10\n */\n minute: {\n _func: args => evaluate(args, a => getDateObj(a).getMinutes()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Return the remainder when one number is divided by another number.\n * @param {number|number[]} dividend The number for which to find the remainder.\n * @param {number|number[]} divisor The number by which to divide number.\n * @return {number|number[]} Computes the remainder of `dividend`/`divisor`.\n * If `dividend` is negative, the result will also be negative.\n * If `dividend` is zero, an error is thrown.\n * @function mod\n * @example\n * mod(3, 2) // returns 1\n * mod(-3, 2) // returns -1\n */\n mod: {\n _func: args => evaluate(args, (a, b) => {\n const result = a % b;\n if (Number.isNaN(result)) throw evaluationError(`Bad parameter for mod: '${a} % ${b}'`);\n return result;\n }),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Finds the month of a date.\n * @param {number|number[]} date source <<_date_and_time_values, date/time value>>.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The month number value, ranging from 1 (January) to 12 (December)\n * @function month\n * @example\n * month(datetime(2008,5,23)) // returns 5\n */\n month: {\n // javascript months start from 0\n _func: args => evaluate(args, a => getDateObj(a).getMonth() + 1),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Compute logical NOT of a value. If the parameter is not boolean\n * it will be <<_type_coercion_rules,cast to boolean>>\n * Note the related <<_not_operator, unary NOT operator>>.\n * @param {any} value - any data type\n * @returns {boolean} The logical NOT applied to the input parameter\n * @example\n * not(length(\"bar\") > 0) // returns false\n * not(false()) // returns true\n * not(\"abcd\") // returns false\n * not(\"\") // returns true\n * @function not\n */\n not: {\n _func: resolveArgs => !toBoolean(valueOf(resolveArgs[0])),\n _signature: [{ types: [TYPE_ANY] }],\n },\n\n /**\n * Finds the first argument that does not resolve to `null`.\n * This function accepts one or more arguments, and will evaluate\n * them in order until a non-null argument is encountered. If all\n * arguments values resolve to null, then return a null value.\n * @param {...any} argument\n * @return {any}\n * @function notNull\n * @example\n * notNull(1, 2, 3, 4, `null`) // returns 1\n * notNull(`null`, 2, 3, 4, `null`) // returns 2\n */\n notNull: {\n _func: resolvedArgs => {\n const result = resolvedArgs.find(arg => getType(arg) !== TYPE_NULL);\n return result === undefined ? null : result;\n },\n _signature: [{ types: [TYPE_ANY], variadic: true }],\n },\n /**\n * Retrieve the current date/time.\n * @return {number} representation of the <<_date_and_time_values, current date/time value>>.\n * @function now\n */\n now: {\n _func: () => getDateNum(Date.now()),\n _signature: [],\n },\n\n /**\n * Return constant null value.\n * Expressions may also use the JSON literal: `` `null` ``\n * @returns {boolean} True\n * @function null\n */\n null: {\n _func: () => null,\n _signature: [],\n },\n\n /**\n * Determines the logical OR result of a set of parameters.\n * If the parameters are not boolean they will be <<_type_coercion_rules,cast to\n * boolean>>.\n * Note the related <<_or_operator, Or Operator>>.\n * @param {any} first logical expression\n * @param {...any} [operand] any number of additional expressions\n * @returns {boolean} The logical result of applying OR to all parameters\n * @example\n * or((x / 2) == y, (y * 2) == x) // true\n * @function or\n */\n or: {\n _func: resolvedArgs => {\n let result = toBoolean(valueOf(resolvedArgs[0]));\n resolvedArgs.slice(1).forEach(arg => {\n result = result || toBoolean(valueOf(arg));\n });\n return result;\n },\n _signature: [{ types: [TYPE_ANY], variadic: true }],\n },\n\n /**\n * Computes `a` raised to a power `x`. (a^x)\n * @param {number|number[]} a The base number -- can be any real number.\n * @param {number|number[]} x The exponent to which the base number is raised.\n * @return {number|number[]}\n * @function power\n * @example\n * power(10, 2) // returns 100 (10 raised to power 2)\n */\n power: {\n _func: args => evaluate(args, (a, b) => validNumber(a ** b, 'power')),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Apply proper casing to a string. Proper casing is where the first letter of each\n * word is converted to an\n * uppercase letter and the rest of the letters in the word converted to lowercase.\n * Words are demarcated by whitespace, punctuation, or numbers.\n * Specifically, any character(s) matching the regular expression: `[\\s\\d\\p{P}]+`.\n * @param {string|string[]} text source string\n * @returns {string|string[]} source string with proper casing applied.\n * @function proper\n * @example\n * proper(\"this is a TITLE\") // returns \"This Is A Title\"\n * proper(\"2-way street\") // returns \"2-Way Street\"\n * proper(\"76BudGet\") // returns \"76Budget\"\n */\n proper: {\n _func: args => evaluate(args, properFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Generate a pseudo random number.\n * @returns {number} A value greater than or equal to zero, and less than one.\n * @function random\n * @example\n * random() // 0.022585461160693265\n */\n random: {\n _func: () => Math.random(),\n _signature: [],\n },\n /**\n * Executes a user-supplied reducer expression on each element of an\n * array, in order, passing in the return value from the expression from the preceding element.\n * The final result of running the reducer across all elements of the input array is a\n * single value.\n * The expression can access the following properties of the current object:\n *\n * * accumulated: accumulated value based on the previous expression.\n * For the first array element use the `initialValue` parameter. If not provided, then `null`\n * * current: current element to process\n * * index: index of the current element in the array\n * * array: original array\n * @param {array} elements array of elements on which the expression will be evaluated\n * @param {expression} expr reducer expression to be executed on each element\n * @param {any} initialValue the accumulated value to pass to the first array element\n * @return {any}\n * @function reduce\n * @example\n * reduce([1, 2, 3], &(accumulated + current)) // returns 6\n * // find maximum entry by age\n * reduce(\n * [{age: 10, name: \"Joe\"},{age: 20, name: \"John\"}],\n * &max(@.accumulated.age, @.current.age), @[0].age)\n * reduce([3, 3, 3], &accumulated * current, 1) // returns 27\n */\n reduce: {\n _func: resolvedArgs => {\n const exprefNode = resolvedArgs[1];\n return resolvedArgs[0].reduce(\n (accumulated, current, index, array) => runtime.interpreter.visit(exprefNode, {\n accumulated, current, index, array,\n }),\n resolvedArgs.length === 3 ? resolvedArgs[2] : null,\n );\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n { types: [TYPE_EXPREF] },\n { types: [TYPE_ANY], optional: true },\n ],\n },\n\n /**\n * Register a function. The registered function may take one parameter.\n * If more parameters are needed, combine them in an array or object.\n * A function may not be re-registered with a different definition.\n * Note that implementations are not required to provide `register()` in order to be conformant.\n * Built-in functions may not be overridden.\n * @param {string} functionName Name of the function to register.\n * `functionName` must begin with an underscore or uppercase letter and follow the regular\n * expression pattern:\n * `{caret}{startsb}_A-Z{endsb}{startsb}_a-zA-Z0-9${endsb}{asterisk}$`\n * @param {expression} expr Expression to execute with this function call\n * @return {{}} returns an empty object\n * @function register\n * @example\n * register(\"_product\", &@[0] * @[1]) // can now call: _product([2,21]) => returns 42\n * register(\"_ltrim\", &split(@,\"\").reduce(@, &accumulated & current | if(@ = \" \", \"\", @), \"\"))\n * // _ltrim(\" abc \") => returns \"abc \"\n */\n register: {\n _func: resolvedArgs => {\n const functionName = resolvedArgs[0];\n const exprefNode = resolvedArgs[1];\n\n if (!/^[_A-Z][_a-zA-Z0-9$]*$/.test(functionName)) throw functionError(`Invalid function name: \"${functionName}\"`);\n if (functionMap[functionName]\n && functionMap[functionName]._exprefNode.value !== exprefNode.value) {\n // custom functions can be re-registered as long as the expression is the same\n throw functionError(`Cannot override function: \"${functionName}\" with a different definition`);\n }\n functionMap[functionName] = {\n _func: args => runtime.interpreter.visit(exprefNode, ...args),\n _signature: [{ types: [TYPE_ANY], optional: true }],\n _exprefNode: exprefNode,\n };\n return {};\n },\n _signature: [\n { types: [TYPE_STRING] },\n { types: [TYPE_EXPREF] },\n ],\n },\n\n /**\n * Register a function that accepts multiple parameters.\n * A function may not be re-registered with a different definition.\n * Note that implementations are not required to provide `registerWithParams()`\n * in order to be conformant.\n * Built-in functions may not be overridden.\n * @param {string} functionName Name of the function to register.\n * `functionName` must begin with an underscore or uppercase letter and follow the regular\n * expression pattern:\n * `{caret}{startsb}_A-Z{endsb}{startsb}_a-zA-Z0-9${endsb}{asterisk}$`\n * @param {expression} expr Expression to execute with this function call.\n * Parameters are passed as an array.\n * @return {{}} returns an empty object\n * @function registerWithParams\n * @example\n * registerWithParams(\"Product\", &@[0] * @[1])\n * // can now call: Product(2,21) => returns 42\n * registerWithParams(\n * \"Ltrim\",\n * &split(@[0],\"\").reduce(@, &accumulated & current | if(@ = \" \", \"\", @), \"\")\n * )\n * // Ltrim(\" abc \") => returns \"abc \"\n */\n registerWithParams: {\n _func: resolvedArgs => {\n const functionName = resolvedArgs[0];\n const exprefNode = resolvedArgs[1];\n\n if (!/^[_A-Z][_a-zA-Z0-9$]*$/.test(functionName)) throw functionError(`Invalid function name: \"${functionName}\"`);\n if (functionMap[functionName]\n && functionMap[functionName]._exprefNode.value !== exprefNode.value) {\n // custom functions can be re-registered as long as the expression is the same\n throw functionError(`Cannot override function: \"${functionName}\" with a different definition`);\n }\n functionMap[functionName] = {\n _func: args => runtime.interpreter.visit(exprefNode, args),\n _signature: [{ types: [TYPE_ANY], optional: true, variadic: true }],\n _exprefNode: exprefNode,\n };\n return {};\n },\n _signature: [\n { types: [TYPE_STRING] },\n { types: [TYPE_EXPREF] },\n ],\n },\n\n /**\n * Generates text (or an array) where we substitute elements at a given start position and\n * length, with new text (or array elements).\n * @param {string|array} subject original text or array\n * @param {integer} start zero-based index in the original text\n * from where to begin the replacement. Must be greater than or equal to 0.\n * @param {integer} length number of code points to be replaced.\n * If `start` + `length` is greater than the length of `subject`,\n * all text past `start` will be replaced.\n * @param {any} replacement Replacement to insert at the start index.\n * If `subject` is an array, and `replacement` is an array, the `replacement` array\n * elements will be inserted into the `subject` array.\n * If `subject` is an array and replacement is not an array, the `replacement` will be\n * inserted as a single element in `subject`\n * If `subject` is a string, the `replacement` will be coerced to a string.\n * @returns {string|array} the resulting text or array\n * @function replace\n * @example\n * replace(\"abcdefghijk\", 5, 5, \"*\") // returns abcde*k\n * replace(\"2009\",2,2,\"10\") // returns 2010\n * replace(\"123456\",0,3,\"@\") // returns @456\n * replace([\"blue\",\"black\",\"white\",\"red\"], 1, 2, [\"green\"]) // returns [\"blue\",\"green\",\"red\"]\n */\n replace: {\n _func: args => {\n const startPos = toInteger(args[1]);\n const numElements = toInteger(args[2]);\n if (startPos < 0) throw evaluationError('replace() start position must be greater than or equal to 0');\n if (numElements < 0) throw evaluationError('replace() length must be greater than or equal to 0');\n if (isArrayType(args[0])) {\n const sourceArray = valueOf(args[0]);\n let replacement = valueOf(args[3]);\n if (!isArrayType(replacement)) replacement = [replacement];\n sourceArray.splice(startPos, numElements, ...replacement);\n return sourceArray;\n }\n const subject = Array.from(toString(args[0]));\n if (isArrayType(args[3]) || getType(args[3]) === TYPE_OBJECT) throw typeError('replace() replacement must not be an array or object');\n const newText = toString(args[3]);\n\n subject.splice(startPos, numElements, newText);\n return subject.join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_ANY] },\n ],\n },\n\n /**\n * Return text repeated `count` times.\n * @param {string|string[]} text text to repeat\n * @param {integer|integer[]} count number of times to repeat the text.\n * Must be greater than or equal to 0.\n * @returns {string|string[]} Text generated from the repeated text.\n * if `count` is zero, returns an empty string.\n * @function rept\n * @example\n * rept(\"x\", 5) // returns \"xxxxx\"\n */\n rept: {\n _func: args => evaluate(args, reptFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Reverses the order of an array or the order of code points in a string\n * @param {string|array} subject the source to be reversed\n * @return {array} The resulting reversed array or string\n * @function reverse\n * @example\n * reverse([\"a\", \"b\", \"c\"]) // returns [\"c\", \"b\", \"a\"]\n */\n reverse: {\n _func: resolvedArgs => {\n const originalStr = valueOf(resolvedArgs[0]);\n const typeName = getType(originalStr);\n if (typeName === TYPE_STRING) {\n return Array.from(originalStr).reverse().join('');\n }\n const reversedArray = resolvedArgs[0].slice(0);\n return reversedArray.reverse();\n },\n _signature: [{ types: [TYPE_STRING, TYPE_ARRAY] }],\n },\n\n /**\n * Generates a string from the right-most code points of a string or\n * a subset of elements from the end of an array\n * @param {string|array} subject The text/array containing the code points/elements to extract\n * @param {integer} [elements=1] number of elements to pick\n * @return {string|array} The extracted substring or array subset\n * Returns null if the number of elements is less than 0\n * @function right\n * @example\n * right(\"Sale Price\", 4) // returns \"rice\"\n * right(\"Sweden\") // returns \"n\"\n * right([4, 5, 6], 2) // returns [5, 6]\n */\n right: {\n _func: args => {\n const numEntries = args.length > 1 ? toInteger(args[1]) : 1;\n if (numEntries < 0) throw evaluationError('right() count must be greater than or equal to 0');\n if (args[0] instanceof Array) {\n if (numEntries === 0) return [];\n return args[0].slice(numEntries * -1);\n }\n if (numEntries === 0) return '';\n const text = Array.from(toString(args[0]));\n return text.slice(numEntries * -1).join('');\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY] },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Round a number to a specified precision:\n *\n * * If `precision` is greater than zero, round to the specified number of decimal places.\n * * If `precision` is 0, round to the nearest integer.\n * * If `precision` is less than 0, round to the left of the decimal point.\n * @param {number|number[]} num number to round\n * @param {integer|integer[]} [precision=0] precision to use for the rounding operation.\n * @returns {number|number[]} rounded value. Rounding a half value will round up.\n * @function round\n * @example\n * round(2.15, 1) // returns 2.2\n * round(626.3,-3) // returns 1000 (Rounds 626.3 to the nearest multiple of 1000)\n * round(626.3, 0) // returns 626\n * round(1.98,-1) // returns 0 (Rounds 1.98 to the nearest multiple of 10)\n * round(-50.55,-2) // -100 (round -50.55 to the nearest multiple of 100)\n * round(1.95583) // 2\n * round(-1.5) // -1\n */\n round: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2)args.push(0);\n return evaluate(args, (a, n) => {\n const digits = toInteger(n);\n return round(a, digits);\n });\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Perform a wildcard search. The search is case-sensitive and supports two forms of wildcards:\n * `{asterisk}` finds a sequence of code points and `?` finds a single code point.\n * To use `{asterisk}` or `?` or `{backslash}` as text values,\n * precede them with an escape (`{backslash}`) character.\n * Note that the wildcard search is not greedy.\n * e.g. `search(\"a{asterisk}b\", \"abb\")` will return `[0, \"ab\"]` Not `[0, \"abb\"]`\n * @param {string|string[]} findText the search string -- which may include wild cards.\n * @param {string|string[]} withinText The string to search.\n * @param {integer|integer[]} [startPos=0] The zero-based position of withinText\n * to start searching.\n * A negative value is not allowed.\n * @returns {array} returns an array with two values:\n *\n * * The start position of the found text and the text string that was found.\n * * If a match was not found, an empty array is returned.\n * @function search\n * @example\n * search(\"a?c\", \"acabc\") // returns [2, \"abc\"]\n */\n search: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2) args.push(0);\n return evaluate(args, searchFn);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n\n },\n\n /**\n * Extract the seconds of the time value in a <<_date_and_time_values, date/time value>>.\n * @param {number|number[]} date datetime/time for which the second is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The number of seconds: 0 through 59\n * @function second\n * @example\n * second(datetime(2008,5,23,12, 10, 53)) // returns 53\n * second(time(12, 10, 53)) // returns 53\n */\n second: {\n _func: args => evaluate(args, a => getDateObj(a).getSeconds()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Computes the sign of a number passed as argument.\n * @param {number|number[]} num any number\n * @return {number|number[]} returns 1 or -1, indicating the sign of `num`.\n * If the `num` is 0, it will return 0.\n * @function sign\n * @example\n * sign(5) // 1\n * sign(-5) // -1\n * sign(0) // 0\n */\n sign: {\n _func: args => evaluate(args, Math.sign),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Computes the sine of a number in radians\n * @param {number|number[]} angle A number representing an angle in radians.\n * @return {number|number[]} The sine of `angle`, between -1 and 1, inclusive\n * @function sin\n * @example\n * sin(0) // 0\n * sin(1) // 0.8414709848078965\n */\n sin: {\n _func: args => evaluate(args, Math.sin),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * This function accepts an array values and returns an\n * array with the elements in sorted order.\n * If there are mixed data types, the values will be grouped in order:\n * numbers, strings, booleans, nulls\n * String sorting is based on code points and is not locale-sensitive.\n * If the sort encounters any objects or arrays, it will throw an evaluation error.\n * @param {any[]} list to be sorted\n * @return {any[]} The ordered result\n * @function sort\n * @example\n * sort([1, 2, 4, 3, 1]) // returns [1, 1, 2, 3, 4]\n * sort([\"20\", 20, true(), \"100\", null(), 100]) // returns [20, 100, \"100\", \"20\", true, null]\n */\n sort: {\n _func: resolvedArgs => {\n /*\n numbers sort first\n strings sort second\n Booleans sort third\n nulls sort last\n */\n const typeVals = resolvedArgs[0].map(value => {\n const type = getType(value);\n if (![TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN, TYPE_NULL].includes(type)) {\n throw evaluationError('Bad datatype for sort');\n }\n return { type, value };\n });\n\n const sortFunction = (a, b) => {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n };\n\n const sorted = typeVals\n .filter(v => v.type === TYPE_NUMBER)\n .map(v => v.value)\n .sort(sortFunction);\n\n sorted.push(\n ...typeVals\n .filter(v => v.type === TYPE_STRING)\n .map(v => v.value)\n .sort(),\n );\n\n sorted.push(...typeVals.filter(v => v.type === TYPE_BOOLEAN).map(v => v.value));\n sorted.push(...typeVals.filter(v => v.type === TYPE_NULL).map(v => v.value));\n return sorted;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Sort an array using an expression to find the sort key. For each element\n * in the array, the expression is applied and the resulting\n * value is used as the sort value. If the result of\n * evaluating the expression against the current array element results in type\n * other than a number or a string, a <<_errors, TypeError>> will occur.\n * @param {array} elements Array to be sorted\n * @param {expression} expr The comparison expression\n * @return {array} The sorted array\n * @function sortBy\n * @example\n * // returns [\"e\", \"def\", \"abcd\"]\n * sortBy([\"abcd\", \"e\", \"def\"], &length(@))\n *\n * // returns [{year: 1910}, {year: 2010}, {year: 2020}]\n * sortBy([{year: 2010}, {year: 2020}, {year: 1910}], &year)\n *\n * // returns [5, -10, -11, -15, 30]\n * sortBy([-15, 30, -10, -11, 5], &abs(@))\n */\n sortBy: {\n _func: resolvedArgs => {\n const sortedArray = resolvedArgs[0].slice(0);\n if (sortedArray.length === 0) {\n return sortedArray;\n }\n const exprefNode = resolvedArgs[1];\n const requiredType = getType(\n runtime.interpreter.visit(exprefNode, sortedArray[0]),\n );\n if (![TYPE_NUMBER, TYPE_STRING].includes(requiredType)) {\n throw typeError('Bad data type for sortBy()');\n }\n // In order to get a stable sort out of an unstable\n // sort algorithm, we decorate/sort/undecorate (DSU)\n // by creating a new list of [index, element] pairs.\n // In the cmp function, if the evaluated elements are\n // equal, then the index will be used as the tiebreaker.\n // After the decorated list has been sorted, it will be\n // undecorated to extract the original elements.\n const decorated = [];\n for (let i = 0; i < sortedArray.length; i += 1) {\n decorated.push([i, sortedArray[i]]);\n }\n decorated.sort((a, b) => {\n const exprA = runtime.interpreter.visit(exprefNode, a[1]);\n const typeA = getType(exprA);\n const exprB = runtime.interpreter.visit(exprefNode, b[1]);\n const typeB = getType(exprB);\n if (typeA !== requiredType) {\n throw typeError(`sortBy expected ${typeNameTable[requiredType]}, received ${typeNameTable[typeA]}`);\n } else if (typeB !== requiredType) {\n throw typeError(`sortyBy expected ${typeNameTable[requiredType]}, received ${typeNameTable[typeB]}`);\n }\n if (exprA > exprB) return 1;\n if (exprA < exprB) return -1;\n // If they\"re equal compare the items by their\n // order to maintain relative order of equal keys\n // (i.e. to get a stable sort).\n return a[0] - b[0];\n });\n // Undecorate: extract out the original list elements.\n for (let j = 0; j < decorated.length; j += 1) {\n [, sortedArray[j]] = decorated[j];\n }\n return sortedArray;\n },\n _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],\n },\n\n /**\n * Split a string into an array, given a separator\n * @param {string|string[]} string string to split\n * @param {string|string[]} separator separator where the split(s) should occur\n * @return {string[]|string[][]} The array of separated strings\n * @function split\n * @example\n * split(\"abcdef\", \"\") // returns [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]\n * split(\"abcdef\", \"e\") // returns [\"abcd\", \"f\"]\n */\n split: {\n _func: args => evaluate(args, splitFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Find the square root of a number\n * @param {number|number[]} num source number\n * @return {number|number[]} The calculated square root value\n * @function sqrt\n * @example\n * sqrt(4) // returns 2\n */\n sqrt: {\n _func: args => evaluate(args, arg => validNumber(Math.sqrt(arg), 'sqrt')),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Determine if a string starts with a prefix.\n * @param {string|string[]} subject string to search\n * @param {string|string[]} prefix prefix to search for\n * @return {boolean|boolean[]} true if `prefix` matches the start of `subject`\n * @function startsWith\n * @example\n * startsWith(\"jack is at home\", \"jack\") // returns true\n */\n startsWith: {\n _func: args => evaluate(args, startsWithFn),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n /**\n * Estimates standard deviation based on a sample.\n * `stdev` assumes that its arguments are a sample of the entire population.\n * If your data represents a entire population,\n * then compute the standard deviation using [stdevp]{@link stdevp}.\n * Non-numeric values (text, boolean, null etc) are ignored.\n * If there are nested arrays, they are flattened.\n * @param {any[]} values The array containing numbers comprising the population.\n * Array size must be greater than 1.\n * @returns {number} [Standard deviation](https://en.wikipedia.org/wiki/Standard_deviation)\n * @function stdev\n * @example\n * stdev([1345, 1301, 1368]) // returns 34.044089061098404\n * stdevp([1345, 1301, 1368]) // returns 27.797\n */\n stdev: {\n _func: args => {\n const values = args.flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER);\n\n if (values.length <= 1) throw evaluationError('stdev() must have at least two values');\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const sumSquare = values.reduce((a, b) => a + b * b, 0);\n const result = Math.sqrt((sumSquare - values.length * mean * mean) / (values.length - 1));\n return validNumber(result, 'stdev');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Estimates standard deviation based on a sample.\n * `stdev` assumes that its arguments are a sample of the entire population.\n * If your data represents a entire population,\n * then compute the standard deviation using [stdevpA]{@link stdevpA}.\n * Nested arrays are flattened.\n * Null values are ignored. All other parameters are converted to number.\n * If conversion to number fails, a type error is thrown.\n * @param {number[]} numbers The array of numbers comprising the population.\n * Array size must be greater than 1.\n * @returns {number} [Standard deviation](https://en.wikipedia.org/wiki/Standard_deviation)\n * @function stdevA\n * @example\n * stdevA([1345, \"1301\", 1368]) // returns 34.044089061098404\n * stdevpA([1345, 1301, \"1368\"]) // returns 27.797\n */\n stdevA: {\n _func: args => {\n let values;\n try {\n values = args.flat(Infinity)\n .filter(a => getType(a) !== TYPE_NULL)\n .map(toNumber);\n } catch (_e) {\n throw evaluationError('stdevA() received non-numeric parameters');\n }\n\n if (values.length <= 1) throw evaluationError('stdevA() must have at least two values');\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const sumSquare = values.reduce((a, b) => a + b * b, 0);\n const result = Math.sqrt((sumSquare - values.length * mean * mean) / (values.length - 1));\n return validNumber(result, 'stdevA');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Calculates standard deviation based on the entire population given as arguments.\n * `stdevp` assumes that its arguments are the entire population.\n * If your data represents a sample of the population,\n * then compute the standard deviation using [stdev]{@link stdev}.\n * Non-numeric values (text, boolean, null etc) are ignored.\n * If there are nested arrays, they are flattened.\n * @param {any[]} values The array containing numbers comprising the population.\n * An empty array is not allowed.\n * @returns {number} Calculated standard deviation\n * @function stdevp\n * @example\n * stdevp([1345, 1301, 1368]) // returns 27.797\n * stdev([1345, 1301, 1368]) // returns 34.044\n */\n stdevp: {\n _func: args => {\n const values = args[0]\n .flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER);\n\n if (values.length === 0) throw evaluationError('stdevp() must have at least one value');\n\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const meanSumSquare = values.reduce((a, b) => a + b * b, 0) / values.length;\n const result = Math.sqrt(meanSumSquare - mean * mean);\n return validNumber(result, 'stdevp');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Calculates standard deviation based on the entire population given as arguments.\n * `stdevpA` assumes that its arguments are the entire population.\n * If your data represents a sample of the population,\n * then compute the standard deviation using [stdevA]{@link stdevA}.\n * Nested arrays are flattened.\n * Null values are ignored. All other parameters are converted to number.\n * If conversion to number fails, a type error is thrown.\n * @param {number[]} numbers The array of numbers comprising the population.\n * An empty array is not allowed.\n * @returns {number} Calculated standard deviation\n * @function stdevp\n * @example\n * stdevpA([1345, \"1301\", 1368]) // returns 27.797\n * stdevA([1345, 1301, \"1368\"]) // returns 34.044\n */\n stdevpA: {\n _func: args => {\n const values = args[0]\n .flat(Infinity)\n .filter(a => getType(a) !== TYPE_NULL)\n .map(toNumber);\n\n if (values.length === 0) throw evaluationError('stdevp() must have at least one value');\n\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const meanSumSquare = values.reduce((a, b) => a + b * b, 0) / values.length;\n const result = Math.sqrt(meanSumSquare - mean * mean);\n return validNumber(result, 'stdevp');\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Generates a string from the input `text`,\n * with text `old` replaced by text `new` (when searching from the left).\n * If there is no match, or if `old` has length 0, `text` is returned unchanged.\n * Note that `old` and `new` may have different lengths.\n * @param {string|string[]} text The text for which to substitute code points.\n * @param {string|string[]} old The text to replace.\n * @param {string|string[]} new The text to replace `old` with.\n * If `new` is an empty string, then occurrences of `old` are removed from `text`.\n * @param {integer|integer[]} [which]\n * The zero-based occurrence of `old` text to replace with `new` text.\n * If `which` parameter is omitted, every occurrence of `old` is replaced with `new`.\n * @returns {string|string[]} replaced string\n * @function substitute\n * @example\n * substitute(\"Sales Data\", \"Sales\", \"Cost\") // returns \"Cost Data\"\n * substitute(\"Quarter 1, 2001\", \"1\", \"2\", 1)\" // returns \"Quarter 1, 2002\"\n * substitute(\"Quarter 1, 2011\", \"1\", \"2\", 2)\" // returns \"Quarter 1, 2012\"\n */\n substitute: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n let n;\n if (args.length > 3) {\n if (Array.isArray(args[3])) {\n n = args[3].map(toInteger);\n if (n.find(o => o < 0) !== undefined) throw evaluationError('substitute() which parameter must be greater than or equal to 0');\n } else {\n n = toInteger(args[3]);\n if (n < 0) throw evaluationError('substitute() which parameter must be greater than or equal to 0');\n }\n args[3] = n;\n }\n return evaluate(args, substituteFn);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Calculates the sum of the provided array.\n * An empty array will produce a return value of 0.\n * Any values that are not numbers (null, boolean, strings, objects) will be ignored.\n * If any parameters are arrays, the arrays will be flattened.\n * @param {any[]} collection array of values\n * @return {number} The computed sum\n * @function sum\n * @example\n * sum([1, 2, 3]) // returns 6\n */\n sum: {\n _func: resolvedArgs => {\n let sum = 0;\n resolvedArgs[0]\n .flat(Infinity)\n .filter(a => getType(a) === TYPE_NUMBER)\n .forEach(arg => {\n sum += arg * 1;\n });\n\n return sum;\n },\n _signature: [{ types: [TYPE_ARRAY] }],\n },\n\n /**\n * Computes the tangent of a number in radians\n * @param {number|number[]} angle A number representing an angle in radians.\n * @return {number|number[]} The tangent of `angle`\n * @function tan\n * @example\n * tan(0) // 0\n * tan(1) // 1.5574077246549023\n */\n tan: {\n _func: args => evaluate(args, Math.tan),\n _signature: [{ types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] }],\n },\n\n /**\n * Construct and returns a <<_date_and_time_values, time value>>.\n * If any of the units are greater or less than their normal range,\n * the overflow/underflow will be added/subtracted from the next greater unit.\n * @param {integer} hours Zero-based integer value between 0 and 23 representing\n * the hour of the day.\n * @param {integer} [minutes=0] Zero-based integer value representing\n * the minute segment of a time.\n * @param {integer} [seconds=0] Zero-based integer value representing the seconds\n * segment of a time.\n * @return {number} Returns a date/time value representing the fraction\n * of the day consumed by the given time\n * @function time\n * @example\n * time(12, 0, 0) | [hour(@), minute(@), second(@)] // returns [12, 0, 0]\n */\n time: {\n _func: args => {\n const hours = toInteger(args[0]);\n const minutes = args.length > 1 ? toInteger(args[1]) : 0;\n const seconds = args.length > 2 ? toInteger(args[2]) : 0;\n // Since time values are interchangeable with date and datetime values, it\"s consistent\n // to create them at the epoch\n const epochTime = new Date(1970, 0, 1, hours, minutes, seconds);\n return getDateNum(epochTime);\n },\n _signature: [\n { types: [TYPE_NUMBER] },\n { types: [TYPE_NUMBER], optional: true },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Converts the provided argument to an array.\n * The conversion happens as per the following rules:\n *\n * * array - Returns the provided value.\n * * number/string/object/boolean/null - Returns a one element array containing the argument.\n * @param {any} arg parameter to turn into an array\n * @return {array} The resulting array\n * @function toArray\n * @example\n * toArray(1) // returns [1]\n * toArray(null()) // returns [`null`]\n */\n toArray: {\n _func: resolvedArgs => (isArrayType(resolvedArgs[0]) ? resolvedArgs[0] : [resolvedArgs[0]]),\n _signature: [{ types: [TYPE_ANY] }],\n },\n\n /**\n * Converts the provided string to a date/time value.\n *\n * @param {string} ISOString An [ISO8601 formatted string]{@link https://www.iso.org/iso-8601-date-and-time-format.html}.\n * (limited to the [RFC 3339]{@link https://www.rfc-editor.org/rfc/rfc3339} profile)\n * If the string does not include a timezone offset (or trailing 'Z'),\n * it will be assumed to be local time\n * @return {number} The resulting <<_date_and_time_values, date/time number>>.\n * If conversion fails, return null.\n * @function toDate\n * @example\n * toDate(\"20231110T130000+04:00\") // returns 19671.375\n * toDate(\"2023-11-10T13:00:00+04:00\") // returns 19671.375\n * toDate(\"20231110\") | year(@) & \"/\" & month(@) // returns \"2023/11\"\n */\n toDate: {\n _func: resolvedArgs => {\n // expand compact notation so that the Date() constructor will\n // accept the value\n const iso = toString(resolvedArgs[0])\n .replace(/(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)/, '$1-$2-$3')\n .replace(/T(\\d\\d)(\\d\\d)(\\d\\d)/, 'T$1:$2:$3');\n const dateparts = iso.split(/[\\D,zZ]+/);\n let d;\n if (dateparts.length <= 3) {\n if (dateparts.length < 3 || dateparts.find(x => x === '') === '') {\n debug.push(`Failed to convert \"${resolvedArgs[0]}\" to a date`);\n return null;\n }\n }\n if (dateparts.length < 7) {\n // no timezone component, so assume local time\n // The date constructor always parses an ISO string as\n // UTC -- with or without a trailing 'z'\n // But if there's no timezone component, it needs to be local time\n\n const range = [99999, 12, 31, 23, 59, 59, 999];\n // check that the date parts are in range\n for (let i = 0; i < dateparts.length; i += 1) {\n if (dateparts[i] > range[i]) {\n debug.push(`Failed to convert \"${resolvedArgs[0]}\" to a date`);\n return null;\n }\n }\n // account for zero-based date month parts\n d = new Date(...dateparts.map((x, i) => (i === 1 ? x - 1 : x * 1)));\n } else {\n d = new Date(iso);\n }\n if (d instanceof Date && Number.isFinite(d.getTime())) return getDateNum(d);\n debug.push(`Failed to convert \"${resolvedArgs[0]}\" to a date`);\n\n return null;\n },\n _signature: [{ types: [TYPE_STRING] }],\n },\n\n /**\n * Returns a <<_date_and_time_values, date/time>> value representing\n * the start of the current day. i.e. midnight\n * @return {number} today at midnight\n * @function today\n */\n today: {\n _func: () => {\n const now = new Date(Date.now());\n // We used to take the floor() to truncate h/m/s from Date.now(), but that would return\n // today at UTC time. We want today in local time.\n // i.e. UTC time could be a day ahead or behind\n // But note that means that the result is not an integer.\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n return getDateNum(today);\n },\n _signature: [],\n },\n\n /**\n * Converts the provided arg to a number.\n * The conversions follow the <<_type_coercion_rules,type coercion rules>> but will also:\n * * Convert non-numeric strings to zero\n * * Convert arrays to arrays of numbers\n *\n * @param {any|any[]} value to convert to number\n * @param {integer|integer[]} [base=10] If the input `arg` is a string,\n * the base to use to convert to number.\n * One of: 2, 8, 10, 16. Defaults to 10.\n * @return {number} The resulting number. If conversion to number fails, return null.\n * @function toNumber\n * @example\n * toNumber(1) // returns 1\n * toNumber(\"10\") // returns 10\n * toNumber({a: 1}) // returns null\n * toNumber(true()) // returns 1\n * toNumber(\"10f\") // returns null\n * toNumber(\"FF\", 16) // returns 255\n */\n toNumber: {\n _func: resolvedArgs => {\n const toNumberFn = (value, base) => {\n const num = valueOf(value);\n if (getType(num) === TYPE_STRING && base !== 10) {\n let digitCheck;\n if (base === 2) digitCheck = /^\\s*(\\+|-)?[01.]+\\s*$/;\n else if (base === 8) digitCheck = /^\\s*(\\+|-)?[0-7.]+\\s*$/;\n else if (base === 16) digitCheck = /^\\s*(\\+|-)?[0-9A-Fa-f.]+\\s*$/;\n else throw evaluationError(`Invalid base: \"${base}\" for toNumber()`);\n\n if (num === '') return 0;\n if (!digitCheck.test(num)) {\n debug.push(`Failed to convert \"${num}\" base \"${base}\" to number`);\n return null;\n }\n const parts = num.split('.').map(p => p.trim());\n\n let decimal = 0;\n if (parts.length > 1) {\n decimal = parseInt(parts[1], base) * base ** -parts[1].length;\n }\n\n const result = parseInt(parts[0], base) + decimal;\n if (parts.length > 2 || Number.isNaN(result)) {\n debug.push(`Failed to convert \"${num}\" base \"${base}\" to number`);\n return null;\n }\n return result;\n }\n try {\n return toNumber(num);\n } catch (e) {\n const errorString = arg => {\n const v = toJSON(arg);\n return v.length > 50 ? `${v.substring(0, 20)} ...` : v;\n };\n\n debug.push(`Failed to convert \"${errorString(num)}\" to number`);\n return null;\n }\n };\n let base = 10;\n if (resolvedArgs.length > 1) {\n base = Array.isArray(resolvedArgs[1])\n ? resolvedArgs.map(toInteger)\n : toInteger(resolvedArgs[1]);\n }\n return evaluate([resolvedArgs[0], base], toNumberFn);\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Returns the argument converted to a string.\n * If the argument is a string, it will be returned unchanged.\n * Otherwise, returns the JSON encoded value of the argument.\n * @param {any} arg Value to be converted to a string\n * @param {integer} [indent=0] Indentation to use when converting\n * objects and arrays to a JSON string\n * @return {string} The result string.\n * @function toString\n * @example\n * toString(1) // returns \"1\"\n * toString(true()) // returns \"true\"\n * toString({sum: 12 + 13}) // \"{\"sum\":25}\"\n * toString(\"hello\") // returns \"hello\"\n */\n toString: {\n _func: resolvedArgs => toJSON(resolvedArgs[0], resolvedArgs.length > 1 ? resolvedArgs[1] : 0),\n _signature: [{ types: [TYPE_ANY] }, { types: [TYPE_NUMBER], optional: true }],\n },\n\n /**\n * Remove leading and trailing spaces (U+0020), and replace all internal multiple spaces\n * with a single space. Note that other whitespace characters are left intact.\n * @param {string|string[]} text string to trim\n * @return {string|string[]} trimmed string\n * @function trim\n * @example\n * trim(\" ab c \") // returns \"ab c\"\n */\n trim: {\n _func: args => evaluate(args, s => toString(s).split(' ').filter(x => x).join(' ')),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Return constant boolean true value.\n * Expressions may also use the JSON literal: `` `true` ``\n * @returns {boolean} True\n * @function true\n */\n true: {\n _func: () => true,\n _signature: [],\n },\n\n /**\n * Truncates a number to an integer by removing the fractional part of the number.\n * i.e. it rounds towards zero.\n * @param {number|number[]} numA number to truncate\n * @param {integer|integer[]} [numB=0]\n * A number specifying the number of decimal digits to preserve.\n * @return {number|number[]} Truncated value\n * @function trunc\n * @example\n * trunc(8.9) // returns 8\n * trunc(-8.9) // returns -8\n * trunc(8.912, 2) // returns 8.91\n */\n trunc: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2) args.push(0);\n return evaluate(args, truncFn);\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER], optional: true },\n ],\n },\n\n /**\n * Finds the type name of the given `subject` argument as a string value.\n * The return value will be one of the following:\n *\n * * number\n * * string\n * * boolean\n * * array\n * * object\n * * null\n * @param {any} subject type to evaluate\n * @return {string} The type name\n *\n * @function type\n * @example\n * type(1) // returns \"number\"\n * type(\"\") // returns \"string\"\n */\n type: {\n _func: resolvedArgs => ({\n [TYPE_NUMBER]: 'number',\n [TYPE_STRING]: 'string',\n [TYPE_ARRAY]: 'array',\n [TYPE_ARRAY_NUMBER]: 'array',\n [TYPE_ARRAY_STRING]: 'array',\n [TYPE_ARRAY_ARRAY]: 'array',\n [TYPE_OBJECT]: 'object',\n [TYPE_BOOLEAN]: 'boolean',\n [TYPE_EXPREF]: 'expref',\n [TYPE_NULL]: 'null',\n }[getType(resolvedArgs[0])]),\n _signature: [{ types: [TYPE_ANY] }],\n },\n\n /**\n * Find the set of unique elements within an array\n * @param {array} input input array\n * @return {array} array with duplicate elements removed\n * @function unique\n * @example\n * unique([1, 2, 3, 4, 1, 1, 2]) // returns [1, 2, 3, 4]\n */\n unique: {\n _func: args => {\n // create an array of values for searching. That way if the array elements are\n // represented by class objects with a valueOf(), we'll locate them in the valueArray\n // but return the original class object.\n const valueArray = args[0].map(a => valueOf(a));\n return args[0]\n .filter(\n (v, index) => valueArray.findIndex(\n lookup => strictDeepEqual(lookup, valueOf(v)),\n ) === index,\n );\n },\n _signature: [\n { types: [TYPE_ARRAY] },\n ],\n },\n\n /**\n * Converts all the alphabetic code points in a string to uppercase.\n * @param {string|string[]} input input string\n * @returns {string|string[]} the upper case value of the input string\n * @function upper\n * @example\n * upper(\"abcd\") // returns \"ABCD\"\n */\n upper: {\n _func: args => evaluate(args, a => toString(a).toUpperCase()),\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n ],\n },\n\n /**\n * Perform an indexed lookup on an object or array\n * @param {object | array | null} subject on which to perform the lookup.\n * When querying for <<_hidden_properties,hidden properties>>, `subject` may be any data type.\n * @param {string | integer} index if `subject` is an object, `index` must be a string\n * indicating the key name to search for.\n * If `subject` is an array, then index must be an integer indicating the offset into the array\n * @returns {any} the result of the lookup -- or `null` if not found.\n * @function value\n * @example\n * value({a: 1, b:2, c:3}, \"a\") // returns 1\n * value([1, 2, 3, 4], 2) // returns 3\n */\n value: {\n _func: args => {\n const indexType = getType(args[1]);\n let index = args[1];\n const subjectArray = isArrayType(args[0]);\n // if the object/array has a getter for this property then don't validate types\n // just return the value.\n if (args[0] !== null && Object.getOwnPropertyDescriptor(args[0], index)?.get) {\n return getProperty(args[0], index);\n }\n const obj = valueOf(args[0]);\n if (obj === null) return null;\n if (!(getType(obj) === TYPE_OBJECT || subjectArray)) {\n throw typeError('First parameter to value() must be one of: object, array, null.');\n }\n if (subjectArray) {\n if (indexType !== TYPE_NUMBER) throw typeError('value() requires an integer index for arrays');\n index = toInteger(index);\n } else if (indexType !== TYPE_STRING) {\n throw typeError('value() requires a string index for objects');\n }\n const result = getProperty(args[0], index);\n if (result === undefined) {\n if (subjectArray) {\n debug.push(\n `Index: ${index} out of range for array size: ${obj.length}`,\n );\n } else debugAvailable(debug, obj, index);\n return null;\n }\n return result;\n },\n _signature: [\n { types: [TYPE_ANY] },\n { types: [TYPE_STRING, TYPE_NUMBER] },\n ],\n },\n\n /**\n * Generates an array of the values of the provided object.\n * Note that because JSON objects are\n * inherently unordered, the values associated with the provided object are\n * also unordered.\n * @param {object} obj source object\n * @return {array} array of the values\n * @function values\n * @example\n * values({a : 3, b : 4}) // returns [3, 4]\n */\n values: {\n _func: resolvedArgs => Object.values(resolvedArgs[0]),\n _signature: [{ types: [TYPE_OBJECT] }],\n },\n\n /**\n * Extract the day of the week from a date.\n * The specific numbering of the day of week is controlled by the `returnType` parameter:\n *\n * * 1 : Sunday (1), Monday (2), ..., Saturday (7)\n * * 2 : Monday (1), Tuesday (2), ..., Sunday(7)\n * * 3 : Monday (0), Tuesday (1), ...., Sunday(6)\n * @param {number|number[]} date <<_date_and_time_values, date/time value>> for\n * which the day of the week is to be returned.\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @param {integer|integer[]} [returnType=1] Determines the\n * representation of the result.\n * An unrecognized returnType will result in a error.\n * @returns {integer|integer[]} day of the week\n * @function weekday\n * @example\n * weekday(datetime(2006,5,21)) // 1\n * weekday(datetime(2006,5,21), 2) // 7\n * weekday(datetime(2006,5,21), 3) // 6\n */\n weekday: {\n _func: resolvedArgs => {\n const args = resolvedArgs.slice();\n if (args.length < 2) args.push(1);\n return evaluate(args, weekdayFn);\n },\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n { types: [TYPE_NUMBER], optional: true },\n ],\n },\n\n /**\n * Finds the year of a datetime value\n * @param {number|number[]} date input <<_date_and_time_values, date/time value>>\n * Date/time values can be generated using the\n * [datetime]{@link datetime}, [toDate]{@link todate}, [today]{@link today}, [now]{@link now}\n * and [time]{@link time} functions.\n * @return {integer|integer[]} The year value\n * @function year\n * @example\n * year(datetime(2008,5,23)) // returns 2008\n */\n year: {\n _func: args => evaluate(args, a => getDateObj(a).getFullYear()),\n _signature: [\n { types: [TYPE_NUMBER, TYPE_ARRAY_NUMBER] },\n ],\n },\n\n /**\n * Generates a convolved (zipped) array containing grouped arrays of values from\n * the array arguments from index 0, 1, 2, etc.\n * This function accepts a variable number of arguments.\n * The length of the returned array is equal to the length of the shortest array.\n * @param {...array} arrays array of arrays to zip together\n * @return {array} An array of arrays with elements zipped together\n * @function zip\n * @example\n * zip([1, 2, 3], [4, 5, 6, 7]) // returns [[1, 4], [2, 5], [3, 6]]\n */\n zip: {\n _func: args => {\n const count = args.reduce((min, current) => Math.min(min, current.length), args[0].length);\n const result = new Array(count);\n for (let i = 0; i < count; i += 1) {\n result[i] = [];\n args.forEach(a => {\n result[i].push(a[i]);\n });\n }\n return result;\n },\n _signature: [{ types: [TYPE_ARRAY], variadic: true }],\n },\n };\n return functionMap;\n}\n","/*\nCopyright 2014 James Saryerwinnie\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable max-classes-per-file */\n/* eslint-disable no-underscore-dangle */\nimport TreeInterpreter from './TreeInterpreter.js';\nimport Parser from './Parser.js';\nimport { dataTypes } from './dataTypes.js';\nimport { matchType, getType, isArrayType } from './matchType.js';\nimport functions from './functions.js';\nimport {\n isObject, strictDeepEqual, getValueOf,\n} from './utils.js';\nimport {\n evaluationError, typeError, functionError,\n} from './errors.js';\n\n// Type constants used to define functions.\nconst { TYPE_OBJECT } = dataTypes;\n\nfunction getToNumber(stringToNumber) {\n return value => {\n const n = getValueOf(value); // in case it's an object that implements valueOf()\n if (n === null) return 0;\n if (n instanceof Array) {\n throw typeError('Failed to convert array to number');\n }\n const type = typeof n;\n if (type === 'number') return n;\n if (type === 'string') return stringToNumber(n);\n if (type === 'boolean') return n ? 1 : 0;\n throw typeError('Failed to convert object to number');\n };\n}\nfunction toString(a) {\n if (a === null || a === undefined) return '';\n const type = getType(a);\n if (isArrayType(type)) {\n throw typeError('Failed to convert array to string');\n }\n if (type === TYPE_OBJECT) {\n throw typeError('Failed to convert object to string');\n }\n return a.toString();\n}\n\nconst defaultStringToNumber = (str => {\n const n = +str;\n return Number.isNaN(n) ? 0 : n;\n});\n\nclass Runtime {\n constructor(debug, toNumber, customFunctions = {}) {\n this.strictDeepEqual = strictDeepEqual;\n this.toNumber = toNumber;\n this.functionTable = functions(\n this,\n isObject,\n toNumber,\n getType,\n isArrayType,\n getValueOf,\n toString,\n debug,\n );\n\n Object.entries(customFunctions).forEach(([fname, func]) => {\n // Provide the runtime to custom functions so that\n // they can implement lambda functions\n // eslint-disable-next-line no-param-reassign\n func._runtime = this;\n this.functionTable[fname] = func;\n });\n }\n\n // eslint-disable-next-line class-methods-use-this\n _validateArgs(argName, args, signature, bResolved) {\n // Validating the args requires validating\n // the correct arity and the correct type of each arg.\n // If the last argument is declared as variadic, then we need\n // a minimum number of args to be required. Otherwise it has to\n // be an exact amount.\n if (signature.length === 0 && args.length > 0) {\n throw functionError(`${argName}() does not accept parameters`);\n }\n\n if (signature.length === 0) {\n return;\n }\n let pluralized;\n const argsNeeded = signature.filter(arg => !arg.optional).length;\n const lastArg = signature[signature.length - 1];\n if (lastArg.variadic) {\n if (args.length < signature.length && !lastArg.optional) {\n pluralized = signature.length === 1 ? ' argument' : ' arguments';\n throw functionError(`${argName}() takes at least ${signature.length}${pluralized\n } but received ${args.length}`);\n }\n } else if (args.length < argsNeeded || args.length > signature.length) {\n pluralized = signature.length === 1 ? ' argument' : ' arguments';\n throw functionError(`${argName}() takes ${signature.length}${pluralized\n } but received ${args.length}`);\n }\n // if the arguments are unresolved, there's no point in validating types\n if (!bResolved) return;\n let currentSpec;\n const limit = signature[signature.length - 1].variadic ? args.length\n : Math.min(signature.length, args.length);\n\n for (let i = 0; i < limit; i += 1) {\n currentSpec = i > signature.length - 1 ? signature[signature.length - 1].types\n : signature[i].types;\n // eslint-disable-next-line no-param-reassign\n args[i] = matchType(currentSpec, args[i], argName, this.toNumber, toString);\n }\n }\n\n callFunction(name, resolvedArgs, data, interpreter, bResolved = true) {\n // this check will weed out 'valueOf', 'toString' etc\n if (!Object.prototype.hasOwnProperty.call(this.functionTable, name)) {\n throw functionError(`No such function: ${name}()`);\n }\n\n const functionEntry = this.functionTable[name];\n this._validateArgs(name, resolvedArgs, functionEntry._signature, bResolved);\n return functionEntry._func.call(this, resolvedArgs, data, interpreter);\n }\n}\n\nexport default class Formula {\n constructor(debug, customFunctions, stringToNumberFn) {\n this.debug = debug;\n this.toNumber = getToNumber(stringToNumberFn || defaultStringToNumber);\n this.runtime = new Runtime(debug, this.toNumber, customFunctions);\n }\n\n compile(stream, allowedGlobalNames = []) {\n const parser = new Parser(allowedGlobalNames);\n return parser.parse(stream, this.debug);\n }\n\n search(node, data, globals = {}, language = 'en-US') {\n // This needs to be improved. Both the interpreter and runtime depend on\n // each other. The runtime needs the interpreter to support exprefs.\n // There's likely a clean way to avoid the cyclic dependency.\n this.runtime.interpreter = new TreeInterpreter(\n this.runtime,\n globals,\n this.toNumber,\n toString,\n this.debug,\n language,\n );\n\n try {\n return this.runtime.interpreter.search(node, data);\n } catch (e) {\n this.debug.push(e.message || e.toString());\n if (e.name === 'Error') throw evaluationError(e.message || e.toString());\n throw e;\n }\n }\n}\n","/*\nCopyright 2021 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport Formula from './interpreter.js';\n\n// data type constants re-exported from dataTypes.js\n// which represent the various data types supported by json-formula function params\nexport { dataTypes } from './dataTypes.js';\n/**\n@enum {Number}\n // Type constants used to define functions.\n const dataTypes = {\n TYPE_NUMBER: 0,\n TYPE_ANY: 1,\n TYPE_STRING: 2,\n TYPE_ARRAY: 3,\n TYPE_OBJECT: 4,\n TYPE_BOOLEAN: 5,\n TYPE_EXPREF: 6,\n TYPE_NULL: 7,\n TYPE_ARRAY_NUMBER: 8,\n TYPE_ARRAY_STRING: 9,\n TYPE_ARRAY_ARRAY: 10,\n TYPE_EMPTY_ARRAY: 11,\n };\n */\n\n/**\n * @typedef {object} CustomFunctionDefinition\n * @property {Function} _func - The function implementation\n * @property {array} [_signature] - Function signature metadata\n * @example\n // simple custom functions definition\n const customFunctions = {\n true_fn: {\n _func: () => true,\n _signature: [],\n },\n false_fn: {\n _func: () => false,\n _signature: [],\n },\n };\n @example\n // custom function with a signature for its parameters\n const customFunctions = {\n padEnd: {\n _func: args => {\n const src = args[0];\n const length = args[1];\n const padChar = args[2];\n if (Array.isArray(src)) return src.map(s => s.padEnd(length, padChar));\n return src.padEnd(length, padChar);\n },\n _signature: [\n { types: [TYPE_STRING, TYPE_ARRAY_STRING] },\n { types: [TYPE_NUMBER] },\n { types: [TYPE_STRING] },\n ],\n }\n }\n // May also register functions is via the `register()` or `registerWithParams()` methods. e.g.\n\n const regFormula = `${register(\"${fn_name}\", &${code})`;\n // Run the registration formula after which, the registered function may be called\n this.search(regFormula, {});\n*/\n\n/**\n * Class represents an instance of a JsonFormula Expression that can be executed later on with\n * multiple instances of JSON Data. The instance of the class has a search\n * function that can be used to evaluate the expression on a json payload.\n */\nclass JsonFormula {\n /**\n * @param {object} [customFunctions={}] custom functions needed by a hosting application.\n * @param {function} [stringToNumber='null'] A function that converts string values to numbers.\n * Can be used to convert currencies/dates to numbers\n * @param {array} [debug=[]] will be populated with any errors/warnings\n */\n constructor(\n customFunctions = {},\n stringToNumber = null,\n debug = [],\n ) {\n this.customFunctions = { ...customFunctions };\n this.stringToNumber = stringToNumber;\n this.debug = debug;\n this.formula = new Formula(debug, customFunctions, stringToNumber);\n }\n\n /**\n * @typedef {object} globals\n * An object where each key **MUST** begin with a `$` character, representing global variables\n * that can be accessed inside a json-formula expression.\n * The value of each key can be of any data type supported by json.\n *\n * @example\n * const globals = {\n * $num: 42,\n * $arr: [1, 2, 3],\n * $days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\n * };\n * jsonFormula({}, globals, '$arr * $num') // returns [42, 84, 126]\n */\n\n /**\n * Evaluates the JsonFormula on a particular json payload and return the result\n * @param {string} expression the json-formula expression to evaluate\n * @param {object|array} json the json data on which the expression needs to be evaluated\n * @param {object} [globals={}] global objects that can be accessed via custom functions.\n * @param {string} [language=en-US] BCP-47 language tag\n * @returns {*} the result of the expression being evaluated\n * @example\n * const jf = new JsonFormula();\n * const result = jf.search('toDate(d) | day(@) & \"/\" & month(@)', {d: \"2025-11-12\"});\n * // returns \"12/11\"\n */\n search(expression, json, globals = {}, language = 'en-US') {\n const ast = this.compile(expression, Object.keys(globals));\n return this.run(ast, json, language, globals);\n }\n\n /**\n * Execute a previously compiled expression against a json object and return the result.\n * Use this method for better performance when you will evaluate the same expression\n * multiple times with different data.\n * @param {object} ast The abstract syntax tree returned from compile()\n * @param {object|array} json the json data on which the expression needs to be evaluated\n * @param {string} [language=en-US] BCP-47 language tag\n * @param globals {*} set of objects available in global scope\n * @returns {*} the result of the expression being evaluated\n * @example\n * const globals = {\n * $days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\n * };\n * const jf = new JsonFormula();\n * const ast = jf.compile('value($days, num)', ['$days']); // compile the expression once\n * const result1 = jf.run(ast, {num: 2}, 'en-US', globals); // returns \"Wed\"\n * const result2 = jf.run(ast, {num: 3}, 'en-US', globals); // returns \"Thu\"\n */\n run(ast, json, language, globals) {\n return this.formula.search(\n ast,\n json,\n globals,\n language,\n );\n }\n\n /**\n * Creates a compiled expression that can be executed later on with some data.\n * @param {string} expression the expression to evaluate\n * @param {string[]} [allowedGlobalNames=[]] An array of names of the global variables\n * being used in the expression.\n */\n compile(expression, allowedGlobalNames = []) {\n this.debug.length = 0;\n return this.formula.compile(expression, allowedGlobalNames);\n }\n}\n\n/**\n * Compile and execute a json-formula expression.\n * If executing the same expression multiple times, it is more efficient to create a\n * class instance of JsonFormula and call the search() method or the compile()/run() methods\n * multiple times.\n* @param {object|array} json the json data on which the expression needs to be evaluated\n* @param {object} globals global objects that can be accessed via custom functions.\n* @param {string} expression the expression to evaluate\n* @param {object} [customFunctions={}] custom functions needed by a hosting application.\n* @param {function} [stringToNumber='null'] A function that converts string values to numbers.\n* Can be used to convert currencies/dates to numbers\n* @param {string} [language=en-US]\n* @param {array} [debug=[]] will be populated with any errors/warnings\n* @returns {*} the result of the expression being evaluated\n */\n\nexport function jsonFormula(\n json,\n globals,\n expression,\n customFunctions = {},\n stringToNumber = null,\n debug = [],\n language = 'en-US',\n) {\n return new JsonFormula(customFunctions, stringToNumber, debug)\n .search(expression, json, globals, language);\n}\n\nexport default JsonFormula;\n","/*\nCopyright 2021 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint-disable no-param-reassign */\n/* eslint-disable max-classes-per-file */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable no-underscore-dangle */\n/*\n Field class allows objects to evaluate correctly according to context.\n - if used in an expression, will return a value or string.\n - for JSON.stringify() returns a scalar\n - BUT also allows explicit access to properties. e.g. field.required, field.name etc.\n\n Should allow us to eliminate getFieldProperty()\n */\nclass ArrayClass extends Array {}\nclass ObjectClass {}\n\nfunction createField(name, value, readonly = false, required = true) {\n class Field extends ObjectClass {\n valueOf() { return value; }\n\n toString() { return value.toString(); }\n\n toJSON() { return value; }\n }\n const f = new Field();\n Object.defineProperty(f, '$name', { get: () => name });\n Object.defineProperty(f, '$value', { get: () => value });\n Object.defineProperty(f, '$readonly', { get: () => readonly });\n Object.defineProperty(f, '$required', { get: () => required });\n\n return f;\n}\n\nfunction createFieldset(fsname, isObj, fields, children) {\n class FieldsetObj extends ObjectClass {\n _add(k, v) {\n this[k] = v;\n children.push(v);\n }\n }\n class FieldsetArray extends ArrayClass {\n _add(k, v) {\n this[k] = v;\n children.push(v);\n }\n }\n const fieldset = isObj ? new FieldsetObj() : new FieldsetArray();\n Object.defineProperty(fieldset, '$name', { get: () => fsname });\n Object.defineProperty(fieldset, '$fields', { get: () => fields });\n Object.defineProperty(fieldset, '$value', { get: () => fieldset.valueOf() });\n\n return fieldset;\n}\n\nfunction createFields(parent, childref, child) {\n const result = [];\n if (child instanceof Array) {\n // parent._add(childref, createFieldset(childref, false));\n parent._add(childref, createFieldset(childref, false, result, []));\n child.forEach((item, index) => {\n const fields = createFields(parent[childref], index, item);\n result.push(...fields);\n });\n } else if (child !== null && typeof child === 'object') {\n parent._add(childref, createFieldset(childref, true, result, []));\n Object.keys(child).forEach(k => {\n const fields = createFields(parent[childref], k, child[k]);\n result.push(...fields);\n });\n } else {\n const field = createField(childref, child);\n parent._add(childref, field);\n result.push(field);\n }\n return result;\n}\n\nexport default function createForm(dataRoot) {\n // if it's not an object or array (a scalar) then don't bother trying to create a form\n if (dataRoot === null || typeof dataRoot !== 'object') return dataRoot;\n\n const allFields = [];\n const form = createFieldset('', !Array.isArray(dataRoot), allFields, []);\n Object.entries(dataRoot).forEach(([k, v]) => {\n allFields.push(...createFields(form, k, v));\n });\n return form;\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport { typeError } from './errors.js';\n\nexport default function stringToNumber(n) {\n if (!/^\\s*(-|\\+)?(\\d*)(\\.\\d+)?(e(\\+|-)?\\d+)?\\s*$/i.test(n)) throw typeError(`Failed to convert \"${n}\" to number`);\n const ret = +n;\n if (Number.isNaN(ret)) {\n throw typeError(`Failed to convert \"${n}\" to number`);\n }\n return ret;\n}\n","/*\nCopyright 2021 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* global window, document */\nimport Formula from '../src/json-formula.js';\nimport createForm from './Form.js';\nimport stringToNumber from '../src/stringToNumber.js';\n\nwindow.addEventListener('load', () => {\n const dataElement = document.getElementById('data');\n const expression = document.getElementById('expression');\n const result = document.getElementById('result');\n const debug = document.getElementById('debug');\n const debugInfo = [];\n // keep one instance active for the entire session so that any registered\n // functions are retained\n const formula = new Formula({}, stringToNumber, debugInfo);\n const defaultData = `{\n \"address\": {\n \"street\": \"12 Oak St\",\n \"city\": \"San Jose\",\n \"state\": \"CA\",\n \"country\": \"USA\",\n \"phone\": \"1234561234\"\n },\n \"items\": [\n {\n \"desc\": \"pens\",\n \"quantity\": 2,\n \"price\": 3.23\n },\n {\n \"desc\": \"pencils\",\n \"quantity\": 3,\n \"price\": 1.34\n }\n ],\n \"tax\": 1.13\n }`;\n\n const params = new URLSearchParams(document.location.search);\n if (params.has('sample')) {\n const sampleJSON = JSON.parse(atob(params.get('sample')));\n if (sampleJSON.data) dataElement.value = JSON.stringify(sampleJSON.data, null, 2);\n if (sampleJSON.expression) expression.value = sampleJSON.expression;\n if (sampleJSON.description) {\n document.getElementById('description-row').style.display = 'table-row';\n document.getElementById('description').innerText = sampleJSON.description;\n }\n Array.from(document.getElementsByClassName('controls')).forEach(c => c.classList.add('hidden'));\n } else {\n const d = window.localStorage.getItem('data');\n if (d) dataElement.value = d;\n else dataElement.value = defaultData;\n const exp = window.localStorage.getItem('expression');\n if (exp) expression.value = exp;\n else expression.value = 'sum(items[*].price * items[*].quantity)';\n }\n\n function run() {\n // save for next time...\n window.localStorage.setItem('data', dataElement.value);\n window.localStorage.setItem('expression', expression.value);\n const input = expression.value;\n const useFields = document.getElementById('use-fields').checked;\n let jsonData;\n try {\n jsonData = JSON.parse(dataElement.value);\n if (useFields) {\n jsonData = createForm(jsonData);\n }\n } catch (e) {\n result.value = e.toString();\n return;\n }\n\n try {\n const jsonResult = formula.search(input, jsonData, {});\n debug.innerHTML = debugInfo.join('\\n');\n let r = jsonResult;\n if (jsonResult !== null && jsonResult !== undefined) {\n r = jsonResult.valueOf.call(jsonResult);\n }\n if (typeof r === 'object') {\n result.value = JSON.stringify(r, null, 2);\n } else {\n result.value = r;\n }\n } catch (e) {\n result.value = e.toString();\n debug.innerHTML = debugInfo.join('\\n');\n }\n }\n\n dataElement.addEventListener('blur', run);\n expression.addEventListener('blur', run);\n document.getElementById('data-reset').addEventListener(\n 'click',\n () => {\n dataElement.value = defaultData;\n if (params.has('sample')) {\n expression.value = 'sum(items[*].price * items[*].quantity)';\n document.getElementById('description-row').style.display = 'none';\n Array.from(document.getElementsByClassName('controls')).forEach(c => c.classList.remove('hidden'));\n window.history.pushState({}, document.title, '/');\n run();\n }\n },\n );\n document.getElementById('canned').addEventListener('change', e => {\n expression.value = e.target.value;\n run();\n });\n run();\n\n fetch('../antlr/JsonFormula.g4').then(r => {\n r.text().then(g4 => {\n // remove comments and processing directives.\n const strippedGrammar = g4\n .replace(/[\\s\\S.]*grammar/m, 'grammar')\n .replace(/#.*/g, '');\n document.getElementById('grammar-out').innerHTML = strippedGrammar;\n });\n });\n});\n"],"names":["__webpack_require__","exports","Symbol","toStringTag","Object","defineProperty","value","dataTypes","TYPE_NUMBER","TYPE_ANY","TYPE_STRING","TYPE_ARRAY","TYPE_OBJECT","TYPE_BOOLEAN","TYPE_EXPREF","TYPE_NULL","TYPE_ARRAY_NUMBER","TYPE_ARRAY_STRING","TYPE_ARRAY_ARRAY","TYPE_EMPTY_ARRAY","typeNameTable","TOK_EOF","TOK_IDENTIFIER","TOK_QUOTEDIDENTIFIER","TOK_RBRACKET","TOK_RPAREN","TOK_COMMA","TOK_COLON","TOK_CONCATENATE","TOK_RBRACE","TOK_NUMBER","TOK_CURRENT","TOK_GLOBAL","TOK_EXPREF","TOK_PIPE","TOK_OR","TOK_AND","TOK_ADD","TOK_SUBTRACT","TOK_UNARY_MINUS","TOK_MULTIPLY","TOK_UNION","TOK_DIVIDE","TOK_COMPARATOR","TOK_FLATTEN","TOK_STAR","TOK_FILTER","TOK_DOT","TOK_NOT","TOK_LBRACE","TOK_LBRACKET","TOK_LPAREN","TOK_JSON","TOK_STRING","TOK_INT","typeError","desc","TypeError","syntaxError","e","Error","name","functionError","evaluationError","tokenDefinitions","isArray","t","includes","getType","inputObj","simpleType","obj","Array","length","flat","Infinity","every","a","jmespathType","type","JSON","parse","stringify","isArrayType","getTypeName","arg","matchType","expectedList","argValue","context","toNumber","toString","actual","isObject","some","match","expect","found","filteredList","filter","supportedConversion","to","exactMatch","expected","wrongType","map","join","keys","toArray","coerceString","coerceNumber","prototype","call","getValueOf","i","valueOf","toBoolean","param","val","strictDeepEqual","lhs","rhs","first","second","f","key","hasOwnProperty","getProperty","getOwnPropertyDescriptor","enumerable","get","for","debugAvailable","debug","chainStart","available","push","entries","getOwnPropertyDescriptors","k","test","startsWith","balanceArrayOperands","opLeft","opRight","shorter","diff","Math","abs","fill","TreeInterpreter","constructor","runtime","globals","language","this","visitFunctions","initVisitFunctions","debugChainStart","search","node","visit","field","undefined","Identifier","bind","QuotedIdentifier","ChainedExpression","result","children","BracketExpression","left","Index","index","Slice","sliceParams","start","stop","step","computeSliceParams","Projection","base","collected","forEach","b","current","ValueProjection","projection","values","FilterProjection","filtered","finalResults","Comparator","type1","type2","_e","original","merged","Identity","_node","ArrayExpression","child","ObjectExpression","OrExpression","matched","AndExpression","AddExpression","applyOperator","ConcatenateExpression","UnionExpression","concat","SubtractExpression","MultiplyExpression","DivideExpression","NotExpression","UnaryMinusExpression","minus","Number","isNaN","String","Literal","Integer","Function","callFunction","resolvedArgs","ExpressionReference","refNode","n","v","arrayLength","capSliceRange","arrayLen","stp","actualValue","stepValueNegative","operator","n1","n2","isFinite","basicTokens","operatorStartToken","skipChars","isAlphaNum","ch","isIdentifier","stream","pos","Lexer","allowedGlobalNames","_allowedGlobalNames","tokenize","tokens","identifier","token","_current","prev","slice","_isGlobal","_consumeGlobal","_consumeUnquotedIdentifier","_isNumber","_consumeNumber","_consumeLBracket","_consumeQuotedIdentifier","_consumeRawStringLiteral","json","_consumeJson","_consumeOperator","_consumeUnaryMinus","maxLength","foundNonAlpha","replace","substring","literal","num","toLowerCase","parseFloat","parseInt","global","startingChar","literalString","trimStart","replaceAll","bindingPower","Parser","expression","_loadTokens","ast","_lookahead","_lookaheadToken","rbp","leftToken","_advance","nud","currentToken","led","number","previous","next","_lookAheadIndex","idx","_getIndex","_setIndex","right","args","Not","UnaryMinus","_parseProjectionRHS","Star","_parseObjectExpression","Flatten","_parseIndexExpression","_projectIfSlice","_parseArrayExpression","Expref","_match","_errorToken","condition","leftNode","rightNode","Concatenate","Dot","_parseDotRHS","Pipe","Or","And","Add","Subtract","Multiply","Divide","Union","_parseFunctionArgs","Filter","_parseComparator","tokenType","firstExpression","_parseSignedInt","oldIndex","_parseSliceExpression","indexExpr","parts","comparator","lookahead","indexOf","expressions","pairs","identifierTypes","keyToken","keyName","MS_IN_DAY","getDateObj","dateNum","Date","round","getDateNum","dateObj","validNumber","defaultStringToNumber","str","Runtime","customFunctions","functionTable","toInteger","trunc","toJSON","indent","offset","evaluate","fn","listOfArrays","maxLen","max","allArrays","arrays","row","j","balanceArrays","datedifFn","date1Arg","date2Arg","unitArg","unit","date1","date2","floor","yearDiff","getFullYear","monthDiff","getMonth","dayDiff","getDate","y","setFullYear","endsWithFn","searchArg","suffixArg","searchStr","suffix","from","reverse","c","eomonthFn","dateArg","monthsArg","jsDate","months","findFn","queryArg","textArg","offsetArg","query","text","properFn","capitalize","word","charAt","toUpperCase","wordParts","w","reptFn","countArg","count","repeat","searchFn","findTextString","withinTextString","startPosInt","findText","withinText","startPos","globString","reduce","acc","cur","escape","pop","testMatch","array","glob","testChar","globChar","nextGlob","isStar","within","splitFn","strArg","separatorArg","separator","split","startsWithFn","subjectString","prefixString","subject","prefix","substituteFn","source","oldString","replacementString","nearest","src","old","replacement","whch","truncFn","d","digits","ceil","weekdayFn","date","day","getDay","functionMap","_func","_signature","types","acos","and","variadic","asin","atan2","avg","sum","avgA","casefold","_data","interpreter","s","toLocaleUpperCase","toLocaleLowerCase","codePoint","codePointAt","contains","searchLen","cos","datedif","datetime","year","month","hours","minutes","seconds","ms","optional","deepScan","checkArrays","items","scan","endsWith","eomonth","exp","false","find","fromCodePoint","points","fromEntries","fround","hasProperty","keyType","hour","getHours","if","unresolvedArgs","data","conditionNode","leftBranchNode","rightBranchNode","listJoin","joinChar","numEntries","log","log10","lower","exprefNode","maxA","merge","mid","millisecond","getMilliseconds","min","minA","minute","getMinutes","mod","not","resolveArgs","notNull","now","null","or","power","proper","random","accumulated","register","functionName","_exprefNode","registerWithParams","numElements","sourceArray","splice","newText","rept","originalStr","precision","getSeconds","sign","sin","sort","typeVals","sorted","sortFunction","sortBy","sortedArray","requiredType","decorated","exprA","typeA","exprB","typeB","sqrt","stdev","mean","sumSquare","stdevA","stdevp","meanSumSquare","stdevpA","substitute","o","tan","time","toDate","iso","dateparts","x","range","getTime","today","toNumberFn","digitCheck","p","trim","decimal","errorString","true","unique","valueArray","findIndex","lookup","upper","indexType","subjectArray","weekday","zip","functions","fname","func","_runtime","_validateArgs","argName","signature","bResolved","pluralized","argsNeeded","lastArg","currentSpec","limit","functionEntry","Formula","stringToNumberFn","stringToNumber","getToNumber","compile","message","formula","run","ArrayClass","ObjectClass","createFieldset","fsname","isObj","fields","fieldset","_add","createFields","parent","childref","item","readonly","required","createField","ret","window","addEventListener","dataElement","document","getElementById","debugInfo","defaultData","params","URLSearchParams","location","has","sampleJSON","atob","description","style","display","innerText","getElementsByClassName","classList","add","localStorage","getItem","setItem","input","useFields","checked","jsonData","dataRoot","allFields","form","createForm","jsonResult","innerHTML","r","remove","history","pushState","title","target","fetch","then","g4","strippedGrammar"],"sourceRoot":""} \ No newline at end of file diff --git a/doc/output/JSDOCS.md b/doc/output/JSDOCS.md index f895c3dd..b4847781 100644 --- a/doc/output/JSDOCS.md +++ b/doc/output/JSDOCS.md @@ -8,25 +8,24 @@ function that can be used to evaluate the expression on a json payload. **Kind**: global class * [JsonFormula](#JsonFormula) - * [new JsonFormula([customFunctions], [stringToNumber], [language], [debug])](#new_JsonFormula_new) - * [.search(json, [globals])](#JsonFormula+search) ⇒ \* - * [.run(ast, json, globals)](#JsonFormula+run) ⇒ \* - * [.compile(expression, [allowedGlobalNames], [debug])](#JsonFormula+compile) + * [new JsonFormula([customFunctions], [stringToNumber], [debug])](#new_JsonFormula_new) + * [.search(expression, json, [globals], [language])](#JsonFormula+search) ⇒ \* + * [.run(ast, json, [language], globals)](#JsonFormula+run) ⇒ \* + * [.compile(expression, [allowedGlobalNames])](#JsonFormula+compile) -### new JsonFormula([customFunctions], [stringToNumber], [language], [debug]) +### new JsonFormula([customFunctions], [stringToNumber], [debug]) | Param | Type | Default | Description | | --- | --- | --- | --- | | [customFunctions] | object | {} | custom functions needed by a hosting application. | | [stringToNumber] | function | 'null' | A function that converts string values to numbers. Can be used to convert currencies/dates to numbers | -| [language] | string | "en-US" | | | [debug] | array | [] | will be populated with any errors/warnings | -### jsonFormula.search(json, [globals]) ⇒ \* +### jsonFormula.search(expression, json, [globals], [language]) ⇒ \* Evaluates the JsonFormula on a particular json payload and return the result **Kind**: instance method of [JsonFormula](#JsonFormula) @@ -34,26 +33,47 @@ Evaluates the JsonFormula on a particular json payload and return the result | Param | Type | Default | Description | | --- | --- | --- | --- | +| expression | string | | the json-formula expression to evaluate | | json | object \| array | | the json data on which the expression needs to be evaluated | | [globals] | object | {} | global objects that can be accessed via custom functions. | - +| [language] | string | "en-US" | BCP-47 language tag | + +**Example** +```js +const jf = new JsonFormula(); +const result = jf.search('toDate(d) | day(@) & "/" & month(@)', {d: "2025-11-12"}); +// returns "12/11" +``` -### jsonFormula.run(ast, json, globals) ⇒ \* -Execute a previously compiled expression against a json object and return the result +### jsonFormula.run(ast, json, [language], globals) ⇒ \* +Execute a previously compiled expression against a json object and return the result. +Use this method for better performance when you will evaluate the same expression +multiple times with different data. **Kind**: instance method of [JsonFormula](#JsonFormula) **Returns**: \* - the result of the expression being evaluated -| Param | Type | Description | -| --- | --- | --- | -| ast | object | The abstract syntax tree returned from compile() | -| json | object \| array | the json data on which the expression needs to be evaluated | -| globals | \* | set of objects available in global scope | - +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| ast | object | | The abstract syntax tree returned from compile() | +| json | object \| array | | the json data on which the expression needs to be evaluated | +| [language] | string | "en-US" | BCP-47 language tag | +| globals | \* | | set of objects available in global scope | + +**Example** +```js +const globals = { + $days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] +}; +const jf = new JsonFormula(); +const ast = jf.compile('value($days, num)', ['$days']); // compile the expression once +const result1 = jf.run(ast, {num: 2}, 'en-US', globals); // returns "Wed" +const result2 = jf.run(ast, {num: 3}, 'en-US', globals); // returns "Thu" +``` -### jsonFormula.compile(expression, [allowedGlobalNames], [debug]) +### jsonFormula.compile(expression, [allowedGlobalNames]) Creates a compiled expression that can be executed later on with some data. **Kind**: instance method of [JsonFormula](#JsonFormula) @@ -61,15 +81,15 @@ Creates a compiled expression that can be executed later on with some data. | Param | Type | Default | Description | | --- | --- | --- | --- | | expression | string | | the expression to evaluate | -| [allowedGlobalNames] | Array.<string> | [] | A list of names of the global variables being used in the expression. | -| [debug] | array | [] | will be populated with any errors/warnings | +| [allowedGlobalNames] | Array.<string> | [] | An array of names of the global variables being used in the expression. | ## jsonFormula(json, globals, expression, [customFunctions], [stringToNumber], [language], [debug]) ⇒ \* Compile and execute a json-formula expression. If executing the same expression multiple times, it is more efficient to create a -class instance of {JsonFormula} and call the search method multiple times. +class instance of JsonFormula and call the search() method or the compile()/run() methods +multiple times. **Kind**: global function **Returns**: \* - the result of the expression being evaluated @@ -84,3 +104,71 @@ class instance of {JsonFormula} and call the search method multiple times. | [language] | string | "en-US" | | | [debug] | array | [] | will be populated with any errors/warnings | + + +## CustomFunctionDefinition : object +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| _func | function | The function implementation | +| [_signature] | array | Function signature metadata | + +**Example** +```js +// simple custom functions definition + const customFunctions = { + true_fn: { + _func: () => true, + _signature: [], + }, + false_fn: { + _func: () => false, + _signature: [], + }, + }; + +``` +**Example** +```js +// custom function with a signature for its parameters + const customFunctions = { + padEnd: { + _func: args => { + const src = args[0]; + const length = args[1]; + const padChar = args[2]; + if (Array.isArray(src)) return src.map(s => s.padEnd(length, padChar)); + return src.padEnd(length, padChar); + }, + _signature: [ + { types: [TYPE_STRING, TYPE_ARRAY_STRING] }, + { types: [TYPE_NUMBER] }, + { types: [TYPE_STRING] }, + ], + } + } + // May also register functions is via the `register()` or `registerWithParams()` methods. e.g. + + const regFormula = `${register("${fn_name}", &${code})`; + // Run the registration formula after which, the registered function may be called + this.search(regFormula, {}); +``` + + +## globals : object +An object where each key **MUST** begin with a `$` character, representing global variables +that can be accessed inside a json-formula expression. +The value of each key can be of any data type supported by json. + +**Kind**: global typedef +**Example** +```js +const globals = { + $num: 42, + $arr: [1, 2, 3], + $days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] +}; +jsonFormula({}, globals, '$arr * $num') // returns [42, 84, 126] +``` diff --git a/doc/output/json-formula-specification-2.0.0.html b/doc/output/json-formula-specification-2.0.0.html index 35c7df89..088c4126 100644 --- a/doc/output/json-formula-specification-2.0.0.html +++ b/doc/output/json-formula-specification-2.0.0.html @@ -443,7 +443,7 @@

json-formula Specification

PDF Association Forms Technical Working Group
version 2.0.0, -2025-11-10 +2025-11-12
@@ -544,7 +544,7 @@

Scope

-

The intended audience are both end-users of json-formula as well as implementors; the contents are then both a user guide and a specification.

+

The intended audience are both end-users of json-formula as well as implementers; the contents are then both a user guide and a specification.

@@ -552,7 +552,7 @@

Scope

1. Notation

-

In the specification, examples are shown through the use of a search function. The syntax for this function is:

+

In the specification, examples are shown through the use of a search function called eval. The syntax for this function is:

@@ -601,8 +601,7 @@

2. Data Types

-

There is an additional type that is not a JSON type that’s used in -json-formula functions:

+

There is an additional type that is not a JSON type that’s used in json-formula functions: