summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c34
-rw-r--r--copy.c14
-rw-r--r--decls_cgen.c34
-rw-r--r--eval.c31
-rw-r--r--main.c4
-rw-r--r--parse.c15
-rwxr-xr-xtest-build.sh2
-rw-r--r--test.toc3
-rw-r--r--types.c124
-rw-r--r--types.h13
10 files changed, 147 insertions, 127 deletions
diff --git a/cgen.c b/cgen.c
index f962e4c..5927858 100644
--- a/cgen.c
+++ b/cgen.c
@@ -2135,16 +2135,6 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
unsigned has_expr = r->flags & RET_HAS_EXPR;
cgen_ret(g, r->referring_to, has_expr ? &r->expr : NULL);
} break;
- case STMT_INCLUDE: {
- Include *i = s->inc;
- if (i->inc_file && (i->inc_file->flags & INC_FILE_CGEND)){
- /* already generated */
- } else {
- if (i->inc_file) i->inc_file->flags |= INC_FILE_CGEND;
- arr_foreach(i->stmts, Statement, sub)
- cgen_stmt(g, sub);
- }
- } break;
case STMT_BREAK: {
Block *b = s->referring_to;
cgen_deferred_up_to(g, b);
@@ -2165,6 +2155,13 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
case STMT_USE:
case STMT_MESSAGE:
break;
+ case STMT_INLINE_BLOCK:
+ arr_foreach(s->inline_block, Statement, sub)
+ cgen_stmt(g, sub);
+ break;
+ case STMT_INCLUDE:
+ assert(0);
+ break;
}
}
@@ -2210,16 +2207,6 @@ static void cgen_defs_stmt(CGenerator *g, Statement *s) {
if (s->ret->flags & RET_HAS_EXPR)
cgen_defs_expr(g, &s->ret->expr);
break;
- case STMT_INCLUDE: {
- Include *i = s->inc;
- if (i->inc_file && (i->inc_file->flags & INC_FILE_CGEND_DEFS)) {
- /* already generated */
- } else {
- if (i->inc_file) i->inc_file->flags |= INC_FILE_CGEND_DEFS;
- arr_foreach(i->stmts, Statement, sub)
- cgen_defs_stmt(g, sub);
- }
- } break;
case STMT_BREAK:
case STMT_CONT:
case STMT_MESSAGE:
@@ -2230,6 +2217,13 @@ static void cgen_defs_stmt(CGenerator *g, Statement *s) {
case STMT_USE:
cgen_defs_expr(g, &s->use->expr);
break;
+ case STMT_INLINE_BLOCK:
+ arr_foreach(s->inline_block, Statement, sub)
+ cgen_defs_stmt(g, sub);
+ break;
+ case STMT_INCLUDE:
+ assert(0);
+ break;
}
}
diff --git a/copy.c b/copy.c
index 13615ac..05b1eea 100644
--- a/copy.c
+++ b/copy.c
@@ -378,6 +378,7 @@ static void copy_decl(Copier *c, Declaration *out, Declaration *in) {
static void copy_stmt(Copier *c, Statement *out, Statement *in) {
*out = *in;
+ assert(!(in->flags & STMT_TYPED));
switch (in->kind) {
case STMT_RET:
out->ret = copier_malloc(c, sizeof *out->ret);
@@ -388,15 +389,7 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
case STMT_INCLUDE:
out->inc = copier_malloc(c, sizeof *out->inc);
*out->inc = *in->inc;
- if (in->flags & STMT_TYPED) {
- size_t nstmts = arr_len(in->inc->stmts);
- arr_set_lena(out->inc->stmts, nstmts, c->allocr);
- for (size_t i = 0; i < nstmts; ++i) {
- copy_stmt(c, &out->inc->stmts[i], &in->inc->stmts[i]);
- }
- } else {
- copy_expr(c, &out->inc->filename, &in->inc->filename);
- }
+ copy_expr(c, &out->inc->filename, &in->inc->filename);
break;
case STMT_EXPR:
out->expr = copy_expr_(c, in->expr);
@@ -420,6 +413,9 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
*out->use = *in->use;
copy_expr(c, &out->use->expr, &in->use->expr);
break;
+ case STMT_INLINE_BLOCK:
+ assert(0); /* only exists after typing */
+ break;
}
}
diff --git a/decls_cgen.c b/decls_cgen.c
index 80b6a38..5b2603b 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -138,16 +138,6 @@ static void cgen_sdecls_stmt(CGenerator *g, Statement *s) {
if (r->flags & RET_HAS_EXPR)
cgen_sdecls_expr(g, &r->expr);
} break;
- case STMT_INCLUDE: {
- Include *i = s->inc;
- if (i->inc_file && (i->inc_file->flags & INC_FILE_CGEND_SDECLS)) {
- /* already generated */
- } else {
- if (i->inc_file) i->inc_file->flags |= INC_FILE_CGEND_SDECLS;
- arr_foreach(i->stmts, Statement, sub)
- cgen_sdecls_stmt(g, sub);
- }
- } break;
case STMT_BREAK:
if (!s->referring_to->c.break_lbl) {
s->referring_to->c.break_lbl = ++g->lbl_counter;
@@ -166,6 +156,13 @@ static void cgen_sdecls_stmt(CGenerator *g, Statement *s) {
case STMT_USE:
cgen_sdecls_expr(g, &s->use->expr);
break;
+ case STMT_INLINE_BLOCK:
+ arr_foreach(s->inline_block, Statement, sub)
+ cgen_sdecls_stmt(g, sub);
+ break;
+ case STMT_INCLUDE:
+ assert(0);
+ break;
}
}
@@ -386,16 +383,6 @@ static void cgen_decls_stmt(CGenerator *g, Statement *s) {
if (r->flags & RET_HAS_EXPR)
cgen_decls_expr(g, &r->expr);
} break;
- case STMT_INCLUDE: {
- Include *i = s->inc;
- if (i->inc_file && (i->inc_file->flags & INC_FILE_CGEND_DECLS)) {
- /* already generated */
- } else {
- if (i->inc_file) i->inc_file->flags |= INC_FILE_CGEND_DECLS;
- arr_foreach(i->stmts, Statement, sub)
- cgen_decls_stmt(g, sub);
- }
- } break;
case STMT_BREAK:
case STMT_CONT:
case STMT_MESSAGE:
@@ -406,6 +393,13 @@ static void cgen_decls_stmt(CGenerator *g, Statement *s) {
case STMT_USE:
cgen_sdecls_expr(g, &s->use->expr);
break;
+ case STMT_INLINE_BLOCK:
+ arr_foreach(s->inline_block, Statement, sub)
+ cgen_decls_stmt(g, sub);
+ break;
+ case STMT_INCLUDE:
+ assert(0);
+ break;
}
}
diff --git a/eval.c b/eval.c
index 0ade240..cda97da 100644
--- a/eval.c
+++ b/eval.c
@@ -1641,7 +1641,7 @@ static void eval_exit_stmts(Statement *stmts, Statement *last_reached) {
Declaration *d = s->decl;
decl_remove_val(d);
}
- /* STMT_INCLUDEs are handled by eval_stmt; don't worry */
+ /* inline blocks are handled by eval_stmt; don't worry */
}
}
}
@@ -1675,19 +1675,6 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
ev->returning = stmt->referring_to;
ev->is_break = false;
break;
- case STMT_INCLUDE: {
- Include *i = stmt->inc;
- Statement *last_reached = arr_last_ptr(i->stmts);
- arr_foreach(i->stmts, Statement, sub) {
- if (!eval_stmt(ev, sub))
- return false;
- if (ev->returning) {
- last_reached = sub;
- break;
- }
- }
- eval_exit_stmts(i->stmts, last_reached);
- } break;
case STMT_MESSAGE:
break;
case STMT_DEFER:
@@ -1695,6 +1682,22 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
break;
case STMT_USE:
break;
+ case STMT_INLINE_BLOCK: {
+ Statement *stmts = stmt->inline_block;
+ Statement *last_reached = arr_last_ptr(stmts);
+ arr_foreach(stmts, Statement, s) {
+ if (!eval_stmt(ev, s))
+ return false;
+ if (ev->returning) {
+ last_reached = s;
+ break;
+ }
+ }
+ eval_exit_stmts(stmts, last_reached);
+ } break;
+ case STMT_INCLUDE:
+ assert(0);
+ break;
}
return true;
}
diff --git a/main.c b/main.c
index b002d8c..704b534 100644
--- a/main.c
+++ b/main.c
@@ -8,10 +8,10 @@
/*
@TODO:
-#if should not create a block
&void
null
fix including something twice - just use the non-namespacey version if it exists or pick one namespace to use everywhere otherwise
+ - maybe store info about namespaces which are secretly the same as inline blocks/other namespaces in the Typer
&&, ||
start making a standard library... (printf; stringbuilder would be nice to have)
improve type_to_str:
@@ -214,7 +214,7 @@ int main(int argc, char **argv) {
Typer tr;
Evaluator ev;
evalr_create(&ev, &tr, &main_allocr);
- typer_create(&tr, &ev, &file, &err_ctx, &main_allocr, &globals);
+ typer_create(&tr, &ev, &err_ctx, &main_allocr, &globals);
if (!types_file(&tr, &f)) {
err_text_important(&err_ctx, "Errors occured while determining types.\n");
diff --git a/parse.c b/parse.c
index 4031170..3780b40 100644
--- a/parse.c
+++ b/parse.c
@@ -2869,14 +2869,9 @@ static void fprint_stmt(FILE *out, Statement *s) {
} break;
case STMT_INCLUDE: {
Include *i = s->inc;
- if (s->flags & STMT_TYPED) {
- arr_foreach(i->stmts, Statement, sub)
- fprint_stmt(out, sub);
- } else {
- fprintf(out, "#include ");
- fprint_expr(out, &i->filename);
- fprintf(out, ";\n");
- }
+ fprintf(out, "#include ");
+ fprint_expr(out, &i->filename);
+ fprintf(out, ";\n");
} break;
case STMT_MESSAGE: {
Message *m = s->message;
@@ -2909,6 +2904,10 @@ static void fprint_stmt(FILE *out, Statement *s) {
fprint_expr(out, &s->use->expr);
fprintf(out, ";\n");
break;
+ case STMT_INLINE_BLOCK:
+ arr_foreach(s->inline_block, Statement, sub)
+ fprint_stmt(out, sub);
+ break;
}
}
diff --git a/test-build.sh b/test-build.sh
index ec63972..45a44f7 100755
--- a/test-build.sh
+++ b/test-build.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-echo "tcc -w main.c -o toc" && tcc -w main.c -o toc || exit 1
+echo "tcc -Wall main.c -o toc" && tcc -Wall main.c -o toc || exit 1 # test without any compiler flags
for CC in tcc gcc clang g++ ; do
CC="$CC" CFLAGS='-Werror' ./build.sh || exit 1
CC="$CC" CFLAGS='-Werror' ./build.sh release || exit 1
diff --git a/test.toc b/test.toc
index f489e67..822084b 100644
--- a/test.toc
+++ b/test.toc
@@ -4,7 +4,8 @@ main ::= fn() {
#if "hello" {
x := 5;
} else {
- x := 6;
+ x : FOOTYPE = 6.3 + "foo";
+ _+3=bar;
}
puti(x);
}
diff --git a/types.c b/types.c
index 112573a..22126a0 100644
--- a/types.c
+++ b/types.c
@@ -2162,39 +2162,9 @@ static Status types_expr(Typer *tr, Expression *e) {
IfExpr *i = e->if_;
IfExpr *curr = i;
if (curr->flags & IF_STATIC) {
- while (1) {
- Expression *cond = curr->cond;
- Expression *next = curr->next_elif;
- Value v;
- if (cond) {
- if (!types_expr(tr, cond))
- return false;
- if (!eval_expr(tr->evalr, cond, &v))
- return false;
- }
- if (!cond || val_truthiness(v, &cond->type)) {
- Block *true_block = &curr->body;
- Statement *last = arr_last_ptr(true_block->stmts);
- if (last && last->kind == STMT_EXPR && (last->flags & STMT_EXPR_NO_SEMICOLON)) {
- err_print(last->where, "#ifs can't return values.");
- return false;
- }
- e->kind = EXPR_BLOCK;
- e->block = true_block;
- break;
- }
- if (!next) break;
- curr = next->if_;
- }
- if (e->kind == EXPR_IF) {
- /* all conds were false */
- e->kind = EXPR_BLOCK;
- e->block = typer_calloc(tr, 1, sizeof *e->block);
- e->block->where = e->where;
- e->block->parent = tr->block;
- idents_create(&e->block->idents, tr->allocr, e->block);
- }
- goto expr_block;
+ /* handled in types_stmt unless there's a problem */
+ err_print(e->where, "You can't use #if in this way. It has to be a statement on its own, and can't return a value.");
+ return false;
}
Type *curr_type = t;
bool has_else = false;
@@ -2852,7 +2822,6 @@ static Status types_expr(Typer *tr, Expression *e) {
free(order);
*t = *ret_type;
} break;
- expr_block:
case EXPR_BLOCK: {
Block *b = e->block;
if (!types_block(tr, b))
@@ -3623,11 +3592,77 @@ static Status types_decl(Typer *tr, Declaration *d) {
return success;
}
+static Status fix_ident_decls_inline_block(Typer *tr, Statement *stmts) {
+ Identifiers *idents = typer_get_idents(tr);
+ arr_foreach(stmts, Statement, s) {
+ if (s->kind == STMT_DECL) {
+ Declaration *d = s->decl;
+ arr_foreach(d->idents, Identifier, ident) {
+ Identifier i = *ident = ident_translate_forced(*ident, idents);
+ if (i->decl) {
+ char *istr = ident_to_str(i);
+ err_print(d->where, "Redeclaration of identifier %s.", istr);
+ info_print(i->decl->where, "%s was also declared here.", istr);
+ free(istr);
+ return false;
+ }
+ i->decl = d;
+ }
+ }
+ }
+ return true;
+}
+
static Status types_stmt(Typer *tr, Statement *s) {
if (s->flags & STMT_TYPED) return true;
switch (s->kind) {
case STMT_EXPR: {
Expression *e = s->expr;
+ if (e->kind == EXPR_IF && (e->if_->flags & IF_STATIC)) {
+ /* handle #if */
+ IfExpr *curr = e->if_;
+ while (1) {
+ Expression *cond = curr->cond;
+ Expression *next = curr->next_elif;
+ Value v;
+ if (cond) {
+ if (!types_expr(tr, cond))
+ return false;
+ if (!eval_expr(tr->evalr, cond, &v))
+ return false;
+ }
+ if (!cond || val_truthiness(v, &cond->type)) {
+ Block *true_block = &curr->body;
+ Statement *last = arr_last_ptr(true_block->stmts);
+ if (last && last->kind == STMT_EXPR && (last->flags & STMT_EXPR_NO_SEMICOLON)) {
+ err_print(last->where, "#ifs can't return values.");
+ return false;
+ }
+ s->kind = STMT_INLINE_BLOCK;
+ s->inline_block = true_block->stmts;
+ if (!fix_ident_decls_inline_block(tr, s->inline_block))
+ return false;
+ bool success = true;
+ arr_foreach(s->inline_block, Statement, sub) {
+ if (!types_stmt(tr, sub)) {
+ success = false;
+ }
+ }
+ if (!success) return false;
+ goto success;
+ }
+ if (!next) break;
+ curr = next->if_;
+ }
+ if (e->kind == EXPR_IF) {
+ /* all conds were false */
+ /* empty inline block */
+ s->kind = STMT_INLINE_BLOCK;
+ s->inline_block = NULL;
+ }
+ break;
+ }
+
if (!types_expr(tr, e)) {
return false;
}
@@ -3696,6 +3731,9 @@ static Status types_stmt(Typer *tr, Statement *s) {
return false;
size_t filename_len = strlen(filename);
IncludedFile *inc_f = NULL;
+
+ s->kind = STMT_INLINE_BLOCK;
+
if (s->flags & STMT_INC_TO_NMS) {
if (!(inc->flags & INC_FORCED)) {
inc_f = str_hash_table_get(&tr->included_files, filename, filename_len);
@@ -3703,12 +3741,11 @@ static Status types_stmt(Typer *tr, Statement *s) {
tr->nms->body.idents = inc_f->main_nms->body.idents;
tr->nms->body.idents.scope = &tr->nms->body;
tr->nms->points_to = inc_f->main_nms;
- inc->inc_file = inc_f;
- inc->stmts = inc_f->stmts;
+ s->inline_block = inc_f->stmts;
break;
}
}
- inc->inc_file = inc_f = str_hash_table_insert(&tr->included_files, filename, filename_len);
+ inc_f = str_hash_table_insert(&tr->included_files, filename, filename_len);
inc_f->main_nms = tr->nms;
}
char *contents = read_file_contents(tr->allocr, filename, s->where);
@@ -3737,16 +3774,12 @@ static Status types_stmt(Typer *tr, Statement *s) {
if (inc_f) {
inc_f->stmts = stmts_inc;
}
- inc->stmts = stmts_inc;
- File *prev = tr->file;
- tr->file = file;
+ s->inline_block = stmts_inc;
arr_foreach(stmts_inc, Statement, s_incd) {
if (!types_stmt(tr, s_incd)) {
- tr->file = prev;
return false;
}
}
- tr->file = prev;
} break;
case STMT_MESSAGE: {
Message *m = s->message;
@@ -3805,18 +3838,21 @@ static Status types_stmt(Typer *tr, Statement *s) {
else
typer_arr_add(tr, tr->uses, u);
} break;
+ case STMT_INLINE_BLOCK:
+ assert(0); /* only exists after typing */
+ break;
}
+success:
s->flags |= STMT_TYPED;
return true;
}
-static void typer_create(Typer *tr, Evaluator *ev, File *file, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents) {
+static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents) {
tr->block = NULL;
tr->blocks = NULL;
tr->fn = NULL;
tr->nms = NULL;
tr->evalr = ev;
- tr->file = file;
tr->err_ctx = err_ctx;
tr->in_decls = NULL;
tr->had_include_err = false;
diff --git a/types.h b/types.h
index d2d8a9b..f3fff36 100644
--- a/types.h
+++ b/types.h
@@ -915,10 +915,11 @@ typedef enum {
STMT_RET,
STMT_BREAK,
STMT_CONT,
- STMT_INCLUDE,
+ STMT_INCLUDE, /* turns into STMT_INLINE_BLOCK after typing */
STMT_MESSAGE,
STMT_DEFER,
- STMT_USE
+ STMT_USE,
+ STMT_INLINE_BLOCK /* a group of statements acting as one statement */
} StatementKind;
enum {
@@ -949,11 +950,7 @@ enum {
typedef union {
U8 flags;
- union {
- Expression filename; /* before typing */
- struct Statement *stmts; /* after typing */
- };
- IncludedFile *inc_file;
+ Expression filename;
} Include;
typedef enum {
@@ -989,6 +986,7 @@ typedef struct Statement {
Message *message; /* #error, #warn, #info */
Block *referring_to; /* for break/continue; set during typing */
struct Statement *defer;
+ struct Statement *inline_block; /* statements in an inline block (dynamic array) */
Use *use;
};
} Statement;
@@ -1044,7 +1042,6 @@ typedef struct Typer {
ParsedFile *parsed_file;
Namespace *nms;
StrHashTable included_files; /* maps to IncludedFile */
- File *file;
/*
have we had an error because we couldn't find a file that was #include'd
(so that we can stop compiling immediately)