interp: fix map range handling

This commit is contained in:
Dan Kortschak
2019-10-01 21:24:03 +09:30
committed by Traefiker Bot
parent 47923866ff
commit 4bf4aeecbb
7 changed files with 89 additions and 17 deletions

View File

@@ -19,7 +19,6 @@ cache:
matrix:
fast_finish: true
include:
- go: 1.11.x
- go: 1.12.x
- go: 1.13.x
env: STABLE=true

14
_test/range3.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
m := map[int]bool{1: true, 3: true, 5: true}
for k := range m {
m[k*2] = true
}
fmt.Println("ok")
}
// Output:
// ok

15
_test/range4.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import "fmt"
func main() {
m := map[int]bool{1: true, 3: true, 5: true}
for _, v := range m {
fmt.Println(v)
}
}
// Output:
// true
// true
// true

15
_test/range5.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import "fmt"
func main() {
m := map[int]bool{1: true, 3: true, 5: true}
var n int
for range m {
n++
}
fmt.Println(n)
}
// Output:
// 3

18
_test/range6.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"fmt"
"math"
)
func main() {
m := map[float64]bool{math.NaN(): true, math.NaN(): true, math.NaN(): true}
for _, v := range m {
fmt.Println(v)
}
}
// Output:
// true
// true
// true

View File

@@ -87,6 +87,8 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
}
case mapT:
n.anc.gen = rangeMap
ityp := &itype{cat: valueT, rtype: reflect.TypeOf((*reflect.MapIter)(nil))}
sc.add(ityp)
ktyp = o.typ.key
vtyp = o.typ.val
case ptrT:

View File

@@ -1601,31 +1601,40 @@ func rangeChan(n *node) {
}
func rangeMap(n *node) {
index0 := n.child[0].findex // array index location in frame
index1 := n.child[1].findex // array value location in frame
value := genValue(n.child[2]) // array
index0 := n.child[0].findex // map index location in frame
index2 := index0 - 1 // iterator for range, always just behind index0
fnext := getExec(n.fnext)
tnext := getExec(n.tnext)
// TODO: move i and keys to frame
var i int
var keys []reflect.Value
var value func(*frame) reflect.Value
if len(n.child) == 4 {
index1 := n.child[1].findex // map value location in frame
value = genValue(n.child[2]) // map
n.exec = func(f *frame) bltn {
a := value(f)
i++
if i >= a.Len() {
iter := f.data[index2].Interface().(*reflect.MapIter)
if !iter.Next() {
return fnext
}
f.data[index0].Set(keys[i])
f.data[index1].Set(a.MapIndex(keys[i]))
f.data[index0].Set(iter.Key())
f.data[index1].Set(iter.Value())
return tnext
}
} else {
value = genValue(n.child[1]) // map
n.exec = func(f *frame) bltn {
iter := f.data[index2].Interface().(*reflect.MapIter)
if !iter.Next() {
return fnext
}
f.data[index0].Set(iter.Key())
return tnext
}
}
// Init sequence
next := n.exec
n.child[0].exec = func(f *frame) bltn {
keys = value(f).MapKeys()
i = -1
f.data[index2].Set(reflect.ValueOf(value(f).MapRange()))
return next
}
}