}
}
}
+
+ if info.kind == .Distinct {
+ d := cast(^Type_Info_Distinct) info;
+
+ output->write(d.name);
+ output->write("[");
+ print_any(output, formatting, any.{ v.data, d.base_type });
+ output->write("]");
+ }
}
}
}
write_type_name(writer, f.return_type);
}
+
+ case .Distinct {
+ d := cast(^Type_Info_Distinct) info;
+ io.write_str(writer, d.name);
+ }
}
}
Dynamic_Array :: 0x09;
Variadic_Argument :: 0x0a;
Enum :: 0x0b;
+ Distinct :: 0x0c;
}
kind := Kind.Invalid;
components : [] type_expr;
}
+Type_Info_Distinct :: struct {
+ use base : Type_Info;
+
+ base_type: type_expr;
+ name: str;
+}
+
get_type_info :: (t: type_expr) -> ^Type_Info {
// Grossness to get around the fact that type_exprs are not technically comparable, because in most
// cases you should not compare them as the number assigned to them is arbitrary.
NODE(TypeRawAlias) \
NODE(CompoundType) \
NODE(TypeOf) \
+ NODE(DistinctType) \
\
NODE(Binding) \
NODE(Alias) \
Ast_Kind_Type_Raw_Alias,
Ast_Kind_Type_Compound,
Ast_Kind_Typeof,
+ Ast_Kind_Distinct_Type,
Ast_Kind_Type_End,
Ast_Kind_Struct_Member,
AstTyped* expr;
Type* resolved_type;
};
+struct AstDistinctType {
+ AstType_base;
+ char *name;
+ AstType *base_type;
+ Type *dtcache;
+};
// Top level nodes
struct AstBinding { AstTyped_base; AstNode* node; };
char* name; \
Type* backing; \
b32 is_flags; \
+ }) \
+ TYPE_KIND(Distinct, struct { \
+ char* name; \
+ Type* base_type; \
})
"TYPE RAW ALIAS",
"COMPOUND TYPE",
"TYPE OF",
+ "DISTINCT TYPE",
"TYPE_END (BAD)",
"STRUCT MEMBER",
}
}
+ if (to->kind == Type_Kind_Distinct) {
+ if (!types_are_compatible(to->Distinct.base_type, from)) {
+ // :BadErrorMessage
+ *err_msg = "Cannot convert to a distinct type using the wrong base type.";
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ if (from->kind == Type_Kind_Distinct) {
+ if (!types_are_compatible(from->Distinct.base_type, to)) {
+ // :BadErrorMessage
+ *err_msg = "Cannot convert from a distinct type to the wrong destination type.";
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
if (from->kind == Type_Kind_Slice || to->kind == Type_Kind_Slice) {
*err_msg = "Cannot cast to or from a slice.";
return 0;
if (parser->curr->type == Token_Type_Keyword_Enum) return (AstTyped *) parse_enum_declaration(parser);
if (parser->curr->type == Token_Type_Keyword_Macro) return (AstTyped *) parse_macro(parser);
- if (parse_possible_directive(parser, "type")) {
- AstTypeAlias* alias = make_node(AstTypeAlias, Ast_Kind_Type_Alias);
- alias->to = parse_type(parser);
- return (AstTyped *) alias;
- }
+ if (parser->curr->type == '#') {
+ if (parse_possible_directive(parser, "type")) {
+ AstTypeAlias* alias = make_node(AstTypeAlias, Ast_Kind_Type_Alias);
+ alias->to = parse_type(parser);
+ return (AstTyped *) alias;
+ }
- if (parse_possible_directive(parser, "match")) {
- // :LinearTokenDependent
- OnyxToken* directive_token = parser->curr - 2;
- AstOverloadedFunction* ofunc = parse_overloaded_function(parser, directive_token);
- return (AstTyped *) ofunc;
- }
+ if (parse_possible_directive(parser, "match")) {
+ // :LinearTokenDependent
+ OnyxToken* directive_token = parser->curr - 2;
+ AstOverloadedFunction* ofunc = parse_overloaded_function(parser, directive_token);
+ return (AstTyped *) ofunc;
+ }
- if (parse_possible_directive(parser, "init")) {
- // :LinearTokenDependent
- AstDirectiveInit *init = parse_init_directive(parser, parser->curr - 2);
- return (AstTyped *) init;
+ if (parse_possible_directive(parser, "init")) {
+ // :LinearTokenDependent
+ AstDirectiveInit *init = parse_init_directive(parser, parser->curr - 2);
+ return (AstTyped *) init;
+ }
+
+ if (parse_possible_directive(parser, "distinct")) {
+ // :LinearTokenDependent
+ AstDistinctType *distinct = make_node(AstDistinctType, Ast_Kind_Distinct_Type);
+ distinct->token = parser->curr - 2;
+ distinct->base_type = parse_type(parser);
+ return (AstTyped *) distinct;
+ }
}
return parse_expression(parser, 1);
case Ast_Kind_Struct_Type:
case Ast_Kind_Poly_Struct_Type:
case Ast_Kind_Enum_Type:
+ case Ast_Kind_Distinct_Type:
((AstStructType *) node)->name = generate_name_within_scope(parser, symbol);
goto default_case;
SYMRES(expression, &type_of->expr);
break;
}
+
+ case Ast_Kind_Distinct_Type: {
+ AstDistinctType *distinct = (AstDistinctType *) *type;
+ SYMRES(type, &distinct->base_type);
+ break;
+ }
}
return Symres_Success;
return 1;
}
+ case Type_Kind_Distinct:
+ // If the above cases didn't catch it, then these distinct types are not compatible.
+ return 0;
+
default:
assert(("Invalid type", 0));
break;
case Type_Kind_VarArgs: return 16; // but there are alignment issues right now with that so I decided to not fight it and just make them 16 bytes in size.
case Type_Kind_DynArray: return 32; // data (8), count (4), capacity (4), allocator { func (4), ---(4), data (8) }
case Type_Kind_Compound: return type->Compound.size;
+ case Type_Kind_Distinct: return type_size_of(type->Distinct.base_type);
default: return 0;
}
}
case Type_Kind_VarArgs: return 8;
case Type_Kind_DynArray: return 8;
case Type_Kind_Compound: return 4; // HACK
+ case Type_Kind_Distinct: return type_alignment_of(type->Distinct.base_type);
default: return 1;
}
}
return NULL;
}
+
+ case Ast_Kind_Distinct_Type: {
+ AstDistinctType* distinct = (AstDistinctType *) type_node;
+ if (distinct->dtcache) return distinct->dtcache;
+
+ Type *base_type = type_build_from_ast(alloc, distinct->base_type);
+ if (base_type == NULL) return NULL;
+ if (base_type->kind != Type_Kind_Basic) {
+ onyx_report_error(distinct->token->pos, "Distinct types can only be made out of primitive types. '%s' is not a primitive type.", type_get_name(base_type));
+ return NULL;
+ }
+
+ Type *distinct_type = type_create(Type_Kind_Distinct, alloc, 0);
+ distinct_type->Distinct.base_type = base_type;
+ distinct_type->Distinct.name = distinct->name;
+ distinct->dtcache = distinct_type;
+
+ type_register(distinct_type);
+ return distinct_type;
+ }
}
return NULL;
return bh_aprintf(global_scratch_allocator, "%s", buf);
}
+ case Type_Kind_Distinct: {
+ return bh_aprintf(global_scratch_allocator, "%s@%l", type->Distinct.name, type->id);
+ }
default: return "unknown";
}
return bh_aprintf(global_scratch_allocator, "%s", buf);
}
+ case Type_Kind_Distinct: {
+ return bh_aprintf(global_scratch_allocator, "%s", type->Distinct.name);
+ }
+
default: return "unknown";
}
}
}
case Type_Kind_Compound: *two = type->Compound.linear_members[idx]; return 1;
case Type_Kind_Struct: *two = type->Struct.linear_members[idx]; return 1;
+
+ case Type_Kind_Distinct:
+ two->type = type->Distinct.base_type;
+ two->offset = 0;
+ return 1;
+
default: {
if (idx > 0) return 0;
two->offset = 0;
return onyx_type_to_wasm_type(type->Enum.backing);
}
+ if (type->kind == Type_Kind_Distinct) {
+ return onyx_type_to_wasm_type(type->Distinct.base_type);
+ }
+
if (type->kind == Type_Kind_Pointer) {
return WASM_TYPE_PTR;
}
if (local->kind == Ast_Kind_Local && local->flags & Ast_Flag_Address_Taken) return 0;
if (local->type->kind == Type_Kind_Basic) return 1;
if (local->type->kind == Type_Kind_Enum && local->type->Enum.backing->kind == Type_Kind_Basic) return 1;
+ if (local->type->kind == Type_Kind_Distinct && local->type->Distinct.base_type->kind == Type_Kind_Basic) return 1;
if (local->type->kind == Type_Kind_Pointer) return 1;
return 0;
}
}
if (type->kind == Type_Kind_Enum) type = type->Enum.backing;
+ if (type->kind == Type_Kind_Distinct) type = type->Distinct.base_type;
if (type->kind == Type_Kind_Function) type = &basic_types[Basic_Kind_U32];
u32 alignment = type_get_alignment_log2(type);
}
if (type->kind == Type_Kind_Enum) type = type->Enum.backing;
+ if (type->kind == Type_Kind_Distinct) type = type->Distinct.base_type;
if (type->kind == Type_Kind_Function) type = &basic_types[Basic_Kind_U32];
i32 load_size = type_size_of(type);
return;
}
+ if (to->kind == Type_Kind_Distinct || from->kind == Type_Kind_Distinct) {
+ // Nothing needs to be done because they are identical
+ *pcode = code;
+ return;
+ }
+
i32 fromidx = -1, toidx = -1;
if (from->Basic.flags & Basic_Flag_Pointer || from->kind == Type_Kind_Array) {
fromidx = 10;
break;
}
+
+ case Type_Kind_Distinct: {
+ u32 name_base = table_buffer.length;
+ u32 name_length = strlen(type->Distinct.name);
+ bh_buffer_append(&table_buffer, type->Distinct.name, name_length);
+ bh_buffer_align(&table_buffer, 8);
+
+ table_info[type_idx] = table_buffer.length;
+ bh_buffer_write_u32(&table_buffer, type->kind);
+ bh_buffer_write_u32(&table_buffer, type_size_of(type));
+ bh_buffer_write_u32(&table_buffer, type_alignment_of(type));
+ bh_buffer_write_u32(&table_buffer, type->Distinct.base_type->id);
+ PATCH;
+ bh_buffer_write_u64(&table_buffer, name_base);
+ bh_buffer_write_u64(&table_buffer, name_length);
+ break;
+ }
}
}