Skip to content

Commit 5e0e0b2

Browse files
author
Johan Wiltink
committed
2 parents 6d6842e + 2e8e1d6 commit 5e0e0b2

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

src/lambda-calculus.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,12 +343,15 @@ function evalLC(term) {
343343
// term :: Tuple
344344
// isRight :: bool (indicating whether the term is left or right side of an Application)
345345
// isEvaluated :: bool (indicating whether the current term should be stored in the Env)
346+
// callstack :: [String] (History of var lookups, for better error messages)
346347
function runEval({term,env},stack) { // stack: [[term, isRight, isEvaluated]], term: LC term, env = Env { name => term }
348+
const callstack = []; // Does not persist between requests for arguments
347349
while ( ! ( term instanceof L ) || stack.length > 0 ) {
348350
if ( term instanceof V )
349351
if ( term.name==="()" )
350-
{ console.error(`eval: evaluating undefined inside definition of "${term.defName}"`); throw new EvalError; } // depend on verbosity here
352+
{ printStackTrace("eval: evaluating undefined", term, callstack); throw new EvalError; }
351353
else {
354+
callstack.push(term.name);
352355
const res = env.getValue(term.name);
353356
if ( ! res.env )
354357
term = res;
@@ -405,6 +408,32 @@ function evalLC(term) {
405408
return runEval(term, []);
406409
}
407410

411+
// Print an error, with stack trace according to verbosity level
412+
function printStackTrace(error, term, stack) {
413+
if (config.verbosity == "Calm") return; // No error message for Calm
414+
else if (config.verbosity == "Concise")
415+
console.error(`${error} inside definition of <code>${term.defName}</code>`);
416+
else if (config.verbosity == "Loquacious") {
417+
// Loquacious will provide a stack trace localised to the definition
418+
if (stack.length == 0 || stack[stack.length-1] == term.defName)
419+
console.error(`${error} inside definition of <code>${term.defName}</code>`);
420+
else {
421+
const localStack = stack.slice(stack.indexOf(term.defName)+1).reverse();
422+
console.error(`${error} inside definition of <code>${term.defName}</code>
423+
${localStack.map(v=>'\twhile evaluating <code>' + v + '</code>').join('\n')}`)
424+
}
425+
} else if (config.verbosity == "Verbose") {
426+
// Verbose will provide a full stack trace
427+
if (stack.length == 0)
428+
console.error(`${error} inside definition of <code>${term.defName}</code>`);
429+
else {
430+
const localStack = stack.reverse();
431+
console.error(`${error} inside definition of <code>${term.defName}</code>
432+
${localStack.map(v=>'\twhile evaluating <code>' + v + '</code>').join('\n')}`)
433+
}
434+
}
435+
}
436+
408437
Object.defineProperty( Function.prototype, "valueOf", { value: function valueOf() { return toInt(this); } } );
409438

410439
exports.config = config;

0 commit comments

Comments
 (0)