ref: 14043f0e11d6a464df9688a67c239e666b4d84c3
parent: a6a5bd79946f3c2c05f8bb2099e54a6a1c63f5a4
author: Tor Andersson <tor@ccxvii.net>
date: Tue Jan 21 22:52:28 EST 2014
Implement unlabeled break and continue. TODO: Does not traverse block edges to add balancing endwith instructions.
--- a/jscompile.c
+++ b/jscompile.c
@@ -146,6 +146,11 @@
F->code[inst] = F->codelen;
}
+static void labelto(JF, int inst, int addr)
+{
+ F->code[inst] = addr;
+}
+
/* Expressions */
static void cunary(JF, js_Ast *exp, int opcode)
@@ -551,6 +556,22 @@
}
}
+/* Patch break and continue statements */
+
+static void labelexit(JF, js_Ast *top, js_Ast *node, js_AstType T, int addr)
+{
+ if (node->type == T) {
+ // TODO: check if top is our real target
+ if (F->code[node->inst] == 0)
+ labelto(J, F, node->inst, addr);
+ } else if (node->type >= STM_BLOCK || node->type == AST_LIST) {
+ if (node->a) labelexit(J, F, top, node->a, T, addr);
+ if (node->b) labelexit(J, F, top, node->b, T, addr);
+ if (node->c) labelexit(J, F, top, node->c, T, addr);
+ if (node->d) labelexit(J, F, top, node->d, T, addr);
+ }
+}
+
/* Statements */
static void cstm(JF, js_Ast *stm)
@@ -563,6 +584,8 @@
case STM_BLOCK:
cstmlist(J, F, stm->a);
+ if (stm->parent && stm->parent->type == STM_LABEL)
+ labelexit(J, F, stm, stm->a, STM_BREAK, here(J, F));
break;
case STM_NOP:
@@ -594,6 +617,8 @@
cstm(J, F, stm->a);
cexp(J, F, stm->b);
jumpto(J, F, OP_JTRUE, loop);
+ labelexit(J, F, stm, stm->a, STM_CONTINUE, loop);
+ labelexit(J, F, stm, stm->a, STM_BREAK, here(J, F));
break;
case STM_WHILE:
@@ -603,6 +628,8 @@
cstm(J, F, stm->b);
jumpto(J, F, OP_JUMP, loop);
label(J, F, end);
+ labelexit(J, F, stm, stm->b, STM_CONTINUE, loop);
+ labelexit(J, F, stm, stm->b, STM_BREAK, here(J, F));
break;
case STM_FOR:
@@ -621,6 +648,8 @@
emit(J, F, OP_POP);
jumpto(J, F, OP_JUMP, loop);
label(J, F, end);
+ labelexit(J, F, stm, stm->d, STM_CONTINUE, loop);
+ labelexit(J, F, stm, stm->d, STM_BREAK, here(J, F));
break;
case STM_FOR_IN:
@@ -640,11 +669,19 @@
cstm(J, F, stm->c);
jumpto(J, F, OP_JUMP, loop);
label(J, F, end);
+ labelexit(J, F, stm, stm->c, STM_CONTINUE, loop);
+ labelexit(J, F, stm, stm->c, STM_BREAK, here(J, F));
break;
// label
- // break
- // continue
+
+ case STM_BREAK:
+ stm->inst = jump(J, F, OP_JUMP);
+ break;
+
+ case STM_CONTINUE:
+ stm->inst = jump(J, F, OP_JUMP);
+ break;
case STM_RETURN:
if (stm->a)
--- a/jsparse.c
+++ b/jsparse.c
@@ -66,6 +66,13 @@
node->d = d;
node->number = 0;
node->string = NULL;
+ node->inst = 0;
+
+ node->parent = NULL;
+ if (a) a->parent = node;
+ if (b) b->parent = node;
+ if (c) c->parent = node;
+ if (d) d->parent = node;
node->gcnext = J->gcast;
J->gcast = node;
--- a/jsparse.h
+++ b/jsparse.h
@@ -118,9 +118,10 @@
{
int type;
int line;
- js_Ast *a, *b, *c, *d;
+ js_Ast *parent, *a, *b, *c, *d;
double number;
const char *string;
+ int inst; /* for patching jumps */
js_Ast *gcnext; /* next in alloc list */
};