Skip to content

Commit

Permalink
feat: add continue
Browse files Browse the repository at this point in the history
  • Loading branch information
diohabara committed Jul 25, 2023
1 parent eb3eefb commit d5aa742
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 9 deletions.
10 changes: 10 additions & 0 deletions .gdb_history
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
run test
b main
run test
n
b gen
run test
c
n
s
q
1 change: 1 addition & 0 deletions ccc.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ typedef enum {
ND_FOR, // "for"
ND_BLOCK, // { ... }
ND_BREAK, // "break"
ND_CONTINUE, // "continue"
ND_FUNCALL, // Function call
ND_EXPR_STMT, // Expression statement
ND_STMT_EXPR, // statement expression
Expand Down
28 changes: 22 additions & 6 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ char *argreg8[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"};

int labelseq;
int brkseq;
int contseq;
char *funcname;

void truncate(Type *ty) {
Expand Down Expand Up @@ -218,26 +219,31 @@ void gen(Node *node) {
case ND_WHILE: {
int seq = labelseq++;
int brk = brkseq;
brkseq = seq;
int cont = contseq;
brkseq = contseq = seq;

printf(".Lbegin%d:\n", seq);
printf(".L.continue.%d:\n", seq);
gen(node->cond);
printf(" pop rax\n");
printf(" cmp rax, 0\n");
printf(" je .L.break.%d\n", seq);
gen(node->then);
printf(" jmp .Lbegin%d\n", seq);
printf(" jmp .L.continue.%d\n", seq);
printf(".L.break.%d:\n", seq);

brkseq = brk;
contseq = cont;
return;
}
case ND_FOR: {
int seq = labelseq++;
int brk = brkseq;
brkseq = seq;
int cont = contseq;
brkseq = contseq = seq;

if (node->init) gen(node->init);
if (node->init) {
gen(node->init);
}
printf(".Lbegin%d:\n", seq);
if (node->cond) {
gen(node->cond);
Expand All @@ -246,11 +252,15 @@ void gen(Node *node) {
printf(" je .L.break.%d\n", seq);
}
gen(node->then);
if (node->inc) gen(node->inc);
printf(".L.continue.%d:\n", seq);
if (node->inc) {
gen(node->inc);
}
printf(" jmp .Lbegin%d\n", seq);
printf(".L.break.%d:\n", seq);

brkseq = brk;
contseq = cont;
return;
}
case ND_BLOCK:
Expand All @@ -263,6 +273,12 @@ void gen(Node *node) {
}
printf(" jmp .L.break.%d\n", brkseq);
return;
case ND_CONTINUE:
if (contseq == 0) {
error_tok(node->tok, "stray continue");
}
printf(" jmp .L.continue.%d\n", contseq);
return;
case ND_FUNCALL: {
int nargs = 0;
for (Node *arg = node->args; arg; arg = arg->next) {
Expand Down
5 changes: 5 additions & 0 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ bool is_typename() {
// | "for" "(" (expr? ";" | declaration) expr? ";" expr? ")" stmt
// | "{" stmt* "}"
// | "break" ";"
// | "continue" ";"
// | declaration
// | expr ";"
Node *stmt() {
Expand Down Expand Up @@ -714,6 +715,10 @@ Node *stmt() {
expect(";");
return new_node(ND_BREAK, tok);
}
if (tok = consume("continue")) {
expect(";");
return new_node(ND_CONTINUE, tok);
}
if (is_typename()) {
return declaration();
}
Expand Down
7 changes: 7 additions & 0 deletions tests
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,13 @@ int main() {
assert(3, ({ int i=0; for(;i<10;i++) { for (;;) break; if (i == 3) break; } i; }), "int i=0; for(;i<10;i++) { if (i == 3) break; } i;");
assert(4, ({ int i=0; while (1) { while(1) break; if (i++ == 3) break; } i; }), "int i=0; while { if (i == 3) break; } i;");

assert(10, ({ int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } i; }), "int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } i;");
assert(6, ({ int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } j; }), "int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } j;");
assert(10, ({ int i=0; int j=0; for(;!i;) { for (;j!=10;j++) continue; break; } j; }), "int i=0; int j=0; for(;!i;) { for (;j!=10;j++) continue; break; } j;");
assert(11, ({ int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } i; }), "int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } i;");
assert(5, ({ int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } j; }), "int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } j;");
assert(11, ({ int i=0; int j=0; while(!i) { while (j++!=10) continue; break; } j; }), "int i=0; int j=0; while(!i) { while (j++!=10) continue; break; } j;");

printf("OK\n");
return 0;
}
7 changes: 4 additions & 3 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ bool is_alnum(char c) { return is_alpha(c) || ('0' <= c && c <= '9'); }

char *starts_with_reserved(char *p) {
// Keyword
static char *kw[] = {"return", "if", "else", "while", "for", "char",
"int", "sizeof", "struct", "typedef", "short", "long",
"void", "_Bool", "enum", "static", "break"};
static char *kw[] = {"return", "if", "else", "while", "for",
"char", "int", "sizeof", "struct", "typedef",
"short", "long", "void", "_Bool", "enum",
"static", "break", "continue"};
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) {
int len = strlen(kw[i]);
if (startswith(p, kw[i]) && !is_alnum(p[len])) {
Expand Down

0 comments on commit d5aa742

Please sign in to comment.