From a99fb98f84d2106f497a2593cc753589174c86a7 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Wed, 6 Feb 2019 14:50:37 +0100 Subject: [PATCH] fix: append() was not returning a type (#84) append() now returns the underlying array type. Method lookup was skipped for selector expression on arrays. Pointer expression was incorrectly parsed as a dereference instead of type expression. --- _test/a20.go | 19 +++++++++++++++++++ interp/cfg.go | 17 +++++++++++------ interp/interp_test.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 _test/a20.go diff --git a/_test/a20.go b/_test/a20.go new file mode 100644 index 00000000..02f951ef --- /dev/null +++ b/_test/a20.go @@ -0,0 +1,19 @@ +package main + +import "fmt" + +type IntArray []int + +func (h *IntArray) Add(x int) { + *h = append(*h, x) +} + +func main() { + a := IntArray{} + a.Add(4) + + fmt.Println(a) +} + +// Output: +// [4] diff --git a/interp/cfg.go b/interp/cfg.go index 34833314..8b559e3f 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -450,6 +450,10 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) { n.gen = n.child[0].sym.builtin n.child[0].typ = &Type{cat: BuiltinT} switch n.child[0].ident { + case "append": + if n.typ = scope.getType(n.child[1].ident); n.typ == nil { + n.typ, err = nodeType(interp, scope, n.child[1]) + } case "cap", "len": n.typ = scope.getType("int") case "make": @@ -472,7 +476,7 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) { n.typ = &Type{cat: ValueT, rtype: typ.Out(0)} } } else if typ := n.child[0].typ; len(typ.ret) > 0 { - n.typ = n.child[0].typ.ret[0] + n.typ = typ.ret[0] n.fsize = len(typ.ret) } @@ -877,9 +881,6 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) { n.fsize = s.NumOut() } } - } else if n.typ.cat == ArrayT { - n.typ = n.typ.val - n.gen = nop } else if n.typ.cat == SrcPkgT { // Resolve source package symbol if sym, ok := interp.scope[n.child[0].ident].sym[n.child[1].ident]; ok { @@ -914,10 +915,14 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) { } case StarExpr: - if n.anc.kind == Define && len(n.anc.child) == 3 && n.anc.child[1] == n { + switch { + case 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 { + case n.anc.kind == Field: + // pointer type expression in a field expression (arg or struct field) + n.gen = nop + default: // dereference expression wireChild(n) n.typ = n.child[0].typ.val diff --git a/interp/interp_test.go b/interp/interp_test.go index 581c5ff4..2f044b47 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -326,6 +326,36 @@ func main() { // 4 } +func Example_a20() { + src := ` +package main + +import "fmt" + +type IntArray []int + +func (h *IntArray) Add(x int) { + *h = append(*h, x) +} + +func main() { + a := IntArray{} + a.Add(4) + + fmt.Println(a) +} +` + i := interp.New(interp.Opt{Entry: "main"}) + i.Use(stdlib.Value, stdlib.Type) + _, err := i.Eval(src) + if err != nil { + panic(err) + } + + // Output: + // [4] +} + func Example_a3() { src := ` package main