aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/reflect
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2023-03-18 22:57:47 -0700
committerAyke <[email protected]>2023-03-27 18:53:37 +0200
commit855e12df51906acefd49ebc44587926e4cae25ec (patch)
treedad2056d2a255e07038f04b46de3a5b9aa87fe0f /src/reflect
parent0b6bb12e9e97bd7e0709339dbc5f19094813736e (diff)
downloadtinygo-855e12df51906acefd49ebc44587926e4cae25ec.tar.gz
tinygo-855e12df51906acefd49ebc44587926e4cae25ec.zip
reflect: Convert(): add Float() conversions
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/value.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 76ad7718e..2c238efd5 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -330,6 +330,27 @@ func (v Value) Uint() uint64 {
}
}
+func (v Value) Float32() float32 {
+ switch v.Kind() {
+ case Float32:
+ if v.isIndirect() || unsafe.Sizeof(float32(0)) > unsafe.Sizeof(uintptr(0)) {
+ // The float is stored as an external value on systems with 16-bit
+ // pointers.
+ return *(*float32)(v.value)
+ } else {
+ // The float is directly stored in the interface value on systems
+ // with 32-bit and 64-bit pointers.
+ return *(*float32)(unsafe.Pointer(&v.value))
+ }
+
+ case Float64:
+ return float32(v.Float())
+
+ }
+
+ panic(&ValueError{Method: "Float", Kind: v.Kind()})
+}
+
func (v Value) Float() float64 {
switch v.Kind() {
case Float32:
@@ -1103,6 +1124,24 @@ func convertOp(src Value, typ Type) (Value, bool) {
return cvtUintString(src, rtype), true
}
+ case Float32, Float64:
+ switch rtype := typ.(*rawType); rtype.Kind() {
+ case Int, Int8, Int16, Int32, Int64:
+ return cvtFloatInt(src, rtype), true
+ case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return cvtFloatUint(src, rtype), true
+ case Float32, Float64:
+ return cvtFloat(src, rtype), true
+ }
+
+ /*
+ case Complex64, Complex128:
+ switch src.Kind() {
+ case Complex64, Complex128:
+ return cvtComplex
+ }
+ */
+
case Slice:
if typ.Kind() == String && !src.typecode.elem().isNamed() {
rtype := typ.(*rawType)
@@ -1149,6 +1188,24 @@ func cvtUintFloat(v Value, t *rawType) Value {
return makeFloat(v.flags, float64(v.Uint()), t)
}
+func cvtFloatInt(v Value, t *rawType) Value {
+ return makeInt(v.flags, uint64(int64(v.Float())), t)
+}
+
+func cvtFloatUint(v Value, t *rawType) Value {
+ return makeInt(v.flags, uint64(v.Float()), t)
+}
+
+func cvtFloat(v Value, t *rawType) Value {
+ if v.Type().Kind() == Float32 && t.Kind() == Float32 {
+ // Don't do any conversion if both types have underlying type float32.
+ // This avoids converting to float64 and back, which will
+ // convert a signaling NaN to a quiet NaN. See issue 36400.
+ return makeFloat32(v.flags, v.Float32(), t)
+ }
+ return makeFloat(v.flags, v.Float(), t)
+}
+
//go:linkname stringToBytes runtime.stringToBytesTyped
func stringToBytes(x string) []byte
@@ -1209,6 +1266,17 @@ func makeFloat(flags valueFlags, v float64, t *rawType) Value {
}
}
+func makeFloat32(flags valueFlags, v float32, t *rawType) Value {
+ size := t.Size()
+ ptr := alloc(size, nil)
+ *(*float32)(ptr) = float32(v)
+ return Value{
+ typecode: t,
+ value: ptr,
+ flags: flags | valueFlagIndirect,
+ }
+}
+
func cvtIntString(src Value, t *rawType) Value {
panic("cvtUintString: unimplemented")
}