diff --git a/bind-expr-functions.go b/bind-expr-functions.go index 72fe170..cec1c7b 100644 --- a/bind-expr-functions.go +++ b/bind-expr-functions.go @@ -42,3 +42,17 @@ func (functor *exprFunctor) Invoke(ctx ExprContext, name string, args []any) (re result, err = functor.expr.Eval(ctx) 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 +} diff --git a/operator-plugin.go b/operator-plugin.go index 88bd392..aae417c 100644 --- a/operator-plugin.go +++ b/operator-plugin.go @@ -5,9 +5,7 @@ package expr import ( - "fmt" "io" - "plugin" ) //-------- 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) { var childValue any var moduleSpec any @@ -77,7 +33,7 @@ func evalPlugin(ctx ExprContext, self *term) (v any, err error) { it := NewAnyIterator(childValue) for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() { if module, ok := moduleSpec.(string); ok { - if err = importPlugin(ctx, dirList, module); err != nil { + if err = importPlugin(dirList, module); err != nil { break } count++ diff --git a/plugins.go b/plugins.go index c85b274..78baef2 100644 --- a/plugins.go +++ b/plugins.go @@ -25,6 +25,70 @@ func pluginExists(name string) (exists bool) { 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() { pluginRegister = make(map[string]*plugin.Plugin) }