Skip to content

Commit

Permalink
interp: add a function to get globals (#1387)
Browse files Browse the repository at this point in the history
Co-authored-by: Marc Vertes <mvertes@free.fr>
  • Loading branch information
firelizzard18 and mvertes committed Apr 25, 2022
1 parent 7be17d3 commit ad9db37
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 24 deletions.
90 changes: 66 additions & 24 deletions interp/interp_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package interp

import (
"go/constant"
"log"
"reflect"
"testing"

"github.com/traefik/yaegi/stdlib"
)

func init() { log.SetFlags(log.Lshortfile) }
Expand All @@ -19,13 +22,13 @@ func TestIsNatural(t *testing.T) {
n: &node{
typ: &itype{
rtype: func() reflect.Type {
var x uint = 3
return reflect.TypeOf(x)
var a uint = 3
return reflect.TypeOf(a)
}(),
},
rval: func() reflect.Value {
var x uint = 3
return reflect.ValueOf(x)
var a uint = 3
return reflect.ValueOf(a)
}(),
},
expected: true,
Expand All @@ -35,13 +38,13 @@ func TestIsNatural(t *testing.T) {
n: &node{
typ: &itype{
rtype: func() reflect.Type {
x := 3
return reflect.TypeOf(x)
a := 3
return reflect.TypeOf(a)
}(),
},
rval: func() reflect.Value {
x := 3
return reflect.ValueOf(x)
a := 3
return reflect.ValueOf(a)
}(),
},
expected: true,
Expand All @@ -51,13 +54,13 @@ func TestIsNatural(t *testing.T) {
n: &node{
typ: &itype{
rtype: func() reflect.Type {
var x int = 3
return reflect.TypeOf(x)
var a int = 3
return reflect.TypeOf(a)
}(),
},
rval: func() reflect.Value {
var x int = 3
return reflect.ValueOf(x)
var a int = 3
return reflect.ValueOf(a)
}(),
},
expected: true,
Expand All @@ -67,13 +70,13 @@ func TestIsNatural(t *testing.T) {
n: &node{
typ: &itype{
rtype: func() reflect.Type {
var x float64 = 3.0
return reflect.TypeOf(x)
var a float64 = 3.0
return reflect.TypeOf(a)
}(),
},
rval: func() reflect.Value {
var x float64 = 3.0
return reflect.ValueOf(x)
var a float64 = 3.0
return reflect.ValueOf(a)
}(),
},
expected: true,
Expand All @@ -83,13 +86,13 @@ func TestIsNatural(t *testing.T) {
n: &node{
typ: &itype{
rtype: func() reflect.Type {
var x float64 = 3.14
return reflect.TypeOf(x)
var a float64 = 3.14
return reflect.TypeOf(a)
}(),
},
rval: func() reflect.Value {
var x float64 = 3.14
return reflect.ValueOf(x)
var a float64 = 3.14
return reflect.ValueOf(a)
}(),
},
expected: false,
Expand All @@ -99,13 +102,13 @@ func TestIsNatural(t *testing.T) {
n: &node{
typ: &itype{
rtype: func() reflect.Type {
var x int = -3
return reflect.TypeOf(x)
var a int = -3
return reflect.TypeOf(a)
}(),
},
rval: func() reflect.Value {
var x int = -3
return reflect.ValueOf(x)
var a int = -3
return reflect.ValueOf(a)
}(),
},
expected: false,
Expand Down Expand Up @@ -188,3 +191,42 @@ func TestIsNatural(t *testing.T) {
}
}
}

func TestGlobals(t *testing.T) {
i := New(Options{})
if err := i.Use(stdlib.Symbols); err != nil {
t.Fatal(err)
}
if _, err := i.Eval("var a = 1"); err != nil {
t.Fatal(err)
}
if _, err := i.Eval("b := 2"); err != nil {
t.Fatal(err)
}
if _, err := i.Eval("const c = 3"); err != nil {
t.Fatal(err)
}

g := i.Globals()
a := g["a"]
if !a.IsValid() {
t.Fatal("a not found")
}
if a := a.Interface(); a != 1 {
t.Fatalf("wrong a: want (%[1]T) %[1]v, have (%[2]T) %[2]v", 1, a)
}
b := g["b"]
if !b.IsValid() {
t.Fatal("b not found")
}
if b := b.Interface(); b != 2 {
t.Fatalf("wrong b: want (%[1]T) %[1]v, have (%[2]T) %[2]v", 2, b)
}
c := g["c"]
if !c.IsValid() {
t.Fatal("c not found")
}
if cc, ok := c.Interface().(constant.Value); ok && constant.MakeInt64(3) != cc {
t.Fatalf("wrong c: want (%[1]T) %[1]v, have (%[2]T) %[2]v", constant.MakeInt64(3), cc)
}
}
23 changes: 23 additions & 0 deletions interp/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,26 @@ func (interp *Interpreter) initScopePkg(pkgID, pkgName string) *scope {
interp.mutex.Unlock()
return sc
}

// Globals returns a map of global variables and constants in the main package.
func (interp *Interpreter) Globals() map[string]reflect.Value {
syms := map[string]reflect.Value{}
interp.mutex.RLock()
defer interp.mutex.RUnlock()

v, ok := interp.srcPkg["main"]
if !ok {
return syms
}

for n, s := range v {
switch s.kind {
case constSym:
syms[n] = s.rval
case varSym:
syms[n] = interp.frame.data[s.index]
}
}

return syms
}

0 comments on commit ad9db37

Please sign in to comment.