diff options
-rw-r--r-- | allocator.c | 6 | ||||
-rw-r--r-- | cgen.c | 24 | ||||
-rw-r--r-- | copy.c | 24 | ||||
-rw-r--r-- | data_structures.c | 222 | ||||
-rw-r--r-- | decls_cgen.c | 6 | ||||
-rw-r--r-- | eval.c | 43 | ||||
-rw-r--r-- | foreign.c | 2 | ||||
-rw-r--r-- | identifiers.c | 2 | ||||
-rw-r--r-- | instance_table.c | 10 | ||||
-rw-r--r-- | main.c | 20 | ||||
-rw-r--r-- | parse.c | 81 | ||||
-rwxr-xr-x | tests/test.sh | 5 | ||||
-rw-r--r-- | toc.c | 2 | ||||
-rw-r--r-- | tokenizer.c | 16 | ||||
-rw-r--r-- | types.c | 170 | ||||
-rw-r--r-- | types.h | 9 |
16 files changed, 338 insertions, 304 deletions
diff --git a/allocator.c b/allocator.c index 8baedb5..98005ef 100644 --- a/allocator.c +++ b/allocator.c @@ -74,7 +74,7 @@ static void *allocr_calloc(Allocator *a, size_t n, size_t sz) { #endif if (n == 0 || sz == 0) return NULL; if (a == NULL) return err_calloc(n, sz); - /* OPTIM: use calloc */ + /* @OPTIM: use calloc */ size_t bytes = n * sz; void *data = allocr_malloc(a, bytes); memset(data, 0, bytes); @@ -88,11 +88,11 @@ static void allocr_free(Allocator *a, void *data, size_t size) { if (a == NULL) { free(data); } - /* OPTIM */ + /* @OPTIM */ (void)size; } -/* OPTIM */ +/* @OPTIM */ static void *allocr_realloc(Allocator *a, void *data, size_t old_size, size_t new_size) { #if NO_ALLOCATOR a = NULL; @@ -265,7 +265,7 @@ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) { static bool fn_has_instances(FnExpr *f) { if (fn_has_any_const_params(f)) return true; if (!arr_len(f->params)) return false; - return type_is_builtin(&((Declaration *)arr_last(f->params))->type, BUILTIN_VARARGS); + return type_is_builtin(&arr_last(f->params).type, BUILTIN_VARARGS); } static bool cgen_uses_ptr(Type *t) { @@ -392,7 +392,7 @@ static void cgen_type_post(CGenerator *g, Type *t) { cgen_type_pre(g, x); cgen_write(g, "(*)"); cgen_type_post(g, x); - if (x != arr_last(ret_type->tuple)) { + if (x != arr_last_ptr(ret_type->tuple)) { cgen_write(g, ", "); } } @@ -509,7 +509,7 @@ static void cgen_val_ptr_pre(CGenerator *g, void *v, Type *t) { cgen_val_ptr_pre(g, (char *)s->data + (U64)i * compiler_sizeof(t->slice), t->slice); } cgen_type_pre(g, t->slice); - cgen_write(g, "(d%p_[])", v); /* TODO: improve this somehow? */ + cgen_write(g, "(d%p_[])", v); /* @TODO: improve this somehow? */ cgen_type_post(g, t->slice); cgen_write(g, " = {"); for (I64 i = 0; i < s->len; ++i) { @@ -865,7 +865,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, cgen_ident_id(g, id); cgen_type_post(g, type); cgen_write(g, "; "); - *(IdentID *)arr_add(&underscore_ids) = id; + arr_add(underscore_ids, id); } } } @@ -912,7 +912,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, cgen_write(g, "&(%s%d_)", prefix, i); } } - arr_clear(&underscore_ids); + arr_clear(underscore_ids); cgen_writeln(g, "); "); } break; case EXPR_IF: @@ -1155,7 +1155,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { cgen_nl(g); } break; case EXPR_VAL: - /* TODO: don't make a variable for this if it's not needed */ + /* @TODO: don't make a variable for this if it's not needed */ if (type_is_compileonly(&e->type)) break; if (!cgen_is_type_simple(&e->type)) { @@ -1245,7 +1245,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { Value fn_val = *decl_val_at_index(d, index); FnExpr *fn = fn_val.fn; Expression fn_expr; - /* TODO: is this all really necessary? */ + /* @TODO: is this all really necessary? */ fn_expr.kind = EXPR_FN; fn_expr.fn = allocr_malloc(g->allocr, sizeof *fn_expr.fn); @@ -1784,7 +1784,7 @@ static void cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) --g->indent_lvl; if (!(flags & CGEN_BLOCK_NOBRACES)) { cgen_deferred_from_block(g, b); - arr_clear(&b->deferred); + arr_clear(b->deferred); cgen_write(g, "}"); if (b->c.break_lbl) { cgen_lbl(g, b->c.break_lbl); @@ -2019,7 +2019,7 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr) tuple_expr.type = f->ret_type; tuple_expr.kind = EXPR_TUPLE; tuple_expr.tuple = NULL; - arr_set_len(&tuple_expr.tuple, arr_len(f->ret_type.tuple)); + arr_set_len(tuple_expr.tuple, arr_len(f->ret_type.tuple)); int idx = 0; arr_foreach(f->ret_decls, Declaration, d) { arr_foreach(d->idents, Identifier, ident) { @@ -2032,7 +2032,7 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr) } } cgen_set_tuple(g, NULL, NULL, "*ret__", &tuple_expr); - arr_clear(&tuple_expr.tuple); + arr_clear(tuple_expr.tuple); } else if (cgen_uses_ptr(&f->ret_type)) { Expression expr = {0}; expr.flags = EXPR_FOUND_TYPE; @@ -2068,7 +2068,7 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr) static void cgen_stmt(CGenerator *g, Statement *s) { #ifdef CGEN_EMIT_LINE_NUMBER_COMMENTS - /* TODO: add compiler option for this */ + /* @TODO: add compiler option for this */ cgen_write(g, "/* %s:%d */", s->where.ctx->filename, s->where.line); #endif switch (s->kind) { @@ -2114,7 +2114,7 @@ static void cgen_stmt(CGenerator *g, Statement *s) { cgen_writeln(g, ";"); } break; case STMT_DEFER: - *(Statement **)arr_add(&g->block->deferred) = s->defer; + arr_add(g->block->deferred, s->defer); break; case STMT_USE: case STMT_MESSAGE: @@ -41,7 +41,7 @@ static void copy_val(Allocator *a, Value *out, Value in, Type *t) { if (t->builtin == BUILTIN_VARARGS) { size_t n = arr_len(in.varargs); out->varargs = NULL; - arr_set_lena(&out->varargs, n, a); + arr_set_lena(out->varargs, n, a); for (size_t i = 0; i < n; ++i) { Copier c = copier_create(a, NULL); /* since the type is resolved, it doesn't matter that the block is wrong */ out->varargs[i].type = copy_type_(&c, in.varargs[i].type); @@ -100,7 +100,7 @@ static void copy_struct(Copier *c, StructDef *out, StructDef *in) { size_t nfields = arr_len(in->fields); out->fields = NULL; - arr_set_lena(&out->fields, nfields, c->allocr); + arr_set_lena(out->fields, nfields, c->allocr); for (size_t i = 0; i < nfields; ++i) { Field *fout = &out->fields[i]; Field *fin = &in->fields[i]; @@ -110,7 +110,7 @@ static void copy_struct(Copier *c, StructDef *out, StructDef *in) { } size_t nparams = arr_len(in->params); out->params = NULL; - arr_set_lena(&out->params, nparams, c->allocr); + arr_set_lena(out->params, nparams, c->allocr); for (size_t i = 0; i < nparams; ++i) { copy_decl(c, &out->params[i], &in->params[i]); } @@ -131,7 +131,7 @@ static void copy_type(Copier *c, Type *out, Type *in) { case TYPE_FN: { size_t ntypes = arr_len(in->fn.types); out->fn.types = NULL; - arr_set_lena(&out->fn.types, ntypes, c->allocr); + arr_set_lena(out->fn.types, ntypes, c->allocr); for (size_t i = 0; i < ntypes; ++i) { copy_type(c, &out->fn.types[i], &in->fn.types[i]); } @@ -139,7 +139,7 @@ static void copy_type(Copier *c, Type *out, Type *in) { case TYPE_TUPLE: { size_t ntypes = arr_len(in->tuple); out->tuple = NULL; - arr_set_lena(&out->tuple, ntypes, c->allocr); + arr_set_lena(out->tuple, ntypes, c->allocr); for (size_t i = 0; i < ntypes; ++i) { copy_type(c, &out->tuple[i], &in->tuple[i]); } @@ -210,13 +210,13 @@ static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, U8 flags) { size_t i; size_t nparam_decls = arr_len(fin->params); fout->params = NULL; - arr_set_lena(&fout->params, nparam_decls, c->allocr); + arr_set_lena(fout->params, nparam_decls, c->allocr); for (i = 0; i < nparam_decls; ++i) copy_decl(c, fout->params + i, fin->params + i); size_t nret_decls = arr_len(fin->ret_decls); if (fin->ret_decls) { fout->ret_decls = NULL; - arr_set_lena(&fout->ret_decls, nret_decls, c->allocr); + arr_set_lena(fout->ret_decls, nret_decls, c->allocr); for (i = 0; i < nret_decls; ++i) copy_decl(c, fout->ret_decls + i, fin->ret_decls + i); } @@ -308,7 +308,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { copy_expr(c, cout->fn = allocr_malloc(a, sizeof *cout->fn), cin->fn); size_t nargs = arr_len(cin->args); cout->arg_exprs = NULL; - arr_set_lena(&cout->args, nargs, a); + arr_set_lena(cout->args, nargs, a); for (size_t i = 0; i < nargs; ++i) { Argument *arg_in = &cin->args[i]; Argument *arg_out = &cout->args[i]; @@ -322,7 +322,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { case EXPR_TUPLE: { size_t nexprs = arr_len(in->tuple); out->tuple = NULL; - arr_set_lena(&out->tuple, nexprs, a); + arr_set_lena(out->tuple, nexprs, a); for (size_t i = 0; i < nexprs; ++i) copy_expr(c, out->tuple + i, in->tuple + i); } break; @@ -374,7 +374,7 @@ static void copy_decl(Copier *c, Declaration *out, Declaration *in) { copy_type(c, &out->type, &in->type); out->idents = NULL; size_t nidents = arr_len(in->idents); - arr_set_lena(&out->idents, nidents, c->allocr); + arr_set_lena(out->idents, nidents, c->allocr); for (size_t i = 0; i < nidents; ++i) { out->idents[i] = in->idents[i]; assert(c->block); @@ -399,7 +399,7 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) { *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); + 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]); } @@ -448,7 +448,7 @@ static void copy_block(Copier *c, Block *out, Block *in, U8 flags) { out->ret_expr = copy_expr_(c, in->ret_expr); if (!(flags & COPY_BLOCK_DONT_CREATE_IDENTS)) idents_create(&out->idents, c->allocr, out); - arr_set_lena(&out->stmts, nstmts, c->allocr); + arr_set_lena(out->stmts, nstmts, c->allocr); for (size_t i = 0; i < nstmts; ++i) { copy_stmt(c, &out->stmts[i], &in->stmts[i]); } diff --git a/data_structures.c b/data_structures.c index 9bab854..e16ea0d 100644 --- a/data_structures.c +++ b/data_structures.c @@ -23,7 +23,6 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to <http://unlicense.org/> */ -/* OPTIM: is it faster to store void *end? */ typedef struct ArrHeader { size_t len; size_t cap; @@ -31,8 +30,7 @@ typedef struct ArrHeader { } ArrHeader; static inline ArrHeader *arr_hdr(void *arr) { - ArrHeader *hdr = (ArrHeader *)((char *)arr - offsetof(ArrHeader, data)); - return hdr; + return (ArrHeader *)((char *)arr - offsetof(ArrHeader, data)); } static inline size_t arr_len(void *arr) { @@ -44,96 +42,114 @@ static inline void arr_zero_(void *arr, size_t item_sz) { memset(arr, 0, item_sz * arr_len(arr)); } -static void arr_resv_(void **arr, size_t n, size_t item_sz) { - if (*arr == NULL) { - ArrHeader *hdr = err_malloc(item_sz * n + sizeof(ArrHeader) + 1); /* +1 => prevent ptr overflow */ +static WarnUnusedResult void *arr_resv_(void *arr, size_t n, size_t item_sz) { + ArrHeader *hdr; + if (arr == NULL) { + hdr = err_malloc(item_sz * n + sizeof(ArrHeader)); hdr->len = 0; hdr->cap = n; - *arr = hdr->data; } else { - ArrHeader *hdr = arr_hdr(*arr); + hdr = arr_hdr(arr); hdr->cap = n; - hdr = err_realloc(hdr, item_sz * n + sizeof(ArrHeader) + 1); + hdr = err_realloc(hdr, item_sz * n + sizeof(ArrHeader)); if (hdr->len > hdr->cap) hdr->len = hdr->cap; - *arr = hdr->data; } + return hdr->data; } -static void arr_resva_(void **arr, size_t n, size_t item_sz, Allocator *a) { - if (*arr == NULL) { - ArrHeader *hdr = allocr_malloc(a, item_sz * n + sizeof(ArrHeader)); +static WarnUnusedResult void *arr_resva_(void *arr, size_t n, size_t item_sz, Allocator *a) { + ArrHeader *hdr; + if (arr == NULL) { + hdr = allocr_malloc(a, item_sz * n + sizeof(ArrHeader)); hdr->len = 0; hdr->cap = n; - *arr = hdr->data; } else { - ArrHeader *hdr = arr_hdr(*arr); + hdr = arr_hdr(arr); hdr = allocr_realloc(a, hdr, item_sz * hdr->cap + sizeof(ArrHeader), item_sz * n + sizeof(ArrHeader)); hdr->cap = n; if (hdr->len > hdr->cap) hdr->len = hdr->cap; - *arr = hdr->data; - } + } + return hdr->data; } -static void arr_clear_(void **arr) { - if (*arr) { - free(arr_hdr(*arr)); - *arr = NULL; + +/* accommodate one more element if necessary */ +static WarnUnusedResult void *arr_grow(void *arr, size_t item_sz) { + ArrHeader *hdr; + if (arr == NULL) { + hdr = err_malloc(sizeof *hdr + item_sz); + hdr->len = 0; + hdr->cap = 1; + } else { + hdr = arr_hdr(arr); + if (hdr->len >= hdr->cap) { + size_t new_size = sizeof *hdr + item_sz * (hdr->cap *= 2); + hdr = err_realloc(hdr, new_size); + } } + return hdr->data; } -static void arr_cleara_(void **arr, size_t size, Allocator *allocr) { - if (*arr) { - ArrHeader *header = arr_hdr(*arr); +static WarnUnusedResult void *arr_growa(void *arr, size_t item_sz, Allocator *allocr) { + ArrHeader *hdr; + if (arr == NULL) { + hdr = allocr_malloc(allocr, sizeof *hdr + item_sz); + hdr->len = 0; + hdr->cap = 1; + } else { + hdr = arr_hdr(arr); + if (hdr->len >= hdr->cap) { + size_t old_size = sizeof *hdr + item_sz * hdr->cap; + size_t new_size = sizeof *hdr + item_sz * hdr->cap * 2; + hdr = allocr_realloc(allocr, hdr, old_size, new_size); + hdr->cap *= 2; + } + } + return hdr->data; +} + +static WarnUnusedResult void *arr_clear_(void *arr) { + if (arr) { + free(arr_hdr(arr)); + } + return NULL; +} + +static WarnUnusedResult void *arr_cleara_(void *arr, size_t size, Allocator *allocr) { + if (arr) { + ArrHeader *header = arr_hdr(arr); allocr_free(allocr, header, header->cap * size); - *arr = NULL; } + return NULL; } -static void arr_set_len_(void **arr, size_t n, size_t item_sz) { +static WarnUnusedResult void *arr_set_len_(void *arr, size_t n, size_t item_sz) { if (n == 0) { - arr_clear_(arr); - return; + return arr_clear_(arr); } - if (n > arr_len(*arr)) { - arr_resv_(arr, n, item_sz); + if (n > arr_len(arr)) { + arr = arr_resv_(arr, n, item_sz); } - arr_hdr(*arr)->len = n; - /* OPTIM: shrink */ + arr_hdr(arr)->len = n; + /* @OPTIM: shrink */ + return arr; } -static void arr_set_lena_(void **arr, size_t n, size_t item_sz, Allocator *a) { +static WarnUnusedResult void *arr_set_lena_(void *arr, size_t n, size_t item_sz, Allocator *a) { if (n == 0) { - arr_cleara_(arr, item_sz, a); - return; + return arr_cleara_(arr, item_sz, a); } - arr_resva_(arr, n, item_sz, a); - arr_hdr(*arr)->len = n; + arr = arr_resva_(arr, n, item_sz, a); + arr_hdr(arr)->len = n; + return arr; } -static void *arr_add_(void **arr, size_t item_sz) { - ArrHeader *hdr; - if (*arr == NULL) { - arr_resv_(arr, 1, item_sz); - hdr = arr_hdr(*arr); - } else { - hdr = arr_hdr(*arr); - if (hdr->len >= hdr->cap) { - arr_resv_(arr, hdr->len * 2 + 1, item_sz); - hdr = arr_hdr(*arr); - } - } +static void *arr_add_ptr_(void **arr, size_t item_sz) { + *arr = arr_grow(*arr, item_sz); + ArrHeader *hdr = arr_hdr(*arr); return &(((char *)hdr->data)[(hdr->len++) * item_sz]); } -static void *arr_adda_(void **arr, size_t item_sz, Allocator *a) { - ArrHeader *hdr; - if (*arr == NULL) { - arr_resva_(arr, 10, item_sz, a); - hdr = arr_hdr(*arr); - } else { - hdr = arr_hdr(*arr); - if (hdr->len >= hdr->cap) { - arr_resva_(arr, hdr->len * 2 + 1, item_sz, a); - hdr = arr_hdr(*arr); - } - } +static void *arr_adda_ptr_(void **arr, size_t item_sz, Allocator *a) { + *arr = arr_growa(*arr, item_sz, a); + ArrHeader *hdr = arr_hdr(*arr); return &(((char *)hdr->data)[(hdr->len++) * item_sz]); } @@ -156,35 +172,35 @@ static void *arr_end_(void *arr, size_t item_sz) { } } -/* OPTIM: shrink array */ -static void arr_remove_last_(void **arr) { - assert(arr_hdr(*arr)->len); - if (--arr_hdr(*arr)->len == 0) { - arr_clear_(arr); +/* @OPTIM: shrink array */ +static WarnUnusedResult void *arr_remove_last_(void *arr) { + assert(arr_hdr(arr)->len); + if (--arr_hdr(arr)->len == 0) { + return arr_clear_(arr); } + return arr; } -static void arr_remove_lasta_(void **arr, size_t item_sz, Allocator *a) { - assert(arr_hdr(*arr)->len); - if (--arr_hdr(*arr)->len == 0) { - arr_cleara_(arr, item_sz, a); +static WarnUnusedResult void *arr_remove_lasta_(void *arr, size_t item_sz, Allocator *a) { + assert(arr_hdr(arr)->len); + if (--arr_hdr(arr)->len == 0) { + return arr_cleara_(arr, item_sz, a); } + return arr; } -static void arr_copya_(void **out, void *in, size_t item_sz, Allocator *a) { +static WarnUnusedResult void *arr_copya_(void *out, void *in, size_t item_sz, Allocator *a) { size_t len = arr_len(in); - arr_resva_(out, len, item_sz, a); - memcpy(*out, in, len * item_sz); + out = arr_resva_(out, len, item_sz, a); + memcpy(out, in, len * item_sz); + return out; } -#ifdef __GNUC__ -#define typeof __typeof__ -#endif - #if defined(__GNUC__) || defined(__TINYC__) #define HAS_TYPEOF 1 +#define typeof __typeof__ #endif #if HAS_TYPEOF @@ -193,38 +209,42 @@ this is to cast the return value of arr_add so that gcc produces a warning if yo do something like: float *arr = NULL; // ... -int *x = arr_add(&arr); +int *x = arr_add_ptr(&arr); You shouldn't rely on this, though, e.g. by doing -*arr_add(&arr) = 17; +*arr_add_ptr(&arr) = 17; */ -#define arr_ptr_type(arr) __typeof__(*(arr)) +#define arr_ptr_type(arr) typeof(arr) #else #define arr_ptr_type(arr) void * #endif #define arr_zero(arr) arr_zero_(arr, sizeof *(arr)) -#define arr_add(arr) (arr_ptr_type(arr))arr_add_((void **)(arr), sizeof **(arr)) -#define arr_adda(arr, allocr) (arr_ptr_type(arr))arr_adda_((void **)(arr), sizeof **(arr), (allocr)) -#define arr_resv(arr, n) arr_resv_((void **)(arr), n, sizeof **(arr)) -#define arr_resva(arr, n, allocr) arr_resva_((void **)(arr), n, sizeof **(arr), (allocr)) -#define arr_set_len(arr, n) arr_set_len_((void **)(arr), n, sizeof **(arr)) -#define arr_set_lena(arr, n, a) arr_set_lena_((void **)(arr), n, sizeof **(arr), (a)) -#define arr_clear(arr) arr_clear_((void **)(arr)), (void)sizeof **arr /* second part makes sure most of the time that you don't accidentally call it without taking the address */ -#define arr_cleara(arr, allocr) arr_cleara_((void **)(arr), sizeof **(arr), (allocr)) -#define arr_last(arr) arr_last_((void *)(arr), sizeof *(arr)) +#define arr_add(arr, x) arr = arr_grow((arr), sizeof *(arr)), (arr)[arr_hdr(arr)->len++] = x +#define arr_add_ptr(arr) (arr_ptr_type(arr))arr_add_ptr_((void **)(&arr), sizeof *(arr)) +#define arr_adda(arr, x, allocr) arr = arr_growa((arr), sizeof *(arr), (allocr)), (arr)[arr_hdr(arr)->len++] = x +#define arr_adda_ptr(arr, allocr) (arr_ptr_type(arr))arr_adda_ptr_((void **)(&arr), sizeof *(arr), (allocr)) +#define arr_resv(arr, n) arr = arr_resv_((arr), n, sizeof *(arr)) +#define arr_resva(arr, n, allocr) arr = arr_resva_((arr), n, sizeof *(arr), (allocr)) +#define arr_set_len(arr, n) arr = arr_set_len_((arr), n, sizeof *(arr)) +#define arr_set_lena(arr, n, allocr) arr = arr_set_lena_((arr), n, sizeof *(arr), (allocr)) +#define arr_clear(arr) arr = arr_clear_(arr) +#define arr_cleara(arr, allocr) arr = arr_cleara_((arr), sizeof *(arr), (allocr)) +#define arr_last(arr) arr[arr_len(arr)-1] +#define arr_last_ptr(arr) arr_last_((arr), sizeof *(arr)) /* one past last, or NULL if empty */ -#define arr_end(arr) arr_end_((void *)(arr), sizeof *(arr)) +#define arr_end(arr) arr_end_((arr), sizeof *(arr)) #define arr_foreach(arr, type, var) for (type *var = (arr), *var##_foreach_end = arr_end(arr); var != var##_foreach_end; ++var) -#define arr_foreach_reversed(arr, type, var) for (type *var = arr_last(arr), *var##_foreach_last = arr; var; var = var == var##_foreach_last ? NULL : (var-1)) -#define arr_remove_last(arr) arr_remove_last_((void **)(arr)), (void)sizeof **(arr) -#define arr_remove_lasta(arr, a) arr_remove_lasta_((void **)(arr), sizeof **(arr), (a)) -#define arr_copya(out, in, a) do { assert(sizeof *(in) == sizeof **(out)); arr_copya_((void **)(out), (in), sizeof **(out), (a)); } while(0) +#define arr_foreach_reversed(arr, type, var) for (type *var = arr_last_ptr(arr), *var##_foreach_last = arr; var; var = var == var##_foreach_last ? NULL : (var-1)) +#define arr_remove_last(arr) arr = arr_remove_last_(arr) +#define arr_remove_lasta(arr, allocr) arr = arr_remove_lasta_((arr), sizeof *(arr), (allocr)) +#define arr_copya(out, in, allocr) do { assert(sizeof *(in) == sizeof *(out)); out = arr_copya_((out), (in), sizeof *(out), (allocr)); } while(0) -#ifdef RUN_TESTS +#if RUN_TESTS +/* @TODO(eventually): more extensive test? */ static void arr_test(void) { int *foos = NULL; for (int i = 0; i < 10; ++i) { - *(int *)arr_add(&foos) = i; + arr_add(foos, i); } for (int i = 0; i < (int)arr_len(foos); ++i) { assert(foos[i] == i); @@ -234,7 +254,7 @@ static void arr_test(void) { assert(*x == lastx + 1); lastx = *x; } - arr_clear(&foos); + arr_clear(foos); } #endif @@ -281,7 +301,7 @@ static void str_hash_table_grow(StrHashTable *t) { if (slots_cap <= 2 * t->nentries) { StrHashTableSlot **new_slots = NULL; size_t new_slots_cap = slots_cap * 2 + 10; - arr_set_lena(&new_slots, new_slots_cap, t->allocr); + arr_set_lena(new_slots, new_slots_cap, t->allocr); arr_zero(new_slots); arr_foreach(t->slots, StrHashTableSlotPtr, slotp) { StrHashTableSlot *slot = *slotp; @@ -291,7 +311,7 @@ static void str_hash_table_grow(StrHashTable *t) { *new_slot = slot; } } - arr_cleara(&t->slots, t->allocr); + arr_cleara(t->slots, t->allocr); t->slots = new_slots; } } @@ -341,7 +361,7 @@ static void str_hash_table_free(StrHashTable *t) { arr_foreach(t->slots, StrHashTableSlotPtr, slotp) { allocr_free(t->allocr, *slotp, str_hash_table_slot_size(t)); } - arr_cleara(&t->slots, t->allocr); + arr_cleara(t->slots, t->allocr); } static StrHashTableSlot *str_hash_table_get_(StrHashTable *t, const char *str, size_t len) { @@ -357,7 +377,7 @@ static inline void *str_hash_table_get(StrHashTable *t, const char *str, size_t return slot->data; } -#ifdef RUN_TESTS +#if RUN_TESTS static void str_hash_table_test(void) { StrHashTable t; str_hash_table_create(&t, sizeof(int), NULL); diff --git a/decls_cgen.c b/decls_cgen.c index 78f51a3..736df03 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -81,14 +81,14 @@ static void cgen_sdecls_expr(CGenerator *g, Expression *e) { case EXPR_NMS: { char *prefix_part = cgen_nms_prefix_part(g, e->nms); size_t prefix_part_len = strlen(prefix_part); - char const *prev_prefix = g->nms_prefixes ? *(char const **)arr_last(g->nms_prefixes) + char const *prev_prefix = g->nms_prefixes ? arr_last(g->nms_prefixes) : ""; size_t prev_prefix_len = strlen(prev_prefix); char *new_prefix = cgen_malloc(g, prev_prefix_len + prefix_part_len + 1); memcpy(new_prefix, prev_prefix, prev_prefix_len); memcpy(new_prefix + prev_prefix_len, prefix_part, prefix_part_len); free(prefix_part); - *(char const **)arr_add(&g->nms_prefixes) = new_prefix; + arr_add(g->nms_prefixes, new_prefix); new_prefix[prev_prefix_len + prefix_part_len] = 0; e->nms->c.prefix = new_prefix; } break; @@ -98,7 +98,7 @@ static void cgen_sdecls_expr(CGenerator *g, Expression *e) { cgen_recurse_subexprs(g, e, cgen_sdecls_expr, cgen_sdecls_block, cgen_sdecls_decl); } if (e->kind == EXPR_NMS) { - arr_remove_last(&g->nms_prefixes); + arr_remove_last(g->nms_prefixes); } } @@ -205,7 +205,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { } break; case TYPE_FN: - fprintf(f, "<function @ %p>", (void *)*(FnExpr **)p); + fprintf(f, "<function %p>", (void *)*(FnExpr **)p); break; case TYPE_TUPLE: { Value *tuple = *(Value **)p; @@ -217,7 +217,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { fprintf(f, ")"); } break; case TYPE_ARR: { - fprintf(f, "["); /* TODO: change? when array initializers are added */ + fprintf(f, "["); /* @TODO: change? when array initializers are added */ size_t n = t->arr.n; if (n > 5) n = 5; for (size_t i = 0; i < n; ++i) { @@ -233,7 +233,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { fprintf(f, "<pointer: %p>", *(void **)p); break; case TYPE_SLICE: { - fprintf(f, "["); /* TODO: change? when slice initializers are added */ + fprintf(f, "["); /* @TODO: change? when slice initializers are added */ Slice slice = *(Slice *)p; I64 n = slice.len; if (n > 5) n = 5; @@ -247,7 +247,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { fprintf(f, "]"); } break; case TYPE_STRUCT: - fprintf(f, "["); /* TODO: change? when struct initializers are added */ + fprintf(f, "["); /* @TODO: change? when struct initializers are added */ arr_foreach(t->struc->fields, Field, fi) { if (fi != t->struc->fields) fprintf(f, ", "); @@ -670,7 +670,7 @@ static Value *ident_val(Evaluator *ev, Identifier i, Location where) { return NULL; /* silently fail (something went wrong when we typed this decl) */ if (decl->flags & DECL_IS_PARAM) { if (decl->val_stack) { - Value *valp = *(Value **)arr_last(decl->val_stack); + Value *valp = arr_last(decl->val_stack); if (arr_len(decl->idents) > 1) return &valp->tuple[idx]; else @@ -693,7 +693,7 @@ static Value *ident_val(Evaluator *ev, Identifier i, Location where) { } else if (decl->flags & DECL_IS_CONST) { return decl_val_at_index(decl, idx); } else if (decl->val_stack) { - Value *valp = *(Value **)arr_last(decl->val_stack); + Value *valp = arr_last(decl->val_stack); if (arr_len(decl->idents) > 1) return &valp->tuple[idx]; else @@ -1041,8 +1041,8 @@ static Status eval_ident(Evaluator *ev, Identifier ident, Value *v, Location whe } static Value *decl_add_val(Declaration *d) { - Value **valpp = arr_add(&d->val_stack); - Value *valp = *valpp = err_malloc(sizeof *valp); + Value *valp = err_malloc(sizeof *valp); + arr_add(d->val_stack, valp); if (arr_len(d->idents) > 1) { valp->tuple = err_malloc(arr_len(d->idents) * sizeof *valp->tuple); } @@ -1051,8 +1051,7 @@ static Value *decl_add_val(Declaration *d) { static void decl_remove_val(Declaration *d) { assert(arr_len(d->val_stack)); - Value **valpp = arr_last(d->val_stack); - Value *valp = *valpp; + Value *valp = arr_last(d->val_stack); if (arr_len(d->idents) == 1 || d->type.kind == TYPE_TUPLE) { val_free_ptr(valp, &d->type); } else { @@ -1062,7 +1061,7 @@ static void decl_remove_val(Declaration *d) { free(valp->tuple); free(valp); } - arr_remove_last(&d->val_stack); + arr_remove_last(d->val_stack); } static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { @@ -1252,8 +1251,8 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { case EXPR_FOR: { ForExpr *fo = e->for_; Declaration *header = &fo->header; - Value **for_valpp = arr_add(&header->val_stack); - Value *for_valp = *for_valpp = err_malloc(sizeof *for_valp); + Value *for_valp = err_malloc(sizeof *for_valp); + arr_add(header->val_stack, for_valp); /* make a tuple */ Value for_val_tuple[2]; for_valp->tuple = for_val_tuple; @@ -1353,7 +1352,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { ++index->i64; } } - arr_remove_last(&header->val_stack); + arr_remove_last(header->val_stack); free(for_valp); } break; case EXPR_BLOCK: @@ -1435,7 +1434,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { /* set varargs */ pval->varargs = NULL; for (; arg != args_end; ++arg) { - VarArg *varg = arr_add(&pval->varargs); + VarArg *varg = arr_add_ptr(pval->varargs); if (!eval_expr(ev, arg, &varg->val)) return false; varg->type = &arg->type; @@ -1495,7 +1494,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { expr.ident = *ident; if (!eval_expr(ev, &expr, &this_one)) return false; - Value *element = arr_add(&tuple); + Value *element = arr_add_ptr(tuple); Type *type = decl_type_at_index(d, i); copy_val(NULL, element, this_one, type); ++i; @@ -1503,7 +1502,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } if (arr_len(tuple) == 1) { *v = tuple[0]; - arr_clear(&tuple); + arr_clear(tuple); } else { v->tuple = tuple; } @@ -1544,7 +1543,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } else { to = n; } - /* TODO: is this the best check? (Go also checks if from > to) */ + /* @TODO: is this the best check? (Go also checks if from > to) */ if (to > n) { err_print(e->where, "Slice index out of bounds (to = %lu, length = %lu).", (unsigned long)to, (unsigned long)n); return false; @@ -1665,7 +1664,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) { break; case STMT_INCLUDE: { Include *i = stmt->inc; - Statement *last_reached = arr_last(i->stmts); + Statement *last_reached = arr_last_ptr(i->stmts); arr_foreach(i->stmts, Statement, sub) { if (!eval_stmt(ev, sub)) return false; @@ -1679,7 +1678,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) { case STMT_MESSAGE: break; case STMT_DEFER: - *(Statement **)arr_add(&ev->typer->block->deferred) = stmt->defer; + arr_add(ev->typer->block->deferred, stmt->defer); break; case STMT_USE: break; @@ -1692,7 +1691,7 @@ static Status eval_block(Evaluator *ev, Block *b, Value *v) { ev->typer->block = b; b->deferred = NULL; bool success = true; - Statement *last_reached = arr_last(b->stmts); + Statement *last_reached = arr_last_ptr(b->stmts); arr_foreach(b->stmts, Statement, stmt) { if (!eval_stmt(ev, stmt)) { success = false; @@ -1735,7 +1734,7 @@ static Status eval_block(Evaluator *ev, Block *b, Value *v) { if (!eval_stmt(ev, stmt)) return false; } - arr_clear(&b->deferred); + arr_clear(b->deferred); ev->returning = return_block; ev->ret_val = return_val; } @@ -200,7 +200,7 @@ static bool arg_list_add(av_alist *arg_list, Value val, Type *type, Location whe case TYPE_VOID: case TYPE_TUPLE: case TYPE_UNKNOWN: - case TYPE_ARR: { /* TODO: maybe just pass pointer for arr? */ + case TYPE_ARR: { /* @TODO: maybe just pass pointer for arr? */ char *s = type_to_str(type); err_print(where, "Cannot pass type %s to foreign function.", s); free(s); diff --git a/identifiers.c b/identifiers.c index bb30e36..2daa112 100644 --- a/identifiers.c +++ b/identifiers.c @@ -181,7 +181,7 @@ static inline Block *ident_scope(Identifier i) { return i->idents->scope; } -#ifdef RUN_TESTS +#if RUN_TESTS static void idents_test(void) { Identifiers ids; char b[] = "foo_variable bar"; diff --git a/instance_table.c b/instance_table.c index 6a06f4b..924ac1d 100644 --- a/instance_table.c +++ b/instance_table.c @@ -4,7 +4,7 @@ You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>. */ /* - TODO: better hash functions, especially for integers + @TODO: better hash functions, especially for integers (right now, nearby integers are close together in hash space, which is bad with the way these hash tables are designed) @@ -22,7 +22,7 @@ static bool val_eq(Value u, Value v, Type *t); static bool type_eq_exact(Type *t1, Type *t2); static U64 f32_hash(F32 f) { - /* OPTIM */ + /* @OPTIM */ U64 hash = 0; if (f < 0) { hash = 0x9a6db29edcba8af4; @@ -48,7 +48,7 @@ static U64 f32_hash(F32 f) { } static U64 f64_hash(F64 f) { - /* OPTIM */ + /* @OPTIM */ U64 hash = 0; if (f < 0) { hash = 0x9a6db29edcba8af4; @@ -306,7 +306,7 @@ static bool val_eq(Value u, Value v, Type *t) { and set already_exists accordingly make sure v's data remains valid */ -/* OPTIM: store instances in a block array (remember that the pointers need to stay valid!) */ +/* @OPTIM: store instances in a block array (remember that the pointers need to stay valid!) */ static Instance *instance_table_adda(Allocator *a, HashTable *h, Value v, Type *t, bool *already_exists) { if (h->n * 2 >= h->cap) { @@ -318,7 +318,7 @@ static Instance *instance_table_adda(Allocator *a, HashTable *h, Value v, Type * for (U64 i = 0; i < h->cap; ++i) { /* re-hash */ if (old_occupied[i]) { - /* OPTIM: keep hashes around */ + /* @OPTIM: keep hashes around */ U64 index = val_hash(old_data[i]->val, t) % new_cap; while (new_occupied[index]) { ++index; @@ -7,9 +7,8 @@ /* see development.md for development information */ /* -TODO: -arr_add_val -arr_last_val +@TODO: +arr_add-val test for use ... test used ret decls consider: don't do inference for function calls; get rid of was_expr -- now that we have struct params @@ -19,6 +18,9 @@ use - use with struct members (e.g. SuperPoint ::= struct { use p: Point; }) maybe change to #define check(x) do { if_unlikely(x) return 0; } while (0); always use pointers in cgen'd non-range for loops (sometimes also indices) +test: + _ := 5; + _ := 6; is there a problem where we can get TYPE_UNKNOWN in cgen, triggering an assert(0)? -simple example, but maybe try other stuff: x := #C("5"); -also make sure you can't do x:#C("5"); @@ -39,6 +41,7 @@ X ::= newtype(int); or something any odd number of "s for a string use point #except x; optional -Wshadow +format errors so that vim/emacs can jump to them --- make sure that floating point literals are exact as possible have some way of doing Infinity and s/qNaN (you can @@ -46,6 +49,8 @@ make sure that floating point literals are exact as possible once you have a bunch of test code: - analyze memory usage by secretly passing __FILE__, __LINE__ to allocr_m/c/realloc - try making more Expression members pointers +- should val_stack be on the allocator? what about temporary arrays? + -->on the contrary, should in_decls be off the allocator? - branch data: #define if(x) bool join(cond, __LINE__) = x; register_branch(__FILE__, __LINE__, cond); if (join(cond, __LINE__)) error on x ::= {return; 3} struct param inference @@ -65,9 +70,9 @@ passing untyped expressions to macros #include "toc.c" #if defined TOC_DEBUG && defined __GNU_LIBRARY__ && defined UNISTD_AVAILABLE -#define BACKTRACE +#define BACKTRACE 1 #endif -#ifdef BACKTRACE +#if BACKTRACE #include <signal.h> #include <execinfo.h> @@ -104,12 +109,12 @@ static void signal_handler(int num) { } #endif int main(int argc, char **argv) { -#ifdef BACKTRACE +#if BACKTRACE program_name = argv[0]; signal(SIGABRT, signal_handler); signal(SIGSEGV, signal_handler); #endif -#ifdef RUN_TESTS +#if RUN_TESTS printf("running tests...\n"); test_all(); #endif @@ -233,4 +238,3 @@ int main(int argc, char **argv) { fclose(out); return 0; } - @@ -253,7 +253,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { if (def->params) { written += str_copy(buffer + written, bufsize - written, "("); arr_foreach(def->params, Declaration, param) { - /* TODO: val to str */ + /* @TODO: val to str */ if (param != def->params) written += str_copy(buffer + written, bufsize - written, ", "); written += str_copy(buffer + written, bufsize - written, "<argument>"); @@ -297,7 +297,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { return written; } case TYPE_EXPR: - /* TODO: improve this... we're gonna need expr_to_str ): */ + /* @TODO: improve this... we're gonna need expr_to_str ): */ return str_copy(buffer, bufsize, "<type expression>"); } @@ -330,11 +330,10 @@ static inline void parser_put_end(Parser *p, Location *l) { parser_set_end_to_token(p, l, p->tokr->token); } -static inline void *parser_arr_add_(Parser *p, void **a, size_t sz) { - return arr_adda_(a, sz, p->allocr); -} - -#define parser_arr_add(p, a) parser_arr_add_(p, (void **)(a), sizeof **(a)) +#define parser_arr_add_ptr(p, a) arr_adda_ptr(a, p->allocr) +#define parser_arr_add(p, a, x) arr_adda(a, x, p->allocr) +#define parser_arr_set_len(p, a, l) arr_set_lena(a, l, p->allocr) +#define parser_arr_remove_last(p, a) arr_remove_lasta(a, p->allocr) static inline void *parser_malloc(Parser *p, size_t bytes) { return allocr_malloc(p->allocr, bytes); @@ -424,14 +423,14 @@ static Token *expr_find_end(Parser *p, ExprEndFlags flags) { } if (token->kind == TOKEN_EOF) { if (brace_level > 0) { - tokr_err(t, "Opening brace { was never closed."); /* TODO: Find out where this is */ + tokr_err(t, "Opening brace { was never closed."); /* @TODO: Find out where this is */ } else if (paren_level > 0) { tokr_err(t, "Opening parenthesis ( was never closed."); } else if (square_level > 0) { tokr_err(t, "Opening square bracket [ was never closed."); } else { tokr_err(t, "Could not find end of expression (did you forget a semicolon?)."); - /* TODO: ? improve err message */ + /* @TODO: ? improve err message */ } t->token = token; /* don't try to continue */ return NULL; @@ -455,7 +454,7 @@ static Status parse_args(Parser *p, Argument **args) { info_print(token_location(p->file, start), "This is where the argument list starts."); return false; } - Argument *arg = parser_arr_add(p, args); + Argument *arg = parser_arr_add_ptr(p, *args); arg->where = parser_mk_loc(p); /* named arguments */ if (t->token->kind == TOKEN_IDENT && token_is_kw(t->token + 1, KW_EQ)) { @@ -485,7 +484,7 @@ static void correct_ret_type(Parser *p, Type *ret_type) { size_t ntuple_members = arr_len(tuple_members); ret_type->kind = TYPE_TUPLE; ret_type->tuple = NULL; - arr_set_lena(&ret_type->tuple, ntuple_members, p->allocr); + parser_arr_set_len(p, ret_type->tuple, ntuple_members); for (size_t i = 0; i < ntuple_members; ++i) { Type *out_type = &ret_type->tuple[i]; out_type->flags = 0; @@ -525,11 +524,11 @@ static Status parse_type(Parser *p, Type *type, Location *where) { tokr_err(t, "Expected ( to follow fn."); return false; } - parser_arr_add(p, &type->fn.types); /* add return type */ + parser_arr_add_ptr(p, type->fn.types); /* add return type */ ++t->token; if (!token_is_kw(t->token, KW_RPAREN)) { while (1) { - Type *param_type = parser_arr_add(p, &type->fn.types); + Type *param_type = parser_arr_add_ptr(p, type->fn.types); Location type_where; if (!parse_type(p, param_type, &type_where)) return false; if (token_is_kw(t->token, KW_RPAREN)) @@ -623,7 +622,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) { goto struct_fail; } if ((param->flags & DECL_ANNOTATES_TYPE) && type_is_builtin(¶m->type, BUILTIN_VARARGS)) { - /* TODO(eventually) */ + /* @TODO(eventually) */ err_print(param->where, "structs cannot have varargs parameters (yet)."); goto struct_fail; } @@ -823,14 +822,14 @@ static Status parse_block(Parser *p, Block *b, U8 flags) { if (!token_is_kw(t->token, KW_RBRACE)) { /* non-empty block */ while (1) { - Statement *stmt = parser_arr_add(p, &b->stmts); + Statement *stmt = parser_arr_add_ptr(p, b->stmts); bool was_a_statement; bool success = parse_stmt(p, stmt, &was_a_statement); if (!success) { ret = false; } if (!was_a_statement) { - arr_remove_lasta(&b->stmts, p->allocr); + parser_arr_remove_last(p, b->stmts); } if (token_is_kw(t->token, KW_RBRACE)) { break; @@ -861,7 +860,7 @@ static Status parse_decl_list(Parser *p, Declaration **decls, U16 flags) { !token_is_kw(t->token - 1, KW_RPAREN) && !token_is_kw(t->token - 1, KW_LBRACE)))) { first = false; - Declaration *decl = parser_arr_add(p, decls); + Declaration *decl = parser_arr_add_ptr(p, *decls); if (!parse_decl(p, decl, flags)) { ret = false; /* skip to end of list */ @@ -873,13 +872,19 @@ static Status parse_decl_list(Parser *p, Declaration **decls, U16 flags) { /* split this declaration */ size_t nidents = arr_len(decl->idents); for (size_t i = 1; i < nidents; ++i) { - Declaration *new_decl = parser_arr_add(p, decls); + Declaration *new_decl = parser_arr_add_ptr(p, *decls); *new_decl = *decl; new_decl->idents = NULL; - arr_set_lena(&new_decl->idents, 1, p->allocr); + parser_arr_set_len(p, new_decl->idents, 1); new_decl->idents[0] = decl->idents[i]; } - arr_set_lena(&decl->idents, 1, p->allocr); + parser_arr_set_len(p, decl->idents, 1); + } + } + /* correct ident decls because the pointers to declarations might have changed */ + arr_foreach(*decls, Declaration, decl) { + arr_foreach(decl->idents, Identifier, ident) { + (*ident)->decl = decl; } } return ret; @@ -1470,8 +1475,10 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { FnType *fn_type = &fn_t->fn; fn_type->constness = NULL; fn_type->types = NULL; - Type *ret_type = parser_arr_add(p, &fn_type->types); - CType *ret_ctype = parser_arr_add(p, &fn->foreign.ctypes); + /* reserve space for return type (Type + CType) */ + parser_arr_add_ptr(p, fn_type->types); + parser_arr_add_ptr(p, fn->foreign.ctypes); + Expression *name = fn->foreign.name_expr = parser_new_expr(p); if (!parse_expr(p, name, expr_find_end(p, EXPR_CAN_END_WITH_COMMA))) @@ -1506,8 +1513,8 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } ++t->token; while (!token_is_kw(t->token, KW_RPAREN)) { - Type *type = parser_arr_add(p, &fn_type->types); - CType *ctype = parser_arr_add(p, &fn->foreign.ctypes); + Type *type = parser_arr_add_ptr(p, fn_type->types); + CType *ctype = parser_arr_add_ptr(p, fn->foreign.ctypes); if (!parse_c_type(p, ctype, type)) { return false; } @@ -1521,6 +1528,9 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { return false; } } + + Type *ret_type = &fn_type->types[0]; + CType *ret_ctype = &fn->foreign.ctypes[0]; if (t->token == end) { /* void */ ret_ctype->kind = CTYPE_NONE; @@ -1765,14 +1775,14 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { if (lhs.kind == EXPR_TUPLE) { e->tuple = lhs.tuple; } else { - *(Expression *)parser_arr_add(p, &e->tuple) = lhs; + parser_arr_add(p, e->tuple, lhs); } if (rhs.kind == EXPR_TUPLE) { arr_foreach(rhs.tuple, Expression, r) { - *(Expression *)parser_arr_add(p, &e->tuple) = *r; + parser_arr_add(p, e->tuple, *r); } } else { - *(Expression *)parser_arr_add(p, &e->tuple) = rhs; + parser_arr_add(p, e->tuple, rhs); } goto success; } @@ -2042,7 +2052,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { e->kind = EXPR_BLOCK; if (!parse_block(p, e->block = parser_malloc(p, sizeof *e->block), 0)) return false; if (t->token != end) { - tokr_err(t, "Expression continues after end of block."); /* TODO: improve this err message */ + tokr_err(t, "Expression continues after end of block."); /* @TODO: improve this err message */ return false; } goto success; @@ -2114,14 +2124,13 @@ static Status parse_decl(Parser *p, Declaration *d, U16 flags) { } while (1) { - Identifier *ident = parser_arr_add(p, &d->idents); if (t->token->kind != TOKEN_IDENT) { tokr_err(t, "Cannot declare non-identifier (%s).", token_kind_to_str(t->token->kind)); goto ret_false; } - *ident = parser_ident_insert(p, t->token->ident); - if (!(flags & PARSE_DECL_DONT_SET_IDECLS) && !ident_eq_str(*ident, "_")) { - Identifier i = *ident; + Identifier i = parser_ident_insert(p, t->token->ident); + parser_arr_add(p, d->idents, i); + if (!(flags & PARSE_DECL_DONT_SET_IDECLS) && !ident_eq_str(i, "_")) { if (!check_ident_redecl(p, i)) goto ret_false; i->decl = d; @@ -2425,7 +2434,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { d->where = s->where; parser_put_end(p, &d->where); /* we haven't set s->where.end, so... */ d->flags |= DECL_HAS_EXPR|DECL_IS_CONST; - *(Identifier *)parser_arr_add(p, &d->idents) = ident; + parser_arr_add(p, d->idents, ident); if (!check_ident_redecl(p, ident)) { tokr_skip_semicolon(t); @@ -2443,7 +2452,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { body->where = s->where; body->parent = p->block; idents_create(&body->idents, p->allocr, body); - Statement *inc_stmt = parser_arr_add(p, &body->stmts); + Statement *inc_stmt = parser_arr_add_ptr(p, body->stmts); inc_stmt->kind = STMT_INCLUDE; inc_stmt->flags = STMT_INC_TO_NMS; inc_stmt->where = s->where; @@ -2533,11 +2542,11 @@ static Status parse_file(Parser *p, ParsedFile *f) { bool ret = true; while (t->token->kind != TOKEN_EOF) { bool was_a_statement; - Statement *stmt = parser_arr_add(p, &f->stmts); + Statement *stmt = parser_arr_add_ptr(p, f->stmts); if (!parse_stmt(p, stmt, &was_a_statement)) ret = false; if (!was_a_statement) - arr_remove_lasta(&f->stmts, p->allocr); + parser_arr_remove_last(p, f->stmts); if (token_is_kw(t->token, KW_RBRACE)) { tokr_err(t, "} without a matching {."); return false; diff --git a/tests/test.sh b/tests/test.sh index 8df4c46..a603767 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -51,7 +51,7 @@ do_tests() { printf '\x1b[92mpassed!\x1b[0m\n' else printf '\x1b[91mfailed!\x1b[0m\n' - failed=true + exit 1 fi done } @@ -60,6 +60,3 @@ for x in $tests; do done rm got a.out out.c -if $failed; then - exit 1 -fi @@ -138,7 +138,7 @@ static void cgen_sdecls_file(CGenerator *g, ParsedFile *f); #include "cgen.c" #include "decls_cgen.c" -#ifdef RUN_TESTS +#if RUN_TESTS #include "tests.c" #endif diff --git a/tokenizer.c b/tokenizer.c index f155b9f..cdbebd8 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -7,7 +7,7 @@ static inline const char *kw_to_str(Keyword k) { return keywords[k]; } /* Returns KW_COUNT if it's not a keyword */ -/* OPTIM: don't use strncmp so much */ +/* @OPTIM: don't use strncmp so much */ static Keyword tokenize_kw(char **s) { for (Keyword k = 0; k < KW_COUNT; k = k + 1) { size_t len = strlen(keywords[k]); @@ -127,7 +127,7 @@ static inline int char_as_hex_digit(char c) { /* returns -1 if escape sequence is invalid */ static int tokr_esc_seq(Tokenizer *t) { - /* TODO: octal (\032)? */ + /* @TODO: octal (\032)? */ switch (*t->s) { case '\'': tokr_nextchar(t); @@ -251,7 +251,7 @@ until everything is done */ static void tokr_create(Tokenizer *t, ErrCtx *err_ctx, Allocator *allocr) { t->tokens = NULL; - arr_resva(&t->tokens, 256, allocr); + arr_resva(t->tokens, 256, allocr); t->allocr = allocr; t->err_ctx = err_ctx; } @@ -261,7 +261,7 @@ static inline void *tokr_malloc(Tokenizer *t, size_t bytes) { } static Token *tokr_add(Tokenizer *t) { - Token *token = arr_adda(&t->tokens, t->allocr); + Token *token = arr_adda_ptr(t->tokens, t->allocr); tokr_put_start_pos(t, token); return token; } @@ -328,7 +328,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { tokr_put_end_pos(t, &token); token.kind = TOKEN_DIRECT; token.direct = direct; - *(Token *)arr_adda(&t->tokens, t->allocr) = token; + arr_adda(t->tokens, token, t->allocr); continue; } --t->s; /* go back to # */ @@ -345,7 +345,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { tokr_put_end_pos(t, &token); token.kind = TOKEN_KW; token.kw = kw; - *(Token *)arr_adda(&t->tokens, t->allocr) = token; + arr_adda(t->tokens, token, t->allocr); continue; } } @@ -407,7 +407,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { n->kind = NUM_LITERAL_FLOAT; n->floatval = (Floating)n->intval; } - /* TODO: check if exceeding maximum exponent */ + /* @TODO: check if exceeding maximum exponent */ int exponent = 0; if (*t->s == '+') tokr_nextchar(t); /* ignore + after e */ @@ -421,7 +421,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { exponent *= 10; exponent += *t->s - '0'; } - /* OPTIM: Slow for very large exponents (unlikely to happen) */ + /* @OPTIM: Slow for very large exponents (unlikely to happen) */ for (int i = 0; i < exponent; ++i) { if (negative_exponent) n->floatval /= 10; @@ -19,18 +19,17 @@ static inline void *typer_calloc(Typer *tr, size_t n, size_t sz) { return allocr_calloc(tr->allocr, n, sz); } -static inline void *typer_arr_add_(Typer *tr, void **arr, size_t sz) { - return arr_adda_(arr, sz, tr->allocr); -} +#define typer_arr_add(tr, a, x) arr_adda(a, x, tr->allocr) +#define typer_arr_add_ptr(tr, a) arr_adda_ptr(a, tr->allocr) static inline void typer_block_enter(Typer *tr, Block *b) { - *(Block **)arr_adda(&tr->blocks, tr->allocr) = b; + typer_arr_add(tr, tr->blocks, b); tr->block = b; } static inline void typer_block_exit(Typer *tr) { - arr_remove_lasta(&tr->blocks, tr->allocr); - tr->block = *(Block **)arr_last(tr->blocks); + arr_remove_lasta(tr->blocks, tr->allocr); + tr->block = arr_last(tr->blocks); } static inline void construct_resolved_builtin_type(Type *t, BuiltinType builtin) { @@ -183,7 +182,6 @@ static size_t compiler_sizeof(Type *t) { } -#define typer_arr_add(tr, a) typer_arr_add_(tr, (void **)(a), sizeof **(a)) /* are a and b EXACTLY equal (not counting flags)? */ static bool type_eq_exact(Type *a, Type *b) { assert(a->flags & TYPE_IS_RESOLVED); @@ -448,7 +446,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.constness = NULL; /* @OPTIM: constness doesn't need to be a dynamic array */ t->flags = 0; bool success = true; bool entered_fn = false; @@ -456,7 +454,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { FnExpr *prev_fn = tr->fn; FnExpr fn_copy = {0}; - Declaration *last_param = arr_last(f->params); + Declaration *last_param = arr_last_ptr(f->params); bool has_varargs = last_param && (last_param->flags & DECL_ANNOTATES_TYPE) && type_is_builtin(&last_param->type, BUILTIN_VARARGS); if (has_varargs) f->flags |= FN_EXPR_HAS_VARARGS; @@ -469,7 +467,8 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } size_t idx = 0; bool has_constant_params = false; - Type *ret_type = typer_arr_add(tr, &t->fn.types); + /* reserve space for return type */ + typer_arr_add_ptr(tr, t->fn.types); tr->fn = f; typer_block_enter(tr, &f->body); f->body.uses = NULL; @@ -516,12 +515,12 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { if (!t->fn.constness) { has_constant_params = true; for (size_t i = 0; i < idx; ++i) { - *(Constness *)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(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 @@ -535,7 +534,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } else { constn = CONSTNESS_NO; } - *(Constness *)typer_arr_add(tr, &t->fn.constness) = constn; + typer_arr_add(tr, t->fn.constness, constn); } ++idx; } @@ -560,7 +559,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { f->ret_type.tuple = NULL; arr_foreach(f->ret_decls, Declaration, d) { arr_foreach(d->idents, Identifier, i) { - *(Type *)arr_add(&f->ret_type.tuple) = d->type; + typer_arr_add(tr, f->ret_type.tuple, d->type); } } } @@ -596,7 +595,11 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { } t->flags |= TYPE_IS_RESOLVED; } - *ret_type = f->ret_type; + + { + Type *ret_type = &t->fn.types[0]; + *ret_type = f->ret_type; + } ret: /* cleanup */ @@ -619,7 +622,8 @@ top:; Block *decl_scope = ident_scope(i); if (decl_scope->kind != BLOCK_NMS) { /* go back through scopes */ - for (Block **block = arr_last(tr->blocks); *block && *block != decl_scope; --block) { + arr_foreach_reversed(tr->blocks, BlockPtr, block) { + if (*block == NULL || *block == decl_scope) break; if ((*block)->kind == BLOCK_FN) { captured = true; break; @@ -717,7 +721,7 @@ static Status add_block_to_struct(Typer *tr, Block *b, StructDef *s, Statement * err_print(d->where, "struct members can't be inferred."); return false; } - *(Statement *)typer_arr_add(tr, new_stmts) = *stmt; + typer_arr_add(tr, *new_stmts, *stmt); } else { if (flags & DECL_SEMI_CONST) { err_print(d->where, "struct members can't be semi-constant."); @@ -729,14 +733,14 @@ static Status add_block_to_struct(Typer *tr, Block *b, StructDef *s, Statement * } int i = 0; arr_foreach(d->idents, Identifier, ident) { - Field *field = typer_arr_add(tr, &s->fields); + Field *field = typer_arr_add_ptr(tr, s->fields); field->where = d->where; field->name = *ident; field->type = decl_type_at_index(d, i); ++i; } - *(Statement *)typer_arr_add(tr, new_stmts) = *stmt; + typer_arr_add(tr, *new_stmts, *stmt); } if (b != &s->body) { /* we need to translate d's identifiers to s's scope */ @@ -861,8 +865,7 @@ static Status type_resolve(Typer *tr, Type *t, Location where) { } if (!eval_expr(tr->evalr, sub, &typeval)) return false; - Type *subtype = typer_arr_add(tr, &tuple); - *subtype = *typeval.type; + typer_arr_add(tr, tuple, *typeval.type); } if (is_tuple_of_types) { t->kind = TYPE_TUPLE; @@ -1058,7 +1061,7 @@ static CastStatus type_cast_status(Type *from, Type *to) { return CAST_STATUS_NONE; if (to->kind == TYPE_FN) return CAST_STATUS_WARN; - /* TODO: Cast from ptr to arr */ + /* @TODO: Cast from ptr to arr */ return CAST_STATUS_ERR; case TYPE_ARR: return CAST_STATUS_ERR; @@ -1239,7 +1242,7 @@ static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Lo } } this_param = param; - if (param > (Declaration *)arr_last(fn->params)) { + if (param > (Declaration *)arr_last_ptr(fn->params)) { err_print(arg->where, "Too many arguments to function!"); info_print(fn->where, "Declaration is here."); return false; @@ -1411,7 +1414,7 @@ static Value get_builtin_val(BuiltinVal val) { case BUILTIN_SIZEOF_SIZE_T: v.i64 = (I64)sizeof(size_t); break; - /* TODO(eventually): fix these for cross compilation */ + /* @TODO(eventually): fix these for cross compilation */ case BUILTIN_TSIZEOF_SHORT: v.i64 = (I64)sizeof(short); break; @@ -1518,7 +1521,7 @@ static Status get_struct_constant(StructDef *struc, Identifier member, Expressio } static bool fn_type_has_varargs(FnType *f) { - return type_is_builtin(arr_last(f->types), BUILTIN_VARARGS); + return type_is_builtin(arr_last_ptr(f->types), BUILTIN_VARARGS); } static Status types_expr(Typer *tr, Expression *e) { @@ -1573,7 +1576,7 @@ static Status types_expr(Typer *tr, Expression *e) { ForExpr *fo = e->for_; Declaration *header = &fo->header; - *(Declaration **)typer_arr_add(tr, &tr->in_decls) = header; + typer_arr_add(tr, tr->in_decls, header); fo->body.uses = NULL; typer_block_enter(tr, &fo->body); bool annotated_index = true; @@ -1588,13 +1591,13 @@ static Status types_expr(Typer *tr, Expression *e) { annotated_index = false; assert(nidents == 1); /* turn value := arr to value, _ := arr to simplify things */ - *(Identifier *)arr_add(&header->idents) = ident_insert_with_len(typer_get_idents(tr), "_", 1); + typer_arr_add(tr, header->idents, ident_insert_with_len(typer_get_idents(tr), "_", 1)); } } Type *fo_type_tuple = NULL; /* fo_type is (val_type, index_type) */ - arr_set_lena(&fo_type_tuple, 2, tr->allocr); + arr_set_lena(fo_type_tuple, 2, tr->allocr); memset(fo_type_tuple, 0, 2*sizeof *fo_type_tuple); Type *val_type = &fo_type_tuple[0]; Type *index_type = &fo_type_tuple[1]; @@ -1741,7 +1744,7 @@ static Status types_expr(Typer *tr, Expression *e) { case BUILTIN_VARARGS: { /* exit for body */ typer_block_exit(tr); - arr_remove_lasta(&tr->in_decls, tr->allocr); + arr_remove_lasta(tr->in_decls, tr->allocr); /* create one block, containing a block for each vararg */ /* e.g. for x := varargs { total += x; } => { { x := varargs[0]; total += x; } { x := varargs[0]; total += x; } } */ assert(fo->of->kind == EXPR_IDENT); @@ -1756,7 +1759,7 @@ static Status types_expr(Typer *tr, Expression *e) { b->stmts = NULL; b->parent = tr->block; b->where = e->where; - arr_set_lena(&b->stmts, nvarargs, tr->allocr); + arr_set_lena(b->stmts, nvarargs, tr->allocr); Statement *stmt = b->stmts; size_t nstmts = arr_len(fo->body.stmts); Declaration *header_decl = &fo->header; @@ -1779,10 +1782,10 @@ static Status types_expr(Typer *tr, Expression *e) { sub->stmts = NULL; sub->where = e->where; size_t total_nstmts = nstmts + has_val + has_index; - arr_set_lena(&sub->stmts, total_nstmts, tr->allocr); + arr_set_lena(sub->stmts, total_nstmts, tr->allocr); Copier copier = copier_create(tr->allocr, sub); if (has_val) { - /* TODO(eventually): don't put a decl in each block, just put one at the start */ + /* @TODO(eventually): don't put a decl in each block, just put one at the start */ Statement *s = &sub->stmts[0]; s->flags = 0; s->kind = STMT_DECL; @@ -1792,7 +1795,7 @@ static Status types_expr(Typer *tr, Expression *e) { Declaration *decl = s->decl = typer_calloc(tr, 1, sizeof *decl); decl->where = fo->of->where; Identifier ident = ident_translate_forced(val_ident, &sub->idents); - *(Identifier *)arr_adda(&decl->idents, tr->allocr) = ident; + typer_arr_add(tr, decl->idents, ident); ident->decl = decl; decl->flags |= DECL_HAS_EXPR; @@ -1806,7 +1809,7 @@ static Status types_expr(Typer *tr, Expression *e) { index->where = fo->of->where; } if (has_index) { - /* TODO(eventually): don't put a decl in each block, just put one at the start */ + /* @TODO(eventually): don't put a decl in each block, just put one at the start */ Statement *s = &sub->stmts[has_val]; s->flags = 0; s->kind = STMT_DECL; @@ -1816,7 +1819,7 @@ static Status types_expr(Typer *tr, Expression *e) { Declaration *decl = s->decl = typer_calloc(tr, 1, sizeof *decl); decl->where = fo->of->where; Identifier ident = ident_translate_forced(index_ident, &sub->idents); - *(Identifier *)arr_adda(&decl->idents, tr->allocr) = ident; + typer_arr_add(tr, decl->idents, ident); ident->decl = decl; decl->flags |= DECL_HAS_EXPR; @@ -1870,7 +1873,7 @@ static Status types_expr(Typer *tr, Expression *e) { } else *val_type = *iter_type; } - arr_remove_lasta(&tr->in_decls, tr->allocr); + arr_remove_lasta(tr->in_decls, tr->allocr); in_header = false; assert(header->type.flags & TYPE_IS_RESOLVED); @@ -1891,7 +1894,7 @@ static Status types_expr(Typer *tr, Expression *e) { }break; for_fail: if (in_header) - arr_remove_lasta(&tr->in_decls, tr->allocr); + arr_remove_lasta(tr->in_decls, tr->allocr); typer_block_exit(tr); return false; } @@ -1900,7 +1903,7 @@ static Status types_expr(Typer *tr, Expression *e) { Identifier i = e->ident; bool undeclared = true; while (1) { /* for each block we are inside... */ - /* OPTIM: only hash once */ + /* @OPTIM: only hash once */ Identifier translated = ident_translate(i, b ? &b->idents : tr->globals); if (ident_is_declared(translated)) { #if 0 @@ -2175,7 +2178,7 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } Type *arg_types = NULL; - arr_set_len(&arg_types, nparams); + arr_set_len(arg_types, nparams); Value *arg_vals = typer_malloc(tr, nparams * sizeof *arg_vals); ErrCtx *err_ctx = tr->err_ctx; size_t p = 0; @@ -2184,10 +2187,10 @@ static Status types_expr(Typer *tr, Expression *e) { bool is_tuple = arr_len(param->idents) > 1; int ident_idx = 0; /* temporarily add this instance to the stack, while we type the decl, in case you, e.g., pass t = float to struct(t::Type, u::t = "hello") */ - *(Location *)arr_add(&err_ctx->instance_stack) = e->where; + arr_add(err_ctx->instance_stack, e->where); typer_block_enter(tr, &struc.body); bool success = types_decl(tr, param); - arr_remove_last(&err_ctx->instance_stack); + arr_remove_last(err_ctx->instance_stack); typer_block_exit(tr); if (!success) return false; @@ -2211,7 +2214,7 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } if (is_tuple) - *(Value *)arr_adda(¶m_val.tuple, tr->allocr) = ident_val; + typer_arr_add(tr, param_val.tuple, ident_val); else param_val = ident_val; arg_vals[p] = ident_val; @@ -2249,12 +2252,12 @@ static Status types_expr(Typer *tr, Expression *e) { Type struct_t = {0}; struct_t.kind = TYPE_STRUCT; struct_t.struc = &inst->struc; - *(Location *)arr_add(&err_ctx->instance_stack) = e->where; + arr_add(err_ctx->instance_stack, e->where); Block *prev_block = tr->block; tr->block = &inst->struc.body; bool success = type_resolve(tr, &struct_t, e->where); /* resolve the struct */ tr->block = prev_block; - arr_remove_last(&err_ctx->instance_stack); + arr_remove_last(err_ctx->instance_stack); if (!success) return false; inst->struc.instance_id = table->n; @@ -2269,7 +2272,7 @@ static Status types_expr(Typer *tr, Expression *e) { e->typeval->struc = &inst->struc; t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_TYPE; - arr_clear(&arg_types); + arr_clear(arg_types); goto ret; } fn_decl = val.fn; @@ -2302,11 +2305,11 @@ static Status types_expr(Typer *tr, Expression *e) { } arg_exprs = NULL; - arr_set_lena(&arg_exprs, narg_exprs, tr->allocr); + arr_set_lena(arg_exprs, narg_exprs, tr->allocr); if (fn_decl && !is_foreign) { size_t i = 0; - Declaration *last_param = arr_last(fn_decl->params); + Declaration *last_param = arr_last_ptr(fn_decl->params); arr_foreach(fn_decl->params, Declaration, param) { if (has_varargs && param == last_param) continue; arr_foreach(param->idents, Identifier, ident) { @@ -2375,7 +2378,7 @@ static Status types_expr(Typer *tr, Expression *e) { long arg_out_idx = arg_out - arg_exprs; /* save and restore arg_out to prevent realloc from causing problems */ /* add more room (or if nvarargs_here == 0, remove room) for more varargs */ - arr_set_lena(&arg_exprs, narg_exprs, tr->allocr); + arr_set_lena(arg_exprs, narg_exprs, tr->allocr); arg_out = arg_exprs + arg_out_idx; for (size_t i = 0; i < nvarargs_here; ++i) { VarArg *vararg = &varargs_here[i]; @@ -2431,8 +2434,8 @@ static Status types_expr(Typer *tr, Expression *e) { if (has_varargs) { /* set value of varargs param decl */ VarArg *varargs = NULL; - arr_set_lena(&varargs, nvarargs, tr->allocr); - Declaration *varargs_param = arr_last(fn_copy->params); + arr_set_lena(varargs, nvarargs, tr->allocr); + Declaration *varargs_param = arr_last_ptr(fn_copy->params); DeclFlags is_const = varargs_param->flags & DECL_IS_CONST; varargs_param->val.varargs = varargs; for (int v = 0; v < (int)nvarargs; ++v) { @@ -2469,16 +2472,13 @@ static Status types_expr(Typer *tr, Expression *e) { arr_foreach(fn->params, Declaration, param) { arr_foreach(param->idents, Identifier, ident) { if (param->flags & DECL_INFER) { - *(Identifier *)arr_add(&inferred_idents) = *ident; + arr_add(inferred_idents, *ident); } else if ((param->flags & DECL_ANNOTATES_TYPE) && !type_is_builtin(¶m->type, BUILTIN_VARARGS)) { /* add to stuff infer can use */ - Type **p = arr_add(&decl_types); - *p = ¶m->type; - Type **q = arr_add(&arg_types); - *q = &arg_exprs[i].type; - Location *l = arr_add(&arg_wheres); - *l = arg_exprs[i].where; + arr_add(decl_types, ¶m->type); + arr_add(arg_types, &arg_exprs[i].type); + arr_add(arg_wheres, arg_exprs[i].where); } ++i; } @@ -2496,9 +2496,9 @@ static Status types_expr(Typer *tr, Expression *e) { } tr->block = prev; - arr_clear(&inferred_idents); - arr_clear(&arg_types); - arr_clear(&decl_types); + arr_clear(inferred_idents); + arr_clear(arg_types); + arr_clear(decl_types); { Type *type = inferred_types; @@ -2628,13 +2628,13 @@ static Status types_expr(Typer *tr, Expression *e) { table_index_type.flags = TYPE_IS_RESOLVED; table_index_type.kind = TYPE_TUPLE; table_index_type.tuple = NULL; - Type *u64t = typer_arr_add(tr, &table_index_type.tuple); + Type *u64t = typer_arr_add_ptr(tr, table_index_type.tuple); u64t->was_expr = NULL; u64t->flags = TYPE_IS_RESOLVED; u64t->kind = TYPE_BUILTIN; u64t->builtin = BUILTIN_U64; table_index.tuple = NULL; - Value *which_are_const_val = typer_arr_add(tr, &table_index.tuple); + Value *which_are_const_val = typer_arr_add_ptr(tr, table_index.tuple); U64 *which_are_const = &which_are_const_val->u64; *which_are_const = 0; int semi_const_index = 0; @@ -2645,8 +2645,8 @@ static Status types_expr(Typer *tr, Expression *e) { Copier cop = copier_create(tr->allocr, tr->block); if (is_vararg) { /* create one additional table index member for varargs */ - Value *varargs_val = typer_arr_add(tr, &table_index.tuple); - Type *varargs_type = typer_arr_add(tr, &table_index_type.tuple); + Value *varargs_val = typer_arr_add_ptr(tr, table_index.tuple); + Type *varargs_type = typer_arr_add_ptr(tr, table_index_type.tuple); memset(varargs_type, 0, sizeof *varargs_type); varargs_type->flags = TYPE_IS_RESOLVED; varargs_type->kind = TYPE_BUILTIN; @@ -2654,7 +2654,7 @@ static Status types_expr(Typer *tr, Expression *e) { varargs_val->varargs = NULL; for (; i < narg_exprs; ++i) { arg = &arg_exprs[i]; - VarArg *varg = typer_arr_add(tr, &varargs_val->varargs); + VarArg *varg = typer_arr_add_ptr(tr, varargs_val->varargs); varg->type = copy_type_(&cop, &arg->type); if (is_const) { copy_val(tr->allocr, &varg->val, arg->val, varg->type); @@ -2673,8 +2673,8 @@ static Status types_expr(Typer *tr, Expression *e) { *which_are_const |= ((U64)1) << semi_const_index; ++semi_const_index; } - Value *v = typer_arr_add(tr, &table_index.tuple); - Type *type = typer_arr_add(tr, &table_index_type.tuple); + Value *v = typer_arr_add_ptr(tr, table_index.tuple); + Type *type = typer_arr_add_ptr(tr, table_index_type.tuple); copy_type(&cop, type, &arg->type); copy_val(tr->allocr, v, arg->val, type); } @@ -2682,8 +2682,8 @@ static Status types_expr(Typer *tr, Expression *e) { bool instance_already_exists; c->instance = instance_table_adda(tr->allocr, original_fn->instances, table_index, &table_index_type, &instance_already_exists); if (instance_already_exists) { - arr_cleara(&table_index_type.tuple, tr->allocr); - arr_cleara(&table_index.tuple, tr->allocr); + arr_cleara(table_index_type.tuple, tr->allocr); + arr_cleara(table_index.tuple, tr->allocr); } else { c->instance->fn = fn_copy; /* fix parameter and return types (they were kind of problematic before, because we didn't know about the instance) */ @@ -2692,12 +2692,12 @@ static Status types_expr(Typer *tr, Expression *e) { /* if anything happens, make sure we let the user know that this happened while generating a fn */ ErrCtx *err_ctx = e->where.file->ctx; - *(Location *)typer_arr_add(tr, &err_ctx->instance_stack) = e->where; + typer_arr_add(tr, err_ctx->instance_stack, e->where); Block *prev_block = tr->block; tr->block = fn_copy->body.parent; bool success = types_fn(tr, c->instance->fn, &f->type, c->instance); tr->block = prev_block; - arr_remove_lasta(&err_ctx->instance_stack, tr->allocr); + arr_remove_lasta(err_ctx->instance_stack, tr->allocr); if (!success) return false; } @@ -3156,10 +3156,9 @@ static Status types_expr(Typer *tr, Expression *e) { t->kind = TYPE_TUPLE; t->tuple = NULL; arr_foreach(e->tuple, Expression, x) { - Type *x_type = typer_arr_add(tr, &t->tuple); if (!types_expr(tr, x)) return false; - *x_type = x->type; + typer_arr_add(tr, t->tuple, x->type); } break; case EXPR_SLICE: { @@ -3258,14 +3257,14 @@ static Status types_block(Typer *tr, Block *b) { goto ret; } } else { - if (s != (Statement *)arr_last(b->stmts)) { + if (s != (Statement *)arr_last_ptr(b->stmts)) { err_print(e->where, "Return value must be the last statement in a block."); success = false; goto ret; } b->ret_expr = typer_malloc(tr, sizeof *b->ret_expr); *b->ret_expr = *e; - arr_remove_lasta(&b->stmts, tr->allocr); + arr_remove_lasta(b->stmts, tr->allocr); } } @@ -3293,8 +3292,7 @@ static Status types_decl(Typer *tr, Declaration *d) { d->type.flags = 0; return true; } - Declaration **dptr = typer_arr_add(tr, &tr->in_decls); - *dptr = d; + typer_arr_add(tr, tr->in_decls, d); if (d->flags & DECL_ANNOTATES_TYPE) { /* type supplied */ assert(d->type.kind != TYPE_VOID); /* there's no way to annotate void */ @@ -3407,7 +3405,11 @@ static Status types_decl(Typer *tr, Declaration *d) { arr_foreach(d->idents, Identifier, ip) { Identifier i = *ip; /* add to uses */ - Use **usep = arr_add(tr->block ? &tr->block->uses : &tr->uses); + Use **usep; + if (tr->block) + usep = typer_arr_add_ptr(tr, tr->block->uses); + else + usep = typer_arr_add_ptr(tr, tr->uses); Use *use = *usep = typer_calloc(tr, 1, sizeof *use); Expression *used = &use->expr; used->kind = EXPR_IDENT; @@ -3421,7 +3423,6 @@ static Status types_decl(Typer *tr, Declaration *d) { if (n_idents == 1 && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_NMS) { bool is_at_top_level = true; - typedef Block *BlockPtr; arr_foreach(tr->blocks, BlockPtr, b) { if (*b && (*b)->kind != BLOCK_NMS) { is_at_top_level = false; @@ -3448,7 +3449,7 @@ static Status types_decl(Typer *tr, Declaration *d) { d->type.was_expr = NULL; d->type.kind = TYPE_UNKNOWN; } - arr_remove_lasta(&tr->in_decls, tr->allocr); + arr_remove_lasta(tr->in_decls, tr->allocr); return success; } @@ -3644,8 +3645,10 @@ 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; } - Use **up = arr_add(tr->block ? &tr->block->uses : &tr->uses); - *up = u; + if (tr->block) + typer_arr_add(tr, tr->block->uses, u); + else + typer_arr_add(tr, tr->uses, u); } break; } s->flags |= STMT_TYPED; @@ -3663,7 +3666,7 @@ static void typer_create(Typer *tr, Evaluator *ev, File *file, ErrCtx *err_ctx, tr->in_decls = NULL; tr->allocr = allocr; tr->globals = idents; - *(Block **)arr_adda(&tr->blocks, allocr) = NULL; + typer_arr_add(tr, tr->blocks, NULL); str_hash_table_create(&tr->included_files, sizeof(IncludedFile), tr->allocr); } @@ -3676,7 +3679,6 @@ static Status types_file(Typer *tr, ParsedFile *f) { ret = false; } } - arr_clear(&tr->uses); assert(tr->block == NULL); assert(arr_len(tr->blocks) && tr->blocks[0] == NULL); return ret; @@ -68,11 +68,13 @@ typedef U8 bool; #endif #if defined __GNUC__ && !defined NO_WARN_UNUSED_RESULT -#define Status bool __attribute__((warn_unused_result)) +#define WarnUnusedResult __attribute__((warn_unused_result)) #else -#define Status bool +#define WarnUnusedResult #endif +#define Status bool WarnUnusedResult + typedef int8_t I8; #define I8_MAX INT8_MAX typedef int16_t I16; @@ -493,6 +495,7 @@ typedef struct Block { struct Statement **deferred; /* deferred stuff from this block; used by both eval and cgen */ struct Use **uses; /* use statements (for types.c) */ } Block; +typedef Block *BlockPtr; enum { STRUCT_DEF_FOUND_OFFSETS = 0x01, @@ -873,7 +876,7 @@ typedef struct Declaration { /* for eval, for non-constant local decls: */ /* the pointers to values need to be fixed, which is why this isn't just Value *. */ - /* OPTIM: some block array of values somewhere which we can just use a pointer to, which is freed when the block is exited? */ + /* @OPTIM: some block array of values somewhere which we can just use a pointer to, which is freed when the block is exited? */ Value **val_stack; } Declaration; typedef Declaration *DeclarationPtr; |