js-slang
Version:
Javascript-based implementations of Source, written in Typescript
95 lines • 3.97 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInfiniteLoopData = exports.InfiniteLoopError = exports.InfiniteLoopErrorType = exports.isPotentialInfiniteLoop = exports.StackOverflowMessages = void 0;
const errors_1 = require("../errors/errors");
const runtimeSourceError_1 = require("../errors/runtimeSourceError");
const timeoutErrors_1 = require("../errors/timeoutErrors");
const instrument_1 = require("./instrument");
var StackOverflowMessages;
(function (StackOverflowMessages) {
StackOverflowMessages["firefox"] = "InternalError: too much recursion";
// webkit: chrome + safari. Also works for node
StackOverflowMessages["webkit"] = "RangeError: Maximum call stack size exceeded";
StackOverflowMessages["edge"] = "Error: Out of stack space";
})(StackOverflowMessages = exports.StackOverflowMessages || (exports.StackOverflowMessages = {}));
/**
* Checks if the error is a TimeoutError or Stack Overflow.
*
* @returns {true} if the error is a TimeoutError or Stack Overflow.
* @returns {false} otherwise.
*/
function isPotentialInfiniteLoop(error) {
if (error instanceof timeoutErrors_1.TimeoutError) {
return true;
}
else if (error instanceof errors_1.ExceptionError) {
const message = error.explain();
for (const toMatch of Object.values(StackOverflowMessages)) {
if (message.includes(toMatch)) {
return true;
}
}
}
return false;
}
exports.isPotentialInfiniteLoop = isPotentialInfiniteLoop;
var InfiniteLoopErrorType;
(function (InfiniteLoopErrorType) {
InfiniteLoopErrorType[InfiniteLoopErrorType["NoBaseCase"] = 0] = "NoBaseCase";
InfiniteLoopErrorType[InfiniteLoopErrorType["Cycle"] = 1] = "Cycle";
InfiniteLoopErrorType[InfiniteLoopErrorType["FromSmt"] = 2] = "FromSmt";
})(InfiniteLoopErrorType = exports.InfiniteLoopErrorType || (exports.InfiniteLoopErrorType = {}));
class InfiniteLoopError extends runtimeSourceError_1.RuntimeSourceError {
constructor(functionName, streamMode, message, infiniteLoopType) {
super();
this.message = message;
this.infiniteLoopType = infiniteLoopType;
this.functionName = functionName;
this.streamMode = streamMode;
}
explain() {
const entityName = this.functionName ? `function ${(0, instrument_1.getOriginalName)(this.functionName)}` : 'loop';
return this.streamMode
? `The error may have arisen from forcing the infinite stream: ${entityName}.`
: `The ${entityName} has encountered an infinite loop. ` + this.message;
}
}
exports.InfiniteLoopError = InfiniteLoopError;
/**
* Determines whether the error is an infinite loop, and returns a tuple of
* [error type, is stream, error message, previous code].
* *
* @param {Context} - The context being used.
*
* @returns [error type, is stream, error message, previous programs] if the error was an infinite loop
* @returns {undefined} otherwise
*/
function getInfiniteLoopData(context) {
// return error type/string, prevCodeStack
// cast as any to access infiniteLoopError property later
const errors = context.errors;
let latestError = errors[errors.length - 1];
if (latestError instanceof errors_1.ExceptionError) {
latestError = latestError.error;
}
let infiniteLoopError;
if (latestError instanceof InfiniteLoopError) {
infiniteLoopError = latestError;
}
else if (latestError.hasOwnProperty('infiniteLoopError')) {
infiniteLoopError = latestError.infiniteLoopError;
}
if (infiniteLoopError) {
return [
infiniteLoopError.infiniteLoopType,
infiniteLoopError.streamMode,
infiniteLoopError.explain(),
context.previousPrograms
];
}
else {
return undefined;
}
}
exports.getInfiniteLoopData = getInfiniteLoopData;
//# sourceMappingURL=errors.js.map
;