Skip to content

Commit

Permalink
interp: fix array size assignment type inference
Browse files Browse the repository at this point in the history
  • Loading branch information
kortschak authored and traefiker committed Sep 30, 2019
1 parent bb2921b commit 4792386
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 12 deletions.
12 changes: 12 additions & 0 deletions _test/a33.go
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions _test/a34.go
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions _test/a35.go
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions _test/a36.go
Original file line number Diff line number Diff line change
@@ -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 changes: 11 additions & 0 deletions _test/a37.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import "fmt"

func main() {
a := [...]int{1, 2, 3}
fmt.Println(a)
}

// Output:
// [1 2 3]
11 changes: 11 additions & 0 deletions _test/a38.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import "fmt"

func main() {
a := [...]byte{}
fmt.Printf("%T\n", a)
}

// Output:
// [0]uint8
12 changes: 12 additions & 0 deletions _test/a39.go
Original file line number Diff line number Diff line change
@@ -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
17 changes: 12 additions & 5 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 9 additions & 6 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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())
Expand Down

0 comments on commit 4792386

Please sign in to comment.