ref: 8d3c95abbdf285aa5a820607c5d4c32ab3dff70d
parent: b09facc71149bd600d32d2c063c762e78340bda9
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Apr 24 13:30:34 EDT 2014
Add switch statement
--- a/cc1.h
+++ b/cc1.h
@@ -231,7 +231,9 @@
emitsym(Node *), emitunary(Node *),
emitbin(Node *), emitexp(Node *),
emitprint(Node *), emitlabel(Symbol *), emitjump(Symbol *, Node *),
- emitbloop(void), emiteloop(void);
+ emitbloop(void), emiteloop(void),
+ emitswitch(short, Node *), emitcase(Symbol *, Node *),
+ emitdefault(Symbol *);
extern Node
*node(void (*code)(Node *),
--- a/code.c
+++ b/code.c
@@ -235,6 +235,29 @@
emitexp(np);
}
+void
+emitswitch(short nr, Node *np)
+{
+ printf("\teI\t#%0x", nr);
+ emitexp(np);
+}
+
+void
+emitcase(Symbol *sym, Node *np)
+{
+ fputs("\tw", stdout);
+ (*np->code)(np);
+ putchar('\t');
+ emitlabel(sym);
+}
+
+void
+emitdefault(Symbol *sym)
+{
+ fputs("\tf\t", stdout);
+ emitlabel(sym);
+}
+
Node *
castcode(Node *child, Type *tp)
{
--- a/stmt.c
+++ b/stmt.c
@@ -8,11 +8,13 @@
struct scase {
int val;
Symbol *label;
+ Node *expr;
struct scase *next;
};
struct caselist {
short nr;
+ Symbol *deflabel;
struct scase *head;
};
@@ -199,6 +201,30 @@
expect(';');
}
+static void
+Switch(Symbol *lcont)
+{
+ Caselist lcase = {.nr = 0, .head = NULL, .deflabel = NULL};
+ struct scase *p;
+ Symbol *lbreak = label(NULL, 1), *lcond = label(NULL, 1);
+ Node *cond;
+
+ expect(SWITCH);
+ expect ('(');
+ cond = eval(expr());
+ expect (')');
+ /* TODO: check integer type */
+ emitjump(lcond, NULL);
+ stmt(lbreak, lcont, &lcase);
+ emitlabel(lcond);
+ emitswitch(lcase.nr, cond);
+ for (p = lcase.head; p; p = p->next)
+ emitcase(p->label, p->expr);
+ if (lcase.deflabel)
+ emitdefault(lcase.deflabel);
+ emitlabel(lbreak);
+}
+
void
compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
@@ -231,6 +257,7 @@
case BREAK: Break(lbreak); break;
case CONTINUE: Continue(lcont); break;
case GOTO: Goto(); break;
+ case SWITCH: Switch(lcont); break;
case IDEN:
if (ahead() == ':') {
Label();