diff options
author | Damian Gryski <[email protected]> | 2023-03-18 22:57:47 -0700 |
---|---|---|
committer | Ayke <[email protected]> | 2023-03-27 18:53:37 +0200 |
commit | 855e12df51906acefd49ebc44587926e4cae25ec (patch) | |
tree | dad2056d2a255e07038f04b46de3a5b9aa87fe0f /src/reflect | |
parent | 0b6bb12e9e97bd7e0709339dbc5f19094813736e (diff) | |
download | tinygo-855e12df51906acefd49ebc44587926e4cae25ec.tar.gz tinygo-855e12df51906acefd49ebc44587926e4cae25ec.zip |
reflect: Convert(): add Float() conversions
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/value.go | 68 |
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") } |