interp: fix array size assignment type inference

This commit is contained in:
Dan Kortschak
2019-10-01 06:28:04 +09:30
committed by Traefiker Bot
parent bb2921b42f
commit 47923866ff
10 changed files with 106 additions and 12 deletions

12
_test/a33.go Normal file
View File

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

12
_test/a34.go Normal file
View File

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

13
_test/a35.go Normal file
View File

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

13
_test/a36.go Normal file
View File

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

11
_test/a37.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]

11
_test/a38.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := [...]byte{}
fmt.Printf("%T\n", a)
}
// Output:
// [0]uint8

12
_test/a39.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
a := [...]byte{}
b := a
fmt.Printf("%T %T\n", a, b)
}
// Output:
// [0]uint8 [0]uint8

View File

@@ -395,11 +395,11 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
dest.typ = src.typ
}
if dest.typ.sizedef {
dest.typ.size = compositeArrayLen(src)
dest.typ.size = arrayTypeLen(src)
dest.typ.rtype = nil
}
if sc.global {
// Do not overload existings symbols (defined in GTA) in global scope
// Do not overload existing symbols (defined in GTA) in global scope
sym, _, _ = sc.lookup(dest.ident)
} else {
sym = &symbol{index: sc.add(dest.typ), kind: varSym, typ: dest.typ}
@@ -1739,13 +1739,20 @@ func compositeGenerator(n *node) (gen bltnGenerator) {
return
}
// compositeArrayLen return the litteral array length, computed from definition
func compositeArrayLen(n *node) int {
// arrayTypeLen returns the node's array length. If the expression is an
// array variable it is determined from the value's type, otherwise it is
// computed from the source definition.
func arrayTypeLen(n *node) int {
if n.typ != nil && n.typ.sizedef {
return n.typ.size
}
max := -1
for i, c := range n.child[1:] {
r := i
if c.kind == keyValueExpr {
r = int(c.child[0].rval.Int())
if v := c.child[0].rval; v.IsValid() {
r = int(c.child[0].rval.Int())
}
}
if r > max {
max = r

View File

@@ -1351,7 +1351,7 @@ func arrayLit(n *node) {
}
var a reflect.Value
if n.typ.size > 0 {
if n.typ.sizedef {
a, _ = n.typ.zero()
} else {
a = reflect.MakeSlice(n.typ.TypeOf(), max, max)

View File

@@ -123,10 +123,11 @@ type itype struct {
// nodeType returns a type definition for the corresponding AST subtree
func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
var err cfgError
if n.typ != nil && !n.typ.incomplete {
return n.typ, err
if n.kind == sliceExpr {
n.typ.sizedef = false
}
return n.typ, nil
}
var t = &itype{node: n, scope: sc}
@@ -141,6 +142,7 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
}
}
var err cfgError
switch n.kind {
case addressExpr, starExpr:
t.cat = ptrT
@@ -158,7 +160,7 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
t.size = int(n.child[0].rval.Int())
case n.child[0].kind == ellipsisExpr:
// [...]T expression
t.sizedef = true
t.size = arrayTypeLen(n.anc)
default:
if sym, _, ok := sc.lookup(n.child[0].ident); ok {
// Resolve symbol to get size value
@@ -182,6 +184,7 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
if t.val, err = nodeType(interp, sc, n.child[1]); err != nil {
return nil, err
}
t.sizedef = true
t.incomplete = t.incomplete || t.val.incomplete
} else {
if t.val, err = nodeType(interp, sc, n.child[0]); err != nil {
@@ -803,7 +806,7 @@ func (t *itype) refType(defined map[string]bool) reflect.Type {
case aliasT:
t.rtype = t.val.refType(defined)
case arrayT, variadicT:
if t.size > 0 {
if t.sizedef {
t.rtype = reflect.ArrayOf(t.size, t.val.refType(defined))
} else {
t.rtype = reflect.SliceOf(t.val.refType(defined))
@@ -866,7 +869,7 @@ func (t *itype) frameType() (r reflect.Type) {
case aliasT:
r = t.val.frameType()
case arrayT, variadicT:
if t.size > 0 {
if t.sizedef {
r = reflect.ArrayOf(t.size, t.val.frameType())
} else {
r = reflect.SliceOf(t.val.frameType())