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
This commit is contained in:
parent
0dab14d652
commit
1a713d0175
|
@ -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 ] + "."
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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…
Reference in a new issue