external plugins can now request for dependencies
This commit is contained in:
parent
eb4b17f078
commit
5302907dcf
@ -42,3 +42,17 @@ func (functor *exprFunctor) Invoke(ctx ExprContext, name string, args []any) (re
|
|||||||
result, err = functor.expr.Eval(ctx)
|
result, err = functor.expr.Eval(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CallExprFunction(parentCtx ExprContext, funcName string, params ...any) (v any, err error) {
|
||||||
|
ctx := cloneContext(parentCtx)
|
||||||
|
ctx.SetParent(parentCtx)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
if err = checkFunctionCall(ctx, funcName, ¶ms); err == nil {
|
||||||
|
if v, err = ctx.Call(funcName, params); err == nil {
|
||||||
|
exportObjects(parentCtx, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
package expr
|
package expr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"plugin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//-------- plugin term
|
//-------- plugin term
|
||||||
@ -22,48 +20,6 @@ func newPluginTerm(tk *Token) (inst *term) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importPlugin(ctx ExprContext, dirList []string, name string) (err error) {
|
|
||||||
var filePath string
|
|
||||||
var p *plugin.Plugin
|
|
||||||
var sym plugin.Symbol
|
|
||||||
var moduleName string
|
|
||||||
var importFunc func(ctx ExprContext)
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
decoratedName := fmt.Sprintf("expr-%s-plugin.so", name)
|
|
||||||
|
|
||||||
if filePath, err = makeFilepath(decoratedName, dirList); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if p, err = plugin.Open(filePath); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if sym, err = p.Lookup("MODULE_NAME"); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if moduleName = *sym.(*string); moduleName == "" {
|
|
||||||
err = fmt.Errorf("plugin %q does not provide a valid module name", decoratedName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if sym, err = p.Lookup("ImportFuncs"); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if importFunc, ok = sym.(func(ExprContext)); !ok {
|
|
||||||
err = fmt.Errorf("plugin %q does not provide a valid import function", decoratedName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registerPlugin(moduleName, p)
|
|
||||||
importFunc(globalCtx)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func evalPlugin(ctx ExprContext, self *term) (v any, err error) {
|
func evalPlugin(ctx ExprContext, self *term) (v any, err error) {
|
||||||
var childValue any
|
var childValue any
|
||||||
var moduleSpec any
|
var moduleSpec any
|
||||||
@ -77,7 +33,7 @@ func evalPlugin(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
it := NewAnyIterator(childValue)
|
it := NewAnyIterator(childValue)
|
||||||
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
||||||
if module, ok := moduleSpec.(string); ok {
|
if module, ok := moduleSpec.(string); ok {
|
||||||
if err = importPlugin(ctx, dirList, module); err != nil {
|
if err = importPlugin(dirList, module); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
|
64
plugins.go
64
plugins.go
@ -25,6 +25,70 @@ func pluginExists(name string) (exists bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func importPlugin( /*ctx ExprContext,*/ dirList []string, name string) (err error) {
|
||||||
|
var filePath string
|
||||||
|
var p *plugin.Plugin
|
||||||
|
var sym plugin.Symbol
|
||||||
|
var moduleName string
|
||||||
|
var importFunc func(ExprContext)
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
decoratedName := fmt.Sprintf("expr-%s-plugin.so", name)
|
||||||
|
|
||||||
|
if filePath, err = makeFilepath(decoratedName, dirList); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if p, err = plugin.Open(filePath); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sym, err = p.Lookup("MODULE_NAME"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if moduleName = *sym.(*string); moduleName == "" {
|
||||||
|
err = fmt.Errorf("plugin %q does not provide a valid module name", decoratedName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sym, err = p.Lookup("DEPENDENCIES"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if deps := *sym.(*[]string); len(deps) > 0 {
|
||||||
|
// var count int
|
||||||
|
if err = loadModules(dirList, deps); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sym, err = p.Lookup("ImportFuncs"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if importFunc, ok = sym.(func(ExprContext)); !ok {
|
||||||
|
err = fmt.Errorf("plugin %q does not provide a valid import function", decoratedName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registerPlugin(moduleName, p)
|
||||||
|
importFunc(globalCtx)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadModules(dirList []string, moduleNames []string) (err error) {
|
||||||
|
for _, name := range moduleNames {
|
||||||
|
if err1 := importPlugin(dirList, name); err1 != nil {
|
||||||
|
if !ImportInContext(name) {
|
||||||
|
err = err1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
pluginRegister = make(map[string]*plugin.Plugin)
|
pluginRegister = make(map[string]*plugin.Plugin)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user