aboutsummaryrefslogtreecommitdiff
path: root/src/checker/types.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-11-23 12:29:50 +0000
committerGinger Bill <bill@gingerbill.org>2016-11-23 12:29:50 +0000
commit4d30ef7eda0021f0cb827c7a218ef3afc6ce8b55 (patch)
tree9f31e2b07cf610300c1db3c511b84d9d2cc72d6b /src/checker/types.cpp
parenta77c6b3e55c5857c9c0ba36baae2dbdcd7564cd4 (diff)
Change extensions .cpp to .c
Diffstat (limited to 'src/checker/types.cpp')
-rw-r--r--src/checker/types.cpp1487
1 files changed, 0 insertions, 1487 deletions
diff --git a/src/checker/types.cpp b/src/checker/types.cpp
deleted file mode 100644
index f51cbb660..000000000
--- a/src/checker/types.cpp
+++ /dev/null
@@ -1,1487 +0,0 @@
-typedef struct Scope Scope;
-
-typedef enum BasicKind {
- Basic_Invalid,
- Basic_bool,
- Basic_i8,
- Basic_u8,
- Basic_i16,
- Basic_u16,
- Basic_i32,
- Basic_u32,
- Basic_i64,
- Basic_u64,
- Basic_i128,
- Basic_u128,
- // Basic_f16,
- Basic_f32,
- Basic_f64,
- // Basic_f128,
- Basic_int,
- Basic_uint,
- Basic_rawptr,
- Basic_string, // ^u8 + int
- Basic_any, // ^Type_Info + rawptr
-
- Basic_UntypedBool,
- Basic_UntypedInteger,
- Basic_UntypedFloat,
- Basic_UntypedString,
- Basic_UntypedRune,
- Basic_UntypedNil,
-
- Basic_Count,
-
- Basic_byte = Basic_u8,
- Basic_rune = Basic_i32,
-} BasicKind;
-
-typedef enum BasicFlag {
- BasicFlag_Boolean = GB_BIT(0),
- BasicFlag_Integer = GB_BIT(1),
- BasicFlag_Unsigned = GB_BIT(2),
- BasicFlag_Float = GB_BIT(3),
- BasicFlag_Pointer = GB_BIT(4),
- BasicFlag_String = GB_BIT(5),
- BasicFlag_Rune = GB_BIT(6),
- BasicFlag_Untyped = GB_BIT(7),
-
- BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float,
- BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
- BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
-} BasicFlag;
-
-typedef struct BasicType {
- BasicKind kind;
- u32 flags;
- i64 size; // -1 if arch. dep.
- String name;
-} BasicType;
-
-typedef enum TypeRecordKind {
- TypeRecord_Invalid,
-
- TypeRecord_Struct,
- TypeRecord_Enum,
- TypeRecord_RawUnion,
- TypeRecord_Union, // Tagged
-
- TypeRecord_Count,
-} TypeRecordKind;
-
-typedef struct TypeRecord {
- TypeRecordKind kind;
-
- // All record types
- // Theses are arrays
- Entity **fields; // Entity_Variable (otherwise Entity_TypeName if union)
- i32 field_count; // == offset_count is struct
- AstNode *node;
-
- union { // NOTE(bill): Reduce size_of Type
- struct { // enum only
- Type * enum_base; // Default is `int`
- Entity * enum_count;
- Entity * min_value;
- Entity * max_value;
- };
- struct { // struct only
- i64 * struct_offsets;
- bool struct_are_offsets_set;
- bool struct_is_packed;
- bool struct_is_ordered;
- Entity **fields_in_src_order; // Entity_Variable
- };
- };
-
- // Entity_Constant or Entity_TypeName
- Entity **other_fields;
- i32 other_field_count;
-} TypeRecord;
-
-#define TYPE_KINDS \
- TYPE_KIND(Basic, BasicType) \
- TYPE_KIND(Pointer, struct { Type *elem; }) \
- TYPE_KIND(Array, struct { Type *elem; i64 count; }) \
- TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \
- TYPE_KIND(Slice, struct { Type *elem; }) \
- TYPE_KIND(Maybe, struct { Type *elem; }) \
- TYPE_KIND(Record, TypeRecord) \
- TYPE_KIND(Named, struct { \
- String name; \
- Type * base; \
- Entity *type_name; /* Entity_TypeName */ \
- }) \
- TYPE_KIND(Tuple, struct { \
- Entity **variables; /* Entity_Variable */ \
- i32 variable_count; \
- bool are_offsets_set; \
- i64 * offsets; \
- }) \
- TYPE_KIND(Proc, struct { \
- Scope *scope; \
- Type * params; /* Type_Tuple */ \
- Type * results; /* Type_Tuple */ \
- i32 param_count; \
- i32 result_count; \
- bool variadic; \
- })
-
-typedef enum TypeKind {
- Type_Invalid,
-#define TYPE_KIND(k, ...) GB_JOIN2(Type_, k),
- TYPE_KINDS
-#undef TYPE_KIND
- Type_Count,
-} TypeKind;
-
-String const type_strings[] = {
- {cast(u8 *)"Invalid", gb_size_of("Invalid")},
-#define TYPE_KIND(k, ...) {cast(u8 *)#k, gb_size_of(#k)-1},
- TYPE_KINDS
-#undef TYPE_KIND
-};
-
-#define TYPE_KIND(k, ...) typedef __VA_ARGS__ GB_JOIN2(Type, k);
- TYPE_KINDS
-#undef TYPE_KIND
-
-typedef struct Type {
- TypeKind kind;
- union {
-#define TYPE_KIND(k, ...) GB_JOIN2(Type, k) k;
- TYPE_KINDS
-#undef TYPE_KIND
- };
-} Type;
-
-// NOTE(bill): Internal sizes of certain types
-// string: 2*word_size (ptr+len)
-// slice: 3*word_size (ptr+len+cap)
-// array: count*size_of(elem) aligned
-
-// NOTE(bill): Alignment of structures and other types are to be compatible with C
-
-typedef struct BaseTypeSizes {
- i64 word_size;
- i64 max_align;
-} BaseTypeSizes;
-
-typedef Array(isize) Array_isize;
-
-typedef struct Selection {
- Entity * entity;
- Array_isize index;
- bool indirect; // Set if there was a pointer deref anywhere down the line
-} Selection;
-Selection empty_selection = {0};
-
-Selection make_selection(Entity *entity, Array_isize index, bool indirect) {
- Selection s = {entity, index, indirect};
- return s;
-}
-
-void selection_add_index(Selection *s, isize index) {
- // IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form
- // of heap allocation
- if (s->index.e == NULL) {
- array_init(&s->index, heap_allocator());
- }
- array_add(&s->index, index);
-}
-
-
-
-#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
-gb_global Type basic_types[] = {
- {Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
- {Type_Basic, {Basic_bool, BasicFlag_Boolean, 1, STR_LIT("bool")}},
- {Type_Basic, {Basic_i8, BasicFlag_Integer, 1, STR_LIT("i8")}},
- {Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("u8")}},
- {Type_Basic, {Basic_i16, BasicFlag_Integer, 2, STR_LIT("i16")}},
- {Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, 2, STR_LIT("u16")}},
- {Type_Basic, {Basic_i32, BasicFlag_Integer, 4, STR_LIT("i32")}},
- {Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
- {Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
- {Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
- {Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
- {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
- // {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}},
- {Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
- {Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
- // {Type_Basic, {Basic_f128, BasicFlag_Float, 16, STR_LIT("f128")}},
- {Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
- {Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
- {Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
- {Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
- {Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
- {Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
- {Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
- {Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
- {Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
- {Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
- {Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
-};
-
-gb_global Type basic_type_aliases[] = {
- {Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("byte")}},
- {Type_Basic, {Basic_rune, BasicFlag_Integer, 4, STR_LIT("rune")}},
-};
-
-gb_global Type *t_invalid = &basic_types[Basic_Invalid];
-gb_global Type *t_bool = &basic_types[Basic_bool];
-gb_global Type *t_i8 = &basic_types[Basic_i8];
-gb_global Type *t_u8 = &basic_types[Basic_u8];
-gb_global Type *t_i16 = &basic_types[Basic_i16];
-gb_global Type *t_u16 = &basic_types[Basic_u16];
-gb_global Type *t_i32 = &basic_types[Basic_i32];
-gb_global Type *t_u32 = &basic_types[Basic_u32];
-gb_global Type *t_i64 = &basic_types[Basic_i64];
-gb_global Type *t_u64 = &basic_types[Basic_u64];
-gb_global Type *t_i128 = &basic_types[Basic_i128];
-gb_global Type *t_u128 = &basic_types[Basic_u128];
-// gb_global Type *t_f16 = &basic_types[Basic_f16];
-gb_global Type *t_f32 = &basic_types[Basic_f32];
-gb_global Type *t_f64 = &basic_types[Basic_f64];
-// gb_global Type *t_f128 = &basic_types[Basic_f128];
-gb_global Type *t_int = &basic_types[Basic_int];
-gb_global Type *t_uint = &basic_types[Basic_uint];
-gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
-gb_global Type *t_string = &basic_types[Basic_string];
-gb_global Type *t_any = &basic_types[Basic_any];
-gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
-gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
-gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
-gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
-gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
-gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
-gb_global Type *t_byte = &basic_type_aliases[0];
-gb_global Type *t_rune = &basic_type_aliases[1];
-
-
-gb_global Type *t_u8_ptr = NULL;
-gb_global Type *t_int_ptr = NULL;
-
-gb_global Type *t_type_info = NULL;
-gb_global Type *t_type_info_ptr = NULL;
-gb_global Type *t_type_info_member = NULL;
-gb_global Type *t_type_info_member_ptr = NULL;
-
-gb_global Type *t_type_info_named = NULL;
-gb_global Type *t_type_info_integer = NULL;
-gb_global Type *t_type_info_float = NULL;
-gb_global Type *t_type_info_any = NULL;
-gb_global Type *t_type_info_string = NULL;
-gb_global Type *t_type_info_boolean = NULL;
-gb_global Type *t_type_info_pointer = NULL;
-gb_global Type *t_type_info_maybe = NULL;
-gb_global Type *t_type_info_procedure = NULL;
-gb_global Type *t_type_info_array = NULL;
-gb_global Type *t_type_info_slice = NULL;
-gb_global Type *t_type_info_vector = NULL;
-gb_global Type *t_type_info_tuple = NULL;
-gb_global Type *t_type_info_struct = NULL;
-gb_global Type *t_type_info_union = NULL;
-gb_global Type *t_type_info_raw_union = NULL;
-gb_global Type *t_type_info_enum = NULL;
-
-gb_global Type *t_allocator = NULL;
-gb_global Type *t_allocator_ptr = NULL;
-gb_global Type *t_context = NULL;
-gb_global Type *t_context_ptr = NULL;
-
-
-
-
-
-
-gbString type_to_string(Type *type);
-
-Type *base_type(Type *t) {
- for (;;) {
- if (t == NULL || t->kind != Type_Named) {
- break;
- }
- t = t->Named.base;
- }
- return t;
-}
-
-void set_base_type(Type *t, Type *base) {
- if (t && t->kind == Type_Named) {
- t->Named.base = base;
- }
-}
-
-
-Type *alloc_type(gbAllocator a, TypeKind kind) {
- Type *t = gb_alloc_item(a, Type);
- t->kind = kind;
- return t;
-}
-
-
-Type *make_type_basic(gbAllocator a, BasicType basic) {
- Type *t = alloc_type(a, Type_Basic);
- t->Basic = basic;
- return t;
-}
-
-Type *make_type_pointer(gbAllocator a, Type *elem) {
- Type *t = alloc_type(a, Type_Pointer);
- t->Pointer.elem = elem;
- return t;
-}
-
-Type *make_type_maybe(gbAllocator a, Type *elem) {
- Type *t = alloc_type(a, Type_Maybe);
- t->Maybe.elem = elem;
- return t;
-}
-
-Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
- Type *t = alloc_type(a, Type_Array);
- t->Array.elem = elem;
- t->Array.count = count;
- return t;
-}
-
-Type *make_type_vector(gbAllocator a, Type *elem, i64 count) {
- Type *t = alloc_type(a, Type_Vector);
- t->Vector.elem = elem;
- t->Vector.count = count;
- return t;
-}
-
-Type *make_type_slice(gbAllocator a, Type *elem) {
- Type *t = alloc_type(a, Type_Slice);
- t->Array.elem = elem;
- return t;
-}
-
-
-Type *make_type_struct(gbAllocator a) {
- Type *t = alloc_type(a, Type_Record);
- t->Record.kind = TypeRecord_Struct;
- return t;
-}
-
-Type *make_type_union(gbAllocator a) {
- Type *t = alloc_type(a, Type_Record);
- t->Record.kind = TypeRecord_Union;
- return t;
-}
-
-Type *make_type_raw_union(gbAllocator a) {
- Type *t = alloc_type(a, Type_Record);
- t->Record.kind = TypeRecord_RawUnion;
- return t;
-}
-
-Type *make_type_enum(gbAllocator a) {
- Type *t = alloc_type(a, Type_Record);
- t->Record.kind = TypeRecord_Enum;
- return t;
-}
-
-
-
-Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name) {
- Type *t = alloc_type(a, Type_Named);
- t->Named.name = name;
- t->Named.base = base;
- t->Named.type_name = type_name;
- return t;
-}
-
-Type *make_type_tuple(gbAllocator a) {
- Type *t = alloc_type(a, Type_Tuple);
- return t;
-}
-
-Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count, bool variadic) {
- Type *t = alloc_type(a, Type_Proc);
-
- if (variadic) {
- if (param_count == 0) {
- GB_PANIC("variadic procedure must have at least one parameter");
- }
- GB_ASSERT(params != NULL && params->kind == Type_Tuple);
- Entity *e = params->Tuple.variables[param_count-1];
- if (base_type(e->type)->kind != Type_Slice) {
- // NOTE(bill): For custom calling convention
- GB_PANIC("variadic parameter must be of type slice");
- }
- }
-
- t->Proc.scope = scope;
- t->Proc.params = params;
- t->Proc.param_count = param_count;
- t->Proc.results = results;
- t->Proc.result_count = result_count;
- t->Proc.variadic = variadic;
- return t;
-}
-
-
-Type *type_deref(Type *t) {
- if (t != NULL) {
- Type *bt = base_type(t);
- if (bt == NULL)
- return NULL;
- if (bt != NULL && bt->kind == Type_Pointer)
- return bt->Pointer.elem;
- }
- return t;
-}
-
-Type *get_enum_base_type(Type *t) {
- Type *bt = base_type(t);
- if (bt->kind == Type_Record && bt->Record.kind == TypeRecord_Enum) {
- GB_ASSERT(bt->Record.enum_base != NULL);
- return bt->Record.enum_base;
- }
- return t;
-}
-
-bool is_type_named(Type *t) {
- if (t->kind == Type_Basic) {
- return true;
- }
- return t->kind == Type_Named;
-}
-bool is_type_boolean(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Boolean) != 0;
- }
- return false;
-}
-bool is_type_integer(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Integer) != 0;
- }
- return false;
-}
-bool is_type_unsigned(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Unsigned) != 0;
- }
- return false;
-}
-bool is_type_numeric(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Numeric) != 0;
- }
- if (t->kind == Type_Vector) {
- return is_type_numeric(t->Vector.elem);
- }
- return false;
-}
-bool is_type_string(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_String) != 0;
- }
- return false;
-}
-bool is_type_typed(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Untyped) == 0;
- }
- return true;
-}
-bool is_type_untyped(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Untyped) != 0;
- }
- return false;
-}
-bool is_type_ordered(Type *t) {
- t = base_type(get_enum_base_type(t));
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Ordered) != 0;
- }
- if (t->kind == Type_Pointer) {
- return true;
- }
- return false;
-}
-bool is_type_constant_type(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_ConstantType) != 0;
- }
- if (t->kind == Type_Record) {
- return t->Record.kind == TypeRecord_Enum;
- }
- return false;
-}
-bool is_type_float(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Float) != 0;
- }
- return false;
-}
-bool is_type_f32(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return t->Basic.kind == Basic_f32;
- }
- return false;
-}
-bool is_type_f64(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return t->Basic.kind == Basic_f64;
- }
- return false;
-}
-bool is_type_pointer(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Basic) {
- return (t->Basic.flags & BasicFlag_Pointer) != 0;
- }
- return t->kind == Type_Pointer;
-}
-bool is_type_maybe(Type *t) {
- t = base_type(t);
- return t->kind == Type_Maybe;
-}
-bool is_type_tuple(Type *t) {
- t = base_type(t);
- return t->kind == Type_Tuple;
-}
-
-
-bool is_type_int_or_uint(Type *t) {
- if (t->kind == Type_Basic) {
- return (t->Basic.kind == Basic_int) || (t->Basic.kind == Basic_uint);
- }
- return false;
-}
-bool is_type_rawptr(Type *t) {
- if (t->kind == Type_Basic) {
- return t->Basic.kind == Basic_rawptr;
- }
- return false;
-}
-bool is_type_u8(Type *t) {
- if (t->kind == Type_Basic) {
- return t->Basic.kind == Basic_u8;
- }
- return false;
-}
-bool is_type_array(Type *t) {
- t = base_type(t);
- return t->kind == Type_Array;
-}
-bool is_type_slice(Type *t) {
- t = base_type(t);
- return t->kind == Type_Slice;
-}
-bool is_type_u8_slice(Type *t) {
- t = base_type(t);
- if (t->kind == Type_Slice) {
- return is_type_u8(t->Slice.elem);
- }
- return false;
-}
-bool is_type_vector(Type *t) {
- t = base_type(t);
- return t->kind == Type_Vector;
-}
-bool is_type_proc(Type *t) {
- t = base_type(t);
- return t->kind == Type_Proc;
-}
-Type *base_vector_type(Type *t) {
- if (is_type_vector(t)) {
- t = base_type(t);
- return t->Vector.elem;
- }
- return t;
-}
-
-
-bool is_type_enum(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum);
-}
-bool is_type_struct(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct);
-}
-bool is_type_union(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Record && t->Record.kind == TypeRecord_Union);
-}
-bool is_type_raw_union(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Record && t->Record.kind == TypeRecord_RawUnion);
-}
-
-bool is_type_any(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
-}
-bool is_type_untyped_nil(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil);
-}
-
-
-
-bool is_type_indexable(Type *t) {
- return is_type_array(t) || is_type_slice(t) || is_type_vector(t) || is_type_string(t);
-}
-
-
-bool type_has_nil(Type *t) {
- t = base_type(t);
- switch (t->kind) {
- case Type_Basic:
- return is_type_rawptr(t);
-
- case Type_Tuple:
- return false;
-
- case Type_Record:
- switch (t->Record.kind) {
- case TypeRecord_Enum:
- return false;
- }
- break;
- }
- return true;
-}
-
-
-bool is_type_comparable(Type *t) {
- t = base_type(get_enum_base_type(t));
- switch (t->kind) {
- case Type_Basic:
- return t->kind != Basic_UntypedNil;
- case Type_Pointer:
- return true;
- case Type_Record: {
- if (false && is_type_struct(t)) {
- // TODO(bill): Should I even allow this?
- for (isize i = 0; i < t->Record.field_count; i++) {
- if (!is_type_comparable(t->Record.fields[i]->type))
- return false;
- }
- } else if (is_type_enum(t)) {
- return is_type_comparable(t->Record.enum_base);
- }
- return false;
- } break;
- case Type_Array:
- return is_type_comparable(t->Array.elem);
- case Type_Vector:
- return is_type_comparable(t->Vector.elem);
- case Type_Proc:
- return true;
- }
- return false;
-}
-
-bool are_types_identical(Type *x, Type *y) {
- if (x == y)
- return true;
-
- if ((x == NULL && y != NULL) ||
- (x != NULL && y == NULL)) {
- return false;
- }
-
- switch (x->kind) {
- case Type_Basic:
- if (y->kind == Type_Basic) {
- return x->Basic.kind == y->Basic.kind;
- }
- break;
-
- case Type_Array:
- if (y->kind == Type_Array) {
- return (x->Array.count == y->Array.count) && are_types_identical(x->Array.elem, y->Array.elem);
- }
- break;
-
- case Type_Vector:
- if (y->kind == Type_Vector) {
- return (x->Vector.count == y->Vector.count) && are_types_identical(x->Vector.elem, y->Vector.elem);
- }
- break;
-
- case Type_Slice:
- if (y->kind == Type_Slice) {
- return are_types_identical(x->Slice.elem, y->Slice.elem);
- }
- break;
-
- case Type_Record:
- if (y->kind == Type_Record) {
- if (x->Record.kind == y->Record.kind) {
- switch (x->Record.kind) {
- case TypeRecord_Struct:
- case TypeRecord_RawUnion:
- case TypeRecord_Union:
- if (x->Record.field_count == y->Record.field_count &&
- x->Record.struct_is_packed == y->Record.struct_is_packed &&
- x->Record.struct_is_ordered == y->Record.struct_is_ordered) {
- for (isize i = 0; i < x->Record.field_count; i++) {
- if (!are_types_identical(x->Record.fields[i]->type, y->Record.fields[i]->type)) {
- return false;
- }
- if (str_ne(x->Record.fields[i]->token.string, y->Record.fields[i]->token.string)) {
- return false;
- }
- }
- return true;
- }
- break;
-
- case TypeRecord_Enum:
- // NOTE(bill): Each enum is unique
- return x == y;
- }
- }
- }
- break;
-
- case Type_Pointer:
- if (y->kind == Type_Pointer) {
- return are_types_identical(x->Pointer.elem, y->Pointer.elem);
- }
- break;
-
- case Type_Maybe:
- if (y->kind == Type_Maybe) {
- return are_types_identical(x->Maybe.elem, y->Maybe.elem);
- }
- break;
-
- case Type_Named:
- if (y->kind == Type_Named) {
- return x->Named.base == y->Named.base;
- }
- break;
-
- case Type_Tuple:
- if (y->kind == Type_Tuple) {
- if (x->Tuple.variable_count == y->Tuple.variable_count) {
- for (isize i = 0; i < x->Tuple.variable_count; i++) {
- if (!are_types_identical(x->Tuple.variables[i]->type, y->Tuple.variables[i]->type)) {
- return false;
- }
- }
- return true;
- }
- }
- break;
-
- case Type_Proc:
- if (y->kind == Type_Proc) {
- return are_types_identical(x->Proc.params, y->Proc.params) &&
- are_types_identical(x->Proc.results, y->Proc.results);
- }
- break;
- }
-
-
- return false;
-}
-
-
-Type *default_type(Type *type) {
- if (type->kind == Type_Basic) {
- switch (type->Basic.kind) {
- case Basic_UntypedBool: return t_bool;
- case Basic_UntypedInteger: return t_int;
- case Basic_UntypedFloat: return t_f64;
- case Basic_UntypedString: return t_string;
- case Basic_UntypedRune: return t_rune;
- }
- }
- return type;
-}
-
-
-
-
-gb_global Entity *entity__any_type_info = NULL;
-gb_global Entity *entity__any_data = NULL;
-gb_global Entity *entity__string_data = NULL;
-gb_global Entity *entity__string_count = NULL;
-gb_global Entity *entity__slice_count = NULL;
-gb_global Entity *entity__slice_capacity = NULL;
-
-Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel);
-
-Selection lookup_field(gbAllocator a, Type *type_, String field_name, bool is_type) {
- return lookup_field_with_selection(a, type_, field_name, is_type, empty_selection);
-}
-
-Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
- GB_ASSERT(type_ != NULL);
-
- if (str_eq(field_name, str_lit("_"))) {
- return empty_selection;
- }
-
- Type *type = type_deref(type_);
- bool is_ptr = type != type_;
- sel.indirect = sel.indirect || is_ptr;
-
- type = base_type(type);
-
- if (type->kind == Type_Basic) {
- switch (type->Basic.kind) {
- case Basic_any: {
- String type_info_str = str_lit("type_info");
- String data_str = str_lit("data");
- if (entity__any_type_info == NULL) {
- entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 0);
- }
- if (entity__any_data == NULL) {
- entity__any_data = make_entity_field(a, NULL, make_token_ident(data_str), t_rawptr, false, 1);
- }
-
- if (str_eq(field_name, type_info_str)) {
- selection_add_index(&sel, 0);
- sel.entity = entity__any_type_info;
- return sel;
- } else if (str_eq(field_name, data_str)) {
- selection_add_index(&sel, 1);
- sel.entity = entity__any_data;
- return sel;
- }
- } break;
- case Basic_string: {
- String data_str = str_lit("data");
- String count_str = str_lit("count");
- if (entity__string_data == NULL) {
- entity__string_data = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, t_u8), false, 0);
- }
-
- if (entity__string_count == NULL) {
- entity__string_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
- }
-
- if (str_eq(field_name, data_str)) {
- selection_add_index(&sel, 0);
- sel.entity = entity__string_data;
- return sel;
- } else if (str_eq(field_name, count_str)) {
- selection_add_index(&sel, 1);
- sel.entity = entity__string_count;
- return sel;
- }
- } break;
- }
-
- return sel;
- } else if (type->kind == Type_Array) {
- String count_str = str_lit("count");
- // NOTE(bill): Underlying memory address cannot be changed
- if (str_eq(field_name, count_str)) {
- // HACK(bill): Memory leak
- sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Array.count));
- return sel;
- }
- } else if (type->kind == Type_Vector) {
- String count_str = str_lit("count");
- // NOTE(bill): Vectors are not addressable
- if (str_eq(field_name, count_str)) {
- // HACK(bill): Memory leak
- sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Vector.count));
- return sel;
- }
-
- if (type->Vector.count <= 4 && !is_type_boolean(type->Vector.elem)) {
- // HACK(bill): Memory leak
- switch (type->Vector.count) {
- #define _VECTOR_FIELD_CASE(_length, _name) \
- case (_length): \
- if (str_eq(field_name, str_lit(_name))) { \
- selection_add_index(&sel, (_length)-1); \
- sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
- return sel; \
- } \
- /*fallthrough*/
-
- _VECTOR_FIELD_CASE(4, "w");
- _VECTOR_FIELD_CASE(3, "z");
- _VECTOR_FIELD_CASE(2, "y");
- _VECTOR_FIELD_CASE(1, "x");
- default: break;
-
- #undef _VECTOR_FIELD_CASE
- }
- }
-
- } else if (type->kind == Type_Slice) {
- String data_str = str_lit("data");
- String count_str = str_lit("count");
- String capacity_str = str_lit("capacity");
-
- if (str_eq(field_name, data_str)) {
- selection_add_index(&sel, 0);
- // HACK(bill): Memory leak
- sel.entity = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, type->Slice.elem), false, 0);
- return sel;
- } else if (str_eq(field_name, count_str)) {
- selection_add_index(&sel, 1);
- if (entity__slice_count == NULL) {
- entity__slice_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
- }
-
- sel.entity = entity__slice_count;
- return sel;
- } else if (str_eq(field_name, capacity_str)) {
- selection_add_index(&sel, 2);
- if (entity__slice_capacity == NULL) {
- entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
- }
-
- sel.entity = entity__slice_capacity;
- return sel;
- }
- }
-
- if (type->kind != Type_Record) {
- return sel;
- }
- if (is_type) {
- if (is_type_union(type)) {
- // NOTE(bill): The subtype for a union are stored in the fields
- // as they are "kind of" like variables but not
- for (isize i = 0; i < type->Record.field_count; i++) {
- Entity *f = type->Record.fields[i];
- GB_ASSERT(f->kind == Entity_TypeName);
- String str = f->token.string;
-
- if (str_eq(field_name, str)) {
- sel.entity = f;
- selection_add_index(&sel, i);
- return sel;
- }
- }
- }
-
- for (isize i = 0; i < type->Record.other_field_count; i++) {
- Entity *f = type->Record.other_fields[i];
- GB_ASSERT(f->kind != Entity_Variable);
- String str = f->token.string;
-
- if (str_eq(field_name, str)) {
- sel.entity = f;
- selection_add_index(&sel, i);
- return sel;
- }
- }
-
- if (is_type_enum(type)) {
- if (str_eq(field_name, str_lit("count"))) {
- sel.entity = type->Record.enum_count;
- return sel;
- } else if (str_eq(field_name, str_lit("min_value"))) {
- sel.entity = type->Record.min_value;
- return sel;
- } else if (str_eq(field_name, str_lit("max_value"))) {
- sel.entity = type->Record.max_value;
- return sel;
- }
- }
-
- } else if (!is_type_enum(type) && !is_type_union(type)) {
- for (isize i = 0; i < type->Record.field_count; i++) {
- Entity *f = type->Record.fields[i];
- GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
- String str = f->token.string;
- if (str_eq(field_name, str)) {
- selection_add_index(&sel, i); // HACK(bill): Leaky memory
- sel.entity = f;
- return sel;
- }
-
- if (f->flags & EntityFlag_Anonymous) {
- isize prev_count = sel.index.count;
- selection_add_index(&sel, i); // HACK(bill): Leaky memory
-
- sel = lookup_field_with_selection(a, f->type, field_name, is_type, sel);
-
- if (sel.entity != NULL) {
- if (is_type_pointer(f->type)) {
- sel.indirect = true;
- }
- return sel;
- }
- sel.index.count = prev_count;
- }
- }
- }
-
- return sel;
-}
-
-
-
-i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
-i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
-i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
-
-i64 align_formula(i64 size, i64 align) {
- if (align > 0) {
- i64 result = size + align-1;
- return result - result%align;
- }
- return size;
-}
-
-i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
- t = base_type(t);
-
- switch (t->kind) {
- case Type_Array:
- return type_align_of(s, allocator, t->Array.elem);
- case Type_Vector: {
- i64 size = type_size_of(s, allocator, t->Vector.elem);
- i64 count = gb_max(prev_pow2(t->Vector.count), 1);
- i64 total = size * count;
- return gb_clamp(total, 1, s.max_align);
- } break;
-
- case Type_Tuple: {
- i64 max = 1;
- for (isize i = 0; i < t->Tuple.variable_count; i++) {
- i64 align = type_align_of(s, allocator, t->Tuple.variables[i]->type);
- if (max < align) {
- max = align;
- }
- }
- return max;
- } break;
-
- case Type_Maybe:
- return gb_max(type_align_of(s, allocator, t->Maybe.elem), type_align_of(s, allocator, t_bool));
-
- case Type_Record: {
- switch (t->Record.kind) {
- case TypeRecord_Struct:
- if (t->Record.field_count > 0) {
- // TODO(bill): What is this supposed to be?
- if (t->Record.struct_is_packed) {
- i64 max = s.word_size;
- for (isize i = 1; i < t->Record.field_count; i++) {
- // NOTE(bill): field zero is null
- i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
- if (max < align) {
- max = align;
- }
- }
- return max;
- }
- return type_align_of(s, allocator, t->Record.fields[0]->type);
- }
- break;
- case TypeRecord_Union: {
- i64 max = 1;
- for (isize i = 1; i < t->Record.field_count; i++) {
- // NOTE(bill): field zero is null
- i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
- if (max < align) {
- max = align;
- }
- }
- return max;
- } break;
- case TypeRecord_RawUnion: {
- i64 max = 1;
- for (isize i = 0; i < t->Record.field_count; i++) {
- i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
- if (max < align) {
- max = align;
- }
- }
- return max;
- } break;
- case TypeRecord_Enum:
- return type_align_of(s, allocator, t->Record.enum_base);
- }
- } break;
- }
-
- // return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
- // NOTE(bill): Things that are bigger than s.word_size, are actually comprised of smaller types
- // TODO(bill): Is this correct for 128-bit types (integers)?
- return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.word_size);
-}
-
-i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, bool is_packed) {
- i64 *offsets = gb_alloc_array(allocator, i64, field_count);
- i64 curr_offset = 0;
- if (is_packed) {
- for (isize i = 0; i < field_count; i++) {
- offsets[i] = curr_offset;
- curr_offset += type_size_of(s, allocator, fields[i]->type);
- }
-
- } else {
- for (isize i = 0; i < field_count; i++) {
- i64 align = type_align_of(s, allocator, fields[i]->type);
- curr_offset = align_formula(curr_offset, align);
- offsets[i] = curr_offset;
- curr_offset += type_size_of(s, allocator, fields[i]->type);
- }
- }
- return offsets;
-}
-
-bool type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
- t = base_type(t);
- if (is_type_struct(t)) {
- if (!t->Record.struct_are_offsets_set) {
- t->Record.struct_offsets = type_set_offsets_of(s, allocator, t->Record.fields, t->Record.field_count, t->Record.struct_is_packed);
- t->Record.struct_are_offsets_set = true;
- return true;
- }
- } else if (is_type_tuple(t)) {
- if (!t->Tuple.are_offsets_set) {
- t->Tuple.offsets = type_set_offsets_of(s, allocator, t->Tuple.variables, t->Tuple.variable_count, false);
- t->Tuple.are_offsets_set = true;
- return true;
- }
- } else {
- GB_PANIC("Invalid type for setting offsets");
- }
- return false;
-}
-
-i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
- t = base_type(t);
- switch (t->kind) {
- case Type_Basic: {
- GB_ASSERT(is_type_typed(t));
- BasicKind kind = t->Basic.kind;
- i64 size = t->Basic.size;
- if (size > 0) {
- return size;
- }
- switch (kind) {
- case Basic_string: return 2*s.word_size;
- case Basic_any: return 2*s.word_size;
-
- case Basic_int: case Basic_uint: case Basic_rawptr:
- return s.word_size;
- }
- } break;
-
- case Type_Array: {
- i64 count = t->Array.count;
- if (count == 0) {
- return 0;
- }
- i64 align = type_align_of(s, allocator, t->Array.elem);
- i64 size = type_size_of(s, allocator, t->Array.elem);
- i64 alignment = align_formula(size, align);
- return alignment*(count-1) + size;
- } break;
-
- case Type_Vector: {
- i64 count = t->Vector.count;
- if (count == 0) {
- return 0;
- }
- // i64 align = type_align_of(s, allocator, t->Vector.elem);
- i64 bit_size = 8*type_size_of(s, allocator, t->Vector.elem);
- if (is_type_boolean(t->Vector.elem)) {
- bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
- // Silly LLVM spec
- }
- i64 total_size_in_bits = bit_size * count;
- i64 total_size = (total_size_in_bits+7)/8;
- return total_size;
- } break;
-
-
- case Type_Slice: // ptr + len + cap
- return 3 * s.word_size;
-
- case Type_Maybe: { // value + bool
- Type *elem = t->Maybe.elem;
- i64 align = type_align_of(s, allocator, elem);
- i64 size = align_formula(type_size_of(s, allocator, elem), align);
- size += type_size_of(s, allocator, t_bool);
- return align_formula(size, align);
- }
-
- case Type_Tuple: {
- i64 count = t->Tuple.variable_count;
- if (count == 0) {
- return 0;
- }
- type_set_offsets(s, allocator, t);
- i64 size = t->Tuple.offsets[count-1] + type_size_of(s, allocator, t->Tuple.variables[count-1]->type);
- i64 align = type_align_of(s, allocator, t);
- return align_formula(size, align);
- } break;
-
- case Type_Record: {
- switch (t->Record.kind) {
- case TypeRecord_Struct: {
- i64 count = t->Record.field_count;
- if (count == 0) {
- return 0;
- }
- type_set_offsets(s, allocator, t);
- i64 size = t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type);
- i64 align = type_align_of(s, allocator, t);
- return align_formula(size, align);
- } break;
-
- case TypeRecord_Union: {
- i64 count = t->Record.field_count;
- i64 max = 0;
- // NOTE(bill): Zeroth field is invalid
- for (isize i = 1; i < count; i++) {
- i64 size = type_size_of(s, allocator, t->Record.fields[i]->type);
- if (max < size) {
- max = size;
- }
- }
- // NOTE(bill): Align to int
- i64 align = type_align_of(s, allocator, t);
- isize size = align_formula(max, s.word_size);
- size += type_size_of(s, allocator, t_int);
- return align_formula(size, align);
- } break;
-
- case TypeRecord_RawUnion: {
- i64 count = t->Record.field_count;
- i64 max = 0;
- for (isize i = 0; i < count; i++) {
- i64 size = type_size_of(s, allocator, t->Record.fields[i]->type);
- if (max < size) {
- max = size;
- }
- }
- // TODO(bill): Is this how it should work?
- i64 align = type_align_of(s, allocator, t);
- return align_formula(max, align);
- } break;
-
- case TypeRecord_Enum: {
- return type_size_of(s, allocator, t->Record.enum_base);
- } break;
- }
- } break;
- }
-
- // Catch all
- return s.word_size;
-}
-
-i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index) {
- t = base_type(t);
- if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {
- type_set_offsets(s, allocator, t);
- if (gb_is_between(index, 0, t->Record.field_count-1)) {
- return t->Record.struct_offsets[index];
- }
- } else if (t->kind == Type_Tuple) {
- type_set_offsets(s, allocator, t);
- if (gb_is_between(index, 0, t->Tuple.variable_count-1)) {
- return t->Tuple.offsets[index];
- }
- } else if (t->kind == Type_Basic) {
- if (t->Basic.kind == Basic_string) {
- switch (index) {
- case 0: return 0;
- case 1: return s.word_size;
- }
- } else if (t->Basic.kind == Basic_any) {
- switch (index) {
- case 0: return 0;
- case 1: return s.word_size;
- }
- }
- } else if (t->kind == Type_Slice) {
- switch (index) {
- case 0: return 0;
- case 1: return 1*s.word_size;
- case 2: return 2*s.word_size;
- }
- }
- return 0;
-}
-
-
-i64 type_offset_of_from_selection(BaseTypeSizes s, gbAllocator allocator, Type *type, Selection sel) {
- GB_ASSERT(sel.indirect == false);
-
- Type *t = type;
- i64 offset = 0;
- for_array(i, sel.index) {
- isize index = sel.index.e[i];
- t = base_type(t);
- offset += type_offset_of(s, allocator, t, index);
- if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {
- t = t->Record.fields[index]->type;
- } else {
- // NOTE(bill): string/any/slices don't have record fields so this case doesn't need to be handled
- }
- }
- return offset;
-}
-
-
-
-gbString write_type_to_string(gbString str, Type *type) {
- if (type == NULL) {
- return gb_string_appendc(str, "<no type>");
- }
-
- switch (type->kind) {
- case Type_Basic:
- str = gb_string_append_length(str, type->Basic.name.text, type->Basic.name.len);
- break;
-
- case Type_Pointer:
- str = gb_string_appendc(str, "^");
- str = write_type_to_string(str, type->Pointer.elem);
- break;
-
- case Type_Maybe:
- str = gb_string_appendc(str, "?");
- str = write_type_to_string(str, type->Maybe.elem);
- break;
-
- case Type_Array:
- str = gb_string_appendc(str, gb_bprintf("[%td]", type->Array.count));
- str = write_type_to_string(str, type->Array.elem);
- break;
-
- case Type_Vector:
- str = gb_string_appendc(str, gb_bprintf("{%td}", type->Vector.count));
- str = write_type_to_string(str, type->Vector.elem);
- break;
-
- case Type_Slice:
- str = gb_string_appendc(str, "[]");
- str = write_type_to_string(str, type->Array.elem);
- break;
-
- case Type_Record: {
- switch (type->Record.kind) {
- case TypeRecord_Struct:
- str = gb_string_appendc(str, "struct");
- if (type->Record.struct_is_packed) {
- str = gb_string_appendc(str, " #packed");
- }
- if (type->Record.struct_is_ordered) {
- str = gb_string_appendc(str, " #ordered");
- }
- str = gb_string_appendc(str, " {");
- for (isize i = 0; i < type->Record.field_count; i++) {
- Entity *f = type->Record.fields[i];
- GB_ASSERT(f->kind == Entity_Variable);
- if (i > 0)
- str = gb_string_appendc(str, "; ");
- str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
- str = gb_string_appendc(str, ": ");
- str = write_type_to_string(str, f->type);
- }
- str = gb_string_appendc(str, "}");
- break;
-
- case TypeRecord_Union:
- str = gb_string_appendc(str, "union{");
- for (isize i = 1; i < type->Record.field_count; i++) {
- Entity *f = type->Record.fields[i];
- GB_ASSERT(f->kind == Entity_TypeName);
- if (i > 1) {
- str = gb_string_appendc(str, "; ");
- }
- str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
- str = gb_string_appendc(str, ": ");
- str = write_type_to_string(str, base_type(f->type));
- }
- str = gb_string_appendc(str, "}");
- break;
-
- case TypeRecord_RawUnion:
- str = gb_string_appendc(str, "raw_union{");
- for (isize i = 0; i < type->Record.field_count; i++) {
- Entity *f = type->Record.fields[i];
- GB_ASSERT(f->kind == Entity_Variable);
- if (i > 0) {
- str = gb_string_appendc(str, ", ");
- }
- str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
- str = gb_string_appendc(str, ": ");
- str = write_type_to_string(str, f->type);
- }
- str = gb_string_appendc(str, "}");
- break;
-
- case TypeRecord_Enum:
- str = gb_string_appendc(str, "enum ");
- str = write_type_to_string(str, type->Record.enum_base);
- break;
- }
- } break;
-
-
- case Type_Named:
- if (type->Named.type_name != NULL) {
- str = gb_string_append_length(str, type->Named.name.text, type->Named.name.len);
- } else {
- // NOTE(bill): Just in case
- str = gb_string_appendc(str, "<named type>");
- }
- break;
-
- case Type_Tuple:
- if (type->Tuple.variable_count > 0) {
- for (isize i = 0; i < type->Tuple.variable_count; i++) {
- Entity *var = type->Tuple.variables[i];
- if (var != NULL) {
- GB_ASSERT(var->kind == Entity_Variable);
- if (i > 0)
- str = gb_string_appendc(str, ", ");
- str = write_type_to_string(str, var->type);
- }
- }
- }
- break;
-
- case Type_Proc:
- str = gb_string_appendc(str, "proc(");
- if (type->Proc.params)
- str = write_type_to_string(str, type->Proc.params);
- str = gb_string_appendc(str, ")");
- if (type->Proc.results) {
- str = gb_string_appendc(str, " -> ");
- str = write_type_to_string(str, type->Proc.results);
- }
- break;
- }
-
- return str;
-}
-
-
-gbString type_to_string(Type *type) {
- gbString str = gb_string_make(gb_heap_allocator(), "");
- return write_type_to_string(str, type);
-}
-
-