Methods created in the interpreter can now be used by runtime

This commit is contained in:
Marc Vertes
2018-12-19 15:10:26 +01:00
parent 42e891da02
commit 27cbeef38d
6 changed files with 42 additions and 34 deletions

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@
*.dot
cmd/goexports/goexports
dyngo
example/test_plugin/test_plugin
_gi_c/*.o
_gi_c/gi
_gi_c/loop2

View File

@@ -7,27 +7,19 @@ import (
var version = "v1"
// Sample stores middleware metadata
// Sample stores some plugin private metadata
type Sample struct{ Name string }
// Handler processes requests
// Handler is a Sample method to processes HTTP requests
func (s *Sample) Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome to my website", s.Name, version)
}
// Handler2 processes requests
func Handler2(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome to my website", version)
}
// NewSample returns a new sample handler function
func NewSample(name string) func(http.ResponseWriter, *http.Request) {
s := &Sample{"test"}
fmt.Println("in NewSample", name, version, s)
//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) }
return s.Handler
}
//func main() {

View File

@@ -8,32 +8,28 @@ import (
"github.com/containous/dyngo/stdlib"
)
// Plugin struct stores metadata for external modules
type Plugin struct {
name string
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)
}
// This program starts an interpreter which loads a plugin to handle HTTP requests
func main() {
log.SetFlags(log.Lshortfile) // Debug: print source file locations in log output
// Init go interpreter
log.SetFlags(log.Lshortfile)
i := interp.New(interp.Opt{AstDot: true})
//i := interp.New(interp.Opt{})
i.Use(stdlib.Value, stdlib.Type)
i := interp.New(interp.Opt{})
i.Use(stdlib.Value, stdlib.Type) // Use binary standard library
// Load plugin
// Load plugin from sources
_, err := i.Eval(`import "github.com/containous/dyngo/example/test_plugin/plugin"`)
log.Println("err:", err)
if err != nil {
log.Fatal(err)
}
handler, err := i.Eval(`plugin.NewSample("test")`)
log.Println("handler:", handler, "err:", err)
p := &Plugin{"sample", nil}
p.handler = handler.Interface().(func(http.ResponseWriter, *http.Request))
http.HandleFunc("/", p.Handler)
// Obtain a HTTP handler from the plugin
value, err := i.Eval(`plugin.NewSample("test")`)
if err != nil {
log.Fatal(err)
}
handler := value.Interface().(func(http.ResponseWriter, *http.Request))
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}

Binary file not shown.

View File

@@ -817,8 +817,9 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
}
} else if m, lind := n.typ.lookupMethod(n.child[1].ident); m != nil {
// Handle method
n.gen = nop
n.findex = -1
//n.gen = nop
//n.findex = -1
n.gen = getMethod
n.val = m
n.typ = m.typ
n.recv = &Receiver{node: n.child[0], index: lind}

View File

@@ -286,6 +286,9 @@ func genNodeWrapper(n *Node) func(*Frame) reflect.Value {
}
return func(f *Frame) reflect.Value {
if n.frame != nil { // Use closure context if defined
f = n.frame
}
return reflect.MakeFunc(n.typ.TypeOf(), func(in []reflect.Value) []reflect.Value {
// Allocate and init local frame. All values to be settable and addressable.
frame := Frame{anc: f, data: make([]reflect.Value, def.flen)}
@@ -617,6 +620,21 @@ func getFunc(n *Node) {
}
}
func getMethod(n *Node) {
i := n.findex
next := getExec(n.tnext)
n.exec = func(f *Frame) Builtin {
frame := *f
node := *(n.val.(*Node))
node.val = &node
node.recv = n.recv
node.frame = &frame
f.data[i] = reflect.ValueOf(&node)
return next
}
}
func getIndexSeq(n *Node) {
value := genValue(n.child[0])
index := n.val.([]int)