Browse Source

Add `reflect.{to_int, to_uint, to_i64, to_u64, to_f64}`

gingerBill 5 years ago
parent
commit
11dd971e13
2 changed files with 339 additions and 105 deletions
  1. 4 86
      core/fmt/fmt.odin
  2. 335 19
      core/reflect/reflect.odin

+ 4 - 86
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;
 	new_arg_index := arg_index;
 	ok := true;
 	ok := true;
 	if arg_index < len(args) {
 	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 {
 	if ok {
@@ -939,53 +925,8 @@ enum_value_to_string :: proc(val: any) -> (string, bool) {
 	case runtime.Type_Info_Enum:
 	case runtime.Type_Info_Enum:
 		Enum_Value :: runtime.Type_Info_Enum_Value;
 		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 ok {
 			if len(e.values) == 0 {
 			if len(e.values) == 0 {
@@ -1768,30 +1709,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		} else {
 		} else {
 			len_ptr := uintptr(v.data) + uintptr(info.base_integer.size);
 			len_ptr := uintptr(v.data) + uintptr(info.base_integer.size);
 			len_any := any{rawptr(len_ptr), info.base_integer.id};
 			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);
 			slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice);
 
 
 			strings.write_byte(fi.buf, '[');
 			strings.write_byte(fi.buf, '[');

+ 335 - 19
core/reflect/reflect.odin

@@ -502,10 +502,9 @@ enum_string :: proc(a: any) -> string {
 	if a == nil do return "";
 	if a == nil do return "";
 	ti := runtime.type_info_base(type_info_of(a.id));
 	ti := runtime.type_info_base(type_info_of(a.id));
 	if e, ok := ti.variant.(runtime.Type_Info_Enum); ok {
 	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];
 				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 {
     if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok {
         for value_name, i in eti.names {
         for value_name, i in eti.names {
             if value_name != name do continue;
             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 {
     } else {
         panic("expected enum type to reflect.enum_from_name");
         panic("expected enum type to reflect.enum_from_name");
@@ -579,3 +567,331 @@ union_variant_typeid :: proc(a: any) -> typeid {
 
 
 	return nil;
 	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;
+}