Refactor record polymorphic params code for unification

This commit is contained in:
gingerBill
2021-03-27 17:21:12 +00:00
parent 87bc9275fe
commit 342761e83a
2 changed files with 58 additions and 60 deletions

View File

@@ -5915,7 +5915,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
i32 i = id - cast(i32)BuiltinProc__type_simple_boolean_begin;
auto procedure = builtin_type_is_procs[i];
GB_ASSERT_MSG(procedure != nullptr, "%.*s", LIT(builtin_name));
operand->value = exact_value_bool(procedure(operand->type));
bool ok = procedure(operand->type);
operand->value = exact_value_bool(ok);
}
operand->mode = Addressing_Constant;
operand->type = t_untyped_bool;

View File

@@ -338,12 +338,17 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t
}
Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_params,
bool *is_polymorphic_, bool *can_check_fields_,
bool *is_polymorphic_,
Ast *node, Array<Operand> *poly_operands,
Type *named_type, Type *original_type_for_poly) {
Type *polymorphic_params_type = nullptr;
bool can_check_fields = true;
GB_ASSERT(is_polymorphic_ != nullptr);
if (polymorphic_params == nullptr) {
if (!*is_polymorphic_) {
*is_polymorphic_ = polymorphic_params != nullptr && poly_operands == nullptr;
}
return polymorphic_params_type;
}
@@ -463,7 +468,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para
if (is_type_param) {
if (is_type_polymorphic(base_type(operand.type))) {
*is_polymorphic_ = true;
*can_check_fields_ = false;
can_check_fields = false;
}
e = alloc_entity_type_name(scope, token, operand.type);
e->TypeName.is_type_alias = true;
@@ -471,7 +476,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para
} else {
if (is_type_polymorphic(base_type(operand.type))) {
*is_polymorphic_ = true;
*can_check_fields_ = false;
can_check_fields = false;
}
if (e == nullptr) {
e = alloc_entity_constant(scope, token, operand.type, operand.value);
@@ -507,9 +512,42 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para
add_polymorphic_record_entity(ctx, node, named_type, original_type_for_poly);
}
if (!*is_polymorphic_) {
*is_polymorphic_ = polymorphic_params != nullptr && poly_operands == nullptr;
}
return polymorphic_params_type;
}
bool check_record_poly_operand_specialization(CheckerContext *ctx, Type *record_type, Array<Operand> *poly_operands, bool *is_polymorphic_) {
if (poly_operands == nullptr) {
return false;
}
for (isize i = 0; i < poly_operands->count; i++) {
Operand o = (*poly_operands)[i];
if (is_type_polymorphic(o.type)) {
return false;
}
if (record_type == o.type) {
// NOTE(bill): Cycle
return false;
}
if (o.mode == Addressing_Type) {
// NOTE(bill): ANNOYING EDGE CASE FOR `where` clauses
// TODO(bill, 2021-03-27): Is this even a valid HACK?!
Entity *entity = entity_of_node(o.expr);
if (entity != nullptr &&
entity->kind == Entity_TypeName &&
entity->type == t_typeid) {
*is_polymorphic_ = true;
return false;
}
}
}
return true;
}
void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<Operand> *poly_operands, Type *named_type, Type *original_type_for_poly) {
GB_ASSERT(is_type_struct(struct_type));
ast_node(st, StructType, node);
@@ -541,39 +579,18 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<
bool &is_polymorphic = struct_type->Struct.is_polymorphic;
Type *polymorphic_params = nullptr;
bool can_check_fields = true;
bool is_poly_specialized = false;
polymorphic_params = check_record_polymorphic_params(
ctx, st->polymorphic_params,
&is_polymorphic, &can_check_fields,
&is_polymorphic,
node, poly_operands,
named_type, original_type_for_poly
);
if (!is_polymorphic) {
is_polymorphic = polymorphic_params != nullptr && poly_operands == nullptr;
}
if (poly_operands != nullptr) {
is_poly_specialized = true;
for (isize i = 0; i < poly_operands->count; i++) {
Operand o = (*poly_operands)[i];
if (is_type_polymorphic(o.type)) {
is_poly_specialized = false;
break;
}
if (struct_type == o.type) {
// NOTE(bill): Cycle
is_poly_specialized = false;
break;
}
}
}
struct_type->Struct.scope = ctx->scope;
struct_type->Struct.is_packed = st->is_packed;
struct_type->Struct.polymorphic_params = polymorphic_params;
struct_type->Struct.is_poly_specialized = is_poly_specialized;
struct_type->Struct.scope = ctx->scope;
struct_type->Struct.is_packed = st->is_packed;
struct_type->Struct.polymorphic_params = polymorphic_params;
struct_type->Struct.is_poly_specialized = check_record_poly_operand_specialization(ctx, struct_type, poly_operands, &is_polymorphic);
if (!is_polymorphic) {
if (st->where_clauses.count > 0 && st->polymorphic_params == nullptr) {
@@ -611,46 +628,26 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
bool &is_polymorphic = union_type->Union.is_polymorphic;
Type *polymorphic_params = nullptr;
bool can_check_fields = true;
bool is_poly_specialized = false;
polymorphic_params = check_record_polymorphic_params(
ctx, ut->polymorphic_params,
&is_polymorphic, &can_check_fields,
&is_polymorphic,
node, poly_operands,
named_type, original_type_for_poly
);
union_type->Union.scope = ctx->scope;
union_type->Union.polymorphic_params = polymorphic_params;
union_type->Union.is_polymorphic = is_polymorphic;
union_type->Union.is_poly_specialized = check_record_poly_operand_specialization(ctx, union_type, poly_operands, &is_polymorphic);
if (!is_polymorphic) {
is_polymorphic = polymorphic_params != nullptr && poly_operands == nullptr;
}
if (poly_operands != nullptr) {
is_poly_specialized = true;
for (isize i = 0; i < poly_operands->count; i++) {
Operand o = (*poly_operands)[i];
if (is_type_polymorphic(o.type)) {
is_poly_specialized = false;
break;
}
if (union_type == o.type) {
// NOTE(bill): Cycle
is_poly_specialized = false;
break;
}
if (ut->where_clauses.count > 0 && ut->polymorphic_params == nullptr) {
error(ut->where_clauses[0], "'where' clauses can only be used on unions with polymorphic parameters");
} else {
bool where_clause_ok = evaluate_where_clauses(ctx, node, ctx->scope, &ut->where_clauses, true);
}
}
union_type->Union.scope = ctx->scope;
union_type->Union.polymorphic_params = polymorphic_params;
union_type->Union.is_polymorphic = is_polymorphic;
union_type->Union.is_poly_specialized = is_poly_specialized;
if (ut->where_clauses.count > 0 && ut->polymorphic_params == nullptr) {
error(ut->where_clauses[0], "'where' clauses can only be used on unions with polymorphic parameters");
} else {
bool where_clause_ok = evaluate_where_clauses(ctx, node, ctx->scope, &ut->where_clauses, true);
}
for_array(i, ut->variants) {
Ast *node = ut->variants[i];