aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2023-02-25 14:48:58 -0800
committerAyke <[email protected]>2023-02-28 13:10:40 -0800
commitc4dadbaaab353ff820e094b6265ffc6382ffcdc8 (patch)
treeb2c74efd961e6e745ce2612ede74e34582eccdfc
parent828c3169ab688039e1b869b059b9696e27d4ec19 (diff)
downloadtinygo-c4dadbaaab353ff820e094b6265ffc6382ffcdc8.tar.gz
tinygo-c4dadbaaab353ff820e094b6265ffc6382ffcdc8.zip
reflect: add MakeMap()
-rw-r--r--src/reflect/value.go46
-rw-r--r--src/reflect/value_test.go8
2 files changed, 53 insertions, 1 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index b9db1c421..49bd0a105 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -1052,9 +1052,53 @@ func (v Value) FieldByName(name string) Value {
panic("unimplemented: (reflect.Value).FieldByName()")
}
+//go:linkname hashmapMake runtime.hashmapMakeUnsafePointer
+func hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) unsafe.Pointer
+
+// MakeMapWithSize creates a new map with the specified type and initial space
+// for approximately n elements.
+func MakeMapWithSize(typ Type, n int) Value {
+
+ // TODO(dgryski): deduplicate these? runtime and reflect both need them.
+ const (
+ hashmapAlgorithmBinary uint8 = iota
+ hashmapAlgorithmString
+ hashmapAlgorithmInterface
+ )
+
+ if typ.Kind() != Map {
+ panic(&ValueError{"MakeMap", typ.Kind()})
+ }
+
+ if n < 0 {
+ panic("reflect.MakeMapWithSize: negative size hint")
+ }
+
+ key := typ.Key().(*rawType)
+ val := typ.Elem().(*rawType)
+
+ var alg uint8
+
+ if key.Kind() == String {
+ alg = hashmapAlgorithmString
+ } else if key.isBinary() {
+ alg = hashmapAlgorithmBinary
+ } else {
+ panic("reflect.MakeMap: unimplemented key type")
+ }
+
+ m := hashmapMake(key.Size(), val.Size(), uintptr(n), alg)
+
+ return Value{
+ typecode: typ.(*rawType),
+ value: m,
+ flags: valueFlagExported,
+ }
+}
+
// MakeMap creates a new map with the specified type.
func MakeMap(typ Type) Value {
- panic("unimplemented: reflect.MakeMap()")
+ return MakeMapWithSize(typ, 8)
}
func (v Value) Call(in []Value) []Value {
diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go
index 630cf516f..d9b4231dc 100644
--- a/src/reflect/value_test.go
+++ b/src/reflect/value_test.go
@@ -96,6 +96,14 @@ func TestMap(t *testing.T) {
t.Errorf("SetMapIndex(bar, 6) got %v, want %v", got, want)
}
+ m2ref := MakeMap(mref.Type())
+ m2ref.SetMapIndex(ValueOf("foo"), ValueOf(2))
+
+ m2 := m2ref.Interface().(map[string]int)
+
+ if m2["foo"] != 2 {
+ t.Errorf("MakeMap failed to create map")
+ }
}
func equal[T comparable](a, b []T) bool {