interp: support map literals with integer keys
Этот коммит содержится в:
родитель
0308c92e67
коммит
f8a1e5f449
4 изменённых файлов: 44 добавлений и 1 удалений
|
@ -244,13 +244,18 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
|
|||
case callee.Name() == "runtime.hashmapStringSet":
|
||||
// set a string key in the map
|
||||
m := fr.getLocal(inst.Operand(0)).(*MapValue)
|
||||
// "key" is a Go string value, which in the TinyGo calling convention is split up
|
||||
// into separate pointer and length parameters.
|
||||
keyBuf := fr.getLocal(inst.Operand(1))
|
||||
keyLen := fr.getLocal(inst.Operand(2))
|
||||
valPtr := fr.getLocal(inst.Operand(3))
|
||||
m.PutString(keyBuf, keyLen, valPtr)
|
||||
case callee.Name() == "runtime.hashmapBinarySet":
|
||||
// set a binary (int etc.) key in the map
|
||||
// TODO: unimplemented
|
||||
m := fr.getLocal(inst.Operand(0)).(*MapValue)
|
||||
keyBuf := fr.getLocal(inst.Operand(1))
|
||||
valPtr := fr.getLocal(inst.Operand(2))
|
||||
m.PutBinary(keyBuf, valPtr)
|
||||
case callee.Name() == "runtime.stringConcat":
|
||||
// adding two strings together
|
||||
buf1Ptr := fr.getLocal(inst.Operand(0))
|
||||
|
|
|
@ -561,6 +561,38 @@ func (v *MapValue) PutString(keyBuf, keyLen, valPtr Value) {
|
|||
v.Values = append(v.Values, &LocalValue{v.Eval, value})
|
||||
}
|
||||
|
||||
// PutBinary does a map assign operation.
|
||||
func (v *MapValue) PutBinary(keyPtr, valPtr Value) {
|
||||
if !v.Underlying.IsNil() {
|
||||
panic("map already created")
|
||||
}
|
||||
|
||||
var value llvm.Value
|
||||
switch valPtr := valPtr.(type) {
|
||||
case *PointerCastValue:
|
||||
value = valPtr.Underlying.Load()
|
||||
if v.ValueType.IsNil() {
|
||||
v.ValueType = value.Type()
|
||||
if int(v.Eval.TargetData.TypeAllocSize(v.ValueType)) != v.ValueSize {
|
||||
panic("interp: map store value type has the wrong size")
|
||||
}
|
||||
} else {
|
||||
if value.Type() != v.ValueType {
|
||||
panic("interp: map store value type is inconsistent")
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic("interp: todo: handle map value pointer")
|
||||
}
|
||||
|
||||
key := keyPtr.(*PointerCastValue).Underlying.Load()
|
||||
v.KeyType = key.Type()
|
||||
|
||||
// TODO: avoid duplicate keys
|
||||
v.Keys = append(v.Keys, &LocalValue{v.Eval, key})
|
||||
v.Values = append(v.Values, &LocalValue{v.Eval, value})
|
||||
}
|
||||
|
||||
// Get FNV-1a hash of this string.
|
||||
//
|
||||
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash
|
||||
|
|
4
testdata/map.go
предоставленный
4
testdata/map.go
предоставленный
|
@ -15,6 +15,7 @@ var testmap2 = map[string]int{
|
|||
"eleven": 11,
|
||||
"twelve": 12,
|
||||
}
|
||||
var testmapIntInt = map[int]int{1: 1, 2: 4, 3: 9}
|
||||
|
||||
func main() {
|
||||
m := map[string]int{"answer": 42, "foo": 3}
|
||||
|
@ -31,6 +32,9 @@ func main() {
|
|||
var nilmap map[string]int
|
||||
println(m == nil, m != nil, len(m))
|
||||
println(nilmap == nil, nilmap != nil, len(nilmap))
|
||||
println(testmapIntInt[2])
|
||||
testmapIntInt[2] = 42
|
||||
println(testmapIntInt[2])
|
||||
}
|
||||
|
||||
func readMap(m map[string]int, key string) {
|
||||
|
|
2
testdata/map.txt
предоставленный
2
testdata/map.txt
предоставленный
|
@ -50,3 +50,5 @@ lookup with comma-ok: eight 8 true
|
|||
lookup with comma-ok: nokey 0 false
|
||||
false true 2
|
||||
true false 0
|
||||
4
|
||||
42
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче