diff options
author | Damian Gryski <[email protected]> | 2023-02-25 14:48:58 -0800 |
---|---|---|
committer | Ayke <[email protected]> | 2023-02-28 13:10:40 -0800 |
commit | c4dadbaaab353ff820e094b6265ffc6382ffcdc8 (patch) | |
tree | b2c74efd961e6e745ce2612ede74e34582eccdfc | |
parent | 828c3169ab688039e1b869b059b9696e27d4ec19 (diff) | |
download | tinygo-c4dadbaaab353ff820e094b6265ffc6382ffcdc8.tar.gz tinygo-c4dadbaaab353ff820e094b6265ffc6382ffcdc8.zip |
reflect: add MakeMap()
-rw-r--r-- | src/reflect/value.go | 46 | ||||
-rw-r--r-- | src/reflect/value_test.go | 8 |
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 { |