aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap/all.h1
-rw-r--r--bootstrap/cgen.c8
-rw-r--r--bootstrap/parse.c26
-rw-r--r--src/main.cff4
4 files changed, 39 insertions, 0 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h
index d1d58d9..6a0de81 100644
--- a/bootstrap/all.h
+++ b/bootstrap/all.h
@@ -410,6 +410,7 @@ enum stmttype {
Sdecl,
Sifelse,
Swhile,
+ Sdowhile,
Sfor,
Siswitch,
Sreturn,
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 9a28829..f79e112 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -347,6 +347,12 @@ genstmt(struct stmt *stmt) {
genblock(stmt->loop.body);
pri("_cont%d:;} _brk%d:;\n", stmt->loop.id, stmt->loop.id);
break;
+ case Sdowhile:
+ pri("do {");
+ genblock(stmt->loop.body);
+ pri("_cont%d:;} while (%e); _brk%d:;\n",
+ stmt->loop.id, &stmt->loop.test, stmt->loop.id);
+ break;
case Sfor:
pri("{\n");
for (int i = 0; i < stmt->loop.ini.n; ++i)
@@ -566,6 +572,8 @@ liftnested(struct stmt *stmt) {
liftnested(blocktostmt(stmt->ifelse.t));
break;
case Swhile:
+ case Sdowhile:
+ liftnestedex(&stmt->loop.test);
liftnested(blocktostmt(stmt->loop.body));
break;
case Sfor:
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 18aa13b..cff303f 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -2223,6 +2223,8 @@ parsestmt(stmt_yielder_t yield, void *yarg, struct parser *P) {
label = tok.str;
if (lexmatch(P, &tok, TKkw_while))
goto whilel;
+ else if (lexmatch(P, &tok, TKkw_do))
+ goto dowhilel;
else if (lexmatch(P, &tok, TKkw_for))
goto forl;
else
@@ -2249,6 +2251,30 @@ parsestmt(stmt_yielder_t yield, void *yarg, struct parser *P) {
free(env.decls);
popenv(P);
}
+ } else if (lexmatch(P, &tok, TKkw_do)) {
+ dowhilel:
+ st.t = Sdowhile;
+ st.span = tok.span;
+ lexexpect(P, '{');
+ st.loop.id = P->loopid++;
+ struct env env = { P->curenv };
+ if (label) {
+ pushenv(P, &env);
+ putdecl(P, tok.span, &(struct decl) { Dlabel, label, .loopid = st.loop.id });
+ }
+ WITH_TMPCHANGE(int, P->curloop, st.loop.id)
+ st.loop.body = parseblock(P).block;
+ if (label) {
+ free(env.decls);
+ popenv(P);
+ }
+ lexexpect(P, TKkw_while);
+ st.loop.test = parseexpr(P);
+ if (st.loop.test.ty->t != TYbool && st.loop.test.ty->t != TYptr)
+ fatal(P, st.loop.test.span,
+ "do-while statement condition must be bool or pointer (%t)",
+ st.loop.test.ty);
+ lexexpect(P, ';');
} else if (lexmatch(P, &tok, TKkw_for)) {
forl:
st.span = tok.span;
diff --git a/src/main.cff b/src/main.cff
index 9280443..9d92612 100644
--- a/src/main.cff
+++ b/src/main.cff
@@ -15,5 +15,9 @@ extern fn main(argc int, argv **u8) int {
foreach(s, i, args->compact(),
printf("%d: %s\n", i, s);
)
+
+ do {
+ printf("hi");
+ } while #f;
}