mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-13 23:43:40 +00:00
reflect: add Value.Clear; support anytype->interface{}, Slice->(*)Array in Value.Convert
This commit is contained in:
committed by
Damian Gryski
parent
c728e031df
commit
e98fea0bba
+62
-10
@@ -689,6 +689,25 @@ func (v Value) Cap() int {
|
||||
}
|
||||
}
|
||||
|
||||
//go:linkname mapclear runtime.hashmapClear
|
||||
func mapclear(p unsafe.Pointer)
|
||||
|
||||
// Clear clears the contents of a map or zeros the contents of a slice
|
||||
//
|
||||
// It panics if v's Kind is not Map or Slice.
|
||||
func (v Value) Clear() {
|
||||
switch v.typecode.Kind() {
|
||||
case Map:
|
||||
mapclear(v.pointer())
|
||||
case Slice:
|
||||
hdr := (*sliceHeader)(v.value)
|
||||
elemSize := v.typecode.underlying().elem().Size()
|
||||
memzero(hdr.data, elemSize*hdr.len)
|
||||
default:
|
||||
panic(&ValueError{Method: "Clear", Kind: v.Kind()})
|
||||
}
|
||||
}
|
||||
|
||||
// NumField returns the number of fields of this struct. It panics for other
|
||||
// value types.
|
||||
func (v Value) NumField() int {
|
||||
@@ -888,6 +907,9 @@ func (v Value) Index(i int) Value {
|
||||
}
|
||||
|
||||
func (v Value) NumMethod() int {
|
||||
if v.typecode == nil {
|
||||
panic(&ValueError{Method: "reflect.Value.NumMethod", Kind: Invalid})
|
||||
}
|
||||
return v.typecode.NumMethod()
|
||||
}
|
||||
|
||||
@@ -1062,7 +1084,7 @@ func (v Value) Set(x Value) {
|
||||
v.checkAddressable()
|
||||
v.checkRO()
|
||||
if !x.typecode.AssignableTo(v.typecode) {
|
||||
panic("reflect: cannot set")
|
||||
panic("reflect.Value.Set: value of type " + x.typecode.String() + " cannot be assigned to type " + v.typecode.String())
|
||||
}
|
||||
|
||||
if v.typecode.Kind() == Interface && x.typecode.Kind() != Interface {
|
||||
@@ -1240,7 +1262,9 @@ func (v Value) OverflowUint(x uint64) bool {
|
||||
}
|
||||
|
||||
func (v Value) CanConvert(t Type) bool {
|
||||
panic("unimplemented: (reflect.Value).CanConvert()")
|
||||
// TODO: Optimize this to not actually perform a conversion
|
||||
_, ok := convertOp(v, t)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (v Value) Convert(t Type) Value {
|
||||
@@ -1262,6 +1286,15 @@ func convertOp(src Value, typ Type) (Value, bool) {
|
||||
}, true
|
||||
}
|
||||
|
||||
if rtype := typ.(*rawType); rtype.Kind() == Interface && rtype.NumMethod() == 0 {
|
||||
iface := composeInterface(unsafe.Pointer(src.typecode), src.value)
|
||||
return Value{
|
||||
typecode: rtype,
|
||||
value: unsafe.Pointer(&iface),
|
||||
flags: valueFlagExported,
|
||||
}, true
|
||||
}
|
||||
|
||||
switch src.Kind() {
|
||||
case Int, Int8, Int16, Int32, Int64:
|
||||
switch rtype := typ.(*rawType); rtype.Kind() {
|
||||
@@ -1302,14 +1335,33 @@ func convertOp(src Value, typ Type) (Value, bool) {
|
||||
*/
|
||||
|
||||
case Slice:
|
||||
if typ.Kind() == String && !src.typecode.elem().isNamed() {
|
||||
rtype := typ.(*rawType)
|
||||
|
||||
switch src.Type().Elem().Kind() {
|
||||
case Uint8:
|
||||
return cvtBytesString(src, rtype), true
|
||||
case Int32:
|
||||
return cvtRunesString(src, rtype), true
|
||||
switch rtype := typ.(*rawType); rtype.Kind() {
|
||||
case Array:
|
||||
if src.typecode.elem() == rtype.elem() && rtype.Len() <= src.Len() {
|
||||
return Value{
|
||||
typecode: rtype,
|
||||
value: (*sliceHeader)(src.value).data,
|
||||
flags: src.flags | valueFlagIndirect,
|
||||
}, true
|
||||
}
|
||||
case Pointer:
|
||||
if rtype.Elem().Kind() == Array {
|
||||
if src.typecode.elem() == rtype.elem().elem() && rtype.elem().Len() <= src.Len() {
|
||||
return Value{
|
||||
typecode: rtype,
|
||||
value: (*sliceHeader)(src.value).data,
|
||||
flags: src.flags & (valueFlagExported | valueFlagRO),
|
||||
}, true
|
||||
}
|
||||
}
|
||||
case String:
|
||||
if !src.typecode.elem().isNamed() {
|
||||
switch src.Type().Elem().Kind() {
|
||||
case Uint8:
|
||||
return cvtBytesString(src, rtype), true
|
||||
case Int32:
|
||||
return cvtRunesString(src, rtype), true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user