summaryrefslogtreecommitdiff
path: root/types.c
diff options
context:
space:
mode:
Diffstat (limited to 'types.c')
-rw-r--r--types.c239
1 files changed, 150 insertions, 89 deletions
diff --git a/types.c b/types.c
index cda8b16..d09b3ec 100644
--- a/types.c
+++ b/types.c
@@ -296,6 +296,7 @@ static Status struct_resolve(Typer *tr, StructDef *s) {
return false; /* silently fail; do not try to resolve again, because there'll be duplicate errors */
if (!(s->flags & STRUCT_DEF_RESOLVED)) {
s->flags |= STRUCT_DEF_RESOLVING;
+ typer_arr_add(tr, tr->all_structs, s);
{ /* resolving stuff */
Block *body = &s->body;
if (!types_block(tr, body))
@@ -523,8 +524,8 @@ static bool type_is_compileonly(Type *t) {
case TYPE_UNKNOWN:
return false;
case TYPE_BUILTIN:
- return t->builtin == BUILTIN_TYPE || t->builtin == BUILTIN_NMS;
- case TYPE_PTR:
+ return t->builtin == BUILTIN_TYPE || t->builtin == BUILTIN_NMS || t->builtin == BUILTIN_VARARGS;
+ case TYPE_PTR:
return type_is_compileonly(t->ptr);
case TYPE_SLICE:
return type_is_compileonly(t->slice);
@@ -1155,7 +1156,11 @@ static bool arg_is_const(Expression *arg, Constness constness) {
/* pass NULL for instance if this isn't an instance */
static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
- if (f->flags & FN_EXPR_FOREIGN) return true;
+ if (f->flags & FN_EXPR_FOREIGN) {
+ FnWithCtx fn_ctx = {f, tr->nms, tr->block};
+ typer_arr_add(tr, tr->all_fns, fn_ctx);
+ return true;
+ }
FnExpr *prev_fn = tr->fn;
bool success = true;
Expression *ret_expr;
@@ -1168,7 +1173,10 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
if (t->fn.constness)
return true; /* don't type function body yet; we need to do that for every instance */
}
-
+ {
+ FnWithCtx fn_ctx = {f, tr->nms, tr->block};
+ typer_arr_add(tr, tr->all_fns, fn_ctx);
+ }
tr->fn = f;
if (!types_block(tr, &f->body)) {
success = false;
@@ -1577,6 +1585,33 @@ static Status use_ident(Typer *tr, Identifier i, Type *t, Location where) {
return true;
}
+static void typer_gen_nms_prefix(Typer *tr, Namespace *n) {
+ assert(tr->nms != n);
+ /* create a C prefix for this namespace */
+ const char *prev_prefix = "";
+ size_t prev_prefix_len = 0;
+ if (tr->nms) {
+ prev_prefix = tr->nms->c.prefix;
+ assert(prev_prefix);
+ prev_prefix_len = strlen(prev_prefix);
+ }
+ if (n->associated_ident) {
+ size_t ident_len = n->associated_ident->len;
+ char *prefix = n->c.prefix = typer_malloc(tr, ident_len + prev_prefix_len + 3);
+ memcpy(prefix, prev_prefix, prev_prefix_len);
+ prefix += prev_prefix_len;
+ memcpy(prefix, n->associated_ident->str, ident_len);
+ prefix += ident_len;
+ *prefix++ = '_';
+ *prefix++ = '_';
+ *prefix++ = '\0';
+ } else {
+ size_t bytes = prev_prefix_len + 20;
+ char *prefix = n->c.prefix = typer_malloc(tr, bytes);
+ snprintf(prefix, bytes, "%sa%lu__", prev_prefix, ++tr->nms_counter);
+ }
+}
+
static Status types_expr(Typer *tr, Expression *e) {
if (e->flags & EXPR_FOUND_TYPE) return true;
e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */
@@ -1589,14 +1624,15 @@ static Status types_expr(Typer *tr, Expression *e) {
t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */
switch (e->kind) {
case EXPR_FN: {
- if (!type_of_fn(tr, e->fn, &e->type, 0)) {
+ FnExpr *fn = e->fn;
+ if (!type_of_fn(tr, fn, &e->type, 0)) {
return false;
}
- if (fn_has_any_const_params(e->fn) || fn_type_has_varargs(&e->type.fn)) {
- e->fn->instances = typer_calloc(tr, 1, sizeof *e->fn->instances);
+ if (!(fn->flags & FN_EXPR_FOREIGN) && (fn_has_any_const_params(fn) || fn_type_has_varargs(&e->type.fn))) {
+ fn->instances = typer_calloc(tr, 1, sizeof *fn->instances);
t->flags |= TYPE_IS_RESOLVED; /* pretend this type is resolved, even though its children aren't to fix some assertions */
} else {
- if (!types_fn(tr, e->fn, &e->type, NULL)) {
+ if (!types_fn(tr, fn, &e->type, NULL)) {
return false;
}
}
@@ -2769,6 +2805,8 @@ static Status types_expr(Typer *tr, Expression *e) {
arr_remove_last(err_ctx->instance_stack);
if (!success) return false;
}
+ c->fn->kind = EXPR_VAL;
+ c->fn->val.fn = c->instance->fn;
}
free(order);
@@ -3312,13 +3350,14 @@ static Status types_expr(Typer *tr, Expression *e) {
} break;
case EXPR_NMS: {
Namespace *prev_nms = tr->nms;
- Namespace *n = tr->nms = e->nms;
+ Namespace *n = e->nms;
+ typer_gen_nms_prefix(tr, n);
+ tr->nms = n;
if (!types_block(tr, &n->body)) {
tr->nms = prev_nms;
return false;
}
tr->nms = prev_nms;
- n->associated_ident = NULL; /* set when we type the declaration which contains this namespace */
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_NMS;
} break;
@@ -3342,6 +3381,9 @@ static Status types_block(Typer *tr, Block *b) {
return false;
}
b->flags |= BLOCK_FINDING_TYPES;
+
+ b->c.break_lbl = 0;
+ b->c.cont_lbl = 0;
/* for and fn need to deal with their own useds, because you can use stuff in the header */
if (b->kind != BLOCK_FOR && b->kind != BLOCK_FN)
@@ -3391,6 +3433,15 @@ static Status types_block(Typer *tr, Block *b) {
return success;
}
+static bool is_at_top_level(Typer *tr) {
+ arr_foreach(tr->blocks, BlockPtr, b) {
+ if (*b && (*b)->kind != BLOCK_NMS) {
+ return false;
+ }
+ }
+ return true;
+}
+
static Status types_decl(Typer *tr, Declaration *d) {
Type *dtype = &d->type;
if (d->flags & DECL_FOUND_TYPE) return true;
@@ -3423,6 +3474,12 @@ static Status types_decl(Typer *tr, Declaration *d) {
&& tr->fn == NULL) {
e->typeval->struc->name = d->idents[0];
}
+
+ if (e->kind == EXPR_NMS) {
+ if (is_at_top_level(tr))
+ e->nms->associated_ident = d->idents[0];
+ }
+
if (!types_expr(tr, e)) {
success = false;
goto ret;
@@ -3476,6 +3533,9 @@ static Status types_decl(Typer *tr, Declaration *d) {
typer_arr_add(tr, d->val_stack, copy);
}
}
+ if ((tr->block == NULL || tr->block->kind == BLOCK_NMS) && e->kind == EXPR_FN && n_idents == 1) {
+ e->fn->c.name = d->idents[0];
+ }
}
} else if (!tr->block || tr->block->kind == BLOCK_NMS) {
/* give global variables without initializers a value stack */
@@ -3492,7 +3552,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
if (type_is_compileonly(dtype)) {
- if (!(d->flags & DECL_IS_CONST)) {
+ if (!(d->flags & DECL_IS_CONST) && !type_is_builtin(dtype, BUILTIN_VARARGS)) {
char *s = type_to_str(dtype);
err_print(d->where, "Declarations with type %s must be constant.", s);
free(s);
@@ -3569,24 +3629,21 @@ static Status types_decl(Typer *tr, Declaration *d) {
return false;
}
- if (n_idents == 1 && e && e->kind == EXPR_NMS) {
- bool is_at_top_level = true;
- arr_foreach(tr->blocks, BlockPtr, b) {
- if (*b && (*b)->kind != BLOCK_NMS) {
- is_at_top_level = false;
- break;
- }
- }
- if (is_at_top_level)
- d->expr.nms->associated_ident = d->idents[0];
- }
-
if (tr->nms && tr->block == &tr->nms->body) {
arr_foreach(d->idents, Identifier, ident) {
(*ident)->nms = tr->nms;
}
}
+ if (d->flags & DECL_EXPORT) {
+ if (d->expr.kind == EXPR_FN)
+ d->expr.fn->flags |= FN_EXPR_EXPORT;
+ }
+
+ if (is_at_top_level(tr)) {
+ DeclWithCtx dctx = {d, tr->nms, tr->block};
+ typer_arr_add(tr, tr->all_globals, dctx);
+ }
ret:
/* pretend we found the type even if we didn't to prevent too many errors */
@@ -3773,38 +3830,79 @@ static Status types_stmt(Typer *tr, Statement *s) {
Namespace *prev_nms = tr->nms;
IncludedFile *inc_f = NULL;
Namespace *inc_nms = NULL; /* non-NULL if this is an include to nms */
+ bool success = true;
if (inc->nms) {
inc_nms = typer_calloc(tr, 1, sizeof *inc_nms);
+
Block *body = &inc_nms->body;
body->kind = BLOCK_NMS;
body->where = s->where;
idents_create(&body->idents, tr->allocr, body);
body->parent = tr->block;
+
+ inc_nms->inc_file = inc_f;
+ /* turn #include "foo", bar into bar ::= nms { ... } */
+ s->kind = STMT_DECL;
+ Declaration *d = s->decl = typer_calloc(tr, 1, sizeof *d);
+ d->flags = DECL_FOUND_TYPE | DECL_HAS_EXPR | DECL_IS_CONST | DECL_FOUND_VAL;
+ construct_resolved_builtin_type(&d->type, BUILTIN_NMS);
+ char *ident_str = inc->nms;
+ Identifier i = ident_insert(typer_get_idents(tr), &ident_str);
+ if (i->decl) {
+ Declaration *d2 = i->decl;
+ /* maybe they included it twice into one namespace */
+ if ((d2->flags & DECL_HAS_EXPR) && (d2->expr.kind == EXPR_NMS) &&
+ (d2->expr.nms->inc_file == inc_f)) {
+ /* that's okay; get rid of this declaration */
+ s->kind = STMT_INLINE_BLOCK;
+ s->inline_block = NULL;
+ break;
+ } else {
+ char *istr = ident_to_str(i);
+ err_print(s->where, "Redeclaration of identifier %s.", istr);
+ info_print(ident_decl_location(i), "Previous declaration was here.");
+ free(istr);
+ return false; /* NOT goto inc_fail; */
+ }
+ }
+ typer_arr_add(tr, d->idents, i);
+ i->decl = d;
+ if (is_at_top_level(tr)) inc_nms->associated_ident = i;
+ typer_gen_nms_prefix(tr, inc_nms);
+
+ d->expr.kind = EXPR_NMS;
+ d->expr.nms = inc_nms;
+ d->expr.flags = EXPR_FOUND_TYPE;
+ d->expr.type = d->type;
+ d->val.nms = inc_nms;
+ d->where = d->expr.where = s->where;
+
/* go inside namespace and block (it'll help to be there later on) */
tr->nms = inc_nms;
typer_block_enter(tr, &inc_nms->body);
+ } else {
+ s->kind = STMT_INLINE_BLOCK;
}
- s->kind = STMT_INLINE_BLOCK;
-
if (!(inc->flags & INC_FORCED)) {
size_t filename_len = strlen(filename);
if (streq(filename, tr->main_file->filename)) {
err_print(s->where, "Circular #include detected. You can add #force to this #include to force it to be included.");
- goto inc_fail;
+ success = false; goto nms_done;
}
inc_f = str_hash_table_get(&tr->included_files, filename, filename_len);
if (inc_f) {
/* has already been included */
if (inc_f->flags & INC_FILE_INCLUDING) {
err_print(s->where, "Circular #include detected. You can add #force to this #include to force it to be included.");
- goto inc_fail;
+ success = false; goto nms_done;
}
- s->inline_block = NULL; /* nothing needed here */
+ if (s->kind == STMT_INLINE_BLOCK) s->inline_block = NULL; /* nothing needed here */
/* just set ident declarations */
- if (!include_stmts_link_to_nms(tr, inc_f->main_nms, inc_f->stmts))
- goto inc_fail;
- goto nms_transform;
+ if (!include_stmts_link_to_nms(tr, inc_f->main_nms, inc_f->stmts)) {
+ success = false; goto nms_done;
+ }
+ goto nms_done;
}
inc_f = str_hash_table_insert(&tr->included_files, filename, filename_len);
inc_f->flags |= INC_FILE_INCLUDING;
@@ -3814,7 +3912,7 @@ static Status types_stmt(Typer *tr, Statement *s) {
char *contents = read_file_contents(tr->allocr, filename, s->where);
if (!contents) {
tr->had_include_err = true;
- goto inc_fail;
+ success = false; goto nms_done;
}
Tokenizer tokr;
@@ -3824,80 +3922,38 @@ static Status types_stmt(Typer *tr, Statement *s) {
file->contents = contents;
file->ctx = tr->err_ctx;
- if (!tokenize_file(&tokr, file))
- goto inc_fail;
+ if (!tokenize_file(&tokr, file)) {
+ success = false; goto nms_done;
+ }
Parser parser;
parser_create(&parser, tr->globals, &tokr, tr->allocr);
parser.block = tr->block;
ParsedFile parsed_file;
if (!parse_file(&parser, &parsed_file)) {
- goto inc_fail;
+ success = false; goto nms_done;
}
Statement *stmts_inc = parsed_file.stmts;
if (inc_f) {
inc_f->stmts = stmts_inc;
}
- s->inline_block = stmts_inc;
+ if (s->kind == STMT_INLINE_BLOCK) s->inline_block = stmts_inc;
arr_foreach(stmts_inc, Statement, s_incd) {
if (!types_stmt(tr, s_incd)) {
- goto inc_fail;
+ success = false; goto nms_done;
}
}
if (inc_nms) {
inc_nms->body.stmts = stmts_inc;
}
}
- nms_transform:
+ nms_done:
if (inc_nms) {
- /* go back to parent namespace/block because that's where the declaration is gonna be */
tr->nms = prev_nms;
typer_block_exit(tr);
-
- inc_nms->inc_file = inc_f;
- /* turn #include "foo", bar into bar ::= nms { ... } */
- s->kind = STMT_DECL;
- Declaration *d = s->decl = typer_calloc(tr, 1, sizeof *d);
- d->flags = DECL_FOUND_TYPE | DECL_HAS_EXPR | DECL_IS_CONST | DECL_FOUND_VAL;
- construct_resolved_builtin_type(&d->type, BUILTIN_NMS);
- char *ident_str = inc->nms;
- Identifier i = ident_insert(typer_get_idents(tr), &ident_str);
- typer_arr_add(tr, d->idents, i);
- if (i->decl) {
- Declaration *d2 = i->decl;
- /* maybe they included it twice into one namespace */
- if ((d2->flags & DECL_HAS_EXPR) && (d2->expr.kind == EXPR_NMS) &&
- (d2->expr.nms->inc_file == inc_f)) {
- /* that's okay; get rid of this declaration */
- s->kind = STMT_INLINE_BLOCK;
- s->inline_block = NULL;
- break;
- } else {
- char *istr = ident_to_str(i);
- err_print(s->where, "Redeclaration of identifier %s.", istr);
- info_print(ident_decl_location(i), "Previous declaration was here.");
- free(istr);
- return false; /* NOT goto inc_fail; */
- }
- }
- i->decl = d;
- inc_nms->associated_ident = i;
- d->expr.kind = EXPR_NMS;
- d->expr.nms = inc_nms;
- d->expr.flags = EXPR_FOUND_TYPE;
- d->expr.type = d->type;
- d->val.nms = inc_nms;
- d->where = d->expr.where = s->where;
}
if (inc_f) inc_f->flags &= (IncFileFlags)~(IncFileFlags)INC_FILE_INCLUDING;
- break;
- inc_fail:
- if (inc_f) inc_f->flags &= (IncFileFlags)~(IncFileFlags)INC_FILE_INCLUDING;
- if (inc_nms) {
- tr->nms = prev_nms;
- typer_block_exit(tr);
- }
- return false;
- }
+ if (!success) return false;
+ } break;
case STMT_MESSAGE: {
Message *m = s->message;
char *text = eval_expr_as_cstr(tr, &m->text, "message");
@@ -3922,6 +3978,16 @@ static Status types_stmt(Typer *tr, Statement *s) {
for (block = tr->block; block; block = block->parent) {
if (block->kind == BLOCK_FOR || block->kind == BLOCK_WHILE) {
s->referring_to = block;
+ if (s->kind == STMT_BREAK) {
+ if (!block->c.break_lbl) {
+ block->c.break_lbl = ++tr->lbl_counter;
+ }
+ } else {
+ assert(s->kind == STMT_CONT);
+ if (!block->c.cont_lbl) {
+ block->c.cont_lbl = ++tr->lbl_counter;
+ }
+ }
break;
}
}
@@ -3969,15 +4035,10 @@ success:
}
static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents, File *main_file) {
- tr->block = NULL;
- tr->blocks = NULL;
- tr->fn = NULL;
- tr->nms = NULL;
+ memset(tr, 0, sizeof *tr);
tr->evalr = ev;
tr->main_file = main_file;
tr->err_ctx = err_ctx;
- tr->in_decls = NULL;
- tr->had_include_err = false;
tr->allocr = allocr;
tr->globals = idents;
typer_arr_add(tr, tr->blocks, NULL);