UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

82 lines 4.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StepperArrowFunctionExpression = void 0; const generator_1 = require("../../generator"); const utils_1 = require("../../utils"); class StepperArrowFunctionExpression { constructor(params, body, name, expression = true, generator = false, async = false, leadingComments, trailingComments, loc, range) { this.type = 'ArrowFunctionExpression'; this.params = params; this.expression = expression; this.generator = generator; this.async = async; this.name = name; this.leadingComments = leadingComments; this.trailingComments = trailingComments; this.loc = loc; this.range = range; this.body = body; } static create(node) { return new StepperArrowFunctionExpression(node.params.map(param => (0, generator_1.convert)(param)), (0, generator_1.convert)(node.body), undefined, node.expression, node.generator, node.async, node.leadingComments, node.trailingComments, node.loc, node.range); } isContractible() { return false; } isOneStepPossible() { return false; } contract() { throw new Error('Cannot contract an arrow function expression'); } oneStep() { throw new Error('Cannot step an arrow function expression'); } assignName(name) { return new StepperArrowFunctionExpression(this.params, this.body, name, this.expression, this.generator, this.async, this.leadingComments, this.trailingComments, this.loc, this.range); } scanAllDeclarationNames() { const paramNames = this.params.map(param => param.name); let bodyDeclarations = []; // @ts-expect-error gracefully handle block statement as block expression if (this.body.type === 'BlockStatement') { const body = this.body; bodyDeclarations = body.body .filter(stmt => stmt.type === 'VariableDeclaration') .flatMap(decl => decl.declarations.map((d) => d.id.name)); } return [...paramNames, ...bodyDeclarations]; } // TODO: Fix name handling for lambda substitute(id, value, upperBoundName) { const valueFreeNames = value.freeNames(); const scopeNames = this.scanAllDeclarationNames(); const repeatedNames = valueFreeNames.filter(name => scopeNames.includes(name)); let protectedNamesSet = new Set([this.allNames(), upperBoundName ?? []].flat()); repeatedNames.forEach(name => protectedNamesSet.delete(name)); const protectedNames = Array.from(protectedNamesSet); const newNames = (0, utils_1.getFreshName)(repeatedNames, protectedNames); const currentArrowFunction = newNames.reduce((current, name, index) => current.rename(repeatedNames[index], name), this); if (currentArrowFunction.scanAllDeclarationNames().includes(id.name)) { return currentArrowFunction; } return new StepperArrowFunctionExpression(currentArrowFunction.params, currentArrowFunction.body.substitute(id, value, currentArrowFunction.params.flatMap(p => p.allNames())), currentArrowFunction.name, currentArrowFunction.expression, currentArrowFunction.generator, currentArrowFunction.async, currentArrowFunction.leadingComments, currentArrowFunction.trailingComments, currentArrowFunction.loc, currentArrowFunction.range); } freeNames() { const paramNames = this.params .filter(param => param.type === 'Identifier') .map(param => param.name); return this.body.freeNames().filter(name => !paramNames.includes(name)); } allNames() { const paramNames = this.params .filter(param => param.type === 'Identifier') .map(param => param.name); return Array.from(new Set([paramNames, this.body.allNames()].flat())); } rename(before, after) { return new StepperArrowFunctionExpression(this.params.map(param => param.rename(before, after)), this.body.rename(before, after), this.name, this.expression, this.generator, this.async, this.leadingComments, this.trailingComments, this.loc, this.range); } } exports.StepperArrowFunctionExpression = StepperArrowFunctionExpression; //# sourceMappingURL=ArrowFunctionExpression.js.map