summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-04 12:07:27 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-04 12:07:27 -0500
commit39e5e4fbb83188eafde2c7c5822b33ff451fadd8 (patch)
tree08f8946c7ffbc0f9e2458f9c364a7a8f25451c6e
parent9dc97819d38b1a63935a4909b246c88f960e0899 (diff)
slightly improved infer error message; still needs work
-rw-r--r--infer.c41
-rw-r--r--main.c1
-rw-r--r--std/arr.toc2
-rw-r--r--test.toc12
-rw-r--r--types.c31
-rw-r--r--types.h2
6 files changed, 51 insertions, 38 deletions
diff --git a/infer.c b/infer.c
index 49fa364..a6cf34b 100644
--- a/infer.c
+++ b/infer.c
@@ -31,7 +31,6 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
}
break;
case EXPR_CALL: {
-
if (to->kind == EXPR_TYPE && to->typeval->kind == TYPE_STRUCT) {
/* maybe it's a parameterized struct? */
/* it might not be possible that it's not, but might as well keep that possibility around. */
@@ -98,8 +97,9 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
if (to->kind == EXPR_TYPE) {
to = to->typeval->was_expr;
}
- if (!to || to->kind != EXPR_CALL)
- return true; /* give up */
+ if (!to || to->kind != EXPR_CALL) {
+ return true;
+ }
}
Argument *m_args = match->call.args;
@@ -152,21 +152,30 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
return true;
}
-/* if match is not the same kind of type as to, returns true */
-static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents, Value *vals, Type *types) {
+/* wheres points to a Location, with more locations wheres_stride bytes apart */
+static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents, Value *vals, Type *types, Location where) {
assert(to->flags & TYPE_IS_RESOLVED);
assert(!(match->flags & TYPE_IS_RESOLVED));
+ if (match->kind != TYPE_UNKNOWN && match->kind != TYPE_EXPR && to->kind != TYPE_UNKNOWN) {
+ if (match->kind != to->kind) {
+ if (to->kind != TYPE_TUPLE) {
+ char *m = type_to_str(match), *t = type_to_str(to);
+ err_print(where, "Wrong argument type. Expected %s, but got %s.", m, t);
+ free(m); free(t);
+ return false;
+ }
+ }
+ }
switch (match->kind) {
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_BUILTIN:
break; /* nothing we can do here */
case TYPE_TUPLE: {
- if (to->kind != TYPE_TUPLE) return true;
if (arr_len(match->tuple) != arr_len(to->tuple)) return true;
Type *b = to->tuple;
arr_foreach(match->tuple, Type, a) {
- if (!infer_from_type(tr, a, b, idents, vals, types))
+ if (!infer_from_type(tr, a, b, idents, vals, types, where))
return false;
++b;
}
@@ -179,18 +188,18 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
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))
+ if (!infer_from_type(tr, &match->fn.types[i], &to->fn.types[i], idents, vals, types, where))
return false;
}
} break;
case TYPE_PTR:
if (to->kind != TYPE_PTR) return true;
- if (!infer_from_type(tr, match->ptr, to->ptr, idents, vals, types))
+ if (!infer_from_type(tr, match->ptr, to->ptr, idents, vals, types, where))
return false;
break;
case TYPE_SLICE:
if (to->kind != TYPE_SLICE) return true;
- if (!infer_from_type(tr, match->slice, to->slice, idents, vals, types))
+ if (!infer_from_type(tr, match->slice, to->slice, idents, vals, types, where))
return false;
break;
case TYPE_STRUCT: {
@@ -200,7 +209,7 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
size_t i, len = arr_len(fields_m);
if (len != arr_len(fields_t)) return true;
for (i = 0; i < len; ++i) {
- if (!infer_from_type(tr, &fields_m[i].type, &fields_t[i].type, idents, vals, types))
+ if (!infer_from_type(tr, &fields_m[i].type, &fields_t[i].type, idents, vals, types, where))
return false;
}
} break;
@@ -211,6 +220,7 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
e.typeval = allocr_malloc(tr->allocr, sizeof *e.typeval);
*e.typeval = *to;
e.flags = EXPR_FOUND_TYPE;
+ e.where = where;
Type *type = &e.type;
type->flags = TYPE_IS_RESOLVED;
type->kind = TYPE_BUILTIN;
@@ -233,7 +243,7 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
n_type->flags = TYPE_IS_RESOLVED;
if (!infer_from_expr(tr, match->arr.n_expr, &to_n_expr, idents, vals, types))
return false;
- if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types))
+ if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types, where))
return false;
} break;
}
@@ -246,7 +256,7 @@ idents is a dyn array of distinct identifiers
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 unresolved, and all the types in to must be resolved
*/
-static bool infer_ident_vals(Typer *tr, Type **match, Type **to, Identifier *idents, Value *vals, Type *types) {
+static bool infer_ident_vals(Typer *tr, Type **match, Type **to, Identifier *idents, Value *vals, Type *types, Location *wheres) {
size_t ntypes = arr_len(match);
size_t i;
size_t nidents = arr_len(idents);
@@ -254,12 +264,15 @@ static bool infer_ident_vals(Typer *tr, Type **match, Type **to, Identifier *ide
Type *t = types;
for (i = 0; i < nidents; ++i) {
+ memset(t, 0, sizeof *t);
+ t->flags |= TYPE_IS_RESOLVED;
t->kind = TYPE_UNKNOWN;
++t;
}
for (i = 0; i < ntypes; ++i) {
- if (!infer_from_type(tr, *match, *to, idents, vals, types))
+ Location where = wheres[i];
+ if (!infer_from_type(tr, *match, *to, idents, vals, types, where))
return false;
++match, ++to;
}
diff --git a/main.c b/main.c
index f53cce2..6cbc1ce 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
/*
TODO:
+make sure a,b::=, works
variadic fns
#foreign variadic fns
#returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf)
diff --git a/std/arr.toc b/std/arr.toc
index 779de48..c973777 100644
--- a/std/arr.toc
+++ b/std/arr.toc
@@ -20,7 +20,7 @@ resv ::= fn(t ::=, a : &Arr(t), n: int) {
add ::= fn(t ::=, a : &Arr(t), x : t) {
if a.data.len >= a.cap {
- resv(&a, a.cap * 2 + 2);
+ resv(a, a.cap * 2 + 2);
}
a.data.len += 1;
a.data[a.data.len-1] = x;
diff --git a/test.toc b/test.toc
index 1b02eed..eb51a96 100644
--- a/test.toc
+++ b/test.toc
@@ -1,8 +1,7 @@
-/*
#include "std/io.toc", io;
#include "std/arr.toc", arr;
-arr_sum ::= fn(n::=, t::=, a:arr.Arr(t)) t {
+arr_sum ::= fn(t::=, a:arr.Arr(t)) t {
total := 0 as t;
for x := a.data {
total += x;
@@ -21,12 +20,3 @@ main ::= fn() {
io.puti(arr.len(a));
io.puti(arr_sum(a));
};
-*/
-
-a ::= nms {
- x: int;
-};
-
-main ::= fn() {
- a.x;
-};
diff --git a/types.c b/types.c
index bd9cc18..1089d55 100644
--- a/types.c
+++ b/types.c
@@ -1912,6 +1912,7 @@ static Status types_expr(Typer *tr, Expression *e) {
if (param->flags & DECL_HAS_EXPR) {
assert(param->expr.kind == EXPR_VAL); /* evaluated in type_of_fn */
arg_exprs[i].kind = EXPR_VAL;
+ arg_exprs[i].where = param->where;
arg_exprs[i].flags = param->expr.flags;
arg_exprs[i].type = param->type;
arg_exprs[i].val = param->expr.val;
@@ -1966,21 +1967,23 @@ static Status types_expr(Typer *tr, Expression *e) {
Type **arg_types = NULL;
Type **decl_types = NULL;
Identifier *inferred_idents = NULL;
+ Location *arg_wheres = NULL;
arr_foreach(fn->params, Declaration, param) {
arr_foreach(param->idents, Identifier, ident) {
if (param->flags & DECL_INFER) {
- *(Identifier *)typer_arr_add(tr, &inferred_idents) = *ident;
+ *(Identifier *)arr_add(&inferred_idents) = *ident;
} else if ((param->flags & DECL_ANNOTATES_TYPE)
&& !(param->flags & DECL_HAS_EXPR)) {
-
if (param->type.kind == TYPE_TUPLE)
err_print(param->where, "Parameters cannot have tuple types.");
- Type **p = typer_arr_add(tr, &decl_types);
+ Type **p = arr_add(&decl_types);
*p = &param->type;
- Type **q = typer_arr_add(tr, &arg_types);
+ Type **q = arr_add(&arg_types);
*q = &arg_exprs[i].type;
+ Location *l = arr_add(&arg_wheres);
+ *l = arg_exprs[i].where;
}
++i;
}
@@ -1990,11 +1993,17 @@ static Status types_expr(Typer *tr, Expression *e) {
if (ninferred_idents) {
Value *inferred_vals = err_malloc(ninferred_idents * sizeof *inferred_vals);
Type *inferred_types = err_malloc(ninferred_idents * sizeof *inferred_types);
-
- if (!infer_ident_vals(tr, decl_types, arg_types, inferred_idents, inferred_vals, inferred_types))
+ Block *prev = tr->block;
+ tr->block = &fn->body;
+ if (!infer_ident_vals(tr, decl_types, arg_types, inferred_idents, inferred_vals, inferred_types, arg_wheres)) {
+ tr->block = prev;
return false;
-
- arr_cleara(&inferred_idents, tr->allocr);
+ }
+ tr->block = prev;
+
+ arr_clear(&inferred_idents);
+ arr_clear(&arg_types);
+ arr_clear(&decl_types);
{
Type *type = inferred_types;
@@ -2009,7 +2018,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
err_print(decl->where, "Could not infer value of declaration.");
info_print(e->where, "While processing this call");
- return false;
+ return false;
}
++type;
}
@@ -2149,7 +2158,6 @@ static Status types_expr(Typer *tr, Expression *e) {
*got = *expected;
}
}
-
if (fn_type->constness) {
bool instance_already_exists;
c->instance = instance_table_adda(tr->allocr, &original_fn->instances, table_index, &table_index_type, &instance_already_exists);
@@ -2847,7 +2855,8 @@ static Status types_decl(Typer *tr, Declaration *d) {
goto ret;
}
} else if (d->type.kind == TYPE_UNKNOWN) {
- err_print(d->where, "Can't determine type of declaration.");
+ if (!d->where.file->ctx->have_errored) /* don't do an error if we haven't already done one, because it might be because of that */
+ err_print(d->where, "Can't determine type of declaration.");
success = false;
goto ret;
}
diff --git a/types.h b/types.h
index 74b7afc..85c7d73 100644
--- a/types.h
+++ b/types.h
@@ -397,8 +397,8 @@ typedef struct Tokenizer {
typedef enum {
- TYPE_VOID,
TYPE_UNKNOWN,
+ TYPE_VOID,
TYPE_BUILTIN,
TYPE_FN,
TYPE_TUPLE,