Handle enums correctly with printf

This commit is contained in:
Ginger Bill
2017-01-08 23:19:50 +00:00
parent ff473e8342
commit c29d433e38
3 changed files with 112 additions and 59 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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: {