fix: support array operations on array pointers

This commit is contained in:
Marc Vertes
2019-09-18 23:32:04 +02:00
committed by Traefiker Bot
parent e03016b6d7
commit ec1ee5f5b6
8 changed files with 122 additions and 12 deletions

14
_test/copy1.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
a := []int{10, 20, 30}
b := &[4]int{}
c := b[:]
copy(c, a)
fmt.Println(c)
}
// Output:
// [10 20 30 0]

13
_test/ptr_array0.go Normal file
View File

@@ -0,0 +1,13 @@
package main
type T [2]int
func F0(t *T) int { return t[0] }
func main() {
t := &T{1, 2}
println(F0(t))
}
// Output:
// 1

19
_test/ptr_array1.go Normal file
View File

@@ -0,0 +1,19 @@
package main
type T [3]int
func F0(t *T) {
for i, v := range t {
println(i, v)
}
}
func main() {
t := &T{1, 2, 3}
F0(t)
}
// Output:
// 0 1
// 1 2
// 2 3

16
_test/ptr_array2.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import "fmt"
type T [2]int
func F1(t *T) { t[0] = 1 }
func main() {
t := &T{}
F1(t)
fmt.Println(t)
}
// Output:
// &[1 0]

11
_test/ptr_array3.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := &[...]int{1, 2, 3}
fmt.Println(a[:])
}
// Output:
// [1 2 3]

View File

@@ -86,6 +86,14 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
n.anc.gen = rangeMap
ktyp = o.typ.key
vtyp = o.typ.val
case ptrT:
ktyp = sc.getType("int")
vtyp = o.typ.val
if vtyp.cat == valueT {
vtyp = &itype{cat: valueT, rtype: vtyp.rtype.Elem()}
} else {
vtyp = vtyp.val
}
case stringT:
ktyp = sc.getType("int")
vtyp = sc.getType("byte")
@@ -569,20 +577,34 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
wireChild(n)
t := n.child[0].typ
switch t.cat {
case valueT:
n.typ = &itype{cat: valueT, rtype: t.rtype.Elem()}
case ptrT:
n.typ = t.val
if t.val.cat == valueT {
n.typ = &itype{cat: valueT, rtype: t.val.rtype.Elem()}
} else {
n.typ = t.val.val
}
case stringT:
n.typ = sc.getType("byte")
case valueT:
n.typ = &itype{cat: valueT, rtype: t.rtype.Elem()}
default:
n.typ = t.val
}
n.findex = sc.add(n.typ)
n.recv = &receiver{node: n}
switch k := t.TypeOf().Kind(); k {
typ := t.TypeOf()
switch k := typ.Kind(); k {
case reflect.Map:
n.gen = getIndexMap
case reflect.Array, reflect.Slice, reflect.String:
n.gen = getIndexArray
case reflect.Ptr:
if typ2 := typ.Elem(); typ2.Kind() == reflect.Array {
n.gen = getIndexArray
} else {
err = n.cfgErrorf("type %v does not support indexing", typ)
}
default:
err = n.cfgErrorf("type is not an array, slice, string or map: %v", t.id())
}
@@ -1253,7 +1275,11 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
case sliceExpr:
wireChild(n)
if ctyp := n.child[0].typ; ctyp.size != 0 {
ctyp := n.child[0].typ
if ctyp.cat == ptrT {
ctyp = ctyp.val
}
if ctyp.size != 0 {
// Create a slice type from an array type
n.typ = &itype{}
*n.typ = *ctyp

View File

@@ -887,7 +887,7 @@ func getIndexBinPtrMethod(n *node) {
// getIndexArray returns array value from index
func getIndexArray(n *node) {
tnext := getExec(n.tnext)
value0 := genValue(n.child[0]) // array
value0 := genValueArray(n.child[0]) // array
if n.child[1].rval.IsValid() { // constant array index
ai := int(vInt(n.child[1].rval))
@@ -1505,8 +1505,8 @@ func _range(n *node) {
tnext := getExec(n.tnext)
if len(n.child) == 4 {
index1 := n.child[1].findex // array value location in frame
value := genValue(n.child[2]) // array
index1 := n.child[1].findex // array value location in frame
value := genValueArray(n.child[2]) // array
n.exec = func(f *frame) bltn {
a := value(f)
v0 := f.data[index0]
@@ -1519,7 +1519,7 @@ func _range(n *node) {
return tnext
}
} else {
value := genValue(n.child[1]) // array
value := genValueArray(n.child[1]) // array
n.exec = func(f *frame) bltn {
a := value(f)
v0 := f.data[index0]
@@ -1780,7 +1780,7 @@ func _cap(n *node) {
func _copy(n *node) {
dest := genValue(n)
value0 := genValue(n.child[1])
value0 := genValueArray(n.child[1])
value1 := genValue(n.child[2])
next := getExec(n.tnext)
@@ -2109,8 +2109,8 @@ func _select(n *node) {
func slice(n *node) {
i := n.findex
next := getExec(n.tnext)
value0 := genValue(n.child[0]) // array
value1 := genValue(n.child[1]) // low (if 2 or 3 args) or high (if 1 arg)
value0 := genValueArray(n.child[0]) // array
value1 := genValue(n.child[1]) // low (if 2 or 3 args) or high (if 1 arg)
switch len(n.child) {
case 2:
@@ -2143,7 +2143,7 @@ func slice(n *node) {
func slice0(n *node) {
i := n.findex
next := getExec(n.tnext)
value0 := genValue(n.child[0])
value0 := genValueArray(n.child[0])
switch len(n.child) {
case 1:

View File

@@ -107,6 +107,17 @@ func genValue(n *node) func(*frame) reflect.Value {
}
}
func genValueArray(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 value
}
func genValueInterfacePtr(n *node) func(*frame) reflect.Value {
value := genValue(n)
it := reflect.TypeOf((*interface{})(nil)).Elem()