From 31c11a50370ded9865cf8c1da6baabaa97d38a18 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Tue, 20 Sep 2016 09:33:29 +0100 Subject: [PATCH] Sort enum entities; Remove sprint* from fmt.odin --- code/demo.odin | 27 ++++++++++- core/fmt.odin | 108 ++++++++++++++++--------------------------- core/runtime.odin | 13 ++---- src/checker/expr.cpp | 21 +++++++++ 4 files changed, 90 insertions(+), 79 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index e98e0d5a1..d527e8c97 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,8 +1,31 @@ -// #import "fmt.odin" as fmt -// #import "os.odin" as os +#import "fmt.odin" as fmt +#import "os.odin" as os main :: proc() { + Fruit :: enum { + APPLE, + BANANA, + GRAPE, + MELON, + PEACH, + TOMATO, + } + fruit_ti := type_info(Fruit) + name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts + info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts + + fmt.printf("% :: enum ", name); + fmt.fprint_type(os.stdout, info.base) + fmt.printf(" {\n") + for i := 0; i < info.values.count; i++ { + fmt.printf("\t%\t= %,\n", info.names[i], info.values[i]) + } + fmt.printf("}\n") + + Vector3 :: struct {x, y, z: f32} + v := Vector3{x = 1, y = 4, z = 9} + fmt.println(v) } diff --git a/core/fmt.odin b/core/fmt.odin index 1864b0e5c..5c4345d98 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -2,30 +2,6 @@ PRINT_BUF_SIZE :: 1<<12 -bprint :: proc(buf: ^[]byte, args: ..any) { - prev_string := false - - for i := 0; i < args.count; i++ { - arg := args[i] - is_string := arg.data != null && type_info_is_string(arg.type_info) - if i > 0 && !is_string && !prev_string { - print_space_to_buffer(buf) - } - print_any_to_buffer(buf, arg) - prev_string = is_string; - } -} - -bprintln :: proc(buf: ^[]byte, args: ..any) { - for i := 0; i < args.count; i++ { - if i > 0 { - append(buf, #rune " ") - } - print_any_to_buffer(buf, args[i]) - } - print_nl_to_buffer(buf) -} - fprint :: proc(f: ^os.File, args: ..any) { data: [PRINT_BUF_SIZE]byte buf := data[:0] @@ -57,31 +33,6 @@ printf :: proc(fmt: string, args: ..any) { fprintf(os.stdout, fmt, ..args) } -sprint :: proc(args: ..any) -> string { - data: [PRINT_BUF_SIZE]byte - buf := data[:0] - bprint(^buf, ..args) - s := new_slice(byte, buf.count) - copy(s, buf) - return s as string -} -sprintln :: proc(args: ..any) -> string { - data: [PRINT_BUF_SIZE]byte - buf := data[:0] - bprintln(^buf, ..args) - s := new_slice(byte, buf.count) - copy(s, buf) - return s as string -} -sprintf :: proc(fmt: string, args: ..any) -> string { - data: [PRINT_BUF_SIZE]byte - buf := data[:0] - bprintf(^buf, fmt, ..args) - s := new_slice(byte, buf.count) - copy(s, buf) - return s as string -} - fprint_type :: proc(f: ^os.File, info: ^Type_Info) { @@ -578,26 +529,6 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { } } -type_info_is_string :: proc(info: ^Type_Info) -> bool { - using Type_Info - if info == null { - return false - } - - for { - match type i : info { - case Named: - info = i.base - continue - case String: - return true - default: - return false - } - } - return false -} - bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) { is_digit :: proc(r: rune) -> bool #inline { @@ -661,3 +592,42 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) { print_string_to_buffer(buf, fmt[prev:]) } + + +bprint :: proc(buf: ^[]byte, args: ..any) { + is_type_string :: proc(info: ^Type_Info) -> bool { + using Type_Info + info = type_info_base(info) + if info == null { + return false + } + + match type i : info { + case String: + return true + } + return false + } + + + prev_string := false + for i := 0; i < args.count; i++ { + arg := args[i] + is_string := arg.data != null && is_type_string(arg.type_info) + if i > 0 && !is_string && !prev_string { + print_space_to_buffer(buf) + } + print_any_to_buffer(buf, arg) + prev_string = is_string; + } +} + +bprintln :: proc(buf: ^[]byte, args: ..any) { + for i := 0; i < args.count; i++ { + if i > 0 { + append(buf, #rune " ") + } + print_any_to_buffer(buf, args[i]) + } + print_nl_to_buffer(buf) +} diff --git a/core/runtime.odin b/core/runtime.odin index 52c3f68a0..814458b1a 100644 --- a/core/runtime.odin +++ b/core/runtime.odin @@ -64,6 +64,9 @@ Type_Info :: union { } type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { + if info == null { + return null + } for { match type i : info { case Type_Info.Named: @@ -355,17 +358,11 @@ __default_allocator :: proc() -> Allocator { __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string { - for { - match type i : info { - case Type_Info.Named: - info = i.base - continue - } - break - } + info = type_info_base(info) match type ti : info { case Type_Info.Enum: + // TODO(bill): Search faster than linearly for i := 0; i < ti.values.count; i++ { if ti.values[i] == value { return ti.names[i] diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index bea09e678..75c0f71f4 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -541,6 +541,25 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec union_type->Record.other_field_count = other_field_count; } +GB_COMPARE_PROC(cmp_enum_order) { + // Rule: + // Biggest to smallest alignment + // if same alignment: biggest to smallest size + // if same size: order by source order + Entity *x = *(Entity **)a; + Entity *y = *(Entity **)b; + GB_ASSERT(x != NULL); + GB_ASSERT(y != NULL); + GB_ASSERT(x->kind == Entity_Constant); + GB_ASSERT(y->kind == Entity_Constant); + GB_ASSERT(x->Constant.value.kind == ExactValue_Integer); + GB_ASSERT(y->Constant.value.kind == ExactValue_Integer); + i64 i = x->Constant.value.value_integer; + i64 j = y->Constant.value.value_integer; + + return i < j ? -1 : i > j; +} + void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) { @@ -640,6 +659,8 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod add_entity_use(&c->info, f->field, e); } + gb_sort_array(fields, gb_array_count(et->fields), cmp_enum_order); + enum_type->Record.other_fields = fields; enum_type->Record.other_field_count = gb_array_count(et->fields);