interp: fix range expression handling
This commit is contained in:
committed by
Traefiker Bot
parent
2c2b471cb9
commit
bb2921b42f
14
_test/range0.go
Normal file
14
_test/range0.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
v := []int{1, 2, 3}
|
||||
for i := range v {
|
||||
v = append(v, i)
|
||||
}
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [1 2 3 0 1 2]
|
||||
14
_test/range1.go
Normal file
14
_test/range1.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
a := [...]int{2, 1, 0}
|
||||
for _, v := range a {
|
||||
a[v] = v
|
||||
}
|
||||
fmt.Println(a)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [0 1 2]
|
||||
14
_test/range2.go
Normal file
14
_test/range2.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
a := [...]int{2, 1, 0}
|
||||
for _, v := range &a {
|
||||
a[v] = v
|
||||
}
|
||||
fmt.Println(a)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [2 1 2]
|
||||
@@ -77,9 +77,11 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
ktyp = &itype{cat: valueT, rtype: typ.Key()}
|
||||
vtyp = &itype{cat: valueT, rtype: typ.Elem()}
|
||||
case reflect.String:
|
||||
sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
|
||||
ktyp = sc.getType("int")
|
||||
vtyp = sc.getType("rune")
|
||||
case reflect.Array, reflect.Slice:
|
||||
sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
|
||||
ktyp = sc.getType("int")
|
||||
vtyp = &itype{cat: valueT, rtype: typ.Elem()}
|
||||
}
|
||||
@@ -96,9 +98,11 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
vtyp = vtyp.val
|
||||
}
|
||||
case stringT:
|
||||
sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
|
||||
ktyp = sc.getType("int")
|
||||
vtyp = sc.getType("rune")
|
||||
case arrayT, variadicT:
|
||||
sc.add(sc.getType("int")) // Add a dummy type to store array shallow copy for range
|
||||
ktyp = sc.getType("int")
|
||||
vtyp = o.typ.val
|
||||
}
|
||||
|
||||
@@ -1534,6 +1534,7 @@ var rat = reflect.ValueOf((*[]rune)(nil)).Type().Elem() // runes array type
|
||||
|
||||
func _range(n *node) {
|
||||
index0 := n.child[0].findex // array index location in frame
|
||||
index2 := index0 - 1 // shallow array for range, always just behind index0
|
||||
fnext := getExec(n.fnext)
|
||||
tnext := getExec(n.tnext)
|
||||
|
||||
@@ -1544,10 +1545,10 @@ func _range(n *node) {
|
||||
if isString(an.typ.TypeOf()) {
|
||||
value = genValueAs(an, rat) // range on string iterates over runes
|
||||
} else {
|
||||
value = genValueArray(an)
|
||||
value = genValueRangeArray(an)
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
a := value(f)
|
||||
a := f.data[index2]
|
||||
v0 := f.data[index0]
|
||||
v0.SetInt(v0.Int() + 1)
|
||||
i := int(v0.Int())
|
||||
@@ -1562,13 +1563,12 @@ func _range(n *node) {
|
||||
if isString(an.typ.TypeOf()) {
|
||||
value = genValueAs(an, rat) // range on string iterates over runes
|
||||
} else {
|
||||
value = genValueArray(an)
|
||||
value = genValueRangeArray(an)
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
a := value(f)
|
||||
v0 := f.data[index0]
|
||||
v0.SetInt(v0.Int() + 1)
|
||||
if int(v0.Int()) >= a.Len() {
|
||||
if int(v0.Int()) >= f.data[index2].Len() {
|
||||
return fnext
|
||||
}
|
||||
return tnext
|
||||
@@ -1578,7 +1578,8 @@ func _range(n *node) {
|
||||
// Init sequence
|
||||
next := n.exec
|
||||
n.child[0].exec = func(f *frame) bltn {
|
||||
f.data[index0].SetInt(-1)
|
||||
f.data[index2] = value(f) // set array shallow copy for range
|
||||
f.data[index0].SetInt(-1) // assing index value
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,22 @@ func genValueArray(n *node) func(*frame) reflect.Value {
|
||||
return value
|
||||
}
|
||||
|
||||
func genValueRangeArray(n *node) func(*frame) reflect.Value {
|
||||
value := genValue(n)
|
||||
// dereference array pointer, to support array operations on array pointer
|
||||
if n.typ.TypeOf().Kind() == reflect.Ptr {
|
||||
return func(f *frame) reflect.Value {
|
||||
return value(f).Elem()
|
||||
}
|
||||
}
|
||||
return func(f *frame) reflect.Value {
|
||||
// This is necessary to prevent changes in the returned
|
||||
// reflect.Value being reflected back to the value used
|
||||
// for the range expression.
|
||||
return reflect.ValueOf(value(f).Interface())
|
||||
}
|
||||
}
|
||||
|
||||
func genValueInterfacePtr(n *node) func(*frame) reflect.Value {
|
||||
value := genValue(n)
|
||||
it := reflect.TypeOf((*interface{})(nil)).Elem()
|
||||
|
||||
Reference in New Issue
Block a user