UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

146 lines 4.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSteps = void 0; const validator_1 = require("../validator/validator"); const errors_1 = require("../errors/errors"); const generator_1 = require("./generator"); const nodes_1 = require("./nodes"); const ExpressionStatement_1 = require("./nodes/Statement/ExpressionStatement"); const builtins_1 = require("./builtins"); const _1 = require("."); function getSteps(inputNode, context, { stepLimit }) { const node = (0, builtins_1.prelude)(inputNode); const steps = []; const limit = stepLimit === undefined ? 1000 : stepLimit % 2 === 0 ? stepLimit : stepLimit + 1; let hasError = false; let numSteps = 0; function evaluate(node) { numSteps += 1; if (numSteps >= limit) { return node; } try { const isOneStepPossible = node.isOneStepPossible(); if (isOneStepPossible) { const oldNode = node; let newNode; newNode = node.oneStep(); if (_1.redex) { const explanations = _1.redex.preRedex.map(generator_1.explain); const beforeMarkers = _1.redex.preRedex.map((redex, index) => ({ redex: redex, redexType: 'beforeMarker', explanation: explanations[index] })); steps.push({ ast: oldNode, markers: beforeMarkers }); const afterMarkers = _1.redex.postRedex.length > 0 ? _1.redex.postRedex.map((redex, index) => ({ redex: redex, redexType: 'afterMarker', explanation: explanations[index] })) : [ { redexType: 'afterMarker', explanation: explanations[0] // use explanation based on preRedex } ]; steps.push({ ast: newNode, markers: afterMarkers }); } // reset _1.redex.preRedex = []; _1.redex.postRedex = []; return evaluate(newNode); } else { return node; } } catch (error) { // Handle error during step evaluation hasError = true; steps.push({ ast: node, markers: [ { redexType: 'beforeMarker', explanation: error instanceof Error ? error.message : String(error) } ] }); return node; } } // First node steps.push({ ast: node, markers: [ { explanation: 'Start of evaluation' } ] }); // check for undefined variables try { (0, validator_1.checkProgramForUndefinedVariables)(inputNode, context); } catch (error) { steps.push({ ast: node, markers: [ { redexType: 'beforeMarker', explanation: error instanceof errors_1.UndefinedVariable ? `Line ${error.location.start.line}: Name ${error.name} not declared.` : String(error) } ] }); return steps; } let result = evaluate(node); // If program has not completed within the step limit, halt. if (numSteps >= limit) { steps.push({ ast: result, markers: [ { explanation: 'Maximum number of steps exceeded' } ] }); } // If the program does not return anything, return undefined if (result.type === 'Program' && result.body.length === 0) { result = new ExpressionStatement_1.StepperExpressionStatement(nodes_1.undefinedNode); } if (!hasError) { steps.push({ ast: result, markers: [ { explanation: 'Evaluation complete' } ] }); } else { steps.push({ ast: result, markers: [ { explanation: 'Evaluation stuck' } ] }); } return steps; } exports.getSteps = getSteps; //# sourceMappingURL=steppers.js.map