aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-13 07:11:23 +0200
committerlemon <lsof@mailbox.org>2022-08-13 07:11:23 +0200
commit58af6dcf569c7f83b317d30f8dd85d96d314d785 (patch)
tree76d53089d8510ab9cade4e21200b36d648c4ecb6 /bootstrap
parentd98b1ecb7a23b369e533f20386cb7aa83156d25d (diff)
cond switch
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/all.h8
-rw-r--r--bootstrap/cgen.c19
-rw-r--r--bootstrap/parse.c33
3 files changed, 59 insertions, 1 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h
index ceb9841..9bbab37 100644
--- a/bootstrap/all.h
+++ b/bootstrap/all.h
@@ -421,6 +421,7 @@ enum stmttype {
Seuswitch,
Sbreak,
Scontinue,
+ Scswitch,
};
struct iswitchcase {
@@ -471,6 +472,13 @@ struct stmt {
struct {
int id;
} brkcon;
+ struct {
+ slice_t(struct cswitchcase {
+ struct expr test;
+ struct blockstmt t;
+ }) cs;
+ struct blockstmt *f;
+ } cswitch;
};
};
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 7519982..baf8999 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -442,6 +442,17 @@ genstmt(struct stmt *stmt) {
case Scontinue:
pri("goto _cont%d;\n", stmt->brkcon.id);
break;
+ case Scswitch:
+ pri("if (0) ;\n");
+ for (int i = 0; i < stmt->cswitch.cs.n; ++i) {
+ pri("else if (%e)\n", &stmt->cswitch.cs.d[i].test);
+ genblock(stmt->cswitch.cs.d[i].t);
+ }
+ if (stmt->cswitch.f) {
+ pri("else\n");
+ genblock(*stmt->cswitch.f);
+ }
+ break;
}
}
@@ -626,6 +637,14 @@ liftnested(struct stmt *stmt) {
break;
case Sbreak: case Scontinue:
break;
+ case Scswitch:
+ for (int i = 0; i < stmt->cswitch.cs.n; ++i) {
+ liftnestedex(&stmt->cswitch.cs.d[i].test);
+ liftnested(blocktostmt(stmt->cswitch.cs.d[i].t));
+ }
+ if (stmt->cswitch.f)
+ liftnested(blocktostmt(*stmt->cswitch.f));
+ break;
}
}
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index bf6b534..74ab2e2 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -2113,6 +2113,37 @@ psteuswitch(struct parser *P, const struct expr *test) {
}
static struct stmt
+pstcswitch(struct parser *P) {
+ struct stmt st = {Scswitch};
+ struct tok tok;
+ vec_t(struct cswitchcase) cs = {0};
+ struct blockstmt *f = NULL;
+
+ while (!lexmatch(P, &tok, '}')) {
+ struct cswitchcase c = {0};
+
+ lexexpect(P, TKkw_case);
+
+ if (lexmatch(P, &tok, TKkw_else)) {
+ if (f)
+ fatal(P, tok.span, "duplicate 'case else' block");
+ f = malloc(sizeof *f);
+ *f = parseblock0(P);
+ } else {
+ c.test = parseexpr(P);
+ lexexpect(P, ';');
+ c.t = parseblock0(P);
+ vec_push(&cs, c);
+ }
+ }
+
+ vec_slice_cpy(&st.cswitch.cs, &cs);
+ st.cswitch.f = f;
+ return st;
+
+}
+
+static struct stmt
pstswitch(struct parser *P) {
struct tok tok;
struct expr test;
@@ -2126,7 +2157,7 @@ pstswitch(struct parser *P) {
else
fatal(P, test.span, "bad switch test expression (%t)", test.ty);
} else {
- assert(0 && "NYI");
+ return pstcswitch(P);
}
}