summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-16 16:06:19 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-16 16:06:19 -0400
commit35459f4ef5c9076a331acecd0c16328326c4081b (patch)
tree9432b6c6664db1c89e6d8995a9e07cceb960b7e0
parent8e5455bb58956031658caab650f0a162fc471508 (diff)
switched to labels for break/continue so that switch works in the future
-rw-r--r--abbrevs.txt1
-rw-r--r--cgen.c39
-rw-r--r--decls_cgen.c10
-rw-r--r--main.c1
-rw-r--r--sdecls_cgen.c5
-rw-r--r--toc.c1
-rw-r--r--types.h7
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
diff --git a/cgen.c b/cgen.c
index fe905fc..928e0ff 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
}
diff --git a/main.c b/main.c
index e21285a..e183839 100644
--- a/main.c
+++ b/main.c
@@ -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/>.
-*/
diff --git a/toc.c b/toc.c
index f7a310b..75c25b1 100644
--- a/toc.c
+++ b/toc.c
@@ -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
diff --git a/types.h b/types.h
index a9c2268..20eb28b 100644
--- a/types.h
+++ b/types.h
@@ -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;