mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-30 11:20:08 +00:00
Refactor record polymorphic params code for unification
This commit is contained in:
+2
-1
@@ -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;
|
i32 i = id - cast(i32)BuiltinProc__type_simple_boolean_begin;
|
||||||
auto procedure = builtin_type_is_procs[i];
|
auto procedure = builtin_type_is_procs[i];
|
||||||
GB_ASSERT_MSG(procedure != nullptr, "%.*s", LIT(builtin_name));
|
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->mode = Addressing_Constant;
|
||||||
operand->type = t_untyped_bool;
|
operand->type = t_untyped_bool;
|
||||||
|
|||||||
+56
-59
@@ -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,
|
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,
|
Ast *node, Array<Operand> *poly_operands,
|
||||||
Type *named_type, Type *original_type_for_poly) {
|
Type *named_type, Type *original_type_for_poly) {
|
||||||
Type *polymorphic_params_type = nullptr;
|
Type *polymorphic_params_type = nullptr;
|
||||||
|
bool can_check_fields = true;
|
||||||
|
GB_ASSERT(is_polymorphic_ != nullptr);
|
||||||
|
|
||||||
if (polymorphic_params == nullptr) {
|
if (polymorphic_params == nullptr) {
|
||||||
|
if (!*is_polymorphic_) {
|
||||||
|
*is_polymorphic_ = polymorphic_params != nullptr && poly_operands == nullptr;
|
||||||
|
}
|
||||||
return polymorphic_params_type;
|
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_param) {
|
||||||
if (is_type_polymorphic(base_type(operand.type))) {
|
if (is_type_polymorphic(base_type(operand.type))) {
|
||||||
*is_polymorphic_ = true;
|
*is_polymorphic_ = true;
|
||||||
*can_check_fields_ = false;
|
can_check_fields = false;
|
||||||
}
|
}
|
||||||
e = alloc_entity_type_name(scope, token, operand.type);
|
e = alloc_entity_type_name(scope, token, operand.type);
|
||||||
e->TypeName.is_type_alias = true;
|
e->TypeName.is_type_alias = true;
|
||||||
@@ -471,7 +476,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para
|
|||||||
} else {
|
} else {
|
||||||
if (is_type_polymorphic(base_type(operand.type))) {
|
if (is_type_polymorphic(base_type(operand.type))) {
|
||||||
*is_polymorphic_ = true;
|
*is_polymorphic_ = true;
|
||||||
*can_check_fields_ = false;
|
can_check_fields = false;
|
||||||
}
|
}
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
e = alloc_entity_constant(scope, token, operand.type, operand.value);
|
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);
|
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;
|
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) {
|
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));
|
GB_ASSERT(is_type_struct(struct_type));
|
||||||
ast_node(st, StructType, node);
|
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;
|
bool &is_polymorphic = struct_type->Struct.is_polymorphic;
|
||||||
|
|
||||||
Type *polymorphic_params = nullptr;
|
Type *polymorphic_params = nullptr;
|
||||||
bool can_check_fields = true;
|
|
||||||
bool is_poly_specialized = false;
|
|
||||||
|
|
||||||
polymorphic_params = check_record_polymorphic_params(
|
polymorphic_params = check_record_polymorphic_params(
|
||||||
ctx, st->polymorphic_params,
|
ctx, st->polymorphic_params,
|
||||||
&is_polymorphic, &can_check_fields,
|
&is_polymorphic,
|
||||||
node, poly_operands,
|
node, poly_operands,
|
||||||
named_type, original_type_for_poly
|
named_type, original_type_for_poly
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!is_polymorphic) {
|
struct_type->Struct.scope = ctx->scope;
|
||||||
is_polymorphic = polymorphic_params != nullptr && poly_operands == nullptr;
|
struct_type->Struct.is_packed = st->is_packed;
|
||||||
}
|
struct_type->Struct.polymorphic_params = polymorphic_params;
|
||||||
if (poly_operands != nullptr) {
|
struct_type->Struct.is_poly_specialized = check_record_poly_operand_specialization(ctx, struct_type, poly_operands, &is_polymorphic);
|
||||||
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;
|
|
||||||
|
|
||||||
if (!is_polymorphic) {
|
if (!is_polymorphic) {
|
||||||
if (st->where_clauses.count > 0 && st->polymorphic_params == nullptr) {
|
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;
|
bool &is_polymorphic = union_type->Union.is_polymorphic;
|
||||||
|
|
||||||
Type *polymorphic_params = nullptr;
|
Type *polymorphic_params = nullptr;
|
||||||
bool can_check_fields = true;
|
|
||||||
bool is_poly_specialized = false;
|
|
||||||
|
|
||||||
polymorphic_params = check_record_polymorphic_params(
|
polymorphic_params = check_record_polymorphic_params(
|
||||||
ctx, ut->polymorphic_params,
|
ctx, ut->polymorphic_params,
|
||||||
&is_polymorphic, &can_check_fields,
|
&is_polymorphic,
|
||||||
node, poly_operands,
|
node, poly_operands,
|
||||||
named_type, original_type_for_poly
|
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) {
|
if (!is_polymorphic) {
|
||||||
is_polymorphic = polymorphic_params != nullptr && poly_operands == nullptr;
|
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");
|
||||||
if (poly_operands != nullptr) {
|
} else {
|
||||||
is_poly_specialized = true;
|
bool where_clause_ok = evaluate_where_clauses(ctx, node, ctx->scope, &ut->where_clauses, 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
for_array(i, ut->variants) {
|
||||||
Ast *node = ut->variants[i];
|
Ast *node = ut->variants[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user