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:
committed by
Ludovic Fernandez
parent
73afc090bb
commit
63732d4326
@@ -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
12
_test/var5.go
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user