Simplify export to runtime
This commit is contained in:
@@ -12,11 +12,11 @@ type Sample struct{ Name string }
|
||||
var samples = []Sample{}
|
||||
|
||||
func (s *Sample) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "Welcome to my website", s.Name)
|
||||
fmt.Fprintln(w, "Welcome to my website", s.Name, version)
|
||||
}
|
||||
|
||||
func NewSample(name string) int {
|
||||
fmt.Println("in NewSample", version)
|
||||
fmt.Println("in NewSample", name, version)
|
||||
i := len(samples)
|
||||
samples = append(samples, Sample{Name: name})
|
||||
return i
|
||||
|
||||
21
dyngo.go
21
dyngo.go
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -50,20 +49,22 @@ func main() {
|
||||
/*
|
||||
// To run test/plugin1.go or test/plugin2.go
|
||||
p := &Plugin{"sample", "Middleware", 0, nil}
|
||||
p.Syms = i.Exports[p.Pkgname]
|
||||
ns := (*i.Expval[p.Pkgname])["NewSample"]
|
||||
//p.Syms = i.Exports[p.Pkgname]
|
||||
//ns := (*i.Expval[p.Pkgname])["NewSample"]
|
||||
ns := i.Export("sample", "NewSample")
|
||||
log.Println("ns:", ns)
|
||||
rarg := []reflect.Value{reflect.ValueOf("test")}
|
||||
res := ns.Call(rarg)
|
||||
p.Id = res[0].Interface().(int)
|
||||
p.Id = int(res[0].Int())
|
||||
p.handler = i.Export("sample", "WrapHandler").Interface().(func(int, http.ResponseWriter, *http.Request))
|
||||
log.Println("res:", res, p.Id)
|
||||
http.HandleFunc("/", p.Handler)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
*/
|
||||
|
||||
/*
|
||||
// To run test.plugin0.go
|
||||
log.Println("frame:", i.Frame)
|
||||
p := &Plugin{"sample", "Middleware", i, nil}
|
||||
p := &Plugin{"sample", "Middleware", 0, nil}
|
||||
p.Syms = i.Exports[p.Pkgname]
|
||||
log.Println("p.Syms:", p.Syms)
|
||||
http.HandleFunc("/", p.Handler)
|
||||
@@ -71,14 +72,16 @@ func main() {
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
// Plugin struct stores metadata for external modules
|
||||
type Plugin struct {
|
||||
Pkgname, Typename string
|
||||
ID int
|
||||
Syms *interp.BinMap
|
||||
Id int
|
||||
handler func(int, http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
// Handler redirect http.Handler processing in the interpreter
|
||||
func (p *Plugin) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
(*p.Syms)["WrapHandler"].(func(int, http.ResponseWriter, *http.Request))(p.ID, w, r)
|
||||
p.handler(p.Id, w, r)
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -118,8 +118,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
|
||||
scope := interp.universe
|
||||
var loop, loopRestart *Node
|
||||
var initNodes []*Node
|
||||
var exports *BinMap
|
||||
var expval *ValueMap
|
||||
var iotaValue int
|
||||
var pkgName string
|
||||
|
||||
@@ -179,15 +177,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
|
||||
}
|
||||
scope = interp.scope[pkgName]
|
||||
scope.size = interp.fsize
|
||||
if pkg, ok := interp.Exports[pkgName]; ok {
|
||||
exports = pkg
|
||||
expval = interp.Expval[pkgName]
|
||||
} else {
|
||||
exports = &BinMap{}
|
||||
interp.Exports[pkgName] = exports
|
||||
expval = &ValueMap{}
|
||||
interp.Expval[pkgName] = expval
|
||||
}
|
||||
|
||||
case For0, ForRangeStmt:
|
||||
loop, loopRestart = n, n.child[0]
|
||||
@@ -556,7 +545,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
|
||||
case ForRangeStmt:
|
||||
loop, loopRestart = nil, nil
|
||||
n.start = n.child[0].start
|
||||
//n.findex = n.child[0].findex
|
||||
n.child[0].fnext = n
|
||||
scope = scope.pop()
|
||||
|
||||
@@ -569,10 +557,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
|
||||
n.framepos = append(n.framepos, n.child[2].framepos...)
|
||||
scope = scope.pop()
|
||||
funcName := n.child[1].ident
|
||||
if canExport(funcName) {
|
||||
(*exports)[funcName] = reflect.MakeFunc(n.child[2].typ.TypeOf(), n.wrapNode).Interface()
|
||||
(*expval)[funcName] = reflect.MakeFunc(n.child[2].typ.TypeOf(), n.wrapNode)
|
||||
}
|
||||
n.typ = n.child[2].typ
|
||||
n.val = n
|
||||
n.start = n.child[3].start
|
||||
@@ -1184,7 +1168,7 @@ func frameTypes(node *Node, size int) []reflect.Type {
|
||||
|
||||
node.Walk(func(n *Node) bool {
|
||||
if n.kind == FuncDecl || n.kind == ImportDecl || n.kind == TypeDecl || n.kind == FuncLit {
|
||||
return n == node // Do not dive in substree, except if this the entry point
|
||||
return n == node // Do not dive in substree, except if this is the entry point
|
||||
}
|
||||
if n.findex < 0 || n.typ == nil || n.level > 0 || n.kind == BasicLit || n.kind == SelectorSrc || n.typ.cat == BinPkgT {
|
||||
return true
|
||||
|
||||
@@ -8,7 +8,7 @@ func Exported() { println("Hello from Exported") }
|
||||
|
||||
i := NewInterpreter(Opt{}, "export_test")
|
||||
i.Eval(src)
|
||||
f := (*i.Exports["tst"])["Exported"].(func())
|
||||
f := i.Export("tst", "Exported").Interface().(func())
|
||||
f()
|
||||
|
||||
// Output:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/containous/dyngo/stdlib"
|
||||
@@ -81,8 +82,6 @@ type Interpreter struct {
|
||||
scope map[string]*Scope // package level scopes, indexed by package name
|
||||
binValue LibValueMap
|
||||
binType LibTypeMap
|
||||
Exports PkgMap // exported symbols for use by runtime
|
||||
Expval PkgValueMap // same as abobe (TODO: keep only one)
|
||||
}
|
||||
|
||||
// Walk traverses AST n in depth first order, call cbin function
|
||||
@@ -106,8 +105,6 @@ func NewInterpreter(opt Opt, name string) *Interpreter {
|
||||
Opt: opt,
|
||||
universe: initUniverse(),
|
||||
scope: map[string]*Scope{},
|
||||
Exports: make(PkgMap),
|
||||
Expval: make(PkgValueMap),
|
||||
binValue: LibValueMap(stdlib.Value),
|
||||
binType: LibTypeMap(stdlib.Type),
|
||||
Frame: &Frame{data: []reflect.Value{}},
|
||||
@@ -167,7 +164,8 @@ func (i *Interpreter) resizeFrame() {
|
||||
|
||||
// Eval evaluates Go code represented as a string. It returns a map on
|
||||
// current interpreted package exported symbols
|
||||
func (i *Interpreter) Eval(src string) string {
|
||||
func (i *Interpreter) Eval(src string) error {
|
||||
var err error
|
||||
// Parse source to AST
|
||||
pkgName, root := i.Ast(src, i.Name)
|
||||
if i.AstDot {
|
||||
@@ -198,5 +196,22 @@ func (i *Interpreter) Eval(src string) string {
|
||||
i.run(n, i.Frame)
|
||||
}
|
||||
}
|
||||
return root.child[0].ident
|
||||
return err
|
||||
}
|
||||
|
||||
// Export returns a value defined in the interpreter during execution
|
||||
// for use in the runtime
|
||||
func (i *Interpreter) Export(pkg, name string) reflect.Value {
|
||||
sym := i.scope[pkg].sym[name]
|
||||
var res reflect.Value
|
||||
if sym == nil {
|
||||
return res
|
||||
}
|
||||
switch sym.kind {
|
||||
case Func:
|
||||
log.Println("Export func", pkg+"."+name, sym.node.index)
|
||||
wrapper := genNodeWrapper(sym.node)
|
||||
res = wrapper(i.Frame)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -274,44 +274,6 @@ func _panic(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
// wrapNode wraps a call to an interpreter node in a function that can be called from runtime
|
||||
// FIXME: wrapNode is now redundant with genNodeWrapper(). it should be removed.
|
||||
func (n *Node) wrapNode(in []reflect.Value) []reflect.Value {
|
||||
def := n.val.(*Node)
|
||||
var result []reflect.Value
|
||||
if n.frame == nil {
|
||||
n.frame = n.interp.Frame
|
||||
}
|
||||
log.Println(n.index, "in wrapNode", def.index, n.frame)
|
||||
frame := Frame{anc: n.frame, data: make([]reflect.Value, def.flen)}
|
||||
|
||||
// If fucnction is a method, set its receiver data in the frame
|
||||
if len(def.child[0].child) > 0 {
|
||||
//frame.data[def.child[0].findex] = n.recv.node.value(n.frame)
|
||||
}
|
||||
|
||||
// Unwrap input arguments from their reflect value and store them in the frame
|
||||
i := 0
|
||||
for _, arg := range in {
|
||||
frame.data[def.framepos[i]] = arg
|
||||
i++
|
||||
}
|
||||
|
||||
// Interpreter code execution
|
||||
runCfg(def.child[3].start, &frame)
|
||||
|
||||
// Wrap output results in reflect values and return them
|
||||
if len(def.child[2].child) > 1 {
|
||||
if fieldList := def.child[2].child[1]; fieldList != nil {
|
||||
result = make([]reflect.Value, len(fieldList.child))
|
||||
for i := range fieldList.child {
|
||||
result[i] = reflect.ValueOf(frame.data[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func genNodeWrapper(n *Node) func(*Frame) reflect.Value {
|
||||
def := n.val.(*Node)
|
||||
setExec(def.child[3].start)
|
||||
|
||||
Reference in New Issue
Block a user