UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

206 lines (205 loc) 9.99 kB
import * as es from 'estree'; import { Context } from '..'; import { RuntimeSourceError } from '../errors/runtimeSourceError'; import { type Environment, type Node, type StatementSequence, type Value } from '../types'; import { Control, Transformers } from './interpreter'; import { EnvArray, ControlItem, Instr } from './types'; import Closure from './closure'; /** * Typeguard for commands to check if they are scheme values. * * @param command A ControlItem * @returns true if the ControlItem is a scheme value, false otherwise. */ export declare const isSchemeValue: (command: ControlItem) => boolean; /** * Typeguard for Instr to distinguish between program statements and instructions. * * @param command A ControlItem * @returns true if the ControlItem is an instruction and false otherwise. */ export declare const isInstr: (command: ControlItem) => command is Instr; /** * Typeguard for Node to distinguish between program statements and instructions. * * @param command A ControlItem * @returns true if the ControlItem is a Node or StatementSequence, false if it is an instruction. */ export declare const isNode: (command: ControlItem) => command is Node; /** * Typeguard for esIdentifier. To verify if a Node is an esIdentifier. * * @param node a Node * @returns true if node is an esIdentifier, false otherwise. */ export declare const isIdentifier: (node: Node) => node is es.Identifier; /** * Typeguard for esReturnStatement. To verify if a Node is an esReturnStatement. * * @param node a Node * @returns true if node is an esReturnStatement, false otherwise. */ export declare const isReturnStatement: (node: Node) => node is es.ReturnStatement; /** * Typeguard for esIfStatement. To verify if a Node is an esIfStatement. * * @param node a Node * @returns true if node is an esIfStatement, false otherwise. */ export declare const isIfStatement: (node: Node) => node is es.IfStatement; /** * Typeguard for esBlockStatement. To verify if a Node is a block statement. * * @param node a Node * @returns true if node is an esBlockStatement, false otherwise. */ export declare const isBlockStatement: (node: Node) => node is es.BlockStatement; /** * Typeguard for StatementSequence. To verify if a ControlItem is a statement sequence. * * @param node a ControlItem * @returns true if node is a StatementSequence, false otherwise. */ export declare const isStatementSequence: (node: ControlItem) => node is StatementSequence; /** * Typeguard for esRestElement. To verify if a Node is a block statement. * * @param node a Node * @returns true if node is an esRestElement, false otherwise. */ export declare const isRestElement: (node: Node) => node is es.RestElement; /** * Generate a unique id, for use in environments, arrays and closures. * * @param context the context used to provide the new unique id * @returns a unique id */ export declare const uniqueId: (context: Context) => string; /** * Returns whether `item` is an array with `id` and `environment` properties already attached. */ export declare const isEnvArray: (item: any) => item is EnvArray; /** * Returns whether `item` is a non-closure function that returns a stream. * If the function has been called already and we have the result, we can * pass it in here as a 2nd argument for stronger checking */ export declare const isStreamFn: (item: any, result?: any) => result is [any, () => any]; /** * Adds the properties `id` and `environment` to the given array, and adds the array to the * current environment's heap. Adds the array to the heap of `envOverride` instead if it's defined. * * @param context the context used to provide the current environment and new unique id * @param array the array to attach properties to, and for addition to the heap */ export declare const handleArrayCreation: (context: Context, array: any[], envOverride?: Environment) => void; /** * A helper function for handling sequences of statements. * Statements must be pushed in reverse order, and each statement is separated by a pop * instruction so that only the result of the last statement remains on stash. * Value producing statements have an extra pop instruction. * * @param seq Array of statements. * @returns Array of commands to be pushed into control. */ export declare const handleSequence: (seq: es.Statement[]) => ControlItem[]; /** * This function is used for ConditionalExpressions and IfStatements, to create the sequence * of control items to be added. */ export declare const reduceConditional: (node: es.IfStatement | es.ConditionalExpression) => ControlItem[]; /** * To determine if a control item is value producing. JavaScript distinguishes value producing * statements and non-value producing statements. * Refer to https://sourceacademy.nus.edu.sg/sicpjs/4.1.2 exercise 4.8. * * @param command Control item to determine if it is value producing. * @returns true if it is value producing, false otherwise. */ export declare const valueProducing: (command: Node) => boolean; /** * To determine if a control item changes the environment. * There is a change in the environment when * 1. pushEnvironment() is called when creating a new frame, if there are variable declarations. * Called in Program, BlockStatement, and Application instructions. * 2. there is an assignment. * Called in Assignment and Array Assignment instructions. * 3. a new object is created. * Called in ExpressionStatement that contains an ArrowFunctionExpression, or an ArrowFunctionExpression * * @param command Control item to check against. * @returns true if it changes the environment, false otherwise. */ export declare const envChanging: (command: ControlItem) => boolean; /** * To determine if the function is simple. * Simple functions contain a single return statement. * * @param node The function to check against. * @returns true if the function is simple, false otherwise. */ export declare const isSimpleFunction: (node: any) => boolean; /** * Transformers */ export declare const currentTransformers: (context: Context) => Transformers; export declare const setTransformers: (context: Context, transformers: Transformers) => void; /** * Environments */ export declare const currentEnvironment: (context: Context) => Environment; export declare const createEnvironment: (context: Context, closure: Closure, args: Value[], callExpression: es.CallExpression) => Environment; export declare const popEnvironment: (context: Context) => Environment | undefined; export declare const pushEnvironment: (context: Context, environment: Environment) => void; export declare const createBlockEnvironment: (context: Context, name?: string) => Environment; export declare const createProgramEnvironment: (context: Context, isPrelude: boolean) => Environment; export declare function declareIdentifier(context: Context, name: string, node: Node, environment: Environment, constant?: boolean): Environment; export declare function declareFunctionsAndVariables(context: Context, node: es.BlockStatement, environment: Environment): void; export declare function hasDeclarations(node: es.BlockStatement): boolean; export declare function hasImportDeclarations(node: es.BlockStatement): boolean; export declare function defineVariable(context: Context, name: string, value: Value, constant: boolean | undefined, node: es.VariableDeclaration | es.ImportDeclaration): Environment; export declare const getVariable: (context: Context, name: string, node: es.Identifier) => any; export declare const setVariable: (context: Context, name: string, value: any, node: es.AssignmentExpression) => undefined; export declare const handleRuntimeError: (context: Context, error: RuntimeSourceError) => never; export declare const checkNumberOfArguments: (context: Context, callee: Closure | Value, args: Value[], exp: es.CallExpression) => undefined; /** * This function can be used to check for a stack overflow. * The current limit is set to be a control size of 1.0 x 10^5, if the control * flows beyond this limit an error is thrown. * This corresponds to about 10mb of space according to tests ran. */ export declare const checkStackOverFlow: (context: Context, control: Control) => void; /** * Checks whether an `if` statement returns in every possible branch. * @param body The `if` statement to be checked * @return `true` if every branch has a return statement, else `false`. */ export declare const hasReturnStatementIf: (statement: es.IfStatement) => boolean; /** * Checks whether a block returns in every possible branch. * @param body The block to be checked * @return `true` if every branch has a return statement, else `false`. */ export declare const hasReturnStatement: (block: es.BlockStatement | StatementSequence) => boolean; export declare const hasBreakStatementIf: (statement: es.IfStatement) => boolean; /** * Checks whether a block OR any of its child blocks has a `break` statement. * @param body The block to be checked * @return `true` if there is a `break` statement, else `false`. */ export declare const hasBreakStatement: (block: es.BlockStatement | StatementSequence) => boolean; export declare const hasContinueStatementIf: (statement: es.IfStatement) => boolean; /** * Checks whether a block OR any of its child blocks has a `continue` statement. * @param body The block to be checked * @return `true` if there is a `continue` statement, else `false`. */ export declare const hasContinueStatement: (block: es.BlockStatement | StatementSequence) => boolean; /** * Checks whether the evaluation of the given control item depends on the current environment. * The item is also considered environment dependent if its evaluation introduces * environment dependent items * @param item The control item to be checked * @return `true` if the item is environment depedent, else `false`. */ export declare function isEnvDependent(item: ControlItem | null | undefined): boolean;