diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-16 16:06:19 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-16 16:06:19 -0400 |
commit | 35459f4ef5c9076a331acecd0c16328326c4081b (patch) | |
tree | 9432b6c6664db1c89e6d8995a9e07cceb960b7e0 | |
parent | 8e5455bb58956031658caab650f0a162fc471508 (diff) |
switched to labels for break/continue so that switch works in the future
-rw-r--r-- | abbrevs.txt | 1 | ||||
-rw-r--r-- | cgen.c | 39 | ||||
-rw-r--r-- | decls_cgen.c | 10 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | sdecls_cgen.c | 5 | ||||
-rw-r--r-- | toc.c | 1 | ||||
-rw-r--r-- | types.h | 7 |
7 files changed, 48 insertions, 16 deletions
diff --git a/abbrevs.txt b/abbrevs.txt index 3b37880..8c5ad76 100644 --- a/abbrevs.txt +++ b/abbrevs.txt @@ -16,6 +16,7 @@ fn - function ident - identifier inc - include kw - keyword +lbl - label len - length nms - namespace num - number @@ -6,6 +6,7 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Allocator *allocr) { g->outc = out; g->ident_counter = 0; + g->lbl_counter = 0; g->main_ident = ident_get(ids, "main"); g->will_indent = true; g->indent_lvl = 0; @@ -212,6 +213,11 @@ static inline char *cgen_ident_to_str(Identifier i) { static inline void cgen_ident_id(CGenerator *g, IdentID id) { cgen_write(g, "a%lu_", (unsigned long)id); } + +static inline void cgen_lbl(CGenerator *g, IdentID lbl) { + cgen_write(g, "lbl%lu_", (unsigned long)lbl); +} + /* used for fields */ static inline void cgen_ident_simple(CGenerator *g, Identifier i) { cgen_indent(g); @@ -1120,6 +1126,11 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { } } cgen_block(g, &fo->body, ret_name, CGEN_BLOCK_NOBRACES); + if (fo->body.c.break_lbl) { + cgen_lbl(g, fo->body.c.break_lbl); + cgen_writeln(g, ":;"); + } + cgen_write(g, "}}"); } break; case EXPR_BLOCK: @@ -1686,10 +1697,10 @@ static void cgen_expr(CGenerator *g, Expression *e) { static void cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) { Block *prev_block = g->block; g->block = b; + ++g->indent_lvl; if (!(flags & CGEN_BLOCK_NOBRACES)) { - cgen_write(g, "{"); - cgen_nl(g); + cgen_writeln(g, "{"); } arr_foreach(b->stmts, Statement, s) cgen_stmt(g, s); @@ -1702,8 +1713,18 @@ static void cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) } cgen_nl(g); } - if (!(flags & CGEN_BLOCK_NOBRACES)) + if (b->c.cont_lbl) { + cgen_lbl(g, b->c.cont_lbl); + cgen_writeln(g, ":;"); + } + --g->indent_lvl; + if (!(flags & CGEN_BLOCK_NOBRACES)) { cgen_write(g, "}"); + if (b->c.break_lbl) { + cgen_lbl(g, b->c.break_lbl); + cgen_writeln(g, ":;"); + } + } g->block = prev_block; } @@ -1809,8 +1830,8 @@ static void cgen_fn(CGenerator *g, FnExpr *f, Value *compile_time_args) { cgen_ret(g, f->body.ret_expr); } - cgen_write(g, "}"); - cgen_nl(g); + cgen_writeln(g, "}"); + g->fn = prev_fn; cgen_nl(g); cgen_nl(g); @@ -1998,10 +2019,14 @@ static void cgen_stmt(CGenerator *g, Statement *s) { } break; case STMT_BREAK: - cgen_writeln(g, "break;"); + cgen_write(g, "goto "); + cgen_lbl(g, s->referring_to->c.break_lbl); + cgen_writeln(g, ";"); break; case STMT_CONT: - cgen_writeln(g, "continue;"); + cgen_write(g, "goto "); + cgen_lbl(g, s->referring_to->c.cont_lbl); + cgen_writeln(g, ";"); break; case STMT_MESSAGE: break; diff --git a/decls_cgen.c b/decls_cgen.c index 72d9105..045367e 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -37,6 +37,8 @@ static void cgen_sdecls_type(CGenerator *g, Type *type) { static void cgen_sdecls_block(CGenerator *g, Block *b) { Block *prev_block = g->block; g->block = b; + b->c.break_lbl = 0; + b->c.cont_lbl = 0; arr_foreach(b->stmts, Statement, s) cgen_sdecls_stmt(g, s); @@ -150,7 +152,15 @@ static void cgen_sdecls_stmt(CGenerator *g, Statement *s) { } break; case STMT_BREAK: + if (!s->referring_to->c.break_lbl) { + s->referring_to->c.break_lbl = ++g->lbl_counter; + } + break; case STMT_CONT: + if (!s->referring_to->c.cont_lbl) { + s->referring_to->c.cont_lbl = ++g->lbl_counter; + } + break; case STMT_MESSAGE: break; } @@ -18,7 +18,6 @@ sizeof (not #sizeof) start making a standard library... (printf; stringbuilder would be nice to have) switch - #fallthrough - - make sure break works inside a switch with cgen! - you'll need goto enums unions --- diff --git a/sdecls_cgen.c b/sdecls_cgen.c deleted file mode 100644 index 4033d4d..0000000 --- a/sdecls_cgen.c +++ /dev/null @@ -1,5 +0,0 @@ -/* - Copyright (C) 2019, 2020 Leo Tenenbaum. - This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever. - You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>. -*/ @@ -166,7 +166,6 @@ static char *read_file_contents(Allocator *a, const char *filename, Location whe static void cgen_decls_file(CGenerator *g, ParsedFile *f); static void cgen_sdecls_file(CGenerator *g, ParsedFile *f); #include "cgen.c" -#include "sdecls_cgen.c" #include "decls_cgen.c" #ifdef RUN_TESTS @@ -501,6 +501,9 @@ enum { typedef U8 BlockFlags; typedef struct Block { BlockFlags flags; + struct { + IdentID break_lbl, cont_lbl; /* initially 0, set to non-zero values if needed (++g->lbl_counter); set by sdecls_cgen. */ + } c; Location where; Identifiers idents; struct Statement *stmts; @@ -974,7 +977,7 @@ typedef struct Statement { Return ret; Include inc; Message message; /* #error, #warn, #info */ - Block *referring_to; /* for break/continue */ + Block *referring_to; /* for break/continue; set during typing */ }; } Statement; @@ -1038,7 +1041,7 @@ typedef struct Typer { typedef struct CGenerator { Allocator *allocr; FILE *outc; - IdentID ident_counter; + IdentID ident_counter, lbl_counter; int indent_lvl; /* how many levels of indentation? */ bool will_indent; /* will the next thing be indented? */ ParsedFile *file; |