UNPKG

@ibyar/expressions

Version:

Aurora expression, an template expression and evaluation, An 100% spec compliant ES2022 JavaScript toolchain,

213 lines 7.44 kB
import type { Scope, Context } from '../scope/scope.js'; import type { Stack } from '../scope/stack.js'; import { TypeOf } from './utils.js'; /** * Each Position object consists of * a line number (1-indexed) * and a column number (0-indexed) */ export interface Position { line: number; column: number; } export interface SourceLocation { source?: string | null; start: Position; end: Position; } export type NodeType = { type: string; }; export type NodeJsonType = { [key: string]: any; } & NodeType; export type ExpressionEventPathDotNotation = { computed: false; path: string; }; export type ExpressionEventPathBracketNotation = { computed: true; path: string; computedPath: ExpressionEventPath[][]; }; export type ExpressionEventPath = ExpressionEventPathDotNotation | ExpressionEventPathBracketNotation; export type ExpressionEventMap = { [key: string]: ExpressionEventMap; }; export type DeclarationType = 'HoistableDeclaration' | 'ClassDeclaration' | 'LexicalDeclaration'; export type HoistableDeclaration = 'FunctionDeclaration' | 'GeneratorDeclaration' | 'AsyncFunctionDeclaration' | 'AsyncGeneratorDeclaration'; export type LexicalDeclaration = 'Let' | 'Const'; export interface ExpressionNode { /** * The `type` field is a string representing the AST variant type. * Each subtype of `Node` is documented below with the specific string of its type field. * You can use this field to determine which interface a node implements. */ type: string; /** * The `loc` field represents the source location information of the node. * If the node contains no information about the source location, * the field is `null` or `undefined`; * otherwise it is an object consisting of * a start position (the position of the first character of the parsed source region) * and an end position (the position of the first character after the parsed source region): * and offset index (the position of the first character) */ loc?: SourceLocation; /** * start and end position offset */ range?: [number, number]; /** * assign the value to this expression in stack. * * most ExpressionNode will not implement this method, and will throw an exception. * @param stack * @param value */ set(stack: Stack, value: any): any; /** * execute/get the code for this expression and return the result value. * @param stack * @param thisContext */ get(stack: Stack, thisContext?: any): any; /** * get all dependencies form an expression node * * the return from this method, is represent an answer for what identifiers this expression depends-on. * * * ex: * ```js * x + y; * ``` * * - for `+` operator : the answer should be `lhs` and `rhs`, * - for `x` identifier: the answer should be node `x`, * - for `y` identifier: the answer should be node `y`. * * so, the return from `+` will be `[ node 'x', node 'y']` * * and: * - `x.y.z * a` ==> `[ member node `x.y.z`, identifier 'a']` * @param computed */ dependency(computed?: true): ExpressionNode[]; /** * ex: * ```js * x + y; * ``` * * - for `+` operator : the answer should be `lhs` and `rhs`, * - for `x` identifier: the answer should be node `x`, * - for `y` identifier: the answer should be node `y`. * * so, the return from `+` will be `['x', 'y']` * * and: * - `x.y.z` ==> `['x', 'y', 'z']` * - `x[y].z` ==> ['x', ] * @param computed required for member and chaining operators */ dependencyPath(computed?: true): ExpressionEventPath[]; /** * get all the events form this expression * * the return from this method, is represent an answer for what is this expression depends-on as identifier name * * ex: * ```js * x + y; * ``` * * - for `+` operator : the answer should be `lhs` and `rhs`, * - for `x` identifier: the answer should be `x` * - for `y` identifier: the answer should be `y` * the final output will be * * so, the return from `+` will be `{ x: undefined, y: undefined }` * * and: * - `x.y.z * a` ==> `{ x: { y: { z: undefined }, a: undefined } }` * - `x.y.z > x.y.h.g` ==> `{ x: { y: { z: undefined, h: { g: undefined} } } }` * - `x[Symbol.toStringTag] + 'Class' + classType + array[3]` ==> `{ x: { 'Symbol.toStringTag': undefined }, classType: undefined, array: { 3: undefined } }` * - `'name'` ==> {} * - ```js * user[firstName + `son of ${fatherName}`] * ``` ==> `{ user: { 'firstName:fatherName': undefined }, firstName: undefined, fatherName: undefined }` * @param parent */ events(): ExpressionEventMap; /** * re-write this expression as a javascript source */ toString(): string; /** * used to map this object to represent an [ESTree](https://github.com/estree/estree) json object * @param key */ toJSON(): NodeJsonType; /** * just a helper method to force class that implement this interface to * have a static method `fromJSON` to help reconstruct this ExpressionNode * from an [ESTree](https://github.com/estree/estree) json object, * with all necessary implementation to execute the code */ getClass(): ExpressionNodConstructor<ExpressionNode>; } export type NodeDeserializer<N = ExpressionNode> = (node: N) => N; export type VisitNodeType = (expression: ExpressionNode) => void; /** * this is how to: * describe a class with it's static functions and properties * in the interface add getClass method */ export interface ExpressionNodConstructor<N extends ExpressionNode> extends TypeOf<N> { /** * the type of an expression */ type: string; /** * build expression node from [ESTree](https://github.com/estree/estree) json object * @param node * @param deserializer */ fromJSON(node: N, deserializer: NodeDeserializer): N; /** * visit nodes inside expression * @param expression * @param callback */ visit?(node: N, visitNode: Object): void; } export interface DeclarationExpression extends ExpressionNode { /** * declare variable in the current local scope (block), * or closest function scope (global) scop, * the propertyName will be calculated at runtime * @param stack the stack which an identifier will be declared * @param propertyValue the initial value of identifier * @param scope which scop to declare this identifier */ declareVariable(stack: Stack, propertyValue?: any): any; /** * get the variable declaration name */ getDeclarationName?(): string; } /** * An interface meant to be implemented by MemberExpression, * Identifier and ChainExpression and all Literal expressions */ export interface CanFindScope { /** * try to search for scope of this expression * @param stack */ findScope<V extends Context>(stack: Stack): Scope<V>; findScope<V extends Context>(stack: Stack, scope: Scope<Record<PropertyKey, V>>): Scope<V>; findScope<V extends Context>(stack: Stack, scope?: Scope<Record<PropertyKey, V>>): Scope<V> | undefined; } //# sourceMappingURL=expression.d.ts.map