Compile switch statements.

This commit is contained in:
Tor Andersson
2014-01-22 23:31:55 +01:00
parent 60253cedab
commit 4c326a51a4
3 changed files with 49 additions and 2 deletions

View File

@@ -744,6 +744,48 @@ static void ctrycatchfinally(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catch
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 @@ static void cstm(JF, js_Ast *stm)
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 */
@@ -905,8 +952,6 @@ static void cstm(JF, js_Ast *stm)
emit(J, F, OP_ENDWITH);
break;
// switch
case STM_TRY:
if (stm->b && stm->c) {
if (stm->d)

View File

@@ -67,6 +67,7 @@ static js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *
node->number = 0;
node->string = NULL;
node->jumps = NULL;
node->casejump = 0;
node->parent = NULL;
if (a) a->parent = node;

View File

@@ -131,6 +131,7 @@ struct js_Ast
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 */
};