From 47923866ff3bd6d2ab93ad075fc1b29150e4bd51 Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Tue, 1 Oct 2019 06:28:04 +0930 Subject: [PATCH] interp: fix array size assignment type inference --- _test/a33.go | 12 ++++++++++++ _test/a34.go | 12 ++++++++++++ _test/a35.go | 13 +++++++++++++ _test/a36.go | 13 +++++++++++++ _test/a37.go | 11 +++++++++++ _test/a38.go | 11 +++++++++++ _test/a39.go | 12 ++++++++++++ interp/cfg.go | 17 ++++++++++++----- interp/run.go | 2 +- interp/type.go | 15 +++++++++------ 10 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 _test/a33.go create mode 100644 _test/a34.go create mode 100644 _test/a35.go create mode 100644 _test/a36.go create mode 100644 _test/a37.go create mode 100644 _test/a38.go create mode 100644 _test/a39.go diff --git a/_test/a33.go b/_test/a33.go new file mode 100644 index 00000000..acf78b30 --- /dev/null +++ b/_test/a33.go @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + a := [...]int{1, 2, 3} + b := a + fmt.Println(b) +} + +// Output: +// [1 2 3] diff --git a/_test/a34.go b/_test/a34.go new file mode 100644 index 00000000..c474f6a4 --- /dev/null +++ b/_test/a34.go @@ -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] diff --git a/_test/a35.go b/_test/a35.go new file mode 100644 index 00000000..28b42d76 --- /dev/null +++ b/_test/a35.go @@ -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] diff --git a/_test/a36.go b/_test/a36.go new file mode 100644 index 00000000..8408a991 --- /dev/null +++ b/_test/a36.go @@ -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] diff --git a/_test/a37.go b/_test/a37.go new file mode 100644 index 00000000..4aec9272 --- /dev/null +++ b/_test/a37.go @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + a := [...]int{1, 2, 3} + fmt.Println(a) +} + +// Output: +// [1 2 3] diff --git a/_test/a38.go b/_test/a38.go new file mode 100644 index 00000000..41429acf --- /dev/null +++ b/_test/a38.go @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + a := [...]byte{} + fmt.Printf("%T\n", a) +} + +// Output: +// [0]uint8 diff --git a/_test/a39.go b/_test/a39.go new file mode 100644 index 00000000..335e661c --- /dev/null +++ b/_test/a39.go @@ -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 diff --git a/interp/cfg.go b/interp/cfg.go index e7ae45dc..d237932b 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -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 diff --git a/interp/run.go b/interp/run.go index 7fedfac5..1bb8e0c8 100644 --- a/interp/run.go +++ b/interp/run.go @@ -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) diff --git a/interp/type.go b/interp/type.go index 38cfd2cd..1ec9ead1 100644 --- a/interp/type.go +++ b/interp/type.go @@ -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())