shithub: libmujs

Download patch

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 */
 };