Browse Source

Add some useful debug information to some exceptions (#475)

* Add some useful debug information to some exceptions

* Add guard for visitor functions preventing from cryptic errors due to incomplete visitors

* Add guard for js generator for preventing from cryptic errors due to incarrect stack manipulations
master
Mingun 5 years ago
committed by Futago-za Ryuu
parent
commit
1a713d0175
  1. 25
      lib/compiler/passes/generate-js.js
  2. 10
      lib/compiler/visitor.js

25
lib/compiler/passes/generate-js.js

@ -547,7 +547,10 @@ function generateJS( ast, options ) {
"",
" // istanbul ignore next",
" default:",
" throw new Error(\"Invalid opcode: \" + bc[ip] + \".\");",
" throw new Error(",
" \"Rule #\" + index + \"" + ( options.trace ? " ('\" + peg$ruleNames[ index ] + \"')" : "" ) + ", position \" + ip + \": \"",
" + \"Invalid opcode \" + bc[ip] + \".\"",
" );",
" }",
" }",
"",
@ -574,6 +577,9 @@ function generateJS( ast, options ) {
function s( i ) {
// istanbul ignore next
if ( i < 0 ) throw new Error( "Rule '" + rule.name + "': Var stack underflow: attempt to use var at index " + i );
return "s" + i;
} // |stack[i]| of the abstract machine
@ -629,6 +635,7 @@ function generateJS( ast, options ) {
function compileCondition( cond, argCount ) {
const pos = ip;
const baseLength = argCount + 3;
const thenLength = bc[ ip + baseLength - 2 ];
const elseLength = bc[ ip + baseLength - 1 ];
@ -651,7 +658,9 @@ function generateJS( ast, options ) {
if ( thenSp !== elseSp ) {
throw new Error(
"Branches of a condition must move the stack pointer in the same way."
"Rule '" + rule.name + "', position " + pos + ": "
+ "Branches of a condition can't move the stack pointer differently "
+ "(before: " + baseSp + ", after then: " + thenSp + ", after else: " + elseSp + ")."
);
}
@ -672,6 +681,7 @@ function generateJS( ast, options ) {
function compileLoop( cond ) {
const pos = ip;
const baseLength = 2;
const bodyLength = bc[ ip + baseLength - 1 ];
const baseSp = stack.sp;
@ -685,7 +695,11 @@ function generateJS( ast, options ) {
// istanbul ignore if
if ( bodySp !== baseSp ) {
throw new Error( "Body of a loop can't move the stack pointer." );
throw new Error(
"Rule '" + rule.name + "', position " + pos + ": "
+ "Body of a loop can't move the stack pointer "
+ "(before: " + baseSp + ", after: " + bodySp + ")."
);
}
@ -907,7 +921,10 @@ function generateJS( ast, options ) {
// istanbul ignore next
default:
throw new Error( "Invalid opcode: " + bc[ ip ] + "." );
throw new Error(
"Rule '" + rule.name + "', position " + ip + ": "
+ "Invalid opcode " + bc[ ip ] + "."
);
}

10
lib/compiler/visitor.js

@ -9,9 +9,17 @@ class ASTVisitor {
// Will traverse the node, strictly assuming the visitor can handle the node type.
visit( node ) {
// istanbul ignore next
if ( ! node ) throw new Error( "Visitor function called with no or `null` node" );
const func = this[ node.type ];
// istanbul ignore next
if ( ! func ) throw new Error( "Visitor function for node type '" + node.type + " not defined" );
const args = __slice.call( arguments, 0 );
return this[ node.type ].apply( this, args );
return func.apply( this, args );
}

Loading…
Cancel
Save