Interpreter now exports itself, so scripts can do Eval() too
This commit is contained in:
@@ -14,8 +14,8 @@ do
|
||||
END {
|
||||
print "func Example_'${file%.*}'() {"
|
||||
print "src := `" src "`"
|
||||
print "i := NewInterpreter(Opt{Entry: \"main\"}, \"'$file'\")"
|
||||
print "i.Import(stdlib.Value, stdlib.Type)"
|
||||
print "i := New(Opt{Entry: \"main\"})"
|
||||
print "i.Use(stdlib.Value, stdlib.Type)"
|
||||
print "i.Eval(src)"
|
||||
print out
|
||||
print "}"
|
||||
|
||||
13
_test/interp.gi
Normal file
13
_test/interp.gi
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/containous/dyngo/interp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
i := interp.New(interp.Opt{})
|
||||
i.Eval(`println("Hello")`)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Hello
|
||||
48
dyngo.go
48
dyngo.go
@@ -38,12 +38,14 @@ func main() {
|
||||
// Allow executable go scripts, but fix them prior to parse
|
||||
s = strings.Replace(s, "#!", "//", 1)
|
||||
}
|
||||
i := interp.NewInterpreter(opt, args[0])
|
||||
i.Import(stdlib.Value, stdlib.Type)
|
||||
i := interp.New(opt)
|
||||
i.Use(stdlib.Value, stdlib.Type)
|
||||
i.Use(interp.ExportValue, interp.ExportType)
|
||||
i.Eval(string(s))
|
||||
} else {
|
||||
i := interp.NewInterpreter(opt, "")
|
||||
i.Import(stdlib.Value, stdlib.Type)
|
||||
i := interp.New(opt)
|
||||
i.Use(stdlib.Value, stdlib.Type)
|
||||
i.Use(interp.ExportValue, interp.ExportType)
|
||||
s := bufio.NewScanner(os.Stdin)
|
||||
prompt := getPrompt()
|
||||
prompt()
|
||||
@@ -56,46 +58,8 @@ func main() {
|
||||
prompt()
|
||||
}
|
||||
}
|
||||
/*
|
||||
// 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"]
|
||||
ns := i.Export("sample", "NewSample")
|
||||
log.Println("ns:", ns)
|
||||
rarg := []reflect.Value{reflect.ValueOf("test")}
|
||||
res := ns.Call(rarg)
|
||||
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", 0, nil}
|
||||
p.Syms = i.Exports[p.Pkgname]
|
||||
log.Println("p.Syms:", p.Syms)
|
||||
http.HandleFunc("/", p.Handler)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
// Plugin struct stores metadata for external modules
|
||||
type Plugin struct {
|
||||
Pkgname, Typename string
|
||||
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.handler(p.Id, w, r)
|
||||
}
|
||||
*/
|
||||
|
||||
// getPrompt returns a function which prints a prompt only if stdin is a terminal
|
||||
func getPrompt() func() {
|
||||
if stat, err := os.Stdin.Stat(); err == nil && stat.Mode()&os.ModeCharDevice != 0 {
|
||||
|
||||
@@ -24,7 +24,7 @@ func main() {
|
||||
log.SetFlags(log.Lshortfile)
|
||||
//i := interp.NewInterpreter(interp.Opt{AstDot: true}, "")
|
||||
i := interp.NewInterpreter(interp.Opt{}, "")
|
||||
i.Import(stdlib.Value, stdlib.Type)
|
||||
i.Use(stdlib.Value, stdlib.Type)
|
||||
|
||||
// Load plugin
|
||||
_, err := i.Eval(`import "github.com/containous/dyngo/example/test_plugin/plugin"`)
|
||||
|
||||
Binary file not shown.
14
ii
Executable file
14
ii
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env dyngo
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/containous/dyngo/interp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
i := interp.New(interp.Opt{})
|
||||
i.Eval(`println("Hello")`)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Hello
|
||||
@@ -78,6 +78,9 @@ func (interp *Interpreter) Gta(root *Node) {
|
||||
ipath = n.child[0].val.(string)
|
||||
name = path.Base(ipath)
|
||||
}
|
||||
if pkgName == "_" {
|
||||
scope = interp.universe
|
||||
}
|
||||
if values, ok := interp.binValue[ipath]; ok {
|
||||
if name == "." {
|
||||
for n, v := range values {
|
||||
|
||||
@@ -67,8 +67,24 @@ type Interpreter struct {
|
||||
nindex int // next node index
|
||||
universe *Scope // interpreter global level scope
|
||||
scope map[string]*Scope // package level scopes, indexed by package name
|
||||
binValue LibValueMap // imported binary values from runtime
|
||||
binType LibTypeMap // imported binary types from runtime
|
||||
binValue LibValueMap // runtime binary values used in interpreter
|
||||
binType LibTypeMap // runtime binary types used in interpreter
|
||||
}
|
||||
|
||||
var ExportValue = LibValueMap{}
|
||||
var ExportType = LibTypeMap{}
|
||||
|
||||
func init() {
|
||||
me := "github.com/containous/dyngo/interp"
|
||||
ExportValue[me] = map[string]reflect.Value{
|
||||
"New": reflect.ValueOf(New),
|
||||
}
|
||||
ExportType[me] = map[string]reflect.Type{
|
||||
"Interpreter": reflect.TypeOf((*Interpreter)(nil)).Elem(),
|
||||
"Opt": reflect.TypeOf((*Opt)(nil)).Elem(),
|
||||
}
|
||||
ExportValue[me]["ExportType"] = reflect.ValueOf(ExportType)
|
||||
ExportValue[me]["ExportValue"] = reflect.ValueOf(ExportValue)
|
||||
}
|
||||
|
||||
// Walk traverses AST n in depth first order, call cbin function
|
||||
@@ -85,10 +101,9 @@ func (n *Node) Walk(in func(n *Node) bool, out func(n *Node)) {
|
||||
}
|
||||
}
|
||||
|
||||
// NewInterpreter creates and returns a new interpreter object
|
||||
func NewInterpreter(opt Opt, name string) *Interpreter {
|
||||
// New creates and returns a new interpreter object
|
||||
func New(opt Opt) *Interpreter {
|
||||
return &Interpreter{
|
||||
Name: name,
|
||||
Opt: opt,
|
||||
universe: initUniverse(),
|
||||
scope: map[string]*Scope{},
|
||||
@@ -201,9 +216,9 @@ func (i *Interpreter) Eval(src string) (reflect.Value, error) {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Import loads binary runtime symbols in the interpreter context so
|
||||
// Use loads binary runtime symbols in the interpreter context so
|
||||
// they can be used in interpreted code
|
||||
func (i *Interpreter) Import(values LibValueMap, types LibTypeMap) {
|
||||
func (i *Interpreter) Use(values LibValueMap, types LibTypeMap) {
|
||||
for k, v := range values {
|
||||
i.binValue[k] = v
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user