Skip to content

Commit

Permalink
pegjs#30: remove usage of BREAK opcode.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Sep 20, 2013
1 parent 292a4bf commit e14add5
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 38 deletions.
45 changes: 19 additions & 26 deletions lib/compiler/passes/generate-bytecode.js
Expand Up @@ -197,10 +197,9 @@ var utils = require("../../utils"),
* interpret(ip + 3 + t, ip + 3 + t + f);
* }
*
* [29] BREAK x
* [29] BREAK offsetToBreakableInstruction - now instruction not used.
*
* break;
* interpret(ip + 1 + x);
*/
module.exports = function(ast, options) {
var consts = [];
Expand Down Expand Up @@ -564,39 +563,33 @@ module.exports = function(ast, options) {
});*/
var minIndex = addConst(node.min);
var maxIndex = addConst(node.max);
var loopCode = buildLoop(
[op.WHILE_NOT_ERROR], // while (elem !== null) {
buildSequence(
[op.APPEND], // result.push(elem); stack:[ [elem...] ]
[op.PUSH, maxIndex], // stack:[ [elem...], min ]
buildCondition( // if (max !== undefined && result.length >= max)
[op.IF_ARRLEN_MAX], // stack:[ [elem...] ]
[op.PUSH, nullIndex], // elem = null; stack:[ [elem...], null ]
expressionCode // else
) // elem = expr(); stack:[ [elem...], elem ]
)
); // } stack:[ [elem...], elem ]
// var placeholderOffset = 2 + 1 + 2 + 3;
// ^ ^ ^ ^
// | | | '- op.IF_ARRLEN_MAX + `then` len + `else` len
// | | '----- op.PUSH, maxIndex
// | '--------- op.APPEND
// '------------- op.WHILE_NOT_ERROR + loop body len
// Replace placeholder after op.BREAK to offset to breakable instruction.
// loopCode[placeholderOffset+1] = -placeholderOffset;// Go to op.WHILE_NOT_ERROR

return buildSequence(
[op.PUSH, emptyArrayIndex], // var result = [] stack:[ [] ]
expressionCode, // var elem = expr(); stack:[ [], elem ]
loopCode, // while (elem !== null) {...}
buildLoop(
[op.WHILE_NOT_ERROR], // while (elem !== null) {
buildSequence(
[op.APPEND], // result.push(elem); stack:[ [elem...] ]
// Check high boundary.
[op.PUSH, maxIndex], // stack:[ [elem...], min ]
buildCondition( // if (max !== undefined && result.length >= max) {
[op.IF_ARRLEN_MAX], // stack:[ [elem...] ]
// push `null` - this break loop on next iteration.
[op.PUSH, nullIndex], // elem = null; stack:[ [elem...], null ]
expressionCode // } else {
) // elem = expr(); stack:[ [elem...], elem ]
) // }
), // } stack:[ [elem...], elem ]
[op.POP], // stack:[ [elem...] ] (pop elem=`null`)
[op.PUSH, minIndex], // stack:[ [elem...], min ]


// Check low boundary.
[op.PUSH, minIndex], // stack:[ [elem...], min ]
buildCondition( // if (min !== undefined && result.length < min)
[op.IF_ARRLEN_MIN], // stack:[ [elem...] ]
buildSequence( // result = null;
[op.POP], [op.PUSH, nullIndex]// stack:[ null ]
[op.POP],
[op.PUSH, nullIndex] // stack:[ null ]
),
[]
)
Expand Down
23 changes: 11 additions & 12 deletions lib/compiler/passes/generate-javascript.js
Expand Up @@ -321,18 +321,17 @@ module.exports = function(ast, options) {
' i = stack.pop();',
indent10(generateCondition('typeof(i)!=="undefined" && stack[stack.length - 1].length >= i', 0)),
' }',
' case ' + op.BREAK + ': {', // BREAK offsetToBreakableInstruction
' if (ips.length == 0) throw new Error("Illegal bytecode: BREAK instruction not in loop: "+ip);',
// <current ip> + <breakable instruction ip offset>
' i = ip + bc[ip + 1];',// get breakable instruction ip
' do {ip = ips.pop(); end = ends.pop();} while (ip !== i);',
// push element as `null`, that mean 'too many elements, this element match failed'.
' stack.push(null);',
//' ip = (ip + bc[ip + 1]) + 1;',
// <opcode + field for len> + <len of breakable instruction body>
' ip += 2 + bc[ip + 1];',
' break;',
' }',
// ' case ' + op.BREAK + ': {', // BREAK offsetToBreakableInstruction
// ' if (ips.length == 0) throw new Error("Illegal bytecode: BREAK instruction not in loop: "+ip);',
// // <current ip> + <breakable instruction ip offset>
// ' i = ip + bc[ip + 1];',// get breakable instruction ip
// ' do {ip = ips.pop(); end = ends.pop();} while (ip !== i);',
// // push element as `null`, that mean 'too many elements, this element match failed'.
// ' stack.push(null);',
// // <opcode + field for len> + <len of breakable instruction body>
// ' ip += 2 + bc[ip + 1];',
// ' break;',
// ' }',
' default:',
' throw new Error("Invalid opcode: " + bc[ip] + ".");',
' }',
Expand Down

0 comments on commit e14add5

Please sign in to comment.