ref: 4c326a51a42436f9277cc86bf83d2e6dc4d3711e
parent: 60253cedab034cda3765a882fe2525a215c4d390
author: Tor Andersson <[email protected]>
date: Wed Jan 22 18:31:55 EST 2014
Compile switch statements.
--- a/jscompile.c
+++ b/jscompile.c
@@ -744,6 +744,48 @@
cstm(J, F, finallystm);
}
+/* Switch */
+
+static void cswitch(JF, js_Ast *ref, js_Ast *head)
+{
+ js_Ast *node, *clause, *def = NULL;
+ int end;
+
+ cexp(J, F, ref);
+
+ /* emit an if-else chain of tests for the case clause expressions */
+ for (node = head; node; node = node->b) {
+ clause = node->a;
+ if (clause->type == STM_DEFAULT) {
+ if (def)
+ jsC_error(J, clause, "more than one default label in switch");
+ def = clause;
+ } else {
+ emit(J, F, OP_DUP);
+ cexp(J, F, clause->a);
+ emit(J, F, OP_STRICTEQ);
+ clause->casejump = jump(J, F, OP_JTRUE);
+ }
+ }
+ if (def)
+ def->casejump = jump(J, F, OP_JUMP);
+ else
+ end = jump(J, F, OP_JUMP);
+
+ /* emit the casue clause bodies */
+ for (node = head; node; node = node->b) {
+ clause = node->a;
+ label(J, F, clause->casejump);
+ if (clause->type == STM_DEFAULT)
+ cstmlist(J, F, clause->a);
+ else
+ cstmlist(J, F, clause->b);
+ }
+
+ if (!def)
+ label(J, F, end);
+}
+
/* Statements */
static void cstm(JF, js_Ast *stm)
@@ -843,6 +885,11 @@
labeljumps(J, F, stm->jumps, here(J,F), loop);
break;
+ case STM_SWITCH:
+ cswitch(J, F, stm->a, stm->b);
+ labeljumps(J, F, stm->jumps, here(J,F), 0);
+ break;
+
case STM_LABEL:
cstm(J, F, stm->b);
/* skip consecutive labels */
@@ -904,8 +951,6 @@
cstm(J, F, stm->b);
emit(J, F, OP_ENDWITH);
break;
-
- // switch
case STM_TRY:
if (stm->b && stm->c) {
--- a/jsparse.c
+++ b/jsparse.c
@@ -67,6 +67,7 @@
node->number = 0;
node->string = NULL;
node->jumps = NULL;
+ node->casejump = 0;
node->parent = NULL;
if (a) a->parent = node;
--- a/jsparse.h
+++ b/jsparse.h
@@ -131,6 +131,7 @@
double number;
const char *string;
js_JumpList *jumps; /* list of break/continue jumps to patch */
+ int casejump; /* for switch case clauses */
js_Ast *gcnext; /* next in alloc list */
};