UNPKG

@holgerengels/compute-engine

Version:

Symbolic computing and numeric evaluations for JavaScript and Node.js

250 lines (207 loc) 8.85 kB
/* 0.26.0-alpha2 */ /** * A primitive type is a simple type that represents a concrete value. * * - `any`: the top type * - `expression` * - `error`: an invalid value, such as `["Error", "missing"]` * - `nothing`: the type of the `Nothing` symbol, the unit type * - `never`: the bottom type * - `unknown`: a value whose type is not known * * - `expression`: * - a symbolic expression, such as `["Add", "x", 1]` * - <value> * - `symbol`: a symbol, such as `x`. * - `function`: a function expression * such as `["Function", ["Add", "x", 1], "x"]`. * * - `value` * - `scalar` * - <number> * - `boolean`: a boolean value: `True` or `False`. * - `string`: a string of characters. * - `collection` * - `list`: a collection of expressions, possibly recursive, * with optional dimensions, e.g. `[number]`, `[boolean^32]`, * `[number^(2x3)]`. Used to represent a vector, a matrix or a * tensor when the type of its elements is a number * - `set`: a collection of unique expressions, e.g. `set<string>`. * - `tuple`: a fixed-size collection of named or unnamed elements, e.g. * `tuple<number, boolean>`, `tuple<x: number, y: boolean>`. * - `map`: a set key-value pairs, e.g. `map<x: number, y: boolean>`. * * - `number`: any numeric value: * - `finite_number`: <finite_complex> or <finite_imaginary> or * <finite_real> or <finite_rational> or <finite_integer> * - `non_finite_number`: `NaN`, `PositiveInfinity`, `NegativeInfinity` or * `ComplexInfinity` * - `complex` and `finite_complex`: a complex number, with non-zero real * and imaginary parts. * - `imaginary` and `finite_imaginary`: a complex number with a real part * of 0 (pure imaginary). * - `real` and `finite_real`: a complex number with an imaginary part of 0. * - `rational` and `finite_rational`: a pure rational number * (not an integer) * - `integer` and `finite_integer`: a whole number * * */ export type PrimitiveType = NumericType | 'collection' | 'list' | 'set' | 'map' | 'tuple' | 'value' | 'scalar' | 'function' | 'symbol' | 'boolean' | 'string' | 'expression' | 'unknown' | 'error' | 'nothing' | 'never' | 'any'; export type NumericType = 'number' | 'finite_number' | 'complex' | 'finite_complex' | 'imaginary' | 'finite_imaginary' | 'real' | 'finite_real' | 'rational' | 'finite_rational' | 'integer' | 'finite_integer' | 'non_finite_number'; export type NamedElement = { name?: string; type: Type; }; export type FunctionSignature = { kind: 'signature'; args?: NamedElement[]; optArgs?: NamedElement[]; restArg?: NamedElement; result: Type; }; export type AlgebraicType = { kind: 'union' | 'intersection'; types: Type[]; }; export type NegationType = { kind: 'negation'; type: Type; }; export type ValueType = { kind: 'value'; value: any; }; /** Map is not a collection. It is a set of key/value pairs. * An element of a map whose type is a subtype of `nothing` is optional. * For example, in `{x: number, y: boolean | nothing}` the element `y` is optional. */ export type MapType = { kind: 'map'; elements: Record<string, Type>; }; /** Collection, List, Set, Tuple and Map are collections. * * `CollectionType` is a generic collection of elements of a certain type. */ export type CollectionType = { kind: 'collection'; elements: Type; }; /** * The elements of a list are ordered. * * All elements of a list have the same type (but it can be a broad type, * up to `any`). * * The same element can be present in the list more than once. * * A list can be multi-dimensional. For example, a list of integers with * dimensions 2x3x4 is a 3D tensor with 2 layers, 3 rows and 4 columns. * */ export type ListType = { kind: 'list'; elements: Type; dimensions?: number[]; }; /** Each element of a set is unique (is not present in the set more than once). * The elements of a set are not ordered. */ export type SetType = { kind: 'set'; elements: Type; }; export type TupleType = { kind: 'tuple'; elements: NamedElement[]; }; /** Nominal typing */ export type TypeReference = { kind: 'reference'; ref: string; }; export type Type = PrimitiveType | AlgebraicType | NegationType | CollectionType | ListType | SetType | MapType | TupleType | FunctionSignature | ValueType | TypeReference; /** * The type of a boxed expression indicates the kind of expression it is and * the value it represents. * * The type is represented either by a primitive type (e.g. number, complex, collection, etc.), or a compound type (e.g. tuple, function signature, etc.). * * Types are described using the following BNF grammar: ```bnf <type> ::= <union_type> <union_type> ::= <intersection_type> (" | " <intersection_type>)* <intersection_type> ::= <primary_type> (" & " <primary_type>)* <primary_type> ::= <primitive> | <tuple_type> | <function_type> | <list_type> | <wrapped_primary_type> <wrapped_primary_type> ::= "(" <primary_type> ")" <primitive> ::= "any" | "unknown" | <value-type> | <symbolic-type> | <numeric-type> <numeric-type> ::= "number" | "complex" | "imaginary" | "real" | "rational" | "integer" <value-type> ::= "value" | <numeric-type> | "collection" | "boolean" | "string" <symbolic-type> ::= "expression" | "function" | "symbol" <tuple_type> ::= "(" (<name> <type> "," <named_tuple_elements>*) ")" | "(" (<type> "," <unnamed_tuple_elements>*) ")" | | "tuple(" <tuple_elements> ")" <tuple_elements> ::= <unnamed_tuple_elements> | <named_tuple_elements> <unnamed_tuple_elements> ::= <type> ("," <type>)* <named_tuple_elements> ::= <name> <type> ("," <name> <type>)* <function_type> ::= <arguments> " -> " <type> <arguments> ::= "()" | <argument> | "(" <argument-list> ")" | <deferred_evaluation> <deferred_evaluation> ::= "???" <argument> | "???" "(" <argument-list> ")" <argument> ::= <type> | <name> <type> <rest_argument> ::= "..." <type> | <name> "..." <type> <optional_argument> ::= <argument> "?" <optional_arguments> ::= <optional_argument> ("," <optional_argument>)* <required_arguments> ::= <argument> ("," <argument>)* <argument-list> ::= <required_arguments> ("," <rest_argument>)? | <required_arguments> <optional_arguments>? | <optional_arguments>? | <rest_argument> <list_type> ::= "[" <type> <dimensions>? "]" <dimensions> ::= "^" <fixed_size> | "^(" <multi_dimensional_size> ")" <fixed_size> ::= <positive-integer_literal> <multi_dimensional_size> ::= <positive-integer_literal> "x" <positive-integer_literal> ("x" <positive-integer_literal>)* <map> ::= "{}" |"{" <map_elements> "}" | "map(" <map_elements> ")" <map_elements> ::= <name> <type> ("," <name> <type>)* <set> ::= "set<" <type> ">" <collection ::= "collection<" <type> ">" <name> ::= <identifier> ":" <identifier> ::= [a-zA-Z_][a-zA-Z0-9_]* <positive-integer_literal> ::= [1-9][0-9]* ``` Examples of types: "number" -- a simple type primitive "(number, boolean)" -- a tuple type "(x: number, y:boolean)" -- a named tuple/record type. Either all arguments are named, or none are "[any]" -- an arbitrary collection type, with no length or element type restrictions "[integer]" -- a collection type where all the elements are integers "[(number, boolean)]" -- a collection of tuples "[(value:number, seen:boolean)]" -- a collection of named tuples "[boolean]^32" -- a collection type with a fixed size of 32 elements "[integer]^(2x3)" -- an integer matrix of 2 columns and 3 rows "[integer]^(2x3x4)" -- a tensor of dimensions 2x3x4 "number -> number" -- a function type with a single argument "(x: number, number) -> number" -- a function type with a named argument "(number, y:number?) -> number" -- a function type with an optional named argument (can have several optional arguments, at the end) "(number, ...number) -> number" -- a function type with a rest argument (can have only one, and no optional arguments if there is a rest argument). "() -> number" -- a function type with an empty argument list "number | boolean" -- a union type "(x: number) & (y: number)" -- an intersection type "number | ((x: number) & (y: number))" -- a union type with an intersection type "(number -> number) | number" -- a union type with a function type */ export type TypeString = string; export type TypeCompatibility = 'covariant' | 'contravariant' | 'bivariant' | 'invariant'; export type TypeResolver = (name: string) => Type | undefined;