From 11dd971e13dea5e23bf05ebc17e80b07d9603796 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Jun 2020 10:27:32 +0100 Subject: [PATCH] Add `reflect.{to_int, to_uint, to_i64, to_u64, to_f64}` --- core/fmt/fmt.odin | 90 +--------- core/reflect/reflect.odin | 354 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 339 insertions(+), 105 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 6daa552da..81495cd83 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -515,21 +515,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { new_arg_index := arg_index; ok := true; if arg_index < len(args) { - arg := args[arg_index]; - arg.id = runtime.typeid_base(arg.id); - switch i in arg { - case int: num = i; - case i8: num = int(i); - case i16: num = int(i); - case i32: num = int(i); - case i64: num = int(i); - case u8: num = int(i); - case u16: num = int(i); - case u32: num = int(i); - case u64: num = int(i); - case: - ok = false; - } + num, ok = reflect.to_int(args[arg_index]); } if ok { @@ -939,53 +925,8 @@ enum_value_to_string :: proc(val: any) -> (string, bool) { case runtime.Type_Info_Enum: Enum_Value :: runtime.Type_Info_Enum_Value; - ev: Enum_Value; - ok := true; - - bv := v; - bv.id = runtime.typeid_core(e.base.id); - - switch i in bv { - case i8: ev = Enum_Value(i); - case i16: ev = Enum_Value(i); - case i32: ev = Enum_Value(i); - case i64: ev = Enum_Value(i); - case i128: ev = Enum_Value(i); - - case int: ev = Enum_Value(i); - - case u8: ev = Enum_Value(i); - case u16: ev = Enum_Value(i); - case u32: ev = Enum_Value(i); - case u64: ev = Enum_Value(i); - case u128: ev = Enum_Value(i); - case uint: ev = Enum_Value(i); - - case uintptr: ev = Enum_Value(i); - - case i16le: ev = Enum_Value(i); - case i32le: ev = Enum_Value(i); - case i64le: ev = Enum_Value(i); - case i128le: ev = Enum_Value(i); - - case u16le: ev = Enum_Value(i); - case u32le: ev = Enum_Value(i); - case u64le: ev = Enum_Value(i); - case u128le: ev = Enum_Value(i); - - case i16be: ev = Enum_Value(i); - case i32be: ev = Enum_Value(i); - case i64be: ev = Enum_Value(i); - case i128be: ev = Enum_Value(i); - - case u16be: ev = Enum_Value(i); - case u32be: ev = Enum_Value(i); - case u64be: ev = Enum_Value(i); - case u128be: ev = Enum_Value(i); - - case: - ok = false; - } + ev_, ok := reflect.to_i64(val); + ev := Enum_Value(ev_); if ok { if len(e.values) == 0 { @@ -1768,30 +1709,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } else { len_ptr := uintptr(v.data) + uintptr(info.base_integer.size); len_any := any{rawptr(len_ptr), info.base_integer.id}; - len: int = 0; - switch i in len_any { - case u8: len = int(i); - case u16: len = int(i); - case u32: len = int(i); - case u64: len = int(i); - case i8: len = int(i); - case i16: len = int(i); - case i32: len = int(i); - case i64: len = int(i); - case u16le: len = int(i); - case u32le: len = int(i); - case u64le: len = int(i); - case i16le: len = int(i); - case i32le: len = int(i); - case i64le: len = int(i); - case u16be: len = int(i); - case u32be: len = int(i); - case u64be: len = int(i); - case i16be: len = int(i); - case i32be: len = int(i); - case i64be: len = int(i); - } - + len, _ := reflect.to_int(len_any); slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice); strings.write_byte(fi.buf, '['); diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index c971a1011..8ad63a9b6 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -502,10 +502,9 @@ enum_string :: proc(a: any) -> string { if a == nil do return ""; ti := runtime.type_info_base(type_info_of(a.id)); if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { - for _, i in e.values { - value := &e.values[i]; - n := mem.compare_byte_ptrs((^byte)(a.data), (^byte)(value), ti.size); - if n == 0 { + v, _ := to_i64(a); + for value, i in e.values { + if value == runtime.Type_Info_Enum_Value(v) { return e.names[i]; } } @@ -522,21 +521,10 @@ enum_from_name :: proc($EnumType: typeid, name: string) -> (value: EnumType, ok: if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name do continue; - value_union := eti.values[i]; - switch v in value_union { - case rune: value = EnumType(v); ok = true; - case u8: value = EnumType(v); ok = true; - case u16: value = EnumType(v); ok = true; - case u32: value = EnumType(v); ok = true; - case u64: value = EnumType(v); ok = true; - case uint: value = EnumType(v); ok = true; - case uintptr: value = EnumType(v); ok = true; - case i8: value = EnumType(v); ok = true; - case i16: value = EnumType(v); ok = true; - case i32: value = EnumType(v); ok = true; - case i64: value = EnumType(v); ok = true; - case int: value = EnumType(v); ok = true; - } + v := eti.values[i]; + value = EnumType(v); + ok = true; + return; } } else { panic("expected enum type to reflect.enum_from_name"); @@ -579,3 +567,331 @@ union_variant_typeid :: proc(a: any) -> typeid { return nil; } + + +to_int :: proc(a: any) -> (value: int, valid: bool) { + v: i64; + v, valid = to_i64(a); + value = int(v); + return; +} + +to_uint :: proc(a: any) -> (value: uint, valid: bool) { + v: u64; + v, valid = to_u64(a); + value = uint(v); + return; +} + +to_i64 :: proc(a: any) -> (value: i64, valid: bool) { + if a == nil do return; + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_Integer: + valid = true; + switch v in a { + case i8: value = i64(v); + case i16: value = i64(v); + case i32: value = i64(v); + case i64: value = i64(v); + case i128: value = i64(v); + + case u8: value = i64(v); + case u16: value = i64(v); + case u32: value = i64(v); + case u64: value = i64(v); + case u128: value = i64(v); + + case u16le: value = i64(v); + case u32le: value = i64(v); + case u64le: value = i64(v); + case u128le:value = i64(v); + + case i16le: value = i64(v); + case i32le: value = i64(v); + case i64le: value = i64(v); + case i128le:value = i64(v); + + case u16be: value = i64(v); + case u32be: value = i64(v); + case u64be: value = i64(v); + case u128be:value = i64(v); + + case i16be: value = i64(v); + case i32be: value = i64(v); + case i64be: value = i64(v); + case i128be:value = i64(v); + case: valid = false; + } + + case Type_Info_Rune: + r := a.(rune); + value = i64(r); + valid = true; + + case Type_Info_Float: + valid = true; + switch v in a { + case f32: value = i64(f32(v)); + case f64: value = i64(f64(v)); + case f32le: value = i64(f32(v)); + case f64le: value = i64(f64(v)); + case f32be: value = i64(f32(v)); + case f64be: value = i64(f64(v)); + case: valid = false; + } + + case Type_Info_Boolean: + valid = true; + switch v in a { + case bool: value = i64(bool(v)); + case b8: value = i64(bool(v)); + case b16: value = i64(bool(v)); + case b32: value = i64(bool(v)); + case b64: value = i64(bool(v)); + case: valid = false; + } + + case Type_Info_Complex: + switch v in a { + case complex64: + if imag(v) == 0 { + value = i64(real(v)); + valid = true; + } + case complex128: + if imag(v) == 0 { + value = i64(real(v)); + valid = true; + } + } + + case Type_Info_Quaternion: + switch v in a { + case quaternion128: + if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { + value = i64(real(v)); + valid = true; + } + case quaternion256: + if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { + value = i64(real(v)); + valid = true; + } + } + } + + return; +} + +to_u64 :: proc(a: any) -> (value: u64, valid: bool) { + if a == nil do return; + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_Integer: + valid = true; + switch v in a { + case i8: value = u64(v); + case i16: value = u64(v); + case i32: value = u64(v); + case i64: value = u64(v); + case i128: value = u64(v); + + case u8: value = u64(v); + case u16: value = u64(v); + case u32: value = u64(v); + case u64: value = u64(v); + case u128: value = u64(v); + + case u16le: value = u64(v); + case u32le: value = u64(v); + case u64le: value = u64(v); + case u128le:value = u64(v); + + case i16le: value = u64(v); + case i32le: value = u64(v); + case i64le: value = u64(v); + case i128le:value = u64(v); + + case u16be: value = u64(v); + case u32be: value = u64(v); + case u64be: value = u64(v); + case u128be:value = u64(v); + + case i16be: value = u64(v); + case i32be: value = u64(v); + case i64be: value = u64(v); + case i128be:value = u64(v); + case: valid = false; + } + + case Type_Info_Rune: + r := a.(rune); + value = u64(r); + valid = true; + + case Type_Info_Float: + valid = true; + switch v in a { + case f32: value = u64(f32(v)); + case f64: value = u64(f64(v)); + case f32le: value = u64(f32(v)); + case f64le: value = u64(f64(v)); + case f32be: value = u64(f32(v)); + case f64be: value = u64(f64(v)); + case: valid = false; + } + + case Type_Info_Boolean: + valid = true; + switch v in a { + case bool: value = u64(bool(v)); + case b8: value = u64(bool(v)); + case b16: value = u64(bool(v)); + case b32: value = u64(bool(v)); + case b64: value = u64(bool(v)); + case: valid = false; + } + + case Type_Info_Complex: + switch v in a { + case complex64: + if imag(v) == 0 { + value = u64(real(v)); + valid = true; + } + case complex128: + if imag(v) == 0 { + value = u64(real(v)); + valid = true; + } + } + + case Type_Info_Quaternion: + switch v in a { + case quaternion128: + if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { + value = u64(real(v)); + valid = true; + } + case quaternion256: + if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { + value = u64(real(v)); + valid = true; + } + } + } + + return; +} + + +to_f64 :: proc(a: any) -> (value: f64, valid: bool) { + if a == nil do return; + a := a; + ti := runtime.type_info_core(type_info_of(a.id)); + a.id = ti.id; + + #partial switch info in ti.variant { + case Type_Info_Integer: + valid = true; + switch v in a { + case i8: value = f64(v); + case i16: value = f64(v); + case i32: value = f64(v); + case i64: value = f64(v); + case i128: value = f64(v); + + case u8: value = f64(v); + case u16: value = f64(v); + case u32: value = f64(v); + case u64: value = f64(v); + case u128: value = f64(v); + + case u16le: value = f64(v); + case u32le: value = f64(v); + case u64le: value = f64(v); + case u128le:value = f64(v); + + case i16le: value = f64(v); + case i32le: value = f64(v); + case i64le: value = f64(v); + case i128le:value = f64(v); + + case u16be: value = f64(v); + case u32be: value = f64(v); + case u64be: value = f64(v); + case u128be:value = f64(v); + + case i16be: value = f64(v); + case i32be: value = f64(v); + case i64be: value = f64(v); + case i128be:value = f64(v); + case: valid = false; + } + + case Type_Info_Rune: + r := a.(rune); + value = f64(i32(r)); + valid = true; + + case Type_Info_Float: + valid = true; + switch v in a { + case f32: value = f64(f32(v)); + case f64: value = f64(f64(v)); + case f32le: value = f64(f32(v)); + case f64le: value = f64(f64(v)); + case f32be: value = f64(f32(v)); + case f64be: value = f64(f64(v)); + case: valid = false; + } + + case Type_Info_Boolean: + valid = true; + switch v in a { + case bool: value = f64(i32(bool(v))); + case b8: value = f64(i32(bool(v))); + case b16: value = f64(i32(bool(v))); + case b32: value = f64(i32(bool(v))); + case b64: value = f64(i32(bool(v))); + case: valid = false; + } + + case Type_Info_Complex: + switch v in a { + case complex64: + if imag(v) == 0 { + value = f64(real(v)); + valid = true; + } + case complex128: + if imag(v) == 0 { + value = f64(real(v)); + valid = true; + } + } + + case Type_Info_Quaternion: + switch v in a { + case quaternion128: + if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { + value = f64(real(v)); + valid = true; + } + case quaternion256: + if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { + value = f64(real(v)); + valid = true; + } + } + } + + return; +}