aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-08 23:19:50 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-08 23:19:50 +0000
commitc29d433e381a4505045fccc02f2d00fafcc7f32f (patch)
tree353a037477a3791bb40fe0662eef6928f025c3b7
parentff473e83425c74bae2cee4c9d68435c7b346533e (diff)
Handle enums correctly with printf
-rw-r--r--code/demo.odin31
-rw-r--r--core/fmt.odin125
-rw-r--r--src/ir.c15
3 files changed, 112 insertions, 59 deletions
diff --git a/code/demo.odin b/code/demo.odin
index 285abe14d..a237d0545 100644
--- a/code/demo.odin
+++ b/code/demo.odin
@@ -1,31 +1,10 @@
#import "fmt.odin";
main :: proc() {
- using Type_Info;
- is_type_integer :: proc(info: ^Type_Info) -> bool {
- if info == nil {
- return false;
- }
-
- match type i : type_info_base(info) {
- case Integer:
- return true;
- }
- return false;
- }
-
- ti := type_info_base(type_info(Allocator_Mode));
- match type e : ti {
- case Enum:
- is_int := is_type_integer(e.base);
- for i : 0..<e.names.count {
- name := e.names[i];
- value := e.values[i];
- if is_int {
- fmt.printf("%s - %d\n", name, value.i);
- } else {
- fmt.printf("%s - %f\n", name, value.f);
- }
- }
+ Fruit :: enum f32 {
+ Apple = 123,
+ Pear = 321,
+ Tomato,
}
+ fmt.printf("%s = %f\n", Fruit.Apple, Fruit.Apple);
}
diff --git a/core/fmt.odin b/core/fmt.odin
index b5452e531..ed81a340f 100644
--- a/core/fmt.odin
+++ b/core/fmt.odin
@@ -227,19 +227,6 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
bprint :: proc(buf: ^Buffer, args: ...any) -> int {
- is_type_string :: proc(info: ^Type_Info) -> bool {
- using Type_Info;
- if info == nil {
- return false;
- }
-
- match type i : type_info_base(info) {
- case String:
- return true;
- }
- return false;
- }
-
fi: Fmt_Info;
fi.buf = buf;
@@ -270,6 +257,42 @@ bprintln :: proc(buf: ^Buffer, args: ...any) -> int {
}
+is_type_string :: proc(info: ^Type_Info) -> bool {
+ using Type_Info;
+ if info == nil {
+ return false;
+ }
+
+ match type i : type_info_base(info) {
+ case String:
+ return true;
+ }
+ return false;
+}
+is_type_integer :: proc(info: ^Type_Info) -> bool {
+ using Type_Info;
+ if info == nil {
+ return false;
+ }
+
+ match type i : type_info_base(info) {
+ case Integer:
+ return true;
+ }
+ return false;
+}
+is_type_float :: proc(info: ^Type_Info) -> bool {
+ using Type_Info;
+ if info == nil {
+ return false;
+ }
+
+ match type i : type_info_base(info) {
+ case Float:
+ return true;
+ }
+ return false;
+}
@@ -356,6 +379,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
+ assert(verb != 'v');
buffer_write_string(buf, "%!");
buffer_write_rune(buf, verb);
buffer_write_byte(buf, '(');
@@ -527,9 +551,8 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, signed: bool, verb: rune) {
fmt_float :: proc(fi: ^Fmt_Info, v: f64, bits: int, verb: rune) {
// TODO(bill): Actually print a float correctly
// THIS IS FUCKING SHIT!
-
match verb {
- case 'e', 'E', 'f', 'F', 'g', 'G':
+ case 'e', 'E', 'f', 'F', 'g', 'G', 'v':
break;
default:
fmt_bad_verb(fi, verb);
@@ -553,8 +576,9 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bits: int, verb: rune) {
buffer_write_byte(fi.buf, '.');
decimal_places := 5;
- if bits == 64 {
- decimal_places = 9;
+ match bits {
+ case 32: decimal_places = 7;
+ case 64: decimal_places = 15;
}
if fi.prec_set {
decimal_places = fi.prec;
@@ -570,7 +594,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bits: int, verb: rune) {
}
fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
match verb {
- case 'v', 's':
+ case 's', 'v':
buffer_write_string(fi.buf, s);
default:
fmt_bad_verb(fi, verb);
@@ -591,6 +615,69 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
fmt_integer(fi, u, 16, false, __DIGITS_UPPER);
}
+fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
+ if v.type_info == nil || v.data == nil {
+ buffer_write_string(fi.buf, "<nil>");
+ return;
+ }
+
+ using Type_Info;
+ match type e : v.type_info {
+ default:
+ fmt_bad_verb(fi, verb);
+ return;
+ case Enum:
+ match verb {
+ case 'd', 'f':
+ fmt_arg(fi, any{type_info_base(e.base), v.data}, verb);
+ case 's', 'v':
+ i: i64;
+ f: f64;
+ ok := false;
+ a := any{type_info_base(e.base), v.data};
+ match type v : a {
+ case i8: i = v as i64;
+ case i16: i = v as i64;
+ case i32: i = v as i64;
+ case i64: i = v as i64;
+ case int: i = v as i64;
+ case u8: i = v as i64;
+ case u16: i = v as i64;
+ case u32: i = v as i64;
+ case u64: i = v as i64;
+ case uint: i = v as i64;
+ case f32: f = v as f64;
+ case f64: f = v as f64;
+ }
+
+ if is_type_integer(e.base) {
+ for val, idx : e.values {
+ if val.i == i {
+ buffer_write_string(fi.buf, e.names[idx]);
+ ok = true;
+ break;
+ }
+ }
+ } else {
+ for val, idx : e.values {
+ if val.f == f {
+ buffer_write_string(fi.buf, e.names[idx]);
+ ok = true;
+ break;
+ }
+ }
+ }
+
+ if !ok {
+ buffer_write_string(fi.buf, "!%(BAD ENUM VALUE)");
+ }
+ default:
+ fmt_bad_verb(fi, verb);
+ return;
+ }
+ }
+}
+
fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if v.data == nil || v.type_info == nil {
@@ -728,7 +815,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
buffer_write_string(fi.buf, "(raw_union)");
case Enum:
- fmt_arg(fi, any{info.base, v.data}, verb);
+ fmt_enum(fi, v, verb);
case Procedure:
buffer_write_type(fi.buf, v.type_info);
diff --git a/src/ir.c b/src/ir.c
index 69d8d989c..3b99c6bde 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -1616,7 +1616,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
switch (index) {
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break;
case 1: result_type = make_type_pointer(a, t_int); break;
- case 2: result_type = make_type_pointer(a, t_int); break;
}
} else if (is_type_string(t)) {
switch (index) {
@@ -1786,9 +1785,6 @@ irValue *ir_array_len(irProcedure *proc, irValue *array) {
GB_ASSERT(t->kind == Type_Array);
return ir_make_const_int(proc->module->allocator, t->Array.count);
}
-irValue *ir_array_cap(irProcedure *proc, irValue *array) {
- return ir_array_len(proc, array);
-}
irValue *ir_slice_elem(irProcedure *proc, irValue *slice) {
Type *t = ir_type(slice);
@@ -2855,7 +2851,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
case BuiltinProc_new_slice: {
ir_emit_comment(proc, str_lit("new_slice"));
- // new_slice :: proc(Type, len: int[, cap: int]) -> ^Type
+ // new_slice :: proc(Type, len: int) -> ^Type
gbAllocator allocator = proc->module->allocator;
Type *type = type_of_expr(proc->module->info, ce->args.e[0]);
@@ -3226,7 +3222,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
ir_emit_store(proc, slice_elem, base_elem);
irValue *len = ir_make_const_int(allocator, slice_len);
ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 2), len);
}
arg_count = type->param_count;
@@ -5664,11 +5659,9 @@ void ir_gen_tree(irGen *s) {
irValue *elem = ir_emit_struct_ep(proc, slice, 0);
irValue *len = ir_emit_struct_ep(proc, slice, 1);
- irValue *cap = ir_emit_struct_ep(proc, slice, 2);
ir_emit_store(proc, elem, memory);
ir_emit_store(proc, len, field_count);
- ir_emit_store(proc, cap, field_count);
} break;
case TypeRecord_Union:
tag = ir_emit_conv(proc, ti_ptr, t_type_info_union_ptr);
@@ -5713,11 +5706,9 @@ void ir_gen_tree(irGen *s) {
irValue *elem = ir_emit_struct_ep(proc, slice, 0);
irValue *len = ir_emit_struct_ep(proc, slice, 1);
- irValue *cap = ir_emit_struct_ep(proc, slice, 2);
ir_emit_store(proc, elem, memory);
ir_emit_store(proc, len, field_count);
- ir_emit_store(proc, cap, field_count);
} break;
case TypeRecord_Enum:
tag = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr);
@@ -5791,14 +5782,12 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 0), name_array_elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 1), v_count);
- ir_emit_store(proc, ir_emit_struct_ep(proc, names, 2), v_count);
irValue *values = ir_emit_struct_ep(proc, tag, 2);
irValue *value_array_elem = ir_array_elem(proc, value_array);
ir_emit_store(proc, ir_emit_struct_ep(proc, values, 0), value_array_elem);
ir_emit_store(proc, ir_emit_struct_ep(proc, values, 1), v_count);
- ir_emit_store(proc, ir_emit_struct_ep(proc, values, 2), v_count);
}
}
break;
@@ -5837,11 +5826,9 @@ void ir_gen_tree(irGen *s) {
irValue *elem = ir_emit_struct_ep(proc, slice, 0);
irValue *len = ir_emit_struct_ep(proc, slice, 1);
- irValue *cap = ir_emit_struct_ep(proc, slice, 2);
ir_emit_store(proc, elem, memory);
ir_emit_store(proc, len, variable_count);
- ir_emit_store(proc, cap, variable_count);
} break;
case Type_Proc: {