ソースを参照

Handle enums correctly with printf

Ginger Bill 8 年 前
コミット
c29d433e38
3 ファイル変更112 行追加59 行削除
  1. 5 26
      code/demo.odin
  2. 106 19
      core/fmt.odin
  3. 1 14
      src/ir.c

+ 5 - 26
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);
 }

+ 106 - 19
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);

+ 1 - 14
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: {