diff options
-rw-r--r-- | copy.c | 10 | ||||
-rw-r--r-- | parse.c | 6 | ||||
-rw-r--r-- | types.c | 18 |
3 files changed, 20 insertions, 14 deletions
@@ -56,6 +56,7 @@ static void copy_type(Allocator *a, Type *out, Type *in) { } break; case TYPE_TUPLE: { size_t ntypes = arr_len(in->tuple); + out->tuple = NULL; arr_set_lena(&out->tuple, ntypes, a); for (size_t i = 0; i < ntypes; i++) { copy_type(a, &out->tuple[i], &in->tuple[i]); @@ -75,9 +76,9 @@ static void copy_type(Allocator *a, Type *out, Type *in) { out->ptr = allocr_malloc(a, sizeof *out->slice); copy_type(a, out->slice, in->slice); break; - case TYPE_STRUCT: - out->struc.fields = NULL; + case TYPE_STRUCT: { size_t nfields = arr_len(in->struc.fields); + out->struc.fields = NULL; arr_set_lena(&out->struc.fields, nfields, a); for (size_t i = 0; i < nfields; i++) { Field *fout = &out->struc.fields[i]; @@ -85,14 +86,14 @@ static void copy_type(Allocator *a, Type *out, Type *in) { *fout = *fin; copy_type(a, fout->type, fin->type); } - break; + } break; } } static void copy_fn_expr(Allocator *a, FnExpr *fout, FnExpr *fin, bool copy_body) { size_t i; - fout->params = NULL; size_t nparam_decls = arr_len(fin->params); + fout->params = NULL; arr_set_lena(&fout->params, nparam_decls, a); for (i = 0; i < nparam_decls; i++) copy_decl(a, fout->params + i, fin->params + i); @@ -249,6 +250,7 @@ static void copy_stmt(Allocator *a, Statement *out, Statement *in) { static void copy_block(Allocator *a, Block *out, Block *in) { *out = *in; size_t nstmts = arr_len(in->stmts); + out->stmts = NULL; arr_set_lena(&out->stmts, nstmts, a); for (size_t i = 0; i < nstmts; i++) { copy_stmt(a, &out->stmts[i], &in->stmts[i]); @@ -801,6 +801,12 @@ static bool parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end static bool parse_fn_expr(Parser *p, FnExpr *f) { Tokenizer *t = p->tokr; f->ret_decls = NULL; + + { + /* help types.c */ + HashTable z = {0}; + f->instances = z; + } /* only called when token is fn */ assert(token_is_kw(t->token, KW_FN)); t->token++; @@ -181,12 +181,14 @@ static bool expr_must_lval(Expression *e) { return false; } -static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t) { +#define TYPE_OF_FN_NO_COPY_EVEN_IF_CONST 0x01 + +static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) { t->kind = TYPE_FN; t->fn.types = NULL; t->fn.constness = NULL; /* OPTIM: constant doesn't need to be a dynamic array */ FnExpr *newf = NULL; - if (fn_has_any_const_params(f)) { + if (!(flags & TYPE_OF_FN_NO_COPY_EVEN_IF_CONST) && fn_has_any_const_params(f)) { /* OPTIM don't copy so much */ newf = typer_malloc(tr, sizeof *newf); copy_fn_expr(tr->allocr, newf, f, false); @@ -324,7 +326,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { } else { if ((d->flags & DECL_HAS_EXPR) && (d->expr.kind == EXPR_FN)) { /* allow using a function before declaring it */ - if (!type_of_fn(tr, &d->expr.fn, d->expr.where, t)) return false; + if (!type_of_fn(tr, &d->expr.fn, d->expr.where, t, 0)) return false; return true; } else { if (location_after(d->where, where)) { @@ -602,14 +604,8 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where, Instance *instance) { FnExpr *prev_fn = tr->fn; bool success = true; - { - HashTable z = {0}; - f->instances = z; - } assert(t->kind == TYPE_FN); - - if (instance) { copy_fn_expr(tr->allocr, &instance->fn, f, true); f = &instance->fn; @@ -632,6 +628,8 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where, semi_const_arg_idx++; } } + if (!type_of_fn(tr, f, where, t, TYPE_OF_FN_NO_COPY_EVEN_IF_CONST)) + return false; } else { if (t->fn.constness) return true; /* don't type function body yet; we need to do that for every instance */ @@ -700,7 +698,7 @@ static bool types_expr(Typer *tr, Expression *e) { e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */ switch (e->kind) { case EXPR_FN: { - if (!type_of_fn(tr, &e->fn, e->where, &e->type)) + if (!type_of_fn(tr, &e->fn, e->where, &e->type, 0)) return false; if (fn_has_any_const_params(&e->fn)) { HashTable z = {0}; |