Skip to content

Commit f8a1e5f

Browse files
kyegupovaykevl
authored andcommitted
interp: support map literals with integer keys
1 parent 0308c92 commit f8a1e5f

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

interp/frame.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,18 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
244244
case callee.Name() == "runtime.hashmapStringSet":
245245
// set a string key in the map
246246
m := fr.getLocal(inst.Operand(0)).(*MapValue)
247+
// "key" is a Go string value, which in the TinyGo calling convention is split up
248+
// into separate pointer and length parameters.
247249
keyBuf := fr.getLocal(inst.Operand(1))
248250
keyLen := fr.getLocal(inst.Operand(2))
249251
valPtr := fr.getLocal(inst.Operand(3))
250252
m.PutString(keyBuf, keyLen, valPtr)
251253
case callee.Name() == "runtime.hashmapBinarySet":
252254
// set a binary (int etc.) key in the map
253-
// TODO: unimplemented
255+
m := fr.getLocal(inst.Operand(0)).(*MapValue)
256+
keyBuf := fr.getLocal(inst.Operand(1))
257+
valPtr := fr.getLocal(inst.Operand(2))
258+
m.PutBinary(keyBuf, valPtr)
254259
case callee.Name() == "runtime.stringConcat":
255260
// adding two strings together
256261
buf1Ptr := fr.getLocal(inst.Operand(0))

interp/values.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,38 @@ func (v *MapValue) PutString(keyBuf, keyLen, valPtr Value) {
561561
v.Values = append(v.Values, &LocalValue{v.Eval, value})
562562
}
563563

564+
// PutBinary does a map assign operation.
565+
func (v *MapValue) PutBinary(keyPtr, valPtr Value) {
566+
if !v.Underlying.IsNil() {
567+
panic("map already created")
568+
}
569+
570+
var value llvm.Value
571+
switch valPtr := valPtr.(type) {
572+
case *PointerCastValue:
573+
value = valPtr.Underlying.Load()
574+
if v.ValueType.IsNil() {
575+
v.ValueType = value.Type()
576+
if int(v.Eval.TargetData.TypeAllocSize(v.ValueType)) != v.ValueSize {
577+
panic("interp: map store value type has the wrong size")
578+
}
579+
} else {
580+
if value.Type() != v.ValueType {
581+
panic("interp: map store value type is inconsistent")
582+
}
583+
}
584+
default:
585+
panic("interp: todo: handle map value pointer")
586+
}
587+
588+
key := keyPtr.(*PointerCastValue).Underlying.Load()
589+
v.KeyType = key.Type()
590+
591+
// TODO: avoid duplicate keys
592+
v.Keys = append(v.Keys, &LocalValue{v.Eval, key})
593+
v.Values = append(v.Values, &LocalValue{v.Eval, value})
594+
}
595+
564596
// Get FNV-1a hash of this string.
565597
//
566598
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash

testdata/map.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var testmap2 = map[string]int{
1515
"eleven": 11,
1616
"twelve": 12,
1717
}
18+
var testmapIntInt = map[int]int{1: 1, 2: 4, 3: 9}
1819

1920
func main() {
2021
m := map[string]int{"answer": 42, "foo": 3}
@@ -31,6 +32,9 @@ func main() {
3132
var nilmap map[string]int
3233
println(m == nil, m != nil, len(m))
3334
println(nilmap == nil, nilmap != nil, len(nilmap))
35+
println(testmapIntInt[2])
36+
testmapIntInt[2] = 42
37+
println(testmapIntInt[2])
3438
}
3539

3640
func readMap(m map[string]int, key string) {

testdata/map.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,5 @@ lookup with comma-ok: eight 8 true
5050
lookup with comma-ok: nokey 0 false
5151
false true 2
5252
true false 0
53+
4
54+
42

0 commit comments

Comments
 (0)