Browse Source

Begin work on `%w` - 'w'rite as valid Odin literals

gingerBill 1 year ago
parent
commit
573402c97e
1 changed files with 217 additions and 170 deletions
  1. 217 170
      core/fmt/fmt.odin

+ 217 - 170
core/fmt/fmt.odin

@@ -972,7 +972,7 @@ fmt_bad_verb :: proc(fi: ^Info, verb: rune) {
 //
 //
 fmt_bool :: proc(fi: ^Info, b: bool, verb: rune) {
 fmt_bool :: proc(fi: ^Info, b: bool, verb: rune) {
 	switch verb {
 	switch verb {
-	case 't', 'v':
+	case 't', 'v', 'w':
 		fmt_string(fi, b ? "true" : "false", 's')
 		fmt_string(fi, b ? "true" : "false", 's')
 	case:
 	case:
 		fmt_bad_verb(fi, verb)
 		fmt_bad_verb(fi, verb)
@@ -1209,7 +1209,7 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) {
 	switch verb {
 	switch verb {
 	case 'c', 'r', 'v':
 	case 'c', 'r', 'v':
 		io.write_rune(fi.writer, r, &fi.n)
 		io.write_rune(fi.writer, r, &fi.n)
-	case 'q':
+	case 'q', 'w':
 		fi.n += io.write_quoted_rune(fi.writer, r)
 		fi.n += io.write_quoted_rune(fi.writer, r)
 	case:
 	case:
 		fmt_int(fi, u64(r), false, 32, verb)
 		fmt_int(fi, u64(r), false, 32, verb)
@@ -1226,7 +1226,8 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) {
 //
 //
 fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
 fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
 	switch verb {
 	switch verb {
-	case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
+	case 'v', 'w':
+		_fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
 	case 'b': _fmt_int(fi, u,  2, is_signed, bit_size, __DIGITS_LOWER)
 	case 'b': _fmt_int(fi, u,  2, is_signed, bit_size, __DIGITS_LOWER)
 	case 'o': _fmt_int(fi, u,  8, is_signed, bit_size, __DIGITS_LOWER)
 	case 'o': _fmt_int(fi, u,  8, is_signed, bit_size, __DIGITS_LOWER)
 	case 'i', 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
 	case 'i', 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
@@ -1261,7 +1262,8 @@ fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
 //
 //
 fmt_int_128 :: proc(fi: ^Info, u: u128, is_signed: bool, bit_size: int, verb: rune) {
 fmt_int_128 :: proc(fi: ^Info, u: u128, is_signed: bool, bit_size: int, verb: rune) {
 	switch verb {
 	switch verb {
-	case 'v': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
+	case 'v', 'w':
+		_fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
 	case 'b': _fmt_int_128(fi, u,  2, is_signed, bit_size, __DIGITS_LOWER)
 	case 'b': _fmt_int_128(fi, u,  2, is_signed, bit_size, __DIGITS_LOWER)
 	case 'o': _fmt_int_128(fi, u,  8, is_signed, bit_size, __DIGITS_LOWER)
 	case 'o': _fmt_int_128(fi, u,  8, is_signed, bit_size, __DIGITS_LOWER)
 	case 'i', 'd': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
 	case 'i', 'd': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER)
@@ -1351,7 +1353,7 @@ _fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: b
 //
 //
 fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) {
 fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) {
 	switch verb {
 	switch verb {
-	case 'g', 'G', 'v':
+	case 'g', 'G', 'v', 'w':
 		_fmt_float_as(fi, v, bit_size, verb, 'g', -1)
 		_fmt_float_as(fi, v, bit_size, verb, 'g', -1)
 	case 'f', 'F':
 	case 'f', 'F':
 		_fmt_float_as(fi, v, bit_size, verb, 'f', 3)
 		_fmt_float_as(fi, v, bit_size, verb, 'f', 3)
@@ -1424,7 +1426,7 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
 			io.write_string(fi.writer, s, &fi.n)
 			io.write_string(fi.writer, s, &fi.n)
 		}
 		}
 
 
-	case 'q': // quoted string
+	case 'q', 'w': // quoted string
 		io.write_quoted_string(fi.writer, s, '"', &fi.n)
 		io.write_quoted_string(fi.writer, s, '"', &fi.n)
 
 
 	case 'x', 'X':
 	case 'x', 'X':
@@ -1467,7 +1469,7 @@ fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) {
 fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) {
 fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) {
 	u := u64(uintptr(p))
 	u := u64(uintptr(p))
 	switch verb {
 	switch verb {
-	case 'p', 'v':
+	case 'p', 'v', 'w':
 		if !fi.hash && verb == 'v' {
 		if !fi.hash && verb == 'v' {
 			io.write_string(fi.writer, "0x", &fi.n)
 			io.write_string(fi.writer, "0x", &fi.n)
 		}
 		}
@@ -1535,7 +1537,7 @@ string_to_enum_value :: proc($T: typeid, s: string) -> (T, bool) {
 // Inputs:
 // Inputs:
 // - fi: Pointer to the Info struct containing format settings.
 // - fi: Pointer to the Info struct containing format settings.
 // - v: The enum value to format.
 // - v: The enum value to format.
-// - verb: The format specifier character (e.g. 'i','d','f','s','v','q').
+// - verb: The format specifier character (e.g. 'i','d','f','s','v','q','w').
 //
 //
 fmt_enum :: proc(fi: ^Info, v: any, verb: rune) {
 fmt_enum :: proc(fi: ^Info, v: any, verb: rune) {
 	if v.id == nil || v.data == nil {
 	if v.id == nil || v.data == nil {
@@ -1559,6 +1561,15 @@ fmt_enum :: proc(fi: ^Info, v: any, verb: rune) {
 				fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, 'i')
 				fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, 'i')
 				io.write_string(fi.writer, ")", &fi.n)
 				io.write_string(fi.writer, ")", &fi.n)
 			}
 			}
+		case 'w':
+			if str, ok := enum_value_to_string(v); ok {
+				io.write_byte(fi.writer, '.', &fi.n)
+				io.write_string(fi.writer, str, &fi.n)
+			} else {
+				io.write_string(fi.writer, "%!(BAD ENUM VALUE=", &fi.n)
+				fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, 'i')
+				io.write_string(fi.writer, ")", &fi.n)
+			}
 		}
 		}
 	}
 	}
 }
 }
@@ -1747,8 +1758,8 @@ fmt_write_indent :: proc(fi: ^Info) {
 // - verb: The formatting verb to be used for the array elements.
 // - verb: The formatting verb to be used for the array elements.
 //
 //
 fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: int, elem_id: typeid, verb: rune) {
 fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: int, elem_id: typeid, verb: rune) {
-	io.write_byte(fi.writer, '[', &fi.n)
-	defer io.write_byte(fi.writer, ']', &fi.n)
+	io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n)
+	defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
 
 
 	if count <= 0 {
 	if count <= 0 {
 		return
 		return
@@ -1821,6 +1832,13 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb:
 		r, w := utf8.decode_rune_in_string(value)
 		r, w := utf8.decode_rune_in_string(value)
 		value = value[w:]
 		value = value[w:]
 		if value == "" || value[0] == ',' {
 		if value == "" || value[0] == ',' {
+			if verb^ == 'w' {
+				// TODO(bill): is this a good idea overriding that field tags if 'w' is used?
+				switch r {
+				case 's': r = 'q'
+				case:     r = 'w'
+				}
+			}
 			verb^ = r
 			verb^ = r
 			if len(value) > 0 && value[0] == ',' {
 			if len(value) > 0 && value[0] == ',' {
 				field_name := value[1:]
 				field_name := value[1:]
@@ -1832,7 +1850,7 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb:
 					switch r {
 					switch r {
 					case 's', 'q':
 					case 's', 'q':
 						handle_optional_len(data, info, field_name, optional_len)
 						handle_optional_len(data, info, field_name, optional_len)
-					case 'v':
+					case 'v', 'w':
 						#partial switch reflect.type_kind(info.types[idx].id) {
 						#partial switch reflect.type_kind(info.types[idx].id) {
 						case .String, .Multi_Pointer, .Array, .Slice, .Dynamic_Array:
 						case .String, .Multi_Pointer, .Array, .Slice, .Dynamic_Array:
 							handle_optional_len(data, info, field_name, optional_len)
 							handle_optional_len(data, info, field_name, optional_len)
@@ -1854,7 +1872,7 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb:
 // - type_name: The name of the type being formatted
 // - type_name: The name of the type being formatted
 //
 //
 fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string) {
 fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string) {
-	if the_verb != 'v' {
+	if the_verb != 'v' && the_verb != 'w' {
 		fmt_bad_verb(fi, the_verb)
 		fmt_bad_verb(fi, the_verb)
 		return
 		return
 	}
 	}
@@ -1871,7 +1889,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
 	is_soa := info.soa_kind != .None
 	is_soa := info.soa_kind != .None
 
 
 	io.write_string(fi.writer, type_name, &fi.n)
 	io.write_string(fi.writer, type_name, &fi.n)
-	io.write_byte(fi.writer, '[' if is_soa else '{', &fi.n)
+	io.write_byte(fi.writer, '[' if is_soa && the_verb == 'v' else '{', &fi.n)
 	fi.record_level += 1
 	fi.record_level += 1
 	defer fi.record_level -= 1
 	defer fi.record_level -= 1
 
 
@@ -1889,7 +1907,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
 		if hash {
 		if hash {
 			for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
 			for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
 		}
 		}
-		io.write_byte(fi.writer, ']' if is_soa else '}', &fi.n)
+		io.write_byte(fi.writer, ']' if is_soa && the_verb == 'v' else '}', &fi.n)
 	}
 	}
 
 
 	if is_soa {
 	if is_soa {
@@ -1972,7 +1990,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St
 		for name, i in info.names {
 		for name, i in info.names {
 			optional_len: int = -1
 			optional_len: int = -1
 			use_nul_termination: bool = false
 			use_nul_termination: bool = false
-			verb := 'v'
+			verb := the_verb if the_verb == 'w' else 'v'
 			if handle_tag(v.data, info, i, &verb, &optional_len, &use_nul_termination) {
 			if handle_tag(v.data, info, i, &verb, &optional_len, &use_nul_termination) {
 				continue
 				continue
 			}
 			}
@@ -2051,7 +2069,7 @@ fmt_array_nul_terminated :: proc(fi: ^Info, data: rawptr, max_n: int, elem_size:
 // - n: The number of elements in the array.
 // - n: The number of elements in the array.
 // - elem_size: The size of each element in the array.
 // - elem_size: The size of each element in the array.
 // - elem: Pointer to the type information of the array element.
 // - elem: Pointer to the type information of the array element.
-// - verb: The formatting verb (e.g. 's','q','p').
+// - verb: The formatting verb (e.g. 's','q','p','w').
 //
 //
 fmt_array :: proc(fi: ^Info, data: rawptr, n: int, elem_size: int, elem: ^reflect.Type_Info, verb: rune) {
 fmt_array :: proc(fi: ^Info, data: rawptr, n: int, elem_size: int, elem: ^reflect.Type_Info, verb: rune) {
 	if data == nil && n > 0 {
 	if data == nil && n > 0 {
@@ -2130,141 +2148,143 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
 	}
 	}
 
 
 	// Built-in Custom Formatters for core library types
 	// Built-in Custom Formatters for core library types
-	switch a in v {
-	case runtime.Source_Code_Location:
-		io.write_string(fi.writer, a.file_path, &fi.n)
-
-		when ODIN_ERROR_POS_STYLE == .Default {
-			io.write_byte(fi.writer, '(', &fi.n)
-			io.write_int(fi.writer, int(a.line), 10, &fi.n)
-			io.write_byte(fi.writer, ':', &fi.n)
-			io.write_int(fi.writer, int(a.column), 10, &fi.n)
-			io.write_byte(fi.writer, ')', &fi.n)
-		} else when ODIN_ERROR_POS_STYLE == .Unix {
-			io.write_byte(fi.writer, ':', &fi.n)
-			io.write_int(fi.writer, int(a.line), 10, &fi.n)
-			io.write_byte(fi.writer, ':', &fi.n)
-			io.write_int(fi.writer, int(a.column), 10, &fi.n)
-			io.write_byte(fi.writer, ':', &fi.n)
-		} else {
-			#panic("Unhandled ODIN_ERROR_POS_STYLE")
-		}
-		return
+	if verb != 'w' {
+		switch a in v {
+		case runtime.Source_Code_Location:
+			io.write_string(fi.writer, a.file_path, &fi.n)
+
+			when ODIN_ERROR_POS_STYLE == .Default {
+				io.write_byte(fi.writer, '(', &fi.n)
+				io.write_int(fi.writer, int(a.line), 10, &fi.n)
+				io.write_byte(fi.writer, ':', &fi.n)
+				io.write_int(fi.writer, int(a.column), 10, &fi.n)
+				io.write_byte(fi.writer, ')', &fi.n)
+			} else when ODIN_ERROR_POS_STYLE == .Unix {
+				io.write_byte(fi.writer, ':', &fi.n)
+				io.write_int(fi.writer, int(a.line), 10, &fi.n)
+				io.write_byte(fi.writer, ':', &fi.n)
+				io.write_int(fi.writer, int(a.column), 10, &fi.n)
+				io.write_byte(fi.writer, ':', &fi.n)
+			} else {
+				#panic("Unhandled ODIN_ERROR_POS_STYLE")
+			}
+			return
 
 
-	case time.Duration:
-		ffrac :: proc(buf: []byte, v: u64, prec: int) -> (nw: int, nv: u64) {
-			v := v
-			w := len(buf)
-			print := false
-			for _ in 0..<prec {
-				digit := v % 10
-				print = print || digit != 0
+		case time.Duration:
+			ffrac :: proc(buf: []byte, v: u64, prec: int) -> (nw: int, nv: u64) {
+				v := v
+				w := len(buf)
+				print := false
+				for _ in 0..<prec {
+					digit := v % 10
+					print = print || digit != 0
+					if print {
+						w -= 1
+						buf[w] = byte(digit) + '0'
+					}
+					v /= 10
+				}
 				if print {
 				if print {
 					w -= 1
 					w -= 1
-					buf[w] = byte(digit) + '0'
+					buf[w] = '.'
 				}
 				}
-				v /= 10
-			}
-			if print {
-				w -= 1
-				buf[w] = '.'
+				return w, v
 			}
 			}
-			return w, v
-		}
-		fint :: proc(buf: []byte, v: u64) -> int {
-			v := v
-			w := len(buf)
-			if v == 0 {
-				w -= 1
-				buf[w] = '0'
-			} else {
-				for v > 0 {
+			fint :: proc(buf: []byte, v: u64) -> int {
+				v := v
+				w := len(buf)
+				if v == 0 {
 					w -= 1
 					w -= 1
-					buf[w] = byte(v%10) + '0'
-					v /= 10
+					buf[w] = '0'
+				} else {
+					for v > 0 {
+						w -= 1
+						buf[w] = byte(v%10) + '0'
+						v /= 10
+					}
 				}
 				}
+				return w
 			}
 			}
-			return w
-		}
-
-		buf: [32]byte
-		w := len(buf)
-		u := u64(a)
-		neg := a < 0
-		if neg {
-			u = -u
-		}
 
 
-		if u < u64(time.Second) {
-			prec: int
-			w -= 1
-			buf[w] = 's'
-			w -= 1
-			switch {
-			case u == 0:
-				io.write_string(fi.writer, "0s", &fi.n)
-				return
-			case u < u64(time.Microsecond):
-				prec = 0
-				buf[w] = 'n'
-			case u < u64(time.Millisecond):
-				prec = 3
-				// U+00B5 'µ' micro sign == 0xC2 0xB5
-				w -= 1 // Need room for two bytes
-				copy(buf[w:], "µ")
-			case:
-				prec = 6
-				buf[w] = 'm'
+			buf: [32]byte
+			w := len(buf)
+			u := u64(a)
+			neg := a < 0
+			if neg {
+				u = -u
 			}
 			}
-			w, u = ffrac(buf[:w], u, prec)
-			w = fint(buf[:w], u)
-		} else {
-			w -= 1
-			buf[w] = 's'
-			w, u = ffrac(buf[:w], u, 9)
-			w = fint(buf[:w], u%60)
-			u /= 60
-			if u > 0 {
+
+			if u < u64(time.Second) {
+				prec: int
+				w -= 1
+				buf[w] = 's'
+				w -= 1
+				switch {
+				case u == 0:
+					io.write_string(fi.writer, "0s", &fi.n)
+					return
+				case u < u64(time.Microsecond):
+					prec = 0
+					buf[w] = 'n'
+				case u < u64(time.Millisecond):
+					prec = 3
+					// U+00B5 'µ' micro sign == 0xC2 0xB5
+					w -= 1 // Need room for two bytes
+					copy(buf[w:], "µ")
+				case:
+					prec = 6
+					buf[w] = 'm'
+				}
+				w, u = ffrac(buf[:w], u, prec)
+				w = fint(buf[:w], u)
+			} else {
 				w -= 1
 				w -= 1
-				buf[w] = 'm'
+				buf[w] = 's'
+				w, u = ffrac(buf[:w], u, 9)
 				w = fint(buf[:w], u%60)
 				w = fint(buf[:w], u%60)
 				u /= 60
 				u /= 60
 				if u > 0 {
 				if u > 0 {
 					w -= 1
 					w -= 1
-					buf[w] = 'h'
-					w = fint(buf[:w], u)
+					buf[w] = 'm'
+					w = fint(buf[:w], u%60)
+					u /= 60
+					if u > 0 {
+						w -= 1
+						buf[w] = 'h'
+						w = fint(buf[:w], u)
+					}
 				}
 				}
 			}
 			}
-		}
 
 
-		if neg {
-			w -= 1
-			buf[w] = '-'
-		}
-		io.write_string(fi.writer, string(buf[w:]), &fi.n)
-		return
+			if neg {
+				w -= 1
+				buf[w] = '-'
+			}
+			io.write_string(fi.writer, string(buf[w:]), &fi.n)
+			return
 
 
-	case time.Time:
-		t := a
-		y, mon, d := time.date(t)
-		h, min, s := time.clock(t)
-		ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9
-		write_padded_number(fi, i64(y), 4)
-		io.write_byte(fi.writer, '-', &fi.n)
-		write_padded_number(fi, i64(mon), 2)
-		io.write_byte(fi.writer, '-', &fi.n)
-		write_padded_number(fi, i64(d), 2)
-		io.write_byte(fi.writer, ' ', &fi.n)
-
-		write_padded_number(fi, i64(h), 2)
-		io.write_byte(fi.writer, ':', &fi.n)
-		write_padded_number(fi, i64(min), 2)
-		io.write_byte(fi.writer, ':', &fi.n)
-		write_padded_number(fi, i64(s), 2)
-		io.write_byte(fi.writer, '.', &fi.n)
-		write_padded_number(fi, (ns), 9)
-		io.write_string(fi.writer, " +0000 UTC", &fi.n)
-		return
+		case time.Time:
+			t := a
+			y, mon, d := time.date(t)
+			h, min, s := time.clock(t)
+			ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9
+			write_padded_number(fi, i64(y), 4)
+			io.write_byte(fi.writer, '-', &fi.n)
+			write_padded_number(fi, i64(mon), 2)
+			io.write_byte(fi.writer, '-', &fi.n)
+			write_padded_number(fi, i64(d), 2)
+			io.write_byte(fi.writer, ' ', &fi.n)
+
+			write_padded_number(fi, i64(h), 2)
+			io.write_byte(fi.writer, ':', &fi.n)
+			write_padded_number(fi, i64(min), 2)
+			io.write_byte(fi.writer, ':', &fi.n)
+			write_padded_number(fi, i64(s), 2)
+			io.write_byte(fi.writer, '.', &fi.n)
+			write_padded_number(fi, (ns), 9)
+			io.write_string(fi.writer, " +0000 UTC", &fi.n)
+			return
+		}
 	}
 	}
 
 
 	#partial switch b in info.base.variant {
 	#partial switch b in info.base.variant {
@@ -2275,6 +2295,23 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
 	case runtime.Type_Info_Bit_Set:
 	case runtime.Type_Info_Bit_Set:
 		fmt_bit_set(fi, v, verb = verb)
 		fmt_bit_set(fi, v, verb = verb)
 	case:
 	case:
+		if verb == 'w' {
+			#partial switch b in info.base.variant {
+			case runtime.Type_Info_Array,
+			     runtime.Type_Info_Enumerated_Array,
+			     runtime.Type_Info_Dynamic_Array,
+			     runtime.Type_Info_Slice,
+			     runtime.Type_Info_Struct,
+			     runtime.Type_Info_Union,
+			     runtime.Type_Info_Enum,
+			     runtime.Type_Info_Map,
+			     runtime.Type_Info_Bit_Set,
+			     runtime.Type_Info_Simd_Vector,
+			     runtime.Type_Info_Matrix,
+			     runtime.Type_Info_Bit_Field:
+				io.write_string(fi.writer, info.name, &fi.n)
+			}
+		}
 		fmt_value(fi, any{v.data, info.base.id}, verb)
 		fmt_value(fi, any{v.data, info.base.id}, verb)
 	}
 	}
 }
 }
@@ -2341,8 +2378,13 @@ fmt_union :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Union,
 // - info: A runtime.Type_Info_Matrix struct containing matrix type information.
 // - info: A runtime.Type_Info_Matrix struct containing matrix type information.
 //
 //
 fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix) {
 fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix) {
-	io.write_string(fi.writer, "matrix[", &fi.n)
-	defer io.write_byte(fi.writer, ']', &fi.n)
+	if verb == 'w' {
+		io.write_byte(fi.writer, '{', &fi.n)
+	} else {
+		io.write_string(fi.writer, "matrix", &fi.n)
+		io.write_byte(fi.writer, '[', &fi.n)
+	}
+	defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
 
 
 	fi.indent += 1
 	fi.indent += 1
 
 
@@ -2413,8 +2455,8 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit
 		return false
 		return false
 	}
 	}
 
 
-	io.write_string(fi.writer, type_name if len(type_name) != 0 else "bit_field", &fi.n)
-	io.write_string(fi.writer, "{", &fi.n)
+	io.write_string(fi.writer, type_name if len(type_name) != 0 || verb == 'w' else "bit_field", &fi.n)
+	io.write_byte(fi.writer, '{', &fi.n)
 
 
 	hash   := fi.hash;   defer fi.hash = hash
 	hash   := fi.hash;   defer fi.hash = hash
 	indent := fi.indent; defer fi.indent -= 1
 	indent := fi.indent; defer fi.indent -= 1
@@ -2631,11 +2673,12 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		defer fi.record_level -= 1
 		defer fi.record_level -= 1
 
 
 		if fi.hash {
 		if fi.hash {
-			io.write_string(fi.writer, "[\n", &fi.n)
+			io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n)
+			io.write_byte(fi.writer, '\n', &fi.n)
 			defer {
 			defer {
 				io.write_byte(fi.writer, '\n', &fi.n)
 				io.write_byte(fi.writer, '\n', &fi.n)
 				fmt_write_indent(fi)
 				fmt_write_indent(fi)
-				io.write_byte(fi.writer, ']', &fi.n)
+				io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
 			}
 			}
 			indent := fi.indent
 			indent := fi.indent
 			fi.indent += 1
 			fi.indent += 1
@@ -2659,8 +2702,8 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 				io.write_string(fi.writer, ",\n", &fi.n)
 				io.write_string(fi.writer, ",\n", &fi.n)
 			}
 			}
 		} else {
 		} else {
-			io.write_byte(fi.writer, '[', &fi.n)
-			defer io.write_byte(fi.writer, ']', &fi.n)
+			io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n)
+			io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
 			for i in 0..<info.count {
 			for i in 0..<info.count {
 				if i > 0 { io.write_string(fi.writer, ", ", &fi.n) }
 				if i > 0 { io.write_string(fi.writer, ", ", &fi.n) }
 
 
@@ -2725,38 +2768,42 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 
 
 
 
 	case runtime.Type_Info_Map:
 	case runtime.Type_Info_Map:
-		if verb != 'v' {
+		switch verb {
+		case:
 			fmt_bad_verb(fi, verb)
 			fmt_bad_verb(fi, verb)
-			return
-		}
-
-		io.write_string(fi.writer, "map[", &fi.n)
-		defer io.write_byte(fi.writer, ']', &fi.n)
-		fi.record_level += 1
-		defer fi.record_level -= 1
-
-		m := (^mem.Raw_Map)(v.data)
-		if m != nil {
-			if info.map_info == nil {
-				return
+		case 'v', 'w':
+			if verb == 'v' {
+				io.write_string(fi.writer, "map", &fi.n)
 			}
 			}
-			map_cap := uintptr(runtime.map_cap(m^))
-			ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(m^, info.map_info)
-			j := 0
-			for bucket_index in 0..<map_cap {
-				runtime.map_hash_is_valid(hs[bucket_index]) or_continue
+			io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n)
+			defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n)
+
+			fi.record_level += 1
+			defer fi.record_level -= 1
 
 
-				if j > 0 {
-					io.write_string(fi.writer, ", ", &fi.n)
+			m := (^mem.Raw_Map)(v.data)
+			if m != nil {
+				if info.map_info == nil {
+					return
 				}
 				}
-				j += 1
+				map_cap := uintptr(runtime.map_cap(m^))
+				ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(m^, info.map_info)
+				j := 0
+				for bucket_index in 0..<map_cap {
+					runtime.map_hash_is_valid(hs[bucket_index]) or_continue
+
+					if j > 0 {
+						io.write_string(fi.writer, ", ", &fi.n)
+					}
+					j += 1
 
 
-				key   := runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index)
-				value := runtime.map_cell_index_dynamic(vs, info.map_info.vs, bucket_index)
+					key   := runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index)
+					value := runtime.map_cell_index_dynamic(vs, info.map_info.vs, bucket_index)
 
 
-				fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, 'v')
-				io.write_string(fi.writer, "=", &fi.n)
-				fmt_arg(fi, any{rawptr(value), info.value.id}, 'v')
+					fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, verb)
+					io.write_string(fi.writer, "=", &fi.n)
+					fmt_arg(fi, any{rawptr(value), info.value.id}, verb)
+				}
 			}
 			}
 		}
 		}
 
 
@@ -2811,11 +2858,11 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 // - fi: A pointer to an Info struct containing formatting information.
 // - fi: A pointer to an Info struct containing formatting information.
 // - c: The complex128 value to be formatted.
 // - c: The complex128 value to be formatted.
 // - bits: The number of bits in the complex number (32 or 64).
 // - bits: The number of bits in the complex number (32 or 64).
-// - verb: The formatting verb rune ('f', 'F', 'v', 'h', 'H').
+// - verb: The formatting verb rune ('f', 'F', 'v', 'h', 'H', 'w').
 //
 //
 fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) {
 fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) {
 	switch verb {
 	switch verb {
-	case 'f', 'F', 'v', 'h', 'H':
+	case 'f', 'F', 'v', 'h', 'H', 'w':
 		r, i := real(c), imag(c)
 		r, i := real(c), imag(c)
 		fmt_float(fi, r, bits/2, verb)
 		fmt_float(fi, r, bits/2, verb)
 		if !fi.plus && i >= 0 {
 		if !fi.plus && i >= 0 {
@@ -2835,11 +2882,11 @@ fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) {
 // - fi: A pointer to an Info struct containing formatting information.
 // - fi: A pointer to an Info struct containing formatting information.
 // - q: The quaternion256 value to be formatted.
 // - q: The quaternion256 value to be formatted.
 // - bits: The number of bits in the quaternion number (64, 128, or 256).
 // - bits: The number of bits in the quaternion number (64, 128, or 256).
-// - verb: The formatting verb rune ('f', 'F', 'v', 'h', 'H').
+// - verb: The formatting verb rune ('f', 'F', 'v', 'h', 'H', 'w').
 //
 //
 fmt_quaternion  :: proc(fi: ^Info, q: quaternion256, bits: int, verb: rune) {
 fmt_quaternion  :: proc(fi: ^Info, q: quaternion256, bits: int, verb: rune) {
 	switch verb {
 	switch verb {
-	case 'f', 'F', 'v', 'h', 'H':
+	case 'f', 'F', 'v', 'h', 'H', 'w':
 		r, i, j, k := real(q), imag(q), jmag(q), kmag(q)
 		r, i, j, k := real(q), imag(q), jmag(q), kmag(q)
 
 
 		fmt_float(fi, r, bits/4, verb)
 		fmt_float(fi, r, bits/4, verb)