diff options
-rw-r--r-- | infer.c | 22 | ||||
-rw-r--r-- | test.toc | 15 | ||||
-rw-r--r-- | types.c | 11 |
3 files changed, 32 insertions, 16 deletions
@@ -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; @@ -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 @@ -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]; |