summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c2
-rw-r--r--decls_cgen.c3
-rw-r--r--main.c2
-rw-r--r--parse.c9
-rw-r--r--types.c22
-rw-r--r--types.h28
6 files changed, 32 insertions, 34 deletions
diff --git a/cgen.c b/cgen.c
index 6d03947..f84474a 100644
--- a/cgen.c
+++ b/cgen.c
@@ -256,7 +256,7 @@ static inline void cgen_writeln(CGenerator *g, const char *fmt, ...) {
/* should this declaration be a direct function declaration C? (as opposed to using a function pointer or not being a function) */
static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) {
- return (g->block == NULL || (g->block->flags & BLOCK_IS_NMS)) && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1;
+ return g->fn == NULL && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1;
}
static bool fn_has_instances(FnExpr *f) {
diff --git a/decls_cgen.c b/decls_cgen.c
index 1cb5393..08d0727 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -340,7 +340,8 @@ static void cgen_decls_decl(CGenerator *g, Declaration *d) {
if (d->flags & DECL_HAS_EXPR) {
cgen_decls_expr(g, &d->expr);
}
- if ((g->block == NULL || (g->block->flags & BLOCK_IS_NMS)) && g->fn == NULL) {
+ if (g->fn == NULL) {
+ /* global variables */
for (int i = 0, n_idents = (int)arr_len(d->idents); i < n_idents; ++i) {
Identifier ident = d->idents[i];
Type *type = decl_type_at_index(d, i);
diff --git a/main.c b/main.c
index d7f5063..1d49ea6 100644
--- a/main.c
+++ b/main.c
@@ -8,9 +8,11 @@
/*
TODO:
+figure out why we're not getting redecl errors
use
- note: just keep an array of useds on the block
- use with a decl, e.g. use p : Point;
+ - make sure use works with functions and for, e.g. for use p := points
local structs should not be named in C
for some reason forgetting a ; after #include causes a misleading unrecognized expression
simplify eval macros with val_to_u/i64
diff --git a/parse.c b/parse.c
index f0e93b6..f269ea9 100644
--- a/parse.c
+++ b/parse.c
@@ -797,6 +797,7 @@ static Status parse_block(Parser *p, Block *b, U8 flags) {
Tokenizer *t = p->tokr;
Block *prev_block = p->block;
b->flags = 0;
+ b->kind = BLOCK_OTHER;
b->ret_expr = NULL;
assert(p->block != b);
b->parent = p->block;
@@ -947,7 +948,7 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) {
if (!parse_block(p, &f->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
success = false;
ret:
- f->body.flags |= BLOCK_IS_FN;
+ f->body.kind = BLOCK_FN;
p->block = prev_block;
return success;
}
@@ -1378,7 +1379,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
return false;
}
if (!parse_block(p, &w->body, 0)) return false;
- w->body.flags |= BLOCK_IS_LOOP;
+ w->body.kind = BLOCK_WHILE;
goto success;
}
case KW_FOR: {
@@ -1492,7 +1493,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
p->block = prev_block;
if (!parse_block(p, &fo->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
goto for_fail;
- fo->body.flags |= BLOCK_IS_LOOP;
+ fo->body.kind = BLOCK_FOR;
goto success;
for_fail:
p->block = prev_block;
@@ -2453,7 +2454,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
e->where = s->where;
e->nms->associated_ident = ident;
Block *body = &e->nms->body;
- body->flags |= BLOCK_IS_NMS;
+ body->kind = BLOCK_NMS;
body->where = s->where;
body->parent = p->block;
idents_create(&body->idents, p->allocr, body);
diff --git a/types.c b/types.c
index 5e1092f..93e0c24 100644
--- a/types.c
+++ b/types.c
@@ -613,13 +613,14 @@ static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type *
switch (i->decl_kind) {
case IDECL_DECL: {
Declaration *d = i->decl;
+ /* check for trying to capture a variable into a function */
bool captured = false;
- if (ident_scope(i) != NULL && !(ident_scope(i)->flags & BLOCK_IS_NMS)) {
+ if (ident_scope(i) != NULL && ident_scope(i)->kind != BLOCK_NMS) {
Block *decl_scope = ident_scope(i);
- if (!(decl_scope->flags & BLOCK_IS_NMS)) {
+ if (decl_scope->kind != BLOCK_NMS) {
/* go back through scopes */
for (Block **block = arr_last(tr->blocks); *block && *block != decl_scope; --block) {
- if ((*block)->flags & BLOCK_IS_FN) {
+ if ((*block)->kind == BLOCK_FN) {
captured = true;
break;
}
@@ -3100,11 +3101,11 @@ static Status types_expr(Typer *tr, Expression *e) {
Namespace *prev_nms = tr->nms;
Namespace *n = tr->nms = e->nms;
n->points_to = NULL;
- n->body.flags |= BLOCK_IS_NMS;
if (!types_block(tr, &n->body)) {
tr->nms = prev_nms;
return false;
}
+ n->body.kind = BLOCK_NMS;
tr->nms = prev_nms;
n->associated_ident = NULL; /* set when we type the declaration which contains this namespace */
t->kind = TYPE_BUILTIN;
@@ -3218,8 +3219,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
d->type = d->expr.type;
d->type.flags &= (TypeFlags)~(TypeFlags)TYPE_IS_FLEXIBLE; /* x := 5; => x is not flexible */
}
- bool need_value = (d->flags & DECL_IS_CONST) ||
- ((tr->block == NULL || (tr->block->flags & BLOCK_IS_NMS)) && tr->fn == NULL);
+ bool need_value = (d->flags & DECL_IS_CONST) || tr->fn == NULL;
if (need_value) {
if (!(d->flags & DECL_FOUND_VAL)) {
@@ -3299,7 +3299,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
bool is_at_top_level = true;
typedef Block *BlockPtr;
arr_foreach(tr->blocks, BlockPtr, b) {
- if (*b && !((*b)->flags & BLOCK_IS_NMS)) {
+ if (*b && (*b)->kind != BLOCK_NMS) {
is_at_top_level = false;
break;
}
@@ -3476,7 +3476,7 @@ static Status types_stmt(Typer *tr, Statement *s) {
/* make sure we are actually in a loop */
Block *block;
for (block = tr->block; block; block = block->parent) {
- if (block->flags & BLOCK_IS_LOOP) {
+ if (block->kind == BLOCK_FOR || block->kind == BLOCK_WHILE) {
s->referring_to = block;
break;
}
@@ -3512,9 +3512,8 @@ static Status types_stmt(Typer *tr, Statement *s) {
err_print(e->where, "You can't use this value. You should probably assign it to a variable.");
return false;
}
- UsedExpr *u = arr_add(&tr->used);
- u->scope = tr->block;
- u->stmt = s;
+ Statement **sp = arr_add(&tr->block->used);
+ *sp = s;
} break;
}
s->flags |= STMT_TYPED;
@@ -3522,7 +3521,6 @@ static Status types_stmt(Typer *tr, Statement *s) {
}
static void typer_create(Typer *tr, Evaluator *ev, File *file, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents) {
- tr->used = NULL;
tr->block = NULL;
tr->blocks = NULL;
tr->fn = NULL;
diff --git a/types.h b/types.h
index 9960599..db1534f 100644
--- a/types.h
+++ b/types.h
@@ -488,15 +488,21 @@ typedef struct Field {
enum {
- BLOCK_IS_FN = 0x01,
- BLOCK_IS_NMS = 0x02,
- BLOCK_FINDING_TYPES = 0x04,
- BLOCK_FOUND_TYPES = 0x08,
- BLOCK_IS_LOOP = 0x10 /* can we break/continue in this block? */
+ BLOCK_FINDING_TYPES = 0x01,
+ BLOCK_FOUND_TYPES = 0x02,
};
+typedef enum {
+ BLOCK_OTHER,
+ BLOCK_FN,
+ BLOCK_NMS,
+ BLOCK_FOR,
+ BLOCK_WHILE
+} BlockKind;
+
typedef U8 BlockFlags;
typedef struct Block {
BlockFlags flags;
+ BlockKind kind;
struct {
IdentID break_lbl, cont_lbl; /* initially 0, set to non-zero values if needed (++g->lbl_counter); set by sdecls_cgen. */
} c;
@@ -506,6 +512,7 @@ typedef struct Block {
struct Expression *ret_expr; /* the return expression of this block, e.g. {foo(); 3} => 3 NULL for no expression. */
struct Block *parent;
struct Statement **deferred; /* deferred stuff from this block; used by both eval and cgen */
+ struct Statement **used; /* use statements (for types.c) */
} Block;
enum {
@@ -1038,16 +1045,6 @@ typedef struct Evaluator {
ForeignFnManager ffmgr;
} Evaluator;
-/*
-Keeps track of use stmts.
-We need to keep track of the block so that
-it can be removed when we exit the block.
-*/
-typedef struct {
- Statement *stmt;
- Block *scope;
-} UsedExpr;
-
typedef struct Typer {
Allocator *allocr;
Evaluator *evalr;
@@ -1061,7 +1058,6 @@ typedef struct Typer {
ParsedFile *parsed_file;
Namespace *nms;
StrHashTable included_files; /* maps to IncludedFile */
- UsedExpr *used; /* things which are currently being `use`d. dynamic array NOT on the allocator. */
File *file;
} Typer;