external plugins can now request for dependencies

This commit is contained in:
Celestino Amoroso 2024-06-09 17:12:57 +02:00
parent eb4b17f078
commit 5302907dcf
3 changed files with 79 additions and 45 deletions

View File

@ -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, &params); err == nil {
if v, err = ctx.Call(funcName, params); err == nil {
exportObjects(parentCtx, ctx)
}
}
}
return
}

View File

@ -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++

View File

@ -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)
}