aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-21 21:21:54 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-21 21:21:54 +0000
commit047c0e4bcc415a1f0e7b55afd57900319e43dbef (patch)
tree7aa26b8a59cb8634cc309a299a8076aa708967ea /core
parenta94dfdf21d798bc72bbee0cc04b80149f0d4b8d2 (diff)
A decent union type with common fields and variants
Diffstat (limited to 'core')
-rw-r--r--core/_preload.odin97
-rw-r--r--core/fmt.odin50
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)");