Basic polymorphic named procedure parameters for procedures and records

This commit is contained in:
gingerBill
2020-04-13 15:48:56 +01:00
parent f09b6a4c90
commit f229084baa
9 changed files with 165 additions and 44 deletions

View File

@@ -1117,6 +1117,9 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
e->flags |= EntityFlag_Used;
Type *type = e->type;
o->type = type;
switch (e->kind) {
case Entity_Constant:
if (type == t_invalid) {
@@ -1127,6 +1130,14 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
if (o->value.kind == ExactValue_Invalid) {
return e;
}
if (o->value.kind == ExactValue_Procedure) {
Entity *proc = strip_entity_wrapping(o->value.value_procedure);
if (proc != nullptr) {
o->mode = Addressing_Value;
o->type = proc->type;
return proc;
}
}
o->mode = Addressing_Constant;
break;
@@ -1144,6 +1155,7 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
case Entity_Procedure:
o->mode = Addressing_Value;
o->value = exact_value_procedure(n);
break;
case Entity_Builtin:
@@ -1180,7 +1192,6 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
break;
}
o->type = type;
return e;
}
@@ -3602,10 +3613,20 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
add_entity_use(c, selector, entity);
operand->type = entity->type;
operand->expr = node;
switch (entity->kind) {
case Entity_Constant:
operand->mode = Addressing_Constant;
operand->value = entity->Constant.value;
operand->mode = Addressing_Constant;
if (operand->value.kind == ExactValue_Procedure) {
Entity *proc = strip_entity_wrapping(operand->value.value_procedure);
if (proc != nullptr) {
operand->mode = Addressing_Value;
operand->type = proc->type;
}
}
break;
case Entity_Variable:
// TODO(bill): Is this the rule I need?
@@ -3628,6 +3649,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
break;
case Entity_Procedure:
operand->mode = Addressing_Value;
operand->value = exact_value_procedure(node);
break;
case Entity_Builtin:
operand->mode = Addressing_Builtin;
@@ -3645,8 +3667,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
break;
}
operand->type = entity->type;
operand->expr = node;
add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value);
return entity;
}
@@ -7044,10 +7065,17 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
}
o->type = e->type;
if (o->mode != Addressing_Constant) {
if (show_error) {
error(o->expr, "Expected a constant value for this polymorphic type argument");
bool valid = false;
if (is_type_proc(o->type)) {
Entity *proc_entity = entity_from_expr(o->expr);
valid = proc_entity != nullptr;
}
if (!valid) {
if (show_error) {
error(o->expr, "Expected a constant value for this polymorphic type argument");
}
err = CallArgumentError_NoneConstantParameter;
}
err = CallArgumentError_NoneConstantParameter;
}
score += s;
}
@@ -9257,29 +9285,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = check_expr_base_internal(c, o, node, type_hint);
Type *type = nullptr;
ExactValue value = {ExactValue_Invalid};
switch (o->mode) {
case Addressing_Invalid:
type = t_invalid;
break;
case Addressing_NoValue:
type = nullptr;
break;
case Addressing_Constant:
value = o->value;
type = o->type;
break;
default:
type = o->type;
break;
if (o->type != nullptr && is_type_untyped(o->type)) {
add_untyped(&c->checker->info, node, false, o->mode, o->type, o->value);
}
if (type != nullptr && is_type_untyped(type)) {
add_untyped(&c->checker->info, node, false, o->mode, type, value);
}
add_type_and_value(&c->checker->info, node, o->mode, type, value);
add_type_and_value(&c->checker->info, node, o->mode, o->type, o->value);
return kind;
}