From 17d5f1814af8f4b567f43fb617f2573fce0c8139 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Fri, 30 Apr 2021 11:26:04 +0200 Subject: [PATCH] interp: fix support of interpreted functions in map values Interpreted functions were represented in an inconsistent way in the frame: as a node pointer by default, and wrapped in a function wrapper for maps. We now simply use the default (*node) representation, as elsewhere, so values can be assigned, passed and called as for the other types. The alternative (generating a function wrapper) is more complex, costly and reserved for cases where the interpreted function can be called from the runtime. Test that a map of functions can store both binary functions from used packages and interpreted ones. Fixes #1090. --- _test/map30.go | 22 ++++++++++++++++++++++ interp/run.go | 4 ++-- interp/type.go | 2 ++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 _test/map30.go diff --git a/_test/map30.go b/_test/map30.go new file mode 100644 index 00000000..7157cdb0 --- /dev/null +++ b/_test/map30.go @@ -0,0 +1,22 @@ +package main + +import "strings" + +func f(s string) string { return "hello " + s } + +func g(s string) string { return "hi " + s } + +var methods = map[string]func(string) string{"f": f} + +func main() { + methods["i"] = strings.ToUpper + methods["g"] = g + println(methods["f"]("test")) + println(methods["g"]("test")) + println(methods["i"]("test")) +} + +// Output: +// hello test +// hi test +// TEST diff --git a/interp/run.go b/interp/run.go index db01334f..af2044a1 100644 --- a/interp/run.go +++ b/interp/run.go @@ -2349,7 +2349,7 @@ func mapLit(n *node) { if n.nleft == 1 { child = n.child[1:] } - typ := n.typ.TypeOf() + typ := n.typ.frameType() keys := make([]func(*frame) reflect.Value, len(child)) values := make([]func(*frame) reflect.Value, len(child)) for i, c := range child { @@ -2384,7 +2384,7 @@ func compositeBinMap(n *node) { if n.nleft == 1 { child = n.child[1:] } - typ := n.typ.TypeOf() + typ := n.typ.frameType() keys := make([]func(*frame) reflect.Value, len(child)) values := make([]func(*frame) reflect.Value, len(child)) for i, c := range child { diff --git a/interp/type.go b/interp/type.go index e88f25a6..9d2024c3 100644 --- a/interp/type.go +++ b/interp/type.go @@ -1554,6 +1554,8 @@ func (t *itype) frameType() (r reflect.Type) { break } r = reflect.TypeOf((*valueInterface)(nil)).Elem() + case mapT: + r = reflect.MapOf(t.key.frameType(), t.val.frameType()) case ptrT: r = reflect.PtrTo(t.val.frameType()) default: