Eval: wrap returned interpreter node into a callable function

This commit is contained in:
Marc Vertes
2018-12-11 03:12:50 -08:00
parent 6a397e2294
commit 6a23877ce2
5 changed files with 81 additions and 6 deletions

View File

@@ -0,0 +1,33 @@
package plugin
import (
"fmt"
"net/http"
)
var version = "v1"
type Sample struct{ Name string }
func (s *Sample) Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome to my website", s.Name, version)
}
func Handler2(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome to my website", version)
}
func NewSample(name string) func(http.ResponseWriter, *http.Request) {
fmt.Println("in NewSample", name, version)
s := &Sample{"test"}
return s.Handler
//return Handler2
//return func(w http.ResponseWriter, r *http.Request) { return Handler2(w, r) }
//return func(w http.ResponseWriter, r *http.Request) { return s.Handler(w, r) }
}
//func main() {
// s := &Sample{"Test"}
// http.HandleFunc("/", s.Handler)
// http.ListenAndServe(":8080", nil)
//}

View File

@@ -0,0 +1,40 @@
package main
import (
"log"
"net/http"
"github.com/containous/dyngo/interp"
"github.com/containous/dyngo/stdlib"
)
// Plugin struct stores metadata for external modules
type Plugin struct {
Pkgname, Typename string
Id int
handler func(http.ResponseWriter, *http.Request)
}
// Handler redirect http.Handler processing in the interpreter
func (p *Plugin) Handler(w http.ResponseWriter, r *http.Request) {
p.handler(w, r)
}
func main() {
// Init go interpreter
log.SetFlags(log.Lshortfile)
//i := interp.NewInterpreter(interp.Opt{AstDot: true}, "")
i := interp.NewInterpreter(interp.Opt{}, "")
i.Import(stdlib.Value, stdlib.Type)
// Load plugin
_, err := i.Eval(`import "github.com/containous/dyngo/example/test_plugin/plugin"`)
log.Println("err:", err)
handler, err := i.Eval(`plugin.NewSample("test")`)
log.Println("handler:", handler, "err:", err)
p := &Plugin{"sample", "Middleware", 0, nil}
p.handler = handler.Interface().(func(http.ResponseWriter, *http.Request))
http.HandleFunc("/", p.Handler)
http.ListenAndServe(":8080", nil)
}

BIN
example/test_plugin/test_plugin Executable file

Binary file not shown.

View File

@@ -93,8 +93,6 @@ func NewInterpreter(opt Opt, name string) *Interpreter {
Opt: opt,
universe: initUniverse(),
scope: map[string]*Scope{},
//binValue: LibValueMap(stdlib.Value),
//binType: LibTypeMap(stdlib.Type),
binValue: LibValueMap{},
binType: LibTypeMap{},
Frame: &Frame{data: []reflect.Value{}},
@@ -194,6 +192,13 @@ func (i *Interpreter) Eval(src string) (reflect.Value, error) {
v := genValue(root)
res = v(i.Frame)
}
// If result is an interpreter node, wrap it in a runtime callable function
if res.IsValid() {
if n, ok := res.Interface().(*Node); ok {
res = genNodeWrapper(n)(i.Frame)
}
}
return res, err
}

View File

@@ -435,7 +435,7 @@ func (t *Type) TypeOf() reflect.Type {
}
return reflect.SliceOf(t.val.TypeOf())
case BuiltinT:
case BinPkgT, BuiltinT, InterfaceT, SrcPkgT:
return nil
case ChanT:
@@ -456,9 +456,6 @@ func (t *Type) TypeOf() reflect.Type {
}
return reflect.FuncOf(in, out, false)
case InterfaceT:
return nil
case MapT:
return reflect.MapOf(t.key.TypeOf(), t.val.TypeOf())