From: Brendan Hansen Date: Thu, 25 Nov 2021 02:32:53 +0000 (-0600) Subject: added distinct types on primitive types X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=133ff55b031d4bd5e7cd7bcbfcd311e143bddbad;p=onyx.git added distinct types on primitive types --- diff --git a/core/conv.onyx b/core/conv.onyx index 76eaf087..40836974 100644 --- a/core/conv.onyx +++ b/core/conv.onyx @@ -628,6 +628,15 @@ str_format_va :: (buffer: [] u8, format: str, va: [] any) -> str { } } } + + 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("]"); + } } } } diff --git a/core/type_info/helper.onyx b/core/type_info/helper.onyx index 9ddaf5ea..213c2407 100644 --- a/core/type_info/helper.onyx +++ b/core/type_info/helper.onyx @@ -117,6 +117,11 @@ write_type_name :: (writer: ^io.Writer, t: type_expr) { write_type_name(writer, f.return_type); } + + case .Distinct { + d := cast(^Type_Info_Distinct) info; + io.write_str(writer, d.name); + } } } diff --git a/core/type_info/type_info.onyx b/core/type_info/type_info.onyx index 3df1cc63..2a256c5f 100644 --- a/core/type_info/type_info.onyx +++ b/core/type_info/type_info.onyx @@ -20,6 +20,7 @@ Type_Info :: struct { Dynamic_Array :: 0x09; Variadic_Argument :: 0x0a; Enum :: 0x0b; + Distinct :: 0x0c; } kind := Kind.Invalid; @@ -166,6 +167,13 @@ Type_Info_Compound :: struct { 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. diff --git a/include/astnodes.h b/include/astnodes.h index 8cf6d822..939ff013 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -71,6 +71,7 @@ NODE(TypeRawAlias) \ NODE(CompoundType) \ NODE(TypeOf) \ + NODE(DistinctType) \ \ NODE(Binding) \ NODE(Alias) \ @@ -158,6 +159,7 @@ typedef enum AstKind { Ast_Kind_Type_Raw_Alias, Ast_Kind_Type_Compound, Ast_Kind_Typeof, + Ast_Kind_Distinct_Type, Ast_Kind_Type_End, Ast_Kind_Struct_Member, @@ -907,6 +909,12 @@ struct AstTypeOf { 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; }; diff --git a/include/types.h b/include/types.h index d1b9e51a..638adab6 100644 --- a/include/types.h +++ b/include/types.h @@ -127,6 +127,10 @@ struct TypeWithOffset { char* name; \ Type* backing; \ b32 is_flags; \ + }) \ + TYPE_KIND(Distinct, struct { \ + char* name; \ + Type* base_type; \ }) diff --git a/src/astnodes.c b/src/astnodes.c index eafc64dd..55d6b13f 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -46,6 +46,7 @@ static const char* ast_node_names[] = { "TYPE RAW ALIAS", "COMPOUND TYPE", "TYPE OF", + "DISTINCT TYPE", "TYPE_END (BAD)", "STRUCT MEMBER", @@ -900,6 +901,26 @@ b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) { } } + 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; diff --git a/src/parser.c b/src/parser.c index 9c8dde2d..f59a8485 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2717,23 +2717,33 @@ static AstTyped* parse_top_level_expression(OnyxParser* parser) { 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); @@ -2812,6 +2822,7 @@ static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol 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; diff --git a/src/symres.c b/src/symres.c index 069b9cd1..3d209439 100644 --- a/src/symres.c +++ b/src/symres.c @@ -221,6 +221,12 @@ static SymresStatus symres_type(AstType** type) { SYMRES(expression, &type_of->expr); break; } + + case Ast_Kind_Distinct_Type: { + AstDistinctType *distinct = (AstDistinctType *) *type; + SYMRES(type, &distinct->base_type); + break; + } } return Symres_Success; diff --git a/src/types.c b/src/types.c index c89fd320..9ffdfaf6 100644 --- a/src/types.c +++ b/src/types.c @@ -188,6 +188,10 @@ b32 types_are_compatible_(Type* t1, Type* t2, b32 recurse_pointers) { 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; @@ -214,6 +218,7 @@ u32 type_size_of(Type* type) { 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; } } @@ -232,6 +237,7 @@ u32 type_alignment_of(Type* type) { 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; } } @@ -612,6 +618,26 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { 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; @@ -876,6 +902,9 @@ const char* type_get_unique_name(Type* type) { 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"; } @@ -935,6 +964,10 @@ const char* type_get_name(Type* type) { 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"; } } @@ -1090,6 +1123,12 @@ b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) { } 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; diff --git a/src/wasm_emit.c b/src/wasm_emit.c index 3dbe6e02..2e8af1b9 100644 --- a/src/wasm_emit.c +++ b/src/wasm_emit.c @@ -39,6 +39,10 @@ static WasmType onyx_type_to_wasm_type(Type* type) { 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; } @@ -84,6 +88,7 @@ static b32 local_is_wasm_local(AstTyped* local) { 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; } @@ -613,6 +618,7 @@ EMIT_FUNC(store_instruction, Type* type, u32 offset) { } 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); @@ -662,6 +668,7 @@ EMIT_FUNC(load_instruction, Type* type, u32 offset) { } 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); @@ -2906,6 +2913,12 @@ EMIT_FUNC(cast, AstUnaryOp* cast) { 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; diff --git a/src/wasm_type_table.c b/src/wasm_type_table.c index f67f4823..2712843d 100644 --- a/src/wasm_type_table.c +++ b/src/wasm_type_table.c @@ -466,6 +466,23 @@ u64 build_type_table(OnyxWasmModule* module) { 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; + } } }