The previous update (and, embarassingly, the "nasal 1.0" release I
announced on Freshmeat.net) was broken. This is the proper break/continue fix.
This commit is contained in:
@@ -601,11 +601,11 @@ static naRef run(struct Context* ctx)
|
|||||||
ctx->markTop--;
|
ctx->markTop--;
|
||||||
break;
|
break;
|
||||||
case OP_BREAK: // restore stack state (FOLLOW WITH JMP!)
|
case OP_BREAK: // restore stack state (FOLLOW WITH JMP!)
|
||||||
ctx->opTop = ctx->markStack[--ctx->markTop];
|
|
||||||
break;
|
|
||||||
case OP_CONTINUE: // same, but don't modify markTop
|
|
||||||
ctx->opTop = ctx->markStack[ctx->markTop-1];
|
ctx->opTop = ctx->markStack[ctx->markTop-1];
|
||||||
break;
|
break;
|
||||||
|
case OP_BREAK2: // same, but also pop the mark stack
|
||||||
|
ctx->opTop = ctx->markStack[--ctx->markTop];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ERR(ctx, "BUG: bad opcode");
|
ERR(ctx, "BUG: bad opcode");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ enum {
|
|||||||
OP_DUP, OP_XCHG, OP_INSERT, OP_EXTRACT, OP_MEMBER, OP_SETMEMBER,
|
OP_DUP, OP_XCHG, OP_INSERT, OP_EXTRACT, OP_MEMBER, OP_SETMEMBER,
|
||||||
OP_LOCAL, OP_SETLOCAL, OP_NEWVEC, OP_VAPPEND, OP_NEWHASH, OP_HAPPEND,
|
OP_LOCAL, OP_SETLOCAL, OP_NEWVEC, OP_VAPPEND, OP_NEWHASH, OP_HAPPEND,
|
||||||
OP_MARK, OP_UNMARK, OP_BREAK, OP_FTAIL, OP_MTAIL, OP_SETSYM, OP_DUP2,
|
OP_MARK, OP_UNMARK, OP_BREAK, OP_FTAIL, OP_MTAIL, OP_SETSYM, OP_DUP2,
|
||||||
OP_INDEX, OP_CONTINUE
|
OP_INDEX, OP_BREAK2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ static void genBreakContinue(struct Parser* p, struct Token* t)
|
|||||||
bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
|
bp = p->cg->loops[p->cg->loopTop - levels].breakIP;
|
||||||
cp = p->cg->loops[p->cg->loopTop - levels].contIP;
|
cp = p->cg->loops[p->cg->loopTop - levels].contIP;
|
||||||
for(i=0; i<levels; i++)
|
for(i=0; i<levels; i++)
|
||||||
emit(p, (t->type == TOK_BREAK || i>0) ? OP_BREAK : OP_CONTINUE);
|
emit(p, (i<levels-1) ? OP_BREAK2 : OP_BREAK);
|
||||||
if(t->type == TOK_BREAK)
|
if(t->type == TOK_BREAK)
|
||||||
emit(p, OP_PUSHNIL); // breakIP is always a JIFNOT/JIFNIL!
|
emit(p, OP_PUSHNIL); // breakIP is always a JIFNOT/JIFNIL!
|
||||||
emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
|
emitImmediate(p, OP_JMP, t->type == TOK_BREAK ? bp : cp);
|
||||||
|
|||||||
Reference in New Issue
Block a user