From be3c25b68ced6834267a21f04fab57c78f4fe9d1 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 12 Dec 2019 21:53:38 -0500 Subject: more infer setup and better arr_foreach --- allocator.c | 1 - arr.c | 22 +++++++++++++++++----- infer.c | 35 ++++++++++++++++++++++++++++++++++- parse.c | 2 ++ tests/test.sh | 2 +- types.c | 31 +++++++++++++++++++++++++------ types.h | 5 ++++- 7 files changed, 83 insertions(+), 15 deletions(-) diff --git a/allocator.c b/allocator.c index 4cde1a9..c961185 100644 --- a/allocator.c +++ b/allocator.c @@ -17,7 +17,6 @@ static void allocr_create(Allocator *a) { } static void *allocr_malloc(Allocator *a, size_t bytes) { - assert(bytes); #if NO_ALLOCATOR (void)a; return err_malloc(bytes); diff --git a/arr.c b/arr.c index 1be5a26..16737d4 100644 --- a/arr.c +++ b/arr.c @@ -120,11 +120,22 @@ static void *arr_last_(void *arr, size_t item_sz) { } } +static void *arr_end_(void *arr, size_t item_sz) { + if (arr) { + ArrHeader *hdr = arr_hdr(arr); + return hdr->len == 0 ? NULL : (char *)hdr->data + hdr->len * item_sz; + } else { + return NULL; + } +} + /* OPTIM: shrink array */ static void arr_remove_last_(void **arr, size_t item_sz) { - assert(arr_hdr(*arr)->len); - --arr_hdr(*arr)->len; (void)item_sz; + if (--arr_hdr(*arr)->len == 0) + *arr = NULL; + (void)item_sz; + } static void arr_copya_(void **out, void *in, size_t item_sz, Allocator *a) { @@ -165,15 +176,16 @@ You shouldn't rely on this, though, e.g. by doing #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)) -/* OPTIM: maybe replace with less standard-compliant version */ -#define arr_foreach(arr, type, var) for (type *var = arr_len(arr) ? arr : NULL, *var##_foreach_end = arr_last(arr); var; var == var##_foreach_end ? var = NULL : ++var) +/* one past last, or NULL if empty */ +#define arr_end(arr) arr_end_((void *)(arr), sizeof *(arr)) +#define arr_foreach(arr, type, var) for (type *var = arr, *join(var,_foreach_end) = arr_end(arr); var < join(var,_foreach_end); ++var) /* NOTE: < is useful here because currently it's possible for var_foreach_end to be NULL but var could start out not null */ #define arr_remove_last(arr) arr_remove_last_((void **)(arr), sizeof **(arr)) #define arr_copya(out, in, a) do { assert(sizeof *(in) == sizeof **(out)); arr_copya_((void **)(out), (in), sizeof **(out), (a)); } while(0) #ifdef TOC_DEBUG static void arr_test(void) { int *foos = NULL; - for (int i = 0; i < 1000; ++i) { + for (int i = 0; i < 10; ++i) { *(int *)arr_add(&foos) = i; } for (int i = 0; i < (int)arr_len(foos); ++i) { diff --git a/infer.c b/infer.c index 6c2164a..33a7562 100644 --- a/infer.c +++ b/infer.c @@ -1,10 +1,42 @@ +static bool infer_from_type(Type *match, Type *to, Identifier *idents, Value *vals, Type *types) { + /* match resolved, to unresolved */ + switch (to->kind) { + case TYPE_VOID: + case TYPE_UNKNOWN: + case TYPE_BUILTIN: + case TYPE_TYPE: + break; /* nothing we can do here */ + } + return true; +} + /* match and to are dynamic arrays of equal size idents is a dyn array find the value of each ident by matching match[i] to to[i], i = 0..arr_len(match)-1 all the types in match must be resolved, and all the types in to must be unresolved */ -static bool infer(Type **match, Type **to, Identifier *idents, Value *vals, Type *types) { +static bool infer_ident_vals(Type **match, Type **to, Identifier *idents, Value *vals, Type *types) { + size_t ntypes = arr_len(match); + size_t i; + size_t nidents = arr_len(idents); + + Type *t = types; + + for (i = 0; i < nidents; ++i) { + t->kind = TYPE_UNKNOWN; + ++t; + } + + for (i = 0; i < ntypes; ++i) { + if (!infer_from_type(*match, *to, idents, vals, types)) + return false; + ++match, ++to; + } + + + +#if 0 /* TODO DELME */ Value *val = vals; Type *type = types; val->type = calloc(1,sizeof(Type)); @@ -14,6 +46,7 @@ static bool infer(Type **match, Type **to, Identifier *idents, Value *vals, Type type->flags = TYPE_IS_RESOLVED; type->kind = TYPE_TYPE; type->was_expr = NULL; +#endif return true; } diff --git a/parse.c b/parse.c index 78a5b1c..f64ffed 100644 --- a/parse.c +++ b/parse.c @@ -2016,6 +2016,8 @@ static void fprint_arg_exprs(FILE *out, Expression *args) { fprintf(out, "("); arr_foreach(args, Expression, arg) { if (arg != args) fprintf(out, ", "); + Expression *last = arr_last(args); + assert(arg<=last); fprint_expr(out, arg); } fprintf(out, ")"); diff --git a/tests/test.sh b/tests/test.sh index 4fe800e..988bce6 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -13,7 +13,7 @@ compile() { } do_tests() { - valgrind -q $TOC "$DIR/$1/$1.toc" -o "$DIR/$1/$1.c" > /dev/null || exit 1 + valgrind -q --exit-on-first-error=yes --error-exitcode=1 $TOC "$DIR/$1/$1.toc" -o "$DIR/$1/$1.c" > /dev/null || exit 1 for CC in $COMPILERS; do for EXTRA_CFLAGS in "-O0 -g" "-O3 -s"; do diff --git a/types.c b/types.c index a9d5104..b33cadc 100644 --- a/types.c +++ b/types.c @@ -1257,12 +1257,12 @@ static bool types_expr(Typer *tr, Expression *e) { i = 0; Type **arg_types = NULL; Type **decl_types = NULL; - Identifier *infer_idents = NULL; + Identifier *inferred_idents = NULL; arr_foreach(fn->params, Declaration, param) { arr_foreach(param->idents, Identifier, ident) { if (param->flags & DECL_INFER) { - *(Identifier *)arr_add(&infer_idents) = *ident; + *(Identifier *)arr_add(&inferred_idents) = *ident; } else if ((param->flags & DECL_ANNOTATES_TYPE) && !(param->flags & DECL_HAS_EXPR)) { @@ -1278,11 +1278,30 @@ static bool types_expr(Typer *tr, Expression *e) { } } - Value *inferred_vals = typer_malloc(tr, arr_len(infer_idents) * sizeof *inferred_vals); - Type *inferred_types = typer_malloc(tr, arr_len(infer_idents) * sizeof *inferred_types); - if (!infer(arg_types, decl_types, infer_idents, inferred_vals, inferred_types)) + size_t ninferred_idents = arr_len(inferred_idents); + Value *inferred_vals = typer_malloc(tr, ninferred_idents * sizeof *inferred_vals); + Type *inferred_types = typer_malloc(tr, ninferred_idents * sizeof *inferred_types); + if (!infer_ident_vals(arg_types, decl_types, inferred_idents, inferred_vals, inferred_types)) return false; - + { + Type *type = inferred_types; + for (i = 0; i < ninferred_idents; ++i) { + if (type->kind == TYPE_UNKNOWN) { + long counter = (long)i; + Declaration *decl = fn->params; + while (1) { + counter -= (long)arr_len(decl->idents); + if (counter < 0) break; + ++decl; + } + err_print(decl->where, "Could not infer value of declaration."); + info_print(e->where, "While processing this call"); + return false; + } + ++type; + } + } + i = 0; arr_foreach(fn->params, Declaration, param) { arr_foreach(param->idents, Identifier, ident) { diff --git a/types.h b/types.h index 4918ba1..54ffbda 100644 --- a/types.h +++ b/types.h @@ -55,17 +55,20 @@ typedef U32 IdentID; /* identifier ID for cgen (anonymous variables) */ typedef U32 LineNo; typedef U32 CodePos; +#define join(a,b) a##b + /* for keeping track of whence something came */ #ifdef TOC_DEBUG #define SOURCE_LOCATION char *src_file; int src_line; #define SOURCE_LOCATION_PARAMS char *src_file, int src_line, -#define DEBUG_UNDERSCORE(x) x##_ +#define DEBUG_UNDERSCORE(x) join(x,_) #else #define SOURCE_LOCATION #define SOURCE_LOCATION_PARAMS #define DEBUG_UNDERSCORE(x) x #endif + typedef struct Location { LineNo line; CodePos pos; /* position in ctx->str */ -- cgit v1.2.3