js-slang
Version:
Javascript-based implementations of Source, written in Typescript
146 lines • 4.8 kB
JavaScript
"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