mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 10:37:46 +00:00
reflect: add support for remaining map types
This commit is contained in:
committed by
Damian Gryski
parent
a6084767b3
commit
69e5c5088d
+27
-5
@@ -785,6 +785,9 @@ func hashmapStringGet(m unsafe.Pointer, key string, value unsafe.Pointer, valueS
|
||||
//go:linkname hashmapBinaryGet runtime.hashmapBinaryGetUnsafePointer
|
||||
func hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool
|
||||
|
||||
//go:linkname hashmapInterfaceGet runtime.hashmapInterfaceGetUnsafePointer
|
||||
func hashmapInterfaceGet(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool
|
||||
|
||||
func (v Value) MapIndex(key Value) Value {
|
||||
if v.Kind() != Map {
|
||||
panic(&ValueError{Method: "MapIndex", Kind: v.Kind()})
|
||||
@@ -816,10 +819,12 @@ func (v Value) MapIndex(key Value) Value {
|
||||
return Value{}
|
||||
}
|
||||
return elem.Elem()
|
||||
} else {
|
||||
if ok := hashmapInterfaceGet(v.pointer(), key.Interface(), elem.value, elemType.Size()); !ok {
|
||||
return Value{}
|
||||
}
|
||||
return elem.Elem()
|
||||
}
|
||||
|
||||
// TODO(dgryski): Add other map types. For now, just string and binary types are supported.
|
||||
panic("unimplemented: (reflect.Value).MapIndex()")
|
||||
}
|
||||
|
||||
//go:linkname hashmapNewIterator runtime.hashmapNewIterator
|
||||
@@ -1292,12 +1297,18 @@ func hashmapStringSet(m unsafe.Pointer, key string, value unsafe.Pointer)
|
||||
//go:linkname hashmapBinarySet runtime.hashmapBinarySetUnsafePointer
|
||||
func hashmapBinarySet(m unsafe.Pointer, key, value unsafe.Pointer)
|
||||
|
||||
//go:linkname hashmapInterfaceSet runtime.hashmapInterfaceSetUnsafePointer
|
||||
func hashmapInterfaceSet(m unsafe.Pointer, key interface{}, value unsafe.Pointer)
|
||||
|
||||
//go:linkname hashmapStringDelete runtime.hashmapStringDeleteUnsafePointer
|
||||
func hashmapStringDelete(m unsafe.Pointer, key string)
|
||||
|
||||
//go:linkname hashmapBinaryDelete runtime.hashmapBinaryDeleteUnsafePointer
|
||||
func hashmapBinaryDelete(m unsafe.Pointer, key unsafe.Pointer)
|
||||
|
||||
//go:linkname hashmapInterfaceDelete runtime.hashmapInterfaceDeleteUnsafePointer
|
||||
func hashmapInterfaceDelete(m unsafe.Pointer, key interface{})
|
||||
|
||||
func (v Value) SetMapIndex(key, elem Value) {
|
||||
if v.Kind() != Map {
|
||||
panic(&ValueError{Method: "SetMapIndex", Kind: v.Kind()})
|
||||
@@ -1348,7 +1359,18 @@ func (v Value) SetMapIndex(key, elem Value) {
|
||||
hashmapBinarySet(v.pointer(), keyptr, elemptr)
|
||||
}
|
||||
} else {
|
||||
panic("unimplemented: (reflect.Value).MapIndex()")
|
||||
if del {
|
||||
hashmapInterfaceDelete(v.pointer(), key.Interface())
|
||||
} else {
|
||||
var elemptr unsafe.Pointer
|
||||
if elem.isIndirect() || elem.typecode.Size() > unsafe.Sizeof(uintptr(0)) {
|
||||
elemptr = elem.value
|
||||
} else {
|
||||
elemptr = unsafe.Pointer(&elem.value)
|
||||
}
|
||||
|
||||
hashmapInterfaceSet(v.pointer(), key.Interface(), elemptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1398,7 +1420,7 @@ func MakeMapWithSize(typ Type, n int) Value {
|
||||
} else if key.isBinary() {
|
||||
alg = hashmapAlgorithmBinary
|
||||
} else {
|
||||
panic("reflect.MakeMap: unimplemented key type")
|
||||
alg = hashmapAlgorithmInterface
|
||||
}
|
||||
|
||||
m := hashmapMake(key.Size(), val.Size(), uintptr(n), alg)
|
||||
|
||||
@@ -115,6 +115,23 @@ func TestMap(t *testing.T) {
|
||||
if m2["foo"] != 2 {
|
||||
t.Errorf("MakeMap failed to create map")
|
||||
}
|
||||
|
||||
type stringint struct {
|
||||
s string
|
||||
i int
|
||||
}
|
||||
|
||||
simap := make(map[stringint]int)
|
||||
|
||||
refsimap := MakeMap(TypeOf(simap))
|
||||
|
||||
refsimap.SetMapIndex(ValueOf(stringint{"hello", 4}), ValueOf(6))
|
||||
|
||||
six := refsimap.MapIndex(ValueOf(stringint{"hello", 4}))
|
||||
|
||||
if six.Interface().(int) != 6 {
|
||||
t.Errorf("m[hello, 4]=%v, want 6", six)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlice(t *testing.T) {
|
||||
|
||||
@@ -616,6 +616,10 @@ func hashmapInterfaceSet(m *hashmap, key interface{}, value unsafe.Pointer) {
|
||||
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
||||
}
|
||||
|
||||
func hashmapInterfaceSetUnsafePointer(m unsafe.Pointer, key interface{}, value unsafe.Pointer) {
|
||||
hashmapInterfaceSet((*hashmap)(m), key, value)
|
||||
}
|
||||
|
||||
func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
||||
if m == nil {
|
||||
memzero(value, uintptr(valueSize))
|
||||
@@ -625,6 +629,10 @@ func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valu
|
||||
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
||||
}
|
||||
|
||||
func hashmapInterfaceGetUnsafePointer(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
||||
return hashmapInterfaceGet((*hashmap)(m), key, value, valueSize)
|
||||
}
|
||||
|
||||
func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
||||
if m == nil {
|
||||
return
|
||||
@@ -632,3 +640,7 @@ func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
||||
hash := hashmapInterfaceHash(key, m.seed)
|
||||
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
||||
}
|
||||
|
||||
func hashmapInterfaceDeleteUnsafePointer(m unsafe.Pointer, key interface{}) {
|
||||
hashmapInterfaceDelete((*hashmap)(m), key)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user