UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

238 lines 8.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SetPropertyError = exports.GetInheritedPropertyError = exports.GetPropertyError = exports.ConstAssignment = exports.VariableRedeclaration = exports.InvalidNumberOfArguments = exports.UnassignedVariable = exports.UndefinedVariable = exports.CallingNonFunctionValue = exports.MaximumStackLimitExceeded = exports.ExceptionError = exports.InterruptedError = exports.BuiltInFunctionError = void 0; /* tslint:disable: max-classes-per-file */ /* tslint:disable:max-line-length */ const astring_1 = require("astring"); const constants_1 = require("../constants"); const types_1 = require("../types"); const stringify_1 = require("../utils/stringify"); const runtimeSourceError_1 = require("./runtimeSourceError"); //Wrap build-in function error in SourceError class BuiltInFunctionError extends runtimeSourceError_1.RuntimeSourceError { constructor(node, explanation) { super(node); this.explanation = explanation; this.explanation = explanation; } explain() { return `${this.explanation}`; } elaborate() { return this.explain(); } } exports.BuiltInFunctionError = BuiltInFunctionError; class InterruptedError extends runtimeSourceError_1.RuntimeSourceError { constructor(node) { super(node); } explain() { return 'Execution aborted by user.'; } elaborate() { return 'TODO'; } } exports.InterruptedError = InterruptedError; class ExceptionError { constructor(error, location) { this.error = error; this.type = types_1.ErrorType.RUNTIME; this.severity = types_1.ErrorSeverity.ERROR; this.location = location ?? constants_1.UNKNOWN_LOCATION; } explain() { return this.error.toString(); } elaborate() { return 'TODO'; } } exports.ExceptionError = ExceptionError; class MaximumStackLimitExceeded extends runtimeSourceError_1.RuntimeSourceError { constructor(node, calls) { super(node); this.calls = calls; this.customGenerator = { ...astring_1.baseGenerator, CallExpression(node, state) { state.write((0, astring_1.generate)(node.callee)); state.write('('); const argsRepr = node.arguments.map((arg) => (0, stringify_1.stringify)(arg.value)); state.write(argsRepr.join(', ')); state.write(')'); } }; } explain() { const repr = (call) => (0, astring_1.generate)(call, { generator: this.customGenerator }); return ('Maximum call stack size exceeded\n ' + this.calls.map(call => repr(call) + '..').join(' ')); } elaborate() { return 'TODO'; } } exports.MaximumStackLimitExceeded = MaximumStackLimitExceeded; MaximumStackLimitExceeded.MAX_CALLS_TO_SHOW = 3; class CallingNonFunctionValue extends runtimeSourceError_1.RuntimeSourceError { constructor(callee, node) { super(node); this.callee = callee; this.node = node; } explain() { return `Calling non-function value ${(0, stringify_1.stringify)(this.callee)}.`; } elaborate() { const calleeVal = this.callee; const calleeStr = (0, stringify_1.stringify)(calleeVal); let argStr = ''; const callArgs = this.node.arguments; argStr = callArgs.map(astring_1.generate).join(', '); const elabStr = `Because ${calleeStr} is not a function, you cannot run ${calleeStr}(${argStr}).`; const multStr = `If you were planning to perform multiplication by ${calleeStr}, you need to use the * operator.`; if (Number.isFinite(calleeVal)) { return `${elabStr} ${multStr}`; } else { return elabStr; } } } exports.CallingNonFunctionValue = CallingNonFunctionValue; class UndefinedVariable extends runtimeSourceError_1.RuntimeSourceError { constructor(name, node) { super(node); this.name = name; } explain() { return `Name ${this.name} not declared.`; } elaborate() { return `Before you can read the value of ${this.name}, you need to declare it as a variable or a constant. You can do this using the let or const keywords.`; } } exports.UndefinedVariable = UndefinedVariable; class UnassignedVariable extends runtimeSourceError_1.RuntimeSourceError { constructor(name, node) { super(node); this.name = name; } explain() { return `Name ${this.name} declared later in current scope but not yet assigned`; } elaborate() { return `If you're trying to access the value of ${this.name} from an outer scope, please rename the inner ${this.name}. An easy way to avoid this issue in future would be to avoid declaring any variables or constants with the name ${this.name} in the same scope.`; } } exports.UnassignedVariable = UnassignedVariable; class InvalidNumberOfArguments extends runtimeSourceError_1.RuntimeSourceError { constructor(node, expected, got, hasVarArgs = false) { super(node); this.expected = expected; this.got = got; this.hasVarArgs = hasVarArgs; this.calleeStr = (0, astring_1.generate)(node.callee); } explain() { return `Expected ${this.expected} ${this.hasVarArgs ? 'or more ' : ''}arguments, but got ${this.got}.`; } elaborate() { const calleeStr = this.calleeStr; const pluralS = this.expected === 1 ? '' : 's'; return `Try calling function ${calleeStr} again, but with ${this.expected} argument${pluralS} instead. Remember that arguments are separated by a ',' (comma).`; } } exports.InvalidNumberOfArguments = InvalidNumberOfArguments; class VariableRedeclaration extends runtimeSourceError_1.RuntimeSourceError { constructor(node, name, writable) { super(node); this.node = node; this.name = name; this.writable = writable; } explain() { return `Redeclaring name ${this.name}.`; } elaborate() { if (this.writable === true) { const elabStr = `Since ${this.name} has already been declared, you can assign a value to it without re-declaring.`; let initStr = ''; if (this.node.type === 'FunctionDeclaration') { initStr = '(' + this.node.params.map(astring_1.generate).join(',') + ') => {...'; } else if (this.node.type === 'VariableDeclaration') { initStr = (0, astring_1.generate)(this.node.declarations[0].init); } return `${elabStr} As such, you can just do\n\n\t${this.name} = ${initStr};\n`; } else if (this.writable === false) { return `You will need to declare another variable, as ${this.name} is read-only.`; } else { return ''; } } } exports.VariableRedeclaration = VariableRedeclaration; class ConstAssignment extends runtimeSourceError_1.RuntimeSourceError { constructor(node, name) { super(node); this.name = name; } explain() { return `Cannot assign new value to constant ${this.name}.`; } elaborate() { return `As ${this.name} was declared as a constant, its value cannot be changed. You will have to declare a new variable.`; } } exports.ConstAssignment = ConstAssignment; class GetPropertyError extends runtimeSourceError_1.RuntimeSourceError { constructor(node, obj, prop) { super(node); this.obj = obj; this.prop = prop; } explain() { return `Cannot read property ${this.prop} of ${(0, stringify_1.stringify)(this.obj)}.`; } elaborate() { return 'TODO'; } } exports.GetPropertyError = GetPropertyError; class GetInheritedPropertyError extends runtimeSourceError_1.RuntimeSourceError { constructor(node, obj, prop) { super(node); this.obj = obj; this.prop = prop; this.type = types_1.ErrorType.RUNTIME; this.severity = types_1.ErrorSeverity.ERROR; this.location = node.loc ?? constants_1.UNKNOWN_LOCATION; } explain() { return `Cannot read inherited property ${this.prop} of ${(0, stringify_1.stringify)(this.obj)}.`; } elaborate() { return 'TODO'; } } exports.GetInheritedPropertyError = GetInheritedPropertyError; class SetPropertyError extends runtimeSourceError_1.RuntimeSourceError { constructor(node, obj, prop) { super(node); this.obj = obj; this.prop = prop; } explain() { return `Cannot assign property ${this.prop} of ${(0, stringify_1.stringify)(this.obj)}.`; } elaborate() { return 'TODO'; } } exports.SetPropertyError = SetPropertyError; //# sourceMappingURL=errors.js.map