From c29d433e381a4505045fccc02f2d00fafcc7f32f Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 8 Jan 2017 23:19:50 +0000 Subject: [PATCH] Handle enums correctly with printf --- code/demo.odin | 31 ++---------- core/fmt.odin | 125 +++++++++++++++++++++++++++++++++++++++++-------- src/ir.c | 15 +----- 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.. 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, ""); + 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: {