diff options
Diffstat (limited to 'infer.c')
-rw-r--r-- | infer.c | 27 |
1 files changed, 24 insertions, 3 deletions
@@ -2,6 +2,7 @@ static bool call_arg_param_order(Allocator *allocr, FnExpr *fn, Type *fn_type, A static bool types_expr(Typer *tr, Expression *e); /* resolved_to should have the same value as to, but not consist of any identifiers which aren't in scope right now */ +/* TODO: is resolved_to necessary? */ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expression *resolved_to, Identifier *idents, Value *vals, Type *types) { assert(!(match->flags & EXPR_FOUND_TYPE)); assert(to->flags & EXPR_FOUND_TYPE); @@ -78,7 +79,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Expres /* 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) { assert(to->flags & TYPE_IS_RESOLVED); - + assert(!(match->flags & TYPE_IS_RESOLVED)); switch (match->kind) { case TYPE_VOID: case TYPE_UNKNOWN: @@ -118,14 +119,34 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents break; case TYPE_STRUCT: { if (to->kind != TYPE_STRUCT) return true; - Field *fields_m = match->struc->fields; - Field *fields_t = to->struc->fields; + Field *fields_m = match->struc.def->fields; + Field *fields_t = to->struc.def->fields; 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)) return false; } + size_t nargs = arr_len(match->struc.args); + Declaration *param = to->struc.def->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)) { + return false; + } + ++ident_idx; + if (ident_idx >= (int)arr_len(param->idents)) { + ++param; + ident_idx = 0; + } + } } break; case TYPE_EXPR: { Expression *to_expr = to->was_expr; |