diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-02-21 21:21:54 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-02-21 21:21:54 +0000 |
| commit | 047c0e4bcc415a1f0e7b55afd57900319e43dbef (patch) | |
| tree | 7aa26b8a59cb8634cc309a299a8076aa708967ea /core | |
| parent | a94dfdf21d798bc72bbee0cc04b80149f0d4b8d2 (diff) | |
A decent union type with common fields and variants
Diffstat (limited to 'core')
| -rw-r--r-- | core/_preload.odin | 97 | ||||
| -rw-r--r-- | core/fmt.odin | 50 |
2 files changed, 69 insertions, 78 deletions
diff --git a/core/_preload.odin b/core/_preload.odin index c61049290..c1014fa95 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -14,22 +14,11 @@ // IMPORTANT NOTE(bill): Do not change the order of any of this data // The compiler relies upon this _exact_ order -Type_Info_Record :: struct #ordered { - types: []^Type_Info, - names: []string, - offsets: []int, // offsets may not be used in tuples - size: int, // in bytes - align: int, // in bytes - packed: bool, - ordered: bool, - custom_align: bool, -} Type_Info_Enum_Value :: raw_union { f: f64, i: i64, } - -// NOTE(bill): This much the same as the compiler's +// NOTE(bill): This must match the compiler's Calling_Convention :: enum { ODIN = 0, C = 1, @@ -37,67 +26,17 @@ Calling_Convention :: enum { FAST = 3, } -/* -Type_Info :: union { - Named: struct #ordered { - name: string, - base: ^Type_Info, // This will _not_ be a Type_Info.Named - }, - Integer: struct #ordered { - size: int, // in bytes - signed: bool, - }, - Float: struct #ordered { - size: int, // in bytes - }, - String: struct #ordered {}, - Boolean: struct #ordered {}, - Any: struct #ordered {}, - Pointer: struct #ordered { - elem: ^Type_Info, // nil -> rawptr - }, - Procedure: struct #ordered { - params: ^Type_Info, // Type_Info.Tuple - results: ^Type_Info, // Type_Info.Tuple - variadic: bool, - convention: Calling_Convention, - }, - Array: struct #ordered { - elem: ^Type_Info, - elem_size: int, - count: int, - }, - Dynamic_Array: struct #ordered { - elem: ^Type_Info, - elem_size: int, - }, - Slice: struct #ordered { - elem: ^Type_Info, - elem_size: int, - }, - Vector: struct #ordered { - elem: ^Type_Info, - elem_size: int, - count: int, - align: int, - }, - Tuple: Type_Info_Record, // Only really used for procedures - Struct: Type_Info_Record, - Union: Type_Info_Record, - Raw_Union: Type_Info_Record, - Enum: struct #ordered { - base: ^Type_Info, - names: []string, - values: []Type_Info_Enum_Value, - }, - Map: struct #ordered { - key: ^Type_Info, - value: ^Type_Info, - generated_struct: ^Type_Info, - count: int, // == 0 if dynamic - }, +Type_Info_Record :: struct #ordered { + types: []^Type_Info, + names: []string, + offsets: []int, // offsets may not be used in tuples + size: int, // in bytes + align: int, // in bytes + packed: bool, + ordered: bool, + custom_align: bool, } -*/ + Type_Info :: union { Named{name: string, base: ^Type_Info}, Integer{size: int, signed: bool}, @@ -124,8 +63,18 @@ Type_Info :: union { Vector {elem: ^Type_Info, elem_size, count, align: int}, Tuple {using record: Type_Info_Record}, // Only really used for procedures Struct {using record: Type_Info_Record}, - Union {using record: Type_Info_Record}, Raw_Union {using record: Type_Info_Record}, + Union{ + common_fields: struct { + types: []^Type_Info, + names: []string, + offsets: []int, // offsets may not be used in tuples + }, + variant_names: []string, + variant_types: []^Type_Info, + size: int, + align: int, + }, Enum{ base: ^Type_Info, names: []string, @@ -142,7 +91,7 @@ Type_Info :: union { // // NOTE(bill): only the ones that are needed (not all types) // // This will be set by the compiler -// immutable __type_infos: []Type_Info; +__type_infos: []Type_Info; type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { diff --git a/core/fmt.odin b/core/fmt.odin index d340bbe5d..54fbfa7f3 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -215,11 +215,36 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case Union: buffer_write_string(buf, "union {"); - for name, i in info.names { + cf := info.common_fields; + total_count := 0; + for name, i in cf.names { + if i > 0 { + buffer_write_string(buf, ", "); + } buffer_write_string(buf, name); buffer_write_string(buf, ": "); - buffer_write_type(buf, info.types[i]); - buffer_write_byte(buf, ','); + buffer_write_type(buf, cf.types[i]); + total_count += 1; + } + for name, i in info.variant_names { + if i > 0 || total_count > 0 { + buffer_write_string(buf, ", "); + } + buffer_write_string(buf, name); + buffer_write_byte(buf, '{'); + defer buffer_write_byte(buf, '}'); + + variant_type := type_info_base(info.variant_types[i]); + variant := union_cast(^Struct)variant_type; + + for j in cf.names.count..<variant.names.count { + if j > 0 { + buffer_write_byte(buf, ','); + } + buffer_write_string(buf, variant.names[j]); + buffer_write_string(buf, ": "); + buffer_write_type(buf, variant.types[j]); + } } buffer_write_string(buf, "}"); @@ -687,6 +712,9 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { break; } } + } else if e.values.count == 0 { + buffer_write_string(fi.buf, ""); + ok = true; } else { for it, idx in e.values { if it.f == f { @@ -864,7 +892,21 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { } case Union: - buffer_write_string(fi.buf, "(union)"); + buffer_write_byte(fi.buf, '{'); + defer buffer_write_byte(fi.buf, '}'); + + cf := info.common_fields; + + for _, i in cf.names { + if i > 0 { + buffer_write_string(fi.buf, ", "); + } + buffer_write_string(fi.buf, cf.names[i]); + buffer_write_string(fi.buf, " = "); + data := cast(^byte)v.data + cf.offsets[i]; + fmt_value(fi, any{cf.types[i], cast(rawptr)data}, 'v'); + } + case Raw_Union: buffer_write_string(fi.buf, "(raw_union)"); |