From ec25b66e85765bafe7a944d805669c931026a5be Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 10 Jul 2020 15:53:56 -0400 Subject: made types 16 bytes --- allocator.c | 2 +- cgen.c | 74 +++++++++++++++++++++++++++----------------------- copy.c | 40 +++++++++++++++------------ eval.c | 24 ++++++++--------- infer.c | 14 +++++----- instance_table.c | 20 +++++++------- main.c | 4 +-- parse.c | 32 +++++++++++----------- types.c | 82 ++++++++++++++++++++++++++++---------------------------- types.h | 20 +++++++------- 10 files changed, 162 insertions(+), 150 deletions(-) diff --git a/allocator.c b/allocator.c index 6573914..98005ef 100644 --- a/allocator.c +++ b/allocator.c @@ -25,7 +25,7 @@ static void *err_malloc(size_t bytes); static void *err_calloc(size_t n, size_t sz); static void *err_realloc(void *prev, size_t new_size); #ifdef TOC_DEBUG -#define NO_ALLOCATOR 0 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */ +#define NO_ALLOCATOR 1 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */ #endif /* number of bytes a page hold, not including the header */ #define PAGE_BYTES (16384 - sizeof(Page)) diff --git a/cgen.c b/cgen.c index 30a9703..88225be 100644 --- a/cgen.c +++ b/cgen.c @@ -186,14 +186,14 @@ static void cgen_type_pre(CGenerator *g, Type *t) { cgen_write(g, "(*"); break; case TYPE_ARR: - cgen_type_pre(g, t->arr.of); + cgen_type_pre(g, t->arr->of); cgen_write(g, "("); break; case TYPE_FN: - if (cgen_uses_ptr(&t->fn.types[0])) { + if (cgen_uses_ptr(&t->fn->types[0])) { cgen_write(g, "void"); } else { - cgen_type_pre(g, &t->fn.types[0]); + cgen_type_pre(g, &t->fn->types[0]); } cgen_write(g, " (*"); break; @@ -222,23 +222,26 @@ static void cgen_type_post(CGenerator *g, Type *t) { break; case TYPE_ARR: assert(t->flags & TYPE_IS_RESOLVED); - cgen_write(g, "[%lu])", (unsigned long)t->arr.n); - cgen_type_post(g, t->arr.of); + cgen_write(g, "[%lu])", (unsigned long)t->arr->n); + cgen_type_post(g, t->arr->of); break; case TYPE_FN: { - bool out_param = cgen_uses_ptr(&t->fn.types[0]); + Type *types = t->fn->types; + size_t ntypes = arr_len(types); + bool out_param = cgen_uses_ptr(&types[0]); cgen_write(g, ")("); - for (size_t i = 1; i < arr_len(t->fn.types); ++i) { + for (size_t i = 1; i < ntypes; ++i) { + Type *type = &types[i]; if (i != 1) cgen_write(g, ", "); - cgen_type_pre(g, &t->fn.types[i]); - if (cgen_uses_ptr(&t->fn.types[i])) + cgen_type_pre(g, type); + if (cgen_uses_ptr(type)) cgen_write(g, "(*)"); - cgen_type_post(g, &t->fn.types[i]); + cgen_type_post(g, type); } if (out_param) { - Type *ret_type = &t->fn.types[0]; - if (arr_len(t->fn.types) > 1) + Type *ret_type = &types[0]; + if (ntypes > 1) cgen_write(g, ", "); if (ret_type->kind == TYPE_TUPLE) { arr_foreach(ret_type->tuple, Type, x) { @@ -255,11 +258,11 @@ static void cgen_type_post(CGenerator *g, Type *t) { cgen_type_post(g, ret_type); } } - if (arr_len(t->fn.types) == 1 && !out_param) + if (ntypes == 1 && !out_param) cgen_write(g, "void"); cgen_write(g, ")"); if (!out_param) - cgen_type_post(g, &t->fn.types[0]); + cgen_type_post(g, &types[0]); } break; case TYPE_BUILTIN: case TYPE_UNKNOWN: @@ -375,8 +378,8 @@ static void cgen_val_ptr_pre(CGenerator *g, void *v, Type *t) { } } break; case TYPE_ARR: - for (size_t i = 0; i < t->arr.n; ++i) { - cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr.of), t->arr.of); + for (size_t i = 0; i < t->arr->n; ++i) { + cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr->of), t->arr->of); } break; case TYPE_FN: @@ -403,9 +406,10 @@ static void cgen_val_ptr(CGenerator *g, void *v, Type *t) { return; case TYPE_ARR: cgen_write(g, "{"); - for (size_t i = 0; i < t->arr.n; ++i) { + Type *of = t->arr->of; + for (size_t i = 0, n = t->arr->n; i < n; ++i) { if (i) cgen_write(g, ", "); - cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of); + cgen_val_ptr(g, (char *)v + i * compiler_sizeof(of), of); } cgen_write(g, "}"); break; @@ -630,13 +634,14 @@ static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E } cgen_write(g, ";"); break; - case TYPE_ARR: + case TYPE_ARR: { + Type *of_type = type->arr->of; cgen_write(g, "{"); cgen_nl(g); cgen_write(g, "size_t i;"); - cgen_type_pre(g, type->arr.of); + cgen_type_pre(g, of_type); cgen_write(g, "(*arr__in)"); - cgen_type_post(g, type->arr.of); + cgen_type_post(g, of_type); cgen_write(g, " = "); if (to_expr) { cgen_expr(g, to_expr); @@ -644,9 +649,9 @@ static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E cgen_write(g, to_str); } cgen_write(g, "; "); - cgen_type_pre(g, type->arr.of); + cgen_type_pre(g, of_type); cgen_write(g, "(*arr__out)"); - cgen_type_post(g, type->arr.of); + cgen_type_post(g, of_type); cgen_write(g, " = "); if (set_expr) { cgen_expr(g, set_expr); @@ -655,10 +660,10 @@ static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E } cgen_write(g, ";"); cgen_nl(g); - cgen_write(g, "for (i = 0; i < %lu; ++i) arr__out[i] = arr__in[i];", (unsigned long)type->arr.n); + cgen_write(g, "for (i = 0; i < %lu; ++i) arr__out[i] = arr__in[i];", (unsigned long)type->arr->n); cgen_nl(g); cgen_write(g, "}"); - break; + } break; case TYPE_TUPLE: assert(set_expr); assert(to_expr); @@ -700,7 +705,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, } break; case EXPR_CALL: { - FnType *fn_type = &to->call.fn->type.fn; + FnType *fn_type = to->call.fn->type.fn; Type *ret_type = &fn_type->types[0]; Constness *constness = fn_type->constness; int i = 0; @@ -803,8 +808,9 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { case EXPR_CALL: { cgen_expr_pre(g, e->call.fn); size_t i = 0; - Constness *constness = e->call.fn->type.fn.constness; - size_t nparams = arr_len(e->call.fn->type.fn.types)-1; + FnType *fn_type = e->call.fn->type.fn; + Constness *constness = fn_type->constness; + size_t nparams = arr_len(fn_type->types)-1; arr_foreach(e->call.arg_exprs, Expression, arg) { if (!constness || !arg_is_const(arg, constness[i])) { cgen_arg_pre(g, arg); @@ -869,7 +875,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { assert(s->of->type.kind == TYPE_ARR); cgen_write(g, "mkslice_("); cgen_expr(g, s->of); - cgen_write(g, ", " U64_FMT, s->of->type.arr.n); + cgen_write(g, ", " U64_FMT, s->of->type.arr->n); cgen_write(g, ")"); } cgen_write(g, "; i64 "); @@ -1177,7 +1183,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { } else if (cgen_uses_ptr(&e->type)) { cgen_ident_id(g, e->cgen.id); } else { - FnType *fn_type = &e->call.fn->type.fn; + FnType *fn_type = e->call.fn->type.fn; cgen_expr(g, e->call.fn); cgen_write(g, "("); bool first_arg = true; @@ -1737,9 +1743,9 @@ static void cgen_stmt(CGenerator *g, Statement *s) { cgen_write(g, "; "); break; case TYPE_ARR: - cgen_type_pre(g, of_type->arr.of); + cgen_type_pre(g, of_type->arr->of); cgen_write(g, " (* of_)"); - cgen_type_post(g, of_type->arr.of); + cgen_type_post(g, of_type->arr->of); cgen_write(g, " = "); if (uses_ptr) cgen_write(g, "*"); cgen_expr(g, fo->of); @@ -1810,7 +1816,7 @@ static void cgen_stmt(CGenerator *g, Statement *s) { cgen_write(g, ", (*end_) = p_ + "); switch (of_type->kind) { case TYPE_ARR: - cgen_write(g, U64_FMT, (U64)of_type->arr.n); + cgen_write(g, U64_FMT, (U64)of_type->arr->n); break; case TYPE_SLICE: cgen_write(g, "of_.len"); @@ -1869,7 +1875,7 @@ static void cgen_fn_decl(CGenerator *g, FnExpr *f) { Type *t = &f->foreign.type; /* foreign function declaration */ cgen_write(g, "extern "); - Type *fn_types = t->fn.types; + Type *fn_types = t->fn->types; const char *foreign_name = f->foreign.name; CType *ctypes = f->foreign.ctypes; if (ctypes[0].kind == CTYPE_NONE) { diff --git a/copy.c b/copy.c index b6716f5..ea5a9d4 100644 --- a/copy.c +++ b/copy.c @@ -34,6 +34,10 @@ static Copier copier_create(Allocator *a, Block *b) { return c; } +static inline void *copier_malloc(Copier *c, size_t n) { + return allocr_malloc(c->allocr, n); +} + static void copy_val(Allocator *a, Value *out, Value in, Type *t) { assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { @@ -57,7 +61,7 @@ static void copy_val(Allocator *a, Value *out, Value in, Type *t) { *out = in; break; case TYPE_ARR: { - size_t bytes = (size_t)t->arr.n * compiler_sizeof(t->arr.of); + size_t bytes = (size_t)t->arr->n * compiler_sizeof(t->arr->of); out->arr = allocr_malloc(a, bytes); memcpy(out->arr, in.arr, bytes); } break; @@ -129,11 +133,17 @@ static void copy_type(Copier *c, Type *out, Type *in) { out->expr = copy_expr_(c, in->expr); break; case TYPE_FN: { - size_t ntypes = arr_len(in->fn.types); - out->fn.types = NULL; - arr_set_lena(out->fn.types, ntypes, c->allocr); + FnType *outfn = copier_malloc(c, sizeof *outfn), *infn = in->fn; + size_t ntypes = arr_len(infn->types); + *outfn = *infn; + size_t constness_bytes = (ntypes-1) * sizeof *outfn->constness; + outfn->constness = allocr_malloc(c->allocr, constness_bytes); + memmove(outfn->constness, infn->constness, constness_bytes); + + outfn->types = NULL; + arr_set_lena(outfn->types, ntypes, c->allocr); for (size_t i = 0; i < ntypes; ++i) { - copy_type(c, &out->fn.types[i], &in->fn.types[i]); + copy_type(c, &outfn->types[i], &infn->types[i]); } } break; case TYPE_TUPLE: { @@ -144,14 +154,14 @@ static void copy_type(Copier *c, Type *out, Type *in) { copy_type(c, &out->tuple[i], &in->tuple[i]); } } break; - case TYPE_ARR: - if (in->flags & TYPE_IS_RESOLVED) { - out->arr.n = in->arr.n; - } else { - out->arr.n_expr = copy_expr_(c, in->arr.n_expr); + case TYPE_ARR:{ + ArrType *oarr = out->arr = copier_malloc(c, sizeof *oarr), *iarr = in->arr; + *oarr = *iarr; + if (!(in->flags & TYPE_IS_RESOLVED)) { + oarr->n_expr = copy_expr_(c, iarr->n_expr); } - out->arr.of = copy_type_(c, in->arr.of); - break; + oarr->of = copy_type_(c, in->arr->of); + } break; case TYPE_PTR: out->ptr = copy_type_(c, in->ptr); break; @@ -179,10 +189,6 @@ static Type *copy_type_(Copier *c, Type *in) { return out; } -static inline void *copier_malloc(Copier *c, size_t n) { - return allocr_malloc(c->allocr, n); -} - enum { COPY_FN_EXPR_DONT_COPY_BODY = 0x01 }; @@ -195,7 +201,7 @@ static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, U8 flags) { copy_expr(c, fout->foreign.name_expr = copier_malloc(c, sizeof *fin->foreign.name_expr), fin->foreign.name_expr); copy_expr(c, fout->foreign.lib_expr = copier_malloc(c, sizeof *fin->foreign.lib_expr), fin->foreign.lib_expr); copy_type(c, &fout->foreign.type, &fin->foreign.type); - size_t nctypes = arr_len(fin->foreign.type.fn.types); + size_t nctypes = arr_len(fin->foreign.type.fn->types); fout->foreign.ctypes = copier_malloc(c, nctypes * sizeof(CType)); memcpy(fout->foreign.ctypes, fin->foreign.ctypes, nctypes * sizeof(CType)); } else { diff --git a/eval.c b/eval.c index 3be73ea..d6a3487 100644 --- a/eval.c +++ b/eval.c @@ -52,7 +52,7 @@ static inline bool val_truthiness(Value v, Type *t) { case TYPE_BUILTIN: return builtin_truthiness(v, t->builtin); case TYPE_PTR: return v.ptr != NULL; case TYPE_FN: return v.fn != NULL; - case TYPE_ARR: return t->arr.n != 0; + case TYPE_ARR: return t->arr->n != 0; case TYPE_SLICE: return v.slice.len != 0; case TYPE_TUPLE: case TYPE_STRUCT: @@ -211,13 +211,13 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { } break; case TYPE_ARR: { fprintf(f, "["); /* @TODO: change? when array initializers are added */ - size_t n = (size_t)t->arr.n; + size_t n = (size_t)t->arr->n; if (n > 5) n = 5; for (size_t i = 0; i < n; ++i) { if (i) fprintf(f, ", "); - fprint_val_ptr(f, (char *)p + i * compiler_sizeof(t->arr.of), t->arr.of); + fprint_val_ptr(f, (char *)p + i * compiler_sizeof(t->arr->of), t->arr->of); } - if (t->arr.n > n) { + if (t->arr->n > n) { fprintf(f, ", ..."); } fprintf(f, "]"); @@ -232,7 +232,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { if (n > 5) n = 5; for (I64 i = 0; i < n; ++i) { if (i) fprintf(f, ", "); - fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->arr.of), t->arr.of); + fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->arr->of), t->arr->of); } if (slice.len > n) { fprintf(f, ", ..."); @@ -604,13 +604,13 @@ static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr } switch (arr_type->kind) { case TYPE_ARR: { - U64 arr_sz = (U64)arr_type->arr.n; + U64 arr_sz = (U64)arr_type->arr->n; if (i > arr_sz) { /* this is INTENTIONALLY > and not >=, because it's okay to have a pointer to one past the end of an array */ err_print(where, "Array out of bounds (index = %lu, array size = %lu)\n", (unsigned long)i, (unsigned long)arr_sz); return false; } - *ptr = (char *)arr_ptr + compiler_sizeof(arr_type->arr.of) * i; - if (type) *type = arr_type->arr.of; + *ptr = (char *)arr_ptr + compiler_sizeof(arr_type->arr->of) * i; + if (type) *type = arr_type->arr->of; } break; case TYPE_SLICE: { Slice slice = *(Slice *)arr_ptr; @@ -993,7 +993,7 @@ static Value val_zero(Allocator *a, Type *t) { val.struc = allocr_calloc(a, 1, compiler_sizeof(t)); break; case TYPE_ARR: - val.arr = allocr_calloc(a, (size_t)t->arr.n, compiler_sizeof(t->arr.of)); + val.arr = allocr_calloc(a, (size_t)t->arr->n, compiler_sizeof(t->arr->of)); break; default: break; @@ -1278,7 +1278,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i])) return false; } - Type *ret_type = &e->call.fn->type.fn.types[0]; + Type *ret_type = &e->call.fn->type.fn->types[0]; bool success = foreign_call(&ev->ffmgr, fn, ret_type, &e->call.arg_exprs[0].type, sizeof(Expression), args, nargs, e->where, v); free(args); if (!success) @@ -1391,7 +1391,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { Type *of_type = &s->of->type; if (!eval_expr(ev, s->of, &ofv)) return false; - U64 n = of_type->kind == TYPE_ARR ? of_type->arr.n : (U64)ofv.slice.len; + U64 n = of_type->kind == TYPE_ARR ? of_type->arr->n : (U64)ofv.slice.len; U64 from, to; if (s->from) { Value fromv; @@ -1680,7 +1680,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) { } switch (of_type->kind) { case TYPE_ARR: - len = (I64)of_type->arr.n; + len = (I64)of_type->arr->n; if (uses_ptr) { of.arr = of.ptr; } diff --git a/infer.c b/infer.c index aff8c6a..9778fb0 100644 --- a/infer.c +++ b/infer.c @@ -99,14 +99,14 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents } } break; case TYPE_FN: { - if (match->fn.constness || to->fn.constness) { + if (match->fn->constness || to->fn->constness) { return true; } if (to->kind != TYPE_FN) return true; - if (arr_len(match->fn.types) != arr_len(to->fn.types)) return true; - size_t i, len = arr_len(match->fn.types); + if (arr_len(match->fn->types) != arr_len(to->fn->types)) return true; + size_t i, len = arr_len(match->fn->types); for (i = 0; i < len; ++i) { - if (!infer_from_type(tr, &match->fn.types[i], &to->fn.types[i], idents, vals, types, where)) + if (!infer_from_type(tr, &match->fn->types[i], &to->fn->types[i], idents, vals, types, where)) return false; } } break; @@ -137,11 +137,11 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents Type n_type; construct_resolved_builtin_type(&n_type, BUILTIN_I64); Value val; - val.i64 = (I64)to->arr.n; + val.i64 = (I64)to->arr->n; /* try to match match's n expr to to's value */ - if (!infer_from_expr(tr, match->arr.n_expr, val, &n_type, where, idents, vals, types)) + if (!infer_from_expr(tr, match->arr->n_expr, val, &n_type, where, idents, vals, types)) return false; - if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types, where)) + if (!infer_from_type(tr, match->arr->of, to->arr->of, idents, vals, types, where)) return false; } break; } diff --git a/instance_table.c b/instance_table.c index 870ff60..0f1004e 100644 --- a/instance_table.c +++ b/instance_table.c @@ -97,7 +97,7 @@ static U64 type_hash(Type *t) { hash = hash * type_hash(sub) + 0x16225b0aa9993299; return hash; case TYPE_FN: - arr_foreach(t->fn.types, Type, sub) + arr_foreach(t->fn->types, Type, sub) hash = hash * type_hash(sub) + 0x2092d851ab2008de; return hash; case TYPE_PTR: @@ -110,8 +110,8 @@ static U64 type_hash(Type *t) { hash += (U64)t->struc; return hash; case TYPE_ARR: - hash += type_hash(t->arr.of) * 0x3b6256104800a414 + 0xa901e68bbd8968a1 - + 0xbf79c81a3e68e504 * t->arr.n; + hash += type_hash(t->arr->of) * 0x3b6256104800a414 + 0xa901e68bbd8968a1 + + 0xbf79c81a3e68e504 * t->arr->n; return hash; case TYPE_EXPR: break; } @@ -169,9 +169,9 @@ static U64 val_ptr_hash(void *v, Type *t) { case TYPE_ARR: { U32 x = 1; U64 hash = 0; - U64 size = (U64)compiler_sizeof(t->arr.of); - for (U64 i = 0; i < (U64)t->arr.n; ++i) { - hash += (U64)x * val_ptr_hash((char *)v + i * size, t->arr.of); + U64 size = (U64)compiler_sizeof(t->arr->of); + for (U64 i = 0; i < (U64)t->arr->n; ++i) { + hash += (U64)x * val_ptr_hash((char *)v + i * size, t->arr->of); x = rand_u32(x); } return hash; @@ -259,10 +259,10 @@ static bool val_ptr_eq(void *u, void *v, Type *t) { return true; } case TYPE_ARR: { - U64 size = (U64)compiler_sizeof(t->arr.of); + U64 size = (U64)compiler_sizeof(t->arr->of); char *uptr = u, *vptr = v; - for (U64 i = 0; i < t->arr.n; ++i) { - if (!val_ptr_eq(uptr, vptr, t->arr.of)) + for (U64 i = 0; i < t->arr->n; ++i) { + if (!val_ptr_eq(uptr, vptr, t->arr->of)) return false; uptr += size; vptr += size; @@ -270,7 +270,7 @@ static bool val_ptr_eq(void *u, void *v, Type *t) { return true; } case TYPE_SLICE: { - U64 size = (U64)compiler_sizeof(t->arr.of); + U64 size = (U64)compiler_sizeof(t->arr->of); Slice *r = u; Slice *s = v; if (r->len != s->len) return false; diff --git a/main.c b/main.c index a95f566..033b58f 100644 --- a/main.c +++ b/main.c @@ -8,9 +8,7 @@ /* @TODO: -make slice a pointer field of Value -make arr a pointer field of Type -- start passing Types instead of pointers to Type +start passing Types instead of pointers to Type figure out how printf is gonna work if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared) fix #foreign not at global scope - right now the cgen'd definition doesn't use the proper type diff --git a/parse.c b/parse.c index 836e675..c1238ad 100644 --- a/parse.c +++ b/parse.c @@ -220,14 +220,14 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { } case TYPE_FN: { size_t written = str_copy(buffer, bufsize, "fn ("); - Type *ret_type = t->fn.types; + Type *ret_type = t->fn->types; Type *param_types = ret_type + 1; - size_t nparams = arr_len(t->fn.types) - 1; + size_t nparams = arr_len(t->fn->types) - 1; for (size_t i = 0; i < nparams; ++i) { if (i > 0) written += str_copy(buffer + written, bufsize - written, ", "); - if (t->fn.constness) { - switch (t->fn.constness[i]) { + if (t->fn->constness) { + switch (t->fn->constness[i]) { case CONSTNESS_NO: break; case CONSTNESS_SEMI: written += str_copy(buffer + written, bufsize - written, ":::"); @@ -275,13 +275,13 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { case TYPE_ARR: { size_t written = str_copy(buffer, bufsize, "["); if (resolved) { - snprintf(buffer + written, bufsize - written, U64_FMT, t->arr.n); + snprintf(buffer + written, bufsize - written, U64_FMT, t->arr->n); written += strlen(buffer + written); } else { written += str_copy(buffer + written, bufsize - written, "N"); } written += str_copy(buffer + written, bufsize - written, "]"); - written += type_to_str_(t->arr.of, buffer + written, bufsize - written); + written += type_to_str_(t->arr->of, buffer + written, bufsize - written); return written; } case TYPE_SLICE: { @@ -542,18 +542,17 @@ static Status parse_type(Parser *p, Type *type, Location *where) { case KW_FN: { /* function type */ type->kind = TYPE_FN; - type->fn.types = NULL; - type->fn.constness = NULL; + FnType *fn = type->fn = parser_calloc(p, 1, sizeof *type->fn); ++t->token; if (!token_is_kw(t->token, KW_LPAREN)) { tokr_err(t, "Expected ( to follow fn."); return false; } - parser_arr_add_ptr(p, type->fn.types); /* add return type */ + parser_arr_add_ptr(p, fn->types); /* add return type */ ++t->token; if (!token_is_kw(t->token, KW_RPAREN)) { while (1) { - Type *param_type = parser_arr_add_ptr(p, type->fn.types); + Type *param_type = parser_arr_add_ptr(p, fn->types); Location type_where; if (!parse_type(p, param_type, &type_where)) return false; if (token_is_kw(t->token, KW_RPAREN)) @@ -566,7 +565,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) { } } ++t->token; /* move past ) */ - Type *ret_type = type->fn.types; + Type *ret_type = fn->types; /* if there's a symbol that isn't [, (, or &, that can't be the start of a type */ if ((t->token->kind == TOKEN_KW && t->token->kw <= KW_LAST_SYMBOL @@ -587,6 +586,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) { case KW_LSQUARE: { /* array/slice */ type->kind = TYPE_ARR; + ArrType *arr = type->arr = parser_malloc(p, sizeof *type->arr); ++t->token; /* move past [ */ if (token_is_kw(t->token, KW_RSQUARE)) { /* slice */ @@ -598,12 +598,12 @@ static Status parse_type(Parser *p, Type *type, Location *where) { break; } Token *end = expr_find_end(p, 0); - type->arr.n_expr = parser_new_expr(p); - if (!parse_expr(p, type->arr.n_expr, end)) return false; + arr->n_expr = parser_new_expr(p); + if (!parse_expr(p, arr->n_expr, end)) return false; t->token = end + 1; /* go past ] */ - type->arr.of = parser_malloc(p, sizeof *type->arr.of); + arr->of = parser_malloc(p, sizeof *arr->of); Location of_where; - if (!parse_type(p, type->arr.of, &of_where)) return false; + if (!parse_type(p, arr->of, &of_where)) return false; } break; case KW_AMPERSAND: { /* pointer */ @@ -1380,7 +1380,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { ++t->token; Type *fn_t = &fn->foreign.type; fn_t->kind = TYPE_FN; - FnType *fn_type = &fn_t->fn; + FnType *fn_type = fn_t->fn = parser_malloc(p, sizeof *fn_t); fn_type->constness = NULL; fn_type->types = NULL; /* reserve space for return type (Type + CType) */ diff --git a/types.c b/types.c index 496908f..81ebfeb 100644 --- a/types.c +++ b/types.c @@ -239,7 +239,7 @@ static size_t compiler_alignof(Type *t) { case TYPE_TUPLE: return toc_alignof(Value *); case TYPE_ARR: - return compiler_alignof(t->arr.of); + return compiler_alignof(t->arr->of); case TYPE_SLICE: if (sizeof(void *) > sizeof(size_t)) return toc_alignof(void *); @@ -267,7 +267,7 @@ static size_t compiler_sizeof(Type *t) { case TYPE_PTR: return sizeof v.ptr; case TYPE_ARR: - return (size_t)t->arr.n * compiler_sizeof(t->arr.of); + return (size_t)t->arr->n * compiler_sizeof(t->arr->of); case TYPE_TUPLE: return sizeof v.tuple; case TYPE_SLICE: @@ -358,10 +358,11 @@ static bool type_eq_exact(Type *a, Type *b) { case TYPE_STRUCT: return a->struc == b->struc; case TYPE_FN: { - if (arr_len(a->fn.types) != arr_len(b->fn.types)) return false; - Type *a_types = a->fn.types, *b_types = b->fn.types; - Constness *a_constness = a->fn.constness, *b_constness = b->fn.constness; - for (size_t i = 0; i < arr_len(a->fn.types); ++i) { + FnType *afn = a->fn, *bfn = b->fn; + if (arr_len(afn->types) != arr_len(bfn->types)) return false; + Type *a_types = afn->types, *b_types = bfn->types; + Constness *a_constness = afn->constness, *b_constness = bfn->constness; + for (size_t i = 0; i < arr_len(afn->types); ++i) { Constness const_a = CONSTNESS_NO, const_b = CONSTNESS_NO; if (a_constness) const_a = a_constness[i]; @@ -386,8 +387,8 @@ static bool type_eq_exact(Type *a, Type *b) { return true; } case TYPE_ARR: - if (a->arr.n != b->arr.n) return false; - return type_eq_exact(a->arr.of, b->arr.of); + if (a->arr->n != b->arr->n) return false; + return type_eq_exact(a->arr->of, b->arr->of); case TYPE_SLICE: return type_eq_exact(a->slice, b->slice); case TYPE_PTR: @@ -528,9 +529,9 @@ static bool type_is_compileonly(Type *t) { case TYPE_SLICE: return type_is_compileonly(t->slice); case TYPE_ARR: - return type_is_compileonly(t->arr.of); + return type_is_compileonly(t->arr->of); case TYPE_FN: - arr_foreach(t->fn.types, Type, sub) { + arr_foreach(t->fn->types, Type, sub) { if (sub->flags & TYPE_IS_RESOLVED) /* for templates */ { if (type_is_compileonly(sub)) return true; @@ -607,8 +608,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } t->kind = TYPE_FN; - t->fn.types = NULL; - t->fn.constness = NULL; /* @OPTIM: constness doesn't need to be a dynamic array */ + t->fn = typer_calloc(tr, 1, sizeof *t->fn); t->flags = 0; bool success = true; bool entered_fn = false; @@ -624,7 +624,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { size_t idx = 0; bool has_constant_params = false; /* reserve space for return type */ - typer_arr_add_ptr(tr, t->fn.types); + typer_arr_add_ptr(tr, t->fn->types); tr->fn = f; Block *prev_block = tr->block; tr->block = &f->body; @@ -669,15 +669,15 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } U32 is_at_all_const = param->flags & (DECL_IS_CONST | DECL_SEMI_CONST); if (is_at_all_const) { - if (!t->fn.constness) { + if (!t->fn->constness) { has_constant_params = true; for (size_t i = 0; i < idx; ++i) { - typer_arr_add(tr, t->fn.constness, CONSTNESS_NO); + typer_arr_add(tr, t->fn->constness, CONSTNESS_NO); } } } for (size_t i = 0; i < arr_len(param->idents); ++i) { - Type *param_type = typer_arr_add_ptr(tr, t->fn.types); + Type *param_type = typer_arr_add_ptr(tr, t->fn->types); if (param->flags & (DECL_ANNOTATES_TYPE|DECL_FOUND_TYPE)) *param_type = param->type; else @@ -691,7 +691,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } else { constn = CONSTNESS_NO; } - typer_arr_add(tr, t->fn.constness, constn); + typer_arr_add(tr, t->fn->constness, constn); } ++idx; } @@ -753,7 +753,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } { - Type *ret_type = &t->fn.types[0]; + Type *ret_type = &t->fn->types[0]; *ret_type = f->ret_type; } @@ -874,7 +874,7 @@ static Status type_resolve(Typer *tr, Type *t, Location where) { case TYPE_ARR: { /* it's an array */ Value val; - Expression *n_expr = t->arr.n_expr; + Expression *n_expr = t->arr->n_expr; if (!types_expr(tr, n_expr)) return false; if (n_expr->type.kind == TYPE_UNKNOWN) { err_print(n_expr->where, "Cannot determine type of array size at compile time."); @@ -893,19 +893,19 @@ static Status type_resolve(Typer *tr, Type *t, Location where) { if (type_builtin_is_signed(n_expr->type.builtin)) { I64 ssize = val_to_i64(val, n_expr->type.builtin); if (ssize < 0) { - err_print(t->arr.n_expr->where, "Negative array length (" I64_FMT ")", ssize); + err_print(t->arr->n_expr->where, "Negative array length (" I64_FMT ")", ssize); return false; } size = (U64)ssize; } else { size = val_to_u64(val, n_expr->type.builtin); } - t->arr.n = (U64)size; - if (!type_resolve(tr, t->arr.of, where)) + t->arr->n = (U64)size; + if (!type_resolve(tr, t->arr->of, where)) return false; } break; case TYPE_FN: - arr_foreach(t->fn.types, Type, child_type) { + arr_foreach(t->fn->types, Type, child_type) { if (!type_resolve(tr, child_type, where)) return false; } @@ -1201,7 +1201,7 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { if (instance) { f = instance->fn; } else { - if (t->fn.constness) + if (t->fn->constness) return true; /* don't type function body yet; we need to do that for every instance */ } { @@ -1213,7 +1213,7 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { success = false; goto ret; } - ret_type = t->fn.types; + ret_type = t->fn->types; has_named_ret_vals = f->ret_decls != NULL; if (!type_is_builtin(ret_type, BUILTIN_VOID) && !has_named_ret_vals) { Statement *stmts = f->body.stmts; @@ -1239,7 +1239,7 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Location where, I16 **orderp) { *orderp = NULL; assert(fn_type->flags & TYPE_IS_RESOLVED); - size_t nparams = arr_len(fn_type->fn.types)-1; + size_t nparams = arr_len(fn_type->fn->types)-1; size_t nargs = arr_len(args); if (nargs > nparams && !(fn->flags & FN_EXPR_HAS_VARARGS)) { err_print(where, "Expected at most %lu argument%s to function, but got %lu.", @@ -1639,7 +1639,7 @@ static Status types_expr(Typer *tr, Expression *e) { if (!type_of_fn(tr, fn, &e->type, 0)) { return false; } - if (!(fn->flags & FN_EXPR_FOREIGN) && (fn_has_any_const_params(fn) || fn_type_has_varargs(&e->type.fn))) { + 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 { @@ -1839,7 +1839,7 @@ static Status types_expr(Typer *tr, Expression *e) { err_print(e->where, "Calling non-function (type %s).", type); return false; } - bool has_varargs = f->type.kind == TYPE_FN && fn_type_has_varargs(&f->type.fn); + bool has_varargs = f->type.kind == TYPE_FN && fn_type_has_varargs(f->type.fn); if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE) || has_varargs) { Value val; @@ -1983,10 +1983,10 @@ static Status types_expr(Typer *tr, Expression *e) { fn_decl = val.fn; } - Type *ret_type = f->type.fn.types; + Type *ret_type = f->type.fn->types; Type *param_types = ret_type + 1; Argument *args = c->args; - size_t nparams = arr_len(f->type.fn.types) - 1; + size_t nparams = arr_len(f->type.fn->types) - 1; size_t nargs = arr_len(c->args); Expression *arg_exprs = NULL; size_t narg_exprs = 0; @@ -2025,7 +2025,7 @@ static Status types_expr(Typer *tr, Expression *e) { arg_exprs[i].where = param->where; arg_exprs[i].flags = param->expr.flags; arg_exprs[i].type = param->type; - if (has_varargs || f->type.fn.constness) { + if (has_varargs || f->type.fn->constness) { /* param->expr hasn't been typed or evaluated, because we passed type_of_fn a "generic" function */ /* we actually need to make a copy of this, so that copy_fn_expr still works later */ Expression default_arg; @@ -2115,7 +2115,7 @@ static Status types_expr(Typer *tr, Expression *e) { } } - FnType *fn_type = &f->type.fn; + FnType *fn_type = f->type.fn; c->arg_exprs = arg_exprs; FnExpr *original_fn = NULL; FnExpr *fn_copy = NULL; @@ -2304,7 +2304,7 @@ static Status types_expr(Typer *tr, Expression *e) { } } - ret_type = f->type.fn.types; + ret_type = f->type.fn->types; param_types = ret_type + 1; } @@ -2755,7 +2755,7 @@ static Status types_expr(Typer *tr, Expression *e) { } switch (lhs_type->kind) { case TYPE_ARR: - *t = *lhs_type->arr.of; + *t = *lhs_type->arr->of; break; case TYPE_SLICE: *t = *lhs_type->slice; @@ -2900,7 +2900,7 @@ static Status types_expr(Typer *tr, Expression *e) { e->val.i64 = (I64)arr_len(decl->val.varargs); } else if (struct_type->kind == TYPE_ARR) { e->kind = EXPR_VAL; - e->val.i64 = (I64)struct_type->arr.n; + e->val.i64 = (I64)struct_type->arr->n; } } else if (type_is_builtin(struct_type, BUILTIN_NMS)) { Value nms_val; @@ -2951,7 +2951,7 @@ static Status types_expr(Typer *tr, Expression *e) { return false; switch (s->of->type.kind) { case TYPE_ARR: - t->slice = s->of->type.arr.of; + t->slice = s->of->type.arr->of; break; case TYPE_SLICE: t->slice = s->of->type.slice; @@ -3214,16 +3214,16 @@ static Status types_decl(Typer *tr, Declaration *d) { if (!type_resolve(tr, val->type, d->where)) return false; } } - } else if (!(d->flags & DECL_IS_CONST) && t->kind == TYPE_FN && t->fn.constness) { - for (size_t p = 0; p < arr_len(t->fn.types)-1; ++p) { - if (t->fn.constness[p] == CONSTNESS_YES) { + } else if (!(d->flags & DECL_IS_CONST) && t->kind == TYPE_FN && t->fn->constness) { + for (size_t p = 0; p < arr_len(t->fn->types)-1; ++p) { + if (t->fn->constness[p] == CONSTNESS_YES) { err_print(d->where, "You can't have a pointer to a function with constant parameters."); success = false; goto ret; } } /* make constness NULL, so that semi-constant parameters turn into non-constant arguments */ - t->fn.constness = NULL; + t->fn->constness = NULL; } } @@ -3507,7 +3507,7 @@ top: iter_type = iter_type->slice; break; case TYPE_ARR: - iter_type = iter_type->arr.of; + iter_type = iter_type->arr->of; break; case TYPE_BUILTIN: switch (iter_type->builtin) { diff --git a/types.h b/types.h index 8ffd890..b8c1026 100644 --- a/types.h +++ b/types.h @@ -434,9 +434,17 @@ typedef U8 Constness; typedef struct FnType { struct Type *types; /* dynamic array [0] = ret_type, [1:] = param_types */ - Constness *constness; /* [i] = constness of param #i. iff no parameters are constant, this is NULL. don't use it as a dynamic array, because eventually it might not be. */ + Constness *constness; /* [i] = constness of param #i. iff no parameters are constant, this is NULL. don't use it as a dynamic array, because it might not always be. */ } FnType; +typedef struct { + struct Type *of; + union { + U64 n; /* after resolving */ + struct Expression *n_expr; /* before resolving */ + }; +} ArrType; + enum { TYPE_IS_FLEXIBLE = 0x01, TYPE_IS_RESOLVED = 0x02, @@ -447,15 +455,9 @@ typedef struct Type { TypeFlags flags; union { BuiltinType builtin; - FnType fn; + FnType *fn; struct Type *tuple; - struct { - struct Type *of; - union { - U64 n; /* after resolving */ - struct Expression *n_expr; /* before resolving */ - }; - } arr; + ArrType *arr; struct Type *ptr; struct Type *slice; struct StructDef *struc; /* multiple resolved types can refer to the same struct */ -- cgit v1.2.3