UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

76 lines 3.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transpileToLazy = void 0; const create = require("../utils/ast/astCreator"); const uniqueIds_1 = require("../utils/uniqueIds"); const walkers_1 = require("../utils/walkers"); const lazyPrimitives = new Set(['makeLazyFunction', 'wrapLazyCallee', 'forceIt', 'delayIt']); const forcingNodes = new Set(['BinaryExpression', 'UnaryExpression']); function transformFunctionDeclarationsToArrowFunctions(program) { (0, walkers_1.simple)(program, { FunctionDeclaration(node) { const { id, params, body } = node; if (id === null) { throw new Error('Encountered a FunctionDeclaration node without an identifier. This should have been caught when parsing.'); } node.type = 'VariableDeclaration'; node = node; const asArrowFunction = create.callExpression(create.identifier('makeLazyFunction', node.loc), [create.blockArrowFunction(params, body, node.loc)], node.loc); node.declarations = [ { type: 'VariableDeclarator', id, init: asArrowFunction } ]; node.kind = 'const'; } }); } function insertDelayAndForce(program) { function transformConditionals(node) { const test = node.type === 'LogicalExpression' ? 'left' : 'test'; if (forcingNodes.has(node[test].type)) { return; } node[test] = create.callExpression(create.identifier('forceIt'), [node[test]], node.loc); } (0, walkers_1.simple)(program, { BinaryExpression(node) { node.left = create.callExpression(create.identifier('forceIt'), [node.left], node.left.loc); node.right = create.callExpression(create.identifier('forceIt'), [node.right], node.right.loc); }, UnaryExpression(node) { node.argument = create.callExpression(create.identifier('forceIt'), [node.argument], node.argument.loc); }, IfStatement: transformConditionals, ConditionalExpression: transformConditionals, LogicalExpression: transformConditionals, ForStatement: transformConditionals, WhileStatement: transformConditionals, CallExpression(node) { if (node.callee.type === 'Identifier' && lazyPrimitives.has(node.callee.name)) { return; } node.callee = create.callExpression(create.identifier('wrapLazyCallee', node.callee.loc), [node.callee], node.callee.loc); node.arguments = node.arguments.map(arg => create.callExpression(create.identifier('delayIt'), [create.arrowFunctionExpression([], arg, arg.loc)], arg.loc)); } }); } // transpiles if possible and modifies program to a Source program that makes use of lazy primitives function transpileToLazy(program) { const identifiers = (0, uniqueIds_1.getIdentifiersInProgram)(program); if (identifiers.has('forceIt') || identifiers.has('delayIt')) { program.body.unshift(create.expressionStatement(create.callExpression(create.identifier('display'), [ create.literal('Manual use of lazy library detected, turning off automatic lazy evaluation transformation.') ], { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } }))); return; } transformFunctionDeclarationsToArrowFunctions(program); insertDelayAndForce(program); } exports.transpileToLazy = transpileToLazy; //# sourceMappingURL=lazy.js.map