summaryrefslogtreecommitdiff
path: root/infer.c
diff options
context:
space:
mode:
Diffstat (limited to 'infer.c')
-rw-r--r--infer.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/infer.c b/infer.c
index 2a47865..b0b5433 100644
--- a/infer.c
+++ b/infer.c
@@ -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;