fix: set type correctly for variable declaration with assignment (#59)

Do not ignore type node when used in a variable declaration with assign.
The source node in a assign node can be the 2nd or the 3rd (the 2nd being the type).
This commit is contained in:
Marc Vertes
2019-01-28 16:00:15 +01:00
committed by Ludovic Fernandez
parent 73afc090bb
commit 63732d4326
5 changed files with 74 additions and 35 deletions

View File

@@ -1,15 +1,13 @@
package main
type T int
func (t T) foo() { println("foo", t) }
func main() {
o := Coord{3, 4}
println(o.dist())
}
func (c Coord) dist() int { return c.x*c.x + c.y*c.y }
type Coord struct {
x, y int
var t T = 2
t.foo()
}
// Output:
// 25
// foo 2

12
_test/var5.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
var a int64 = 64
fmt.Printf("a: %v %T", a, a)
fmt.Println()
}
// Output:
// a: 64 int64

View File

@@ -148,10 +148,6 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
if l := len(n.child); n.anc.kind == ConstDecl && l == 1 {
// Implicit iota assignment. TODO: replicate previous explicit assignment
n.child = append(n.child, &Node{anc: n, interp: interp, kind: Ident, ident: "iota"})
} else if l%2 == 1 {
// Odd number of children: remove the type node, useless for assign
i := l / 2
n.child = append(n.child[:i], n.child[i+1:]...)
}
case BlockStmt:
@@ -221,9 +217,6 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
case If0, If1, If2, If3:
scope = scope.push(0)
//case SelectStmt:
// err = CfgError(fmt.Errorf("cfg: SelectStmt not implemented; %s", n.fset.Position(n.pos)))
case Switch0:
// Make sure default clause is in last position
c := n.child[1].child
@@ -253,12 +246,16 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
n.findex = scope.inc(interp)
case Define, AssignStmt:
wireChild(n)
dest, src := n.child[0], n.child[1]
dest, src := n.child[0], n.child[len(n.child)-1]
sym, level, _ := scope.lookup(dest.ident)
if n.kind == Define {
if len(n.child) == 3 {
// Type is provided in var declaration
dest.typ, err = nodeType(interp, scope, n.child[1])
} else {
dest.typ = src.typ
}
dest.val = src.val
dest.typ = src.typ
dest.recv = src.recv
dest.findex = sym.index
if src.action == GetFunc {
@@ -273,6 +270,7 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
sym.typ = dest.typ
}
}
wireChild(n)
// Detect invalid float truncate
if isInt(dest.typ) && isFloat(src.typ) {
err = src.cfgError("invalid float truncate")
@@ -293,9 +291,13 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
src.level = level
case src.kind == BasicLit:
// TODO: perform constant folding and propagation here
// Convert literal value to destination type
src.val = reflect.ValueOf(src.val).Convert(dest.typ.TypeOf())
src.typ = dest.typ
if dest.typ.cat == InterfaceT {
src.val = reflect.ValueOf(src.val)
} else {
// Convert literal value to destination type
src.val = reflect.ValueOf(src.val).Convert(dest.typ.TypeOf())
src.typ = dest.typ
}
}
n.typ = dest.typ
if sym != nil {
@@ -895,9 +897,15 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
}
case StarExpr:
wireChild(n)
n.typ = n.child[0].typ.val
n.findex = scope.inc(interp)
if n.anc.kind == Define && len(n.anc.child) == 3 && n.anc.child[1] == n {
// pointer type expression in a var definition
n.gen = nop
} else {
// dereference expression
wireChild(n)
n.typ = n.child[0].typ.val
n.findex = scope.inc(interp)
}
case Switch0:
n.start = n.child[1].start

View File

@@ -2926,15 +2926,13 @@ func Example_method10() {
src := `
package main
type T int
func (t T) foo() { println("foo", t) }
func main() {
o := Coord{3, 4}
println(o.dist())
}
func (c Coord) dist() int { return c.x*c.x + c.y*c.y }
type Coord struct {
x, y int
var t T = 2
t.foo()
}
`
i := interp.New(interp.Opt{Entry: "main"})
@@ -2945,7 +2943,7 @@ type Coord struct {
}
// Output:
// 25
// foo 2
}
func Example_method11() {
@@ -5709,6 +5707,29 @@ func main() {
// 2 3
}
func Example_var5() {
src := `
package main
import "fmt"
func main() {
var a int64 = 64
fmt.Printf("a: %v %T", a, a)
fmt.Println()
}
`
i := interp.New(interp.Opt{Entry: "main"})
i.Use(stdlib.Value, stdlib.Type)
_, err := i.Eval(src)
if err != nil {
panic(err)
}
// Output:
// a: 64 int64
}
func Example_variadic() {
src := `
package main

View File

@@ -185,7 +185,7 @@ func assignX(n *Node) {
// assign implements single value assignment
func assign(n *Node) {
value := genValue(n)
value1 := genValue(n.child[1])
value1 := genValue(n.child[len(n.child)-1])
next := getExec(n.tnext)
if n.child[0].typ.cat == InterfaceT {