diff options
| author | 2022-08-13 07:11:23 +0200 | |
|---|---|---|
| committer | 2022-08-13 07:11:23 +0200 | |
| commit | 58af6dcf569c7f83b317d30f8dd85d96d314d785 (patch) | |
| tree | 76d53089d8510ab9cade4e21200b36d648c4ecb6 /bootstrap | |
| parent | d98b1ecb7a23b369e533f20386cb7aa83156d25d (diff) | |
cond switch
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/all.h | 8 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 19 | ||||
| -rw-r--r-- | bootstrap/parse.c | 33 |
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); } } |