diff options
Diffstat (limited to 'infer.c')
-rw-r--r-- | infer.c | 50 |
1 files changed, 33 insertions, 17 deletions
@@ -25,27 +25,43 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expres break; case EXPR_CALL: { #if 0 - /* TODO: infer from parameterized structs */ - size_t nargs = arr_len(match->struc.args); - Declaration *param = to->struc->params; - int ident_idx = 0; - for (i = 0; i < nargs; ++i) { - Expression *arg = &match->struc.args[i]; - Value val = *decl_val_at_index(param, ident_idx); - Expression val_expr = {0}; - val_expr.kind = EXPR_VAL; - val_expr.val = val; - val_expr.type = *decl_type_at_index(param, ident_idx); - val_expr.flags = EXPR_FOUND_TYPE; - if (!infer_from_expr(tr, arg, &val_expr, &val_expr, idents, vals, types)) { + if (to->kind == EXPR_TYPE) { + /* maybe it's a parameterized struct? */ + /* it might not be possible that it's not, but might as well keep that possibility around. */ + Value fn_val = {0}; + if (!types_expr(tr, match->call.fn)) { return false; } - ++ident_idx; - if (ident_idx >= (int)arr_len(param->idents)) { - ++param; - ident_idx = 0; + if (type_is_builtin(&match->call.fn->type, BUILTIN_TYPE)) { + /* it's a parameterized struct */ + if (!eval_expr(tr->evalr, match->call.fn, &fn_val)) { + return false; + } + assert(fn_val.type->kind == TYPE_STRUCT); + + size_t nargs = arr_len(match->call.args); + Declaration *param = fn_val.type->struc->params; + int ident_idx = 0; + for (size_t i = 0; i < nargs; ++i) { + Expression *arg = &match->call.args[i]; + Value val = *decl_val_at_index(param, ident_idx); + Expression val_expr = {0}; + val_expr.kind = EXPR_VAL; + val_expr.val = val; + val_expr.type = *decl_type_at_index(param, ident_idx); + val_expr.flags = EXPR_FOUND_TYPE; + if (!infer_from_expr(tr, arg, &val_expr, &val_expr, idents, vals, types)) { + return false; + } + ++ident_idx; + if (ident_idx >= (int)arr_len(param->idents)) { + ++param; + ident_idx = 0; + } + } } } + #endif while (to->kind == EXPR_IDENT) { |