Methods created in the interpreter can now be used by runtime
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
*.dot
|
||||
cmd/goexports/goexports
|
||||
dyngo
|
||||
example/test_plugin/test_plugin
|
||||
_gi_c/*.o
|
||||
_gi_c/gi
|
||||
_gi_c/loop2
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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.
@@ -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}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user