summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-14 23:54:01 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-14 23:54:01 -0500
commit7f6d17ddf505e5c3744f50e59449fc882c088b2e (patch)
tree1d4c8159fec4e04e8b704f227f6387074752ccb6
parent16fb5c17f3cbec6fe6c1542eb49bad4a50c32086 (diff)
trying to get call inference to work
-rw-r--r--infer.c22
-rw-r--r--test.toc15
-rw-r--r--types.c11
3 files changed, 32 insertions, 16 deletions
diff --git a/infer.c b/infer.c
index 46c2df1..24a1706 100644
--- a/infer.c
+++ b/infer.c
@@ -1,6 +1,8 @@
+static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Location fn_where, Type *fn_type, Argument *args, Location where, U16 **param_indices);
static bool types_expr(Typer *tr, Expression *e);
static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identifier *idents, Value *vals, Type *types) {
+ assert(!(match->flags & EXPR_FOUND_TYPE));
assert(to->flags & EXPR_FOUND_TYPE);
switch (match->kind) {
case EXPR_IDENT:
@@ -25,10 +27,26 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
Expression *t_args = to->call.arg_exprs;
size_t nargs = arr_len(m_args);
- if (nargs != arr_len(t_args)) return true;
+ U16 *order = NULL;
+ Expression *f = match->call.fn;
+
+ IdentDecl *idecl = ident_decl(f->ident);
+ bool is_direct_fn = idecl && idecl->kind == IDECL_DECL && (idecl->decl->flags & DECL_HAS_EXPR) && idecl->decl->expr.kind == EXPR_FN;
+ if (is_direct_fn) {
+ FnExpr *fn_decl = idecl->decl->expr.fn;
+ if (!call_arg_param_order(tr->allocr, fn_decl, idecl->decl->where, &f->type, m_args, match->where, &order))
+ return false;
+ }
for (size_t i = 0; i < nargs; ++i) {
Argument *m_arg = &m_args[i];
- Expression *t_arg = &t_args[i];
+ Expression *t_arg;
+ if (is_direct_fn) {
+ t_arg = &t_args[order[i]];
+ } else {
+ t_arg = &t_args[i];
+ }
+ if (!infer_from_expr(tr, &m_arg->val, t_arg, idents, vals, types))
+ return false;
}
} break;
default: break;
diff --git a/test.toc b/test.toc
index b367305..c13c093 100644
--- a/test.toc
+++ b/test.toc
@@ -5,18 +5,13 @@ putf ::= fn(x: float) {
#C("printf(\"%f\\n\", x)");
};
-f ::= fn(t::=, u ::=, x :t, y:u) t {
- x + (y as t)
-};
+t ::= fn(a:: Type) Type {a};
-test ::= fn(t::=int,u::=t,x:u)u {
- x*2
+f ::= fn(b::=, a:t(b)) int{
+3
};
main ::= fn() {
- puti(f(13,15));
- puti(f(14,14.4));
- puti(f(15,13.1));
- putf(f(2.2,3.1));
- puti(test(5));
+ x : t(int) = 3;
+ f(x);
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 2f2c03a..6bdf9fa 100644
--- a/types.c
+++ b/types.c
@@ -708,8 +708,8 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where,
return success;
}
-/* returns a dynamic array of the parameter indices of the arguments. */
-static U16 *call_arg_param_order(Allocator *allocr, FnExpr *fn, Location fn_where, Type *fn_type, Argument *args, Location where) {
+/* puts a dynamic array of the parameter indices of the arguments into param_indices. */
+static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Location fn_where, Type *fn_type, Argument *args, Location where, U16 **param_indices) {
size_t nparams = arr_len(fn_type->fn.types)-1;
size_t nargs = arr_len(args);
if (nargs > nparams) {
@@ -774,7 +774,8 @@ static U16 *call_arg_param_order(Allocator *allocr, FnExpr *fn, Location fn_wher
}
}
}
- return order;
+ *param_indices = order;
+ return true;
}
static bool types_expr(Typer *tr, Expression *e) {
@@ -1115,7 +1116,9 @@ static bool types_expr(Typer *tr, Expression *e) {
}
if (fn_decl) {
- U16 *order = call_arg_param_order(tr->allocr, fn_decl, ident_decl(f->ident)->decl->where, &f->type, c->args, e->where);
+ U16 *order;
+ if (!call_arg_param_order(tr->allocr, fn_decl, ident_decl(f->ident)->decl->where, &f->type, c->args, e->where, &order))
+ return false;
size_t arg;
for (arg = 0; arg < nargs; ++arg) {
U16 idx = order[arg];