mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-31 10:22:08 +00:00
Add #subtype struct field prefix, required to have a COM interface hierarchy
This commit is contained in:
@@ -9774,6 +9774,9 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
|
||||
if (f->flags&FieldFlag_const) {
|
||||
str = gb_string_appendc(str, "#const ");
|
||||
}
|
||||
if (f->flags&FieldFlag_subtype) {
|
||||
str = gb_string_appendc(str, "#subtype ");
|
||||
}
|
||||
|
||||
for_array(i, f->names) {
|
||||
Ast *name = f->names[i];
|
||||
|
||||
@@ -144,6 +144,7 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields
|
||||
}
|
||||
|
||||
bool is_using = (p->flags&FieldFlag_using) != 0;
|
||||
bool is_subtype = (p->flags&FieldFlag_subtype) != 0;
|
||||
|
||||
for_array(j, p->names) {
|
||||
Ast *name = p->names[j];
|
||||
@@ -158,6 +159,9 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields
|
||||
Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
|
||||
add_entity(ctx, ctx->scope, name, field);
|
||||
field->Variable.field_group_index = field_group_index;
|
||||
if (is_subtype) {
|
||||
field->flags |= EntityFlag_Subtype;
|
||||
}
|
||||
|
||||
if (j == 0) {
|
||||
field->Variable.docs = docs;
|
||||
@@ -194,6 +198,20 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entity *> *fields
|
||||
|
||||
populate_using_entity_scope(ctx, node, p, type);
|
||||
}
|
||||
|
||||
if (is_subtype && p->names.count > 0) {
|
||||
Type *first_type = fields_array[fields_array.count-1]->type;
|
||||
Type *t = base_type(type_deref(first_type));
|
||||
|
||||
if (!does_field_type_allow_using(t) &&
|
||||
p->names.count >= 1 &&
|
||||
p->names[0]->kind == Ast_Ident) {
|
||||
Token name_token = p->names[0]->Ident.token;
|
||||
gbString type_str = type_to_string(first_type);
|
||||
error(name_token, "'subtype' cannot be applied to the field '%.*s' of type '%s'", LIT(name_token.string), type_str);
|
||||
gb_string_free(type_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*fields = slice_from_array(fields_array);
|
||||
|
||||
@@ -74,6 +74,7 @@ enum EntityFlag : u64 {
|
||||
|
||||
EntityFlag_Test = 1ull<<30,
|
||||
EntityFlag_Init = 1ull<<31,
|
||||
EntityFlag_Subtype = 1ull<<32,
|
||||
|
||||
EntityFlag_CustomLinkName = 1ull<<40,
|
||||
EntityFlag_CustomLinkage_Internal = 1ull<<41,
|
||||
@@ -86,6 +87,10 @@ enum EntityFlag : u64 {
|
||||
EntityFlag_Overridden = 1ull<<63,
|
||||
};
|
||||
|
||||
enum : u64 {
|
||||
EntityFlags_IsSubtype = EntityFlag_Using|EntityFlag_Subtype,
|
||||
};
|
||||
|
||||
enum EntityState : u32 {
|
||||
EntityState_Unresolved = 0,
|
||||
EntityState_InProgress = 1,
|
||||
|
||||
@@ -3504,12 +3504,13 @@ enum FieldPrefixKind : i32 {
|
||||
FieldPrefix_Unknown = -1,
|
||||
FieldPrefix_Invalid = 0,
|
||||
|
||||
FieldPrefix_using,
|
||||
FieldPrefix_using, // implies #subtype
|
||||
FieldPrefix_const,
|
||||
FieldPrefix_no_alias,
|
||||
FieldPrefix_c_vararg,
|
||||
FieldPrefix_auto_cast,
|
||||
FieldPrefix_any_int,
|
||||
FieldPrefix_subtype, // does not imply `using` semantics
|
||||
};
|
||||
|
||||
struct ParseFieldPrefixMapping {
|
||||
@@ -3526,6 +3527,7 @@ gb_global ParseFieldPrefixMapping parse_field_prefix_mappings[] = {
|
||||
{str_lit("c_vararg"), Token_Hash, FieldPrefix_c_vararg, FieldFlag_c_vararg},
|
||||
{str_lit("const"), Token_Hash, FieldPrefix_const, FieldFlag_const},
|
||||
{str_lit("any_int"), Token_Hash, FieldPrefix_any_int, FieldFlag_any_int},
|
||||
{str_lit("subtype"), Token_Hash, FieldPrefix_subtype, FieldFlag_subtype},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -282,6 +282,7 @@ enum FieldFlag : u32 {
|
||||
FieldFlag_auto_cast = 1<<4,
|
||||
FieldFlag_const = 1<<5,
|
||||
FieldFlag_any_int = 1<<6,
|
||||
FieldFlag_subtype = 1<<7,
|
||||
|
||||
// Internal use by the parser only
|
||||
FieldFlag_Tags = 1<<10,
|
||||
@@ -289,7 +290,7 @@ enum FieldFlag : u32 {
|
||||
|
||||
// Parameter List Restrictions
|
||||
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const|FieldFlag_any_int,
|
||||
FieldFlag_Struct = FieldFlag_using|FieldFlag_Tags,
|
||||
FieldFlag_Struct = FieldFlag_using|FieldFlag_subtype|FieldFlag_Tags,
|
||||
};
|
||||
|
||||
enum StmtAllowFlag {
|
||||
|
||||
@@ -2334,7 +2334,7 @@ String lookup_subtype_polymorphic_field(Type *dst, Type *src) {
|
||||
GB_ASSERT(is_type_struct(src) || is_type_union(src));
|
||||
for_array(i, src->Struct.fields) {
|
||||
Entity *f = src->Struct.fields[i];
|
||||
if (f->kind == Entity_Variable && f->flags & EntityFlag_Using) {
|
||||
if (f->kind == Entity_Variable && f->flags & EntityFlags_IsSubtype) {
|
||||
if (are_types_identical(dst, f->type)) {
|
||||
return f->token.string;
|
||||
}
|
||||
@@ -2343,7 +2343,7 @@ String lookup_subtype_polymorphic_field(Type *dst, Type *src) {
|
||||
return f->token.string;
|
||||
}
|
||||
}
|
||||
if (is_type_struct(f->type)) {
|
||||
if ((f->flags & EntityFlag_Using) != 0 && is_type_struct(f->type)) {
|
||||
String name = lookup_subtype_polymorphic_field(dst, f->type);
|
||||
if (name.len > 0) {
|
||||
return name;
|
||||
@@ -2489,9 +2489,9 @@ bool are_types_identical_internal(Type *x, Type *y, bool check_tuple_names) {
|
||||
if (xf->token.string != yf->token.string) {
|
||||
return false;
|
||||
}
|
||||
bool xf_is_using = (xf->flags&EntityFlag_Using) != 0;
|
||||
bool yf_is_using = (yf->flags&EntityFlag_Using) != 0;
|
||||
if (xf_is_using ^ yf_is_using) {
|
||||
u64 xf_flags = (xf->flags&EntityFlags_IsSubtype);
|
||||
u64 yf_flags = (yf->flags&EntityFlags_IsSubtype);
|
||||
if (xf_flags != yf_flags) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3813,7 +3813,7 @@ isize check_is_assignable_to_using_subtype(Type *src, Type *dst, isize level = 0
|
||||
|
||||
for_array(i, src->Struct.fields) {
|
||||
Entity *f = src->Struct.fields[i];
|
||||
if (f->kind != Entity_Variable || (f->flags&EntityFlag_Using) == 0) {
|
||||
if (f->kind != Entity_Variable || (f->flags&EntityFlags_IsSubtype) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user