Skip to content

Commit

Permalink
fix: correctly init variables from index expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
traefiker authored Mar 5, 2020
1 parent 2edd18a commit 0ace924
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 14 deletions.
20 changes: 20 additions & 0 deletions _test/type18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

type T struct {
name string
size int
}

var table = []*T{{
name: "foo",
size: 2,
}}

var s = table[0].size

func main() {
println(s)
}

// Output:
// 2
21 changes: 21 additions & 0 deletions _test/type19.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

type T struct {
name string
size int
}

var table = map[int]*T{
0: {
name: "foo",
size: 2,
}}

var s = table[0].size

func main() {
println(s)
}

// Output:
// 2
27 changes: 19 additions & 8 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
n.findex = sc.add(n.typ)
}
// TODO: Check that composite literal expr matches corresponding type
n.gen = compositeGenerator(n)
n.gen = compositeGenerator(n, sc)

case fallthroughtStmt:
if n.anc.kind != caseBody {
Expand Down Expand Up @@ -1869,21 +1869,32 @@ func gotoLabel(s *symbol) {
}
}

func compositeGenerator(n *node) (gen bltnGenerator) {
func compositeGenerator(n *node, sc *scope) (gen bltnGenerator) {
switch n.typ.cat {
case aliasT, ptrT:
n.typ.val.untyped = n.typ.untyped
n.typ = n.typ.val
gen = compositeGenerator(n)
gen = compositeGenerator(n, sc)
case arrayT:
gen = arrayLit
case mapT:
gen = mapLit
case structT:
if len(n.child) > 0 && n.lastChild().kind == keyValueExpr {
gen = compositeSparse
} else {
gen = compositeLit
switch {
case len(n.child) == 0:
gen = compositeLitNotype
case n.lastChild().kind == keyValueExpr:
if n.child[0].isType(sc) {
gen = compositeSparse
} else {
gen = compositeSparseNotype
}
default:
if n.child[0].isType(sc) {
gen = compositeLit
} else {
gen = compositeLitNotype
}
}
case valueT:
switch k := n.typ.rtype.Kind(); k {
Expand All @@ -1895,7 +1906,7 @@ func compositeGenerator(n *node) (gen bltnGenerator) {
log.Panic(n.cfgErrorf("compositeGenerator not implemented for type kind: %s", k))
}
}
return
return gen
}

// arrayTypeLen returns the node's array length. If the expression is an
Expand Down
18 changes: 12 additions & 6 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -1680,12 +1680,12 @@ func destType(n *node) *itype {
}
}

// compositeLit creates and populates a struct object
func compositeLit(n *node) {
// doCompositeLit creates and populates a struct object
func doCompositeLit(n *node, hasType bool) {
value := valueGenerator(n, n.findex)
next := getExec(n.tnext)
child := n.child
if !n.typ.untyped {
if hasType {
child = n.child[1:]
}
destInterface := destType(n).cat == interfaceT
Expand Down Expand Up @@ -1717,12 +1717,15 @@ func compositeLit(n *node) {
}
}

// compositeSparse creates a struct Object, filling fields from sparse key-values
func compositeSparse(n *node) {
func compositeLit(n *node) { doCompositeLit(n, true) }
func compositeLitNotype(n *node) { doCompositeLit(n, false) }

// doCompositeSparse creates a struct Object, filling fields from sparse key-values
func doCompositeSparse(n *node, hasType bool) {
value := valueGenerator(n, n.findex)
next := getExec(n.tnext)
child := n.child
if !n.typ.untyped {
if hasType {
child = n.child[1:]
}

Expand Down Expand Up @@ -1752,6 +1755,9 @@ func compositeSparse(n *node) {
}
}

func compositeSparse(n *node) { doCompositeSparse(n, true) }
func compositeSparseNotype(n *node) { doCompositeSparse(n, false) }

func empty(n *node) {}

var rat = reflect.ValueOf((*[]rune)(nil)).Type().Elem() // runes array type
Expand Down
14 changes: 14 additions & 0 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,20 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
sc.sym[n.ident] = &symbol{kind: typeSym, typ: t}
}

case indexExpr:
var lt *itype
if lt, err = nodeType(interp, sc, n.child[0]); err != nil {
return nil, err
}
if lt.incomplete {
t.incomplete = true
break
}
switch lt.cat {
case arrayT, mapT:
t = lt.val
}

case interfaceType:
t.cat = interfaceT
if sname := typeName(n); sname != "" {
Expand Down

0 comments on commit 0ace924

Please sign in to comment.