Typecheck method promotion for interfaces

This commit is contained in:
Bruce Hill 2024-05-12 16:09:24 -04:00
parent 3481042259
commit 3c50c182a8
2 changed files with 22 additions and 1 deletions

View File

@ -56,6 +56,11 @@ static bool promote(env_t *env, CORD *code, type_t *actual, type_t *needed)
return true;
}
if (needed->tag == FunctionType && actual->tag == FunctionType) {
*code = CORD_all("(", compile_type(env, needed), ")", *code);
return true;
}
return false;
}
@ -1710,7 +1715,10 @@ CORD compile(env_t *env, ast_t *ast)
binding_t *b = get_namespace_binding(env, impl, field->name);
if (b) {
// TODO: typecheck implementation!
c = CORD_all(c, ", (void*)", b->code);
CORD field_code = b->code;
if (!promote(env, &field_code, b->type, field->type))
code_err(ast, "I can't promote the method '%s' from %T to %T", field->name, b->type, field->type);
c = CORD_all(c, ", ", field_code);
} else {
type_t *member_t = get_field_type(impl_t, field->name);
if (!member_t)

13
types.c
View File

@ -270,6 +270,19 @@ bool can_promote(type_t *actual, type_t *needed)
if (needed->tag == ClosureType && actual->tag == FunctionType)
return type_eq(actual, Match(needed, ClosureType)->fn);
if (actual->tag == FunctionType && needed->tag == FunctionType) {
for (arg_t *actual_arg = Match(actual, FunctionType)->args, *needed_arg = Match(needed, FunctionType)->args;
actual_arg || needed_arg; actual_arg = actual_arg->next, needed_arg = needed_arg->next) {
if (!actual_arg || !needed_arg) return false;
if (type_eq(actual_arg->type, needed_arg->type)) continue;
if (actual_arg->type->tag == PointerType && needed_arg->type->tag == PointerType
&& can_promote(actual_arg->type, needed_arg->type))
continue;
return false;
}
return true;
}
return false;
}