summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-12 21:53:38 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-12 21:53:38 -0500
commitbe3c25b68ced6834267a21f04fab57c78f4fe9d1 (patch)
tree4f380624fbe40499805b1b45a469848ff4fe191f
parent7420a5126f78947e9c5a11e606d59f2ed6391079 (diff)
more infer setup and better arr_foreach
-rw-r--r--allocator.c1
-rw-r--r--arr.c22
-rw-r--r--infer.c35
-rw-r--r--parse.c2
-rwxr-xr-xtests/test.sh2
-rw-r--r--types.c31
-rw-r--r--types.h5
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 */