Compare commits
7 Commits
79889cd8e1
...
1a772597cb
Author | SHA1 | Date | |
---|---|---|---|
1a772597cb | |||
33b3e1fc29 | |||
4e3f5cfbc6 | |||
e35d4e3f70 | |||
b4529499d6 | |||
7745dc24e2 | |||
be25385d02 |
@ -12,6 +12,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
iterParamOperator = "operator"
|
iterParamOperator = "operator"
|
||||||
iterParamVars = "vars"
|
iterParamVars = "vars"
|
||||||
|
iterVarStatus = "status"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseRunArgs(localCtx ExprContext, args []any) (it Iterator, op Functor, err error) {
|
func parseRunArgs(localCtx ExprContext, args []any) (it Iterator, op Functor, err error) {
|
||||||
@ -54,7 +55,7 @@ func runFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
|||||||
var item any
|
var item any
|
||||||
|
|
||||||
localCtx := ctx.Clone()
|
localCtx := ctx.Clone()
|
||||||
localCtx.UnsafeSetVar("it_status", nil)
|
localCtx.UnsafeSetVar(iterVarStatus, nil)
|
||||||
|
|
||||||
if it, op, err = parseRunArgs(localCtx, args); err != nil {
|
if it, op, err = parseRunArgs(localCtx, args); err != nil {
|
||||||
return
|
return
|
||||||
@ -84,7 +85,7 @@ func runFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
|||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
result, _ = localCtx.GetVar("it_status")
|
result, _ = localCtx.GetVar(iterVarStatus)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ func doAdd(ctx ExprContext, name string, it Iterator, count, level int) (result
|
|||||||
if v, err = doAdd(ctx, name, subIter, count, level); err != nil {
|
if v, err = doAdd(ctx, name, subIter, count, level); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if extIter, ok := v.(ExtIterator); ok && extIter.HasOperation(cleanName) {
|
if extIter, ok := v.(ExtIterator); ok && extIter.HasOperation(CleanName) {
|
||||||
if _, err = extIter.CallOperation(cleanName, nil); err != nil {
|
if _, err = extIter.CallOperation(CleanName, nil); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,8 +107,8 @@ func doMul(ctx ExprContext, name string, it Iterator, count, level int) (result
|
|||||||
if v, err = doMul(ctx, name, subIter, count, level); err != nil {
|
if v, err = doMul(ctx, name, subIter, count, level); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if extIter, ok := v.(ExtIterator); ok && extIter.HasOperation(cleanName) {
|
if extIter, ok := v.(ExtIterator); ok && extIter.HasOperation(CleanName) {
|
||||||
if _, err = extIter.CallOperation(cleanName, nil); err != nil {
|
if _, err = extIter.CallOperation(CleanName, nil); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ type dataCursor struct {
|
|||||||
currentFunc Functor
|
currentFunc Functor
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDataCursor(ctx ExprContext, ds map[string]Functor) (dc *dataCursor) {
|
func NewDataCursor(ctx ExprContext, ds map[string]Functor) (dc *dataCursor) {
|
||||||
dc = &dataCursor{
|
dc = &dataCursor{
|
||||||
ds: ds,
|
ds: ds,
|
||||||
index: -1,
|
index: -1,
|
||||||
@ -29,6 +29,10 @@ func newDataCursor(ctx ExprContext, ds map[string]Functor) (dc *dataCursor) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dc *dataCursor) Context() ExprContext {
|
||||||
|
return dc.ctx
|
||||||
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) TypeName() string {
|
func (dc *dataCursor) TypeName() string {
|
||||||
return "DataCursor"
|
return "DataCursor"
|
||||||
}
|
}
|
||||||
@ -62,7 +66,7 @@ func (dc *dataCursor) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
||||||
exists = name == indexName
|
exists = name == IndexName
|
||||||
if !exists {
|
if !exists {
|
||||||
f, ok := dc.ds[name]
|
f, ok := dc.ds[name]
|
||||||
exists = ok && isFunctor(f)
|
exists = ok && isFunctor(f)
|
||||||
@ -71,7 +75,7 @@ func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) CallOperation(name string, args []any) (value any, err error) {
|
func (dc *dataCursor) CallOperation(name string, args []any) (value any, err error) {
|
||||||
if name == indexName {
|
if name == IndexName {
|
||||||
value = int64(dc.Index())
|
value = int64(dc.Index())
|
||||||
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
||||||
if functor == dc.cleanFunc {
|
if functor == dc.cleanFunc {
|
||||||
@ -93,7 +97,7 @@ func (dc *dataCursor) Reset() (success bool, err error) {
|
|||||||
if dc.resetFunc != nil {
|
if dc.resetFunc != nil {
|
||||||
if dc.resource != nil {
|
if dc.resource != nil {
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
if _, err = dc.resetFunc.Invoke(ctx, resetName, []any{dc.resource}); err == nil {
|
if _, err = dc.resetFunc.Invoke(ctx, ResetName, []any{dc.resource}); err == nil {
|
||||||
dc.index = -1
|
dc.index = -1
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, ctx)
|
exportObjects(dc.ctx, ctx)
|
||||||
@ -101,7 +105,7 @@ func (dc *dataCursor) Reset() (success bool, err error) {
|
|||||||
err = errInvalidDataSource()
|
err = errInvalidDataSource()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = errNoOperation(resetName)
|
err = errNoOperation(ResetName)
|
||||||
}
|
}
|
||||||
success = err == nil
|
success = err == nil
|
||||||
return
|
return
|
||||||
@ -111,7 +115,7 @@ func (dc *dataCursor) Clean() (success bool, err error) {
|
|||||||
if dc.cleanFunc != nil {
|
if dc.cleanFunc != nil {
|
||||||
if dc.resource != nil {
|
if dc.resource != nil {
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
_, err = dc.cleanFunc.Invoke(ctx, cleanName, []any{dc.resource})
|
_, err = dc.cleanFunc.Invoke(ctx, CleanName, []any{dc.resource})
|
||||||
dc.resource = nil
|
dc.resource = nil
|
||||||
exportObjects(dc.ctx, ctx)
|
exportObjects(dc.ctx, ctx)
|
||||||
} else {
|
} else {
|
||||||
@ -126,7 +130,7 @@ func (dc *dataCursor) Clean() (success bool, err error) {
|
|||||||
|
|
||||||
func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
|
func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
if item, err = dc.currentFunc.Invoke(ctx, currentName, []any{}); err == nil && item == nil {
|
if item, err = dc.currentFunc.Invoke(ctx, CurrentName, []any{}); err == nil && item == nil {
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, ctx)
|
exportObjects(dc.ctx, ctx)
|
||||||
@ -167,7 +171,7 @@ func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err
|
|||||||
var v any
|
var v any
|
||||||
var ok bool
|
var ok bool
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
if v, err = filter.Invoke(ctx, filterName, []any{item, dc.index}); err == nil && v != nil {
|
if v, err = filter.Invoke(ctx, FilterName, []any{item, dc.index}); err == nil && v != nil {
|
||||||
if accepted, ok = v.(bool); !ok {
|
if accepted, ok = v.(bool); !ok {
|
||||||
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
|
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
|
||||||
}
|
}
|
||||||
@ -177,19 +181,19 @@ func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err
|
|||||||
}
|
}
|
||||||
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
|
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
mappedItem, err = mapper.Invoke(ctx, mapName, []any{item, dc.index});
|
mappedItem, err = mapper.Invoke(ctx, MapName, []any{item, dc.index});
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
|
func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
|
||||||
var accepted bool
|
var accepted bool
|
||||||
if dc.resource != nil {
|
if dc.resource != nil {
|
||||||
filter := dc.ds[filterName]
|
filter := dc.ds[FilterName]
|
||||||
mapper := dc.ds[mapName]
|
mapper := dc.ds[MapName]
|
||||||
|
|
||||||
for item == nil && err == nil {
|
for item == nil && err == nil {
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil {
|
if item, err = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource}); err == nil {
|
||||||
if item == nil {
|
if item == nil {
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
} else {
|
} else {
|
||||||
|
15
dict-type.go
15
dict-type.go
@ -18,7 +18,22 @@ func MakeDict() (dict *DictType) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDict(dictAny map[any]any) (dict *DictType) {
|
||||||
|
var d DictType
|
||||||
|
if dictAny != nil {
|
||||||
|
d = make(DictType, len(dictAny))
|
||||||
|
for i, item := range dictAny {
|
||||||
|
d[i] = item
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d = make(DictType)
|
||||||
|
}
|
||||||
|
dict = &d
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func newDict(dictAny map[any]*term) (dict *DictType) {
|
func newDict(dictAny map[any]*term) (dict *DictType) {
|
||||||
|
// TODO Change wi a call to NewDict()
|
||||||
var d DictType
|
var d DictType
|
||||||
if dictAny != nil {
|
if dictAny != nil {
|
||||||
d = make(DictType, len(dictAny))
|
d = make(DictType, len(dictAny))
|
||||||
|
@ -75,7 +75,11 @@ func isFile(filePath string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func searchAmongPath(filename string, dirList []string) (filePath string) {
|
func searchAmongPath(filename string, dirList []string) (filePath string) {
|
||||||
|
var err error
|
||||||
for _, dir := range dirList {
|
for _, dir := range dirList {
|
||||||
|
if dir, err = ExpandPath(dir); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if fullPath := path.Join(dir, filename); isFile(fullPath) {
|
if fullPath := path.Join(dir, filename); isFile(fullPath) {
|
||||||
filePath = fullPath
|
filePath = fullPath
|
||||||
break
|
break
|
||||||
@ -90,6 +94,10 @@ func isPathRelative(filePath string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeFilepath(filename string, dirList []string) (filePath string, err error) {
|
func makeFilepath(filename string, dirList []string) (filePath string, err error) {
|
||||||
|
if filename, err = ExpandPath(filename); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if path.IsAbs(filename) || isPathRelative(filename) {
|
if path.IsAbs(filename) || isPathRelative(filename) {
|
||||||
if isFile(filename) {
|
if isFile(filename) {
|
||||||
filePath = filename
|
filePath = filename
|
||||||
|
18
iterator.go
18
iterator.go
@ -12,15 +12,15 @@ import (
|
|||||||
// Operator names
|
// Operator names
|
||||||
|
|
||||||
const (
|
const (
|
||||||
initName = "init"
|
InitName = "init"
|
||||||
cleanName = "clean"
|
CleanName = "clean"
|
||||||
resetName = "reset"
|
ResetName = "reset"
|
||||||
nextName = "next"
|
NextName = "next"
|
||||||
currentName = "current"
|
CurrentName = "current"
|
||||||
indexName = "index"
|
IndexName = "index"
|
||||||
countName = "count"
|
CountName = "count"
|
||||||
filterName = "filter"
|
FilterName = "filter"
|
||||||
mapName = "map"
|
MapName = "map"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Iterator interface {
|
type Iterator interface {
|
||||||
|
@ -90,21 +90,21 @@ func (it *ListIterator) TypeName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) HasOperation(name string) bool {
|
func (it *ListIterator) HasOperation(name string) bool {
|
||||||
yes := name == nextName || name == resetName || name == indexName || name == countName || name == currentName
|
yes := name == NextName || name == ResetName || name == IndexName || name == CountName || name == CurrentName
|
||||||
return yes
|
return yes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) CallOperation(name string, args []any) (v any, err error) {
|
func (it *ListIterator) CallOperation(name string, args []any) (v any, err error) {
|
||||||
switch name {
|
switch name {
|
||||||
case nextName:
|
case NextName:
|
||||||
v, err = it.Next()
|
v, err = it.Next()
|
||||||
case resetName:
|
case ResetName:
|
||||||
v, err = it.Reset()
|
v, err = it.Reset()
|
||||||
case indexName:
|
case IndexName:
|
||||||
v = int64(it.Index())
|
v = int64(it.Index())
|
||||||
case currentName:
|
case CurrentName:
|
||||||
v, err = it.Current()
|
v, err = it.Current()
|
||||||
case countName:
|
case CountName:
|
||||||
v = it.count
|
v = it.count
|
||||||
default:
|
default:
|
||||||
err = errNoOperation(name)
|
err = errNoOperation(name)
|
||||||
|
@ -66,7 +66,7 @@ func evalFirstChild(ctx ExprContext, iteratorTerm *term) (value any, err error)
|
|||||||
|
|
||||||
func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]Functor, err error) {
|
func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]Functor, err error) {
|
||||||
if dictAny, ok := firstChildValue.(*DictType); ok {
|
if dictAny, ok := firstChildValue.(*DictType); ok {
|
||||||
requiredFields := []string{currentName, nextName}
|
requiredFields := []string{CurrentName, NextName}
|
||||||
fieldsMask := 0b11
|
fieldsMask := 0b11
|
||||||
foundFields := 0
|
foundFields := 0
|
||||||
ds = make(map[string]Functor)
|
ds = make(map[string]Functor)
|
||||||
@ -108,8 +108,8 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ds != nil {
|
if ds != nil {
|
||||||
dc := newDataCursor(ctx, ds)
|
dc := NewDataCursor(ctx, ds)
|
||||||
if initFunc, exists := ds[initName]; exists && initFunc != nil {
|
if initFunc, exists := ds[InitName]; exists && initFunc != nil {
|
||||||
var args []any
|
var args []any
|
||||||
if len(opTerm.children) > 1 {
|
if len(opTerm.children) > 1 {
|
||||||
if args, err = evalTermArray(ctx, opTerm.children[1:]); err != nil {
|
if args, err = evalTermArray(ctx, opTerm.children[1:]); err != nil {
|
||||||
@ -120,16 +120,16 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initCtx := dc.ctx.Clone()
|
initCtx := dc.ctx.Clone()
|
||||||
if dc.resource, err = initFunc.Invoke(initCtx, initName, args); err != nil {
|
if dc.resource, err = initFunc.Invoke(initCtx, InitName, args); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, initCtx)
|
exportObjects(dc.ctx, initCtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.nextFunc = ds[nextName]
|
dc.nextFunc = ds[NextName]
|
||||||
dc.currentFunc = ds[currentName]
|
dc.currentFunc = ds[CurrentName]
|
||||||
dc.cleanFunc = ds[cleanName]
|
dc.cleanFunc = ds[CleanName]
|
||||||
dc.resetFunc = ds[resetName]
|
dc.resetFunc = ds[ResetName]
|
||||||
|
|
||||||
v = dc
|
v = dc
|
||||||
} else if list, ok := firstChildValue.(*ListType); ok {
|
} else if list, ok := firstChildValue.(*ListType); ok {
|
||||||
|
@ -34,8 +34,8 @@ func evalLength(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
m, _ := childValue.(*DictType)
|
m, _ := childValue.(*DictType)
|
||||||
v = int64(len(*m))
|
v = int64(len(*m))
|
||||||
} else if it, ok := childValue.(Iterator); ok {
|
} else if it, ok := childValue.(Iterator); ok {
|
||||||
if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) {
|
if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(CountName) {
|
||||||
count, _ := extIt.CallOperation(countName, nil)
|
count, _ := extIt.CallOperation(CountName, nil)
|
||||||
v, _ = ToGoInt(count, "")
|
v, _ = ToGoInt(count, "")
|
||||||
} else {
|
} else {
|
||||||
v = int64(it.Index() + 1)
|
v = int64(it.Index() + 1)
|
||||||
|
@ -4,10 +4,6 @@
|
|||||||
// operator-plugin.go
|
// operator-plugin.go
|
||||||
package expr
|
package expr
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
//-------- plugin term
|
//-------- plugin term
|
||||||
|
|
||||||
func newPluginTerm(tk *Token) (inst *term) {
|
func newPluginTerm(tk *Token) (inst *term) {
|
||||||
@ -22,31 +18,13 @@ func newPluginTerm(tk *Token) (inst *term) {
|
|||||||
|
|
||||||
func evalPlugin(ctx ExprContext, opTerm *term) (v any, err error) {
|
func evalPlugin(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||||
var childValue any
|
var childValue any
|
||||||
var moduleSpec any
|
var count int
|
||||||
|
|
||||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dirList := buildSearchDirList("plugin", ENV_EXPR_PLUGIN_PATH)
|
if count, err = importPluginFromSearchPath(childValue); err == nil {
|
||||||
count := 0
|
|
||||||
it := NewAnyIterator(childValue)
|
|
||||||
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
|
||||||
if module, ok := moduleSpec.(string); ok {
|
|
||||||
if err = importPlugin(dirList, module); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
} else {
|
|
||||||
err = opTerm.Errorf("expected string as item nr %d, got %s", it.Index()+1, TypeName(moduleSpec))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err == io.EOF {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
v = int64(count)
|
v = int64(count)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
24
plugins.go
24
plugins.go
@ -6,6 +6,7 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"plugin"
|
"plugin"
|
||||||
"strings"
|
"strings"
|
||||||
@ -90,6 +91,29 @@ func importPlugin( /*ctx ExprContext,*/ dirList []string, name string) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func importPluginFromSearchPath(name any) (count int, err error) {
|
||||||
|
var moduleSpec any
|
||||||
|
|
||||||
|
dirList := buildSearchDirList("plugin", ENV_EXPR_PLUGIN_PATH)
|
||||||
|
count = 0
|
||||||
|
it := NewAnyIterator(name)
|
||||||
|
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
||||||
|
if module, ok := moduleSpec.(string); ok {
|
||||||
|
if err = importPlugin(dirList, module); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("expected string as item nr %d, got %s", it.Index()+1, TypeName(moduleSpec))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == io.EOF {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func loadModules(dirList []string, moduleNames []string) (err error) {
|
func loadModules(dirList []string, moduleNames []string) (err error) {
|
||||||
for _, name := range moduleNames {
|
for _, name := range moduleNames {
|
||||||
if err1 := importPlugin(dirList, name); err1 != nil {
|
if err1 := importPlugin(dirList, name); err1 != nil {
|
||||||
|
@ -14,7 +14,7 @@ func TestFuncRun(t *testing.T) {
|
|||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`builtin "iterator"; it=$(1,2,3); run(it)`, nil, nil},
|
/* 1 */ {`builtin "iterator"; it=$(1,2,3); run(it)`, nil, nil},
|
||||||
/* 2 */ {`builtin "iterator"; run($(1,2,3), func(index,item){item+10})`, nil, nil},
|
/* 2 */ {`builtin "iterator"; run($(1,2,3), func(index,item){item+10})`, nil, nil},
|
||||||
/* 3 */ {`builtin "iterator"; run($(1,2,3), func(index,item){it_status=it_status+item; true}, {"it_status":0})`, int64(6), nil},
|
/* 3 */ {`builtin "iterator"; run($(1,2,3), func(index,item){status=status+item; true}, {"status":0})`, int64(6), nil},
|
||||||
/* 4 */ {`builtin ["iterator", "fmt"]; run($(1,2,3), func(index,item){println(item+10)})`, nil, nil},
|
/* 4 */ {`builtin ["iterator", "fmt"]; run($(1,2,3), func(index,item){println(item+10)})`, nil, nil},
|
||||||
/* 5 */ {`builtin "iterator"; run(nil)`, nil, `paramter "iterator" must be an iterator, passed <nil> [nil]`},
|
/* 5 */ {`builtin "iterator"; run(nil)`, nil, `paramter "iterator" must be an iterator, passed <nil> [nil]`},
|
||||||
/* 6 */ {`builtin "iterator"; run($(1,2,3), nil)`, nil, `paramter "operator" must be a function, passed <nil> [nil]`},
|
/* 6 */ {`builtin "iterator"; run($(1,2,3), nil)`, nil, `paramter "operator" must be a function, passed <nil> [nil]`},
|
||||||
@ -26,25 +26,3 @@ func TestFuncRun(t *testing.T) {
|
|||||||
//runTestSuiteSpec(t, section, inputs, 3)
|
//runTestSuiteSpec(t, section, inputs, 3)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// func TestFmt(t *testing.T) {
|
|
||||||
// section := "Builtin-Fmt"
|
|
||||||
|
|
||||||
// text := "ciao mondo"
|
|
||||||
// inputs := []inputType{
|
|
||||||
// /* 1 */ {fmt.Sprintf(`println("%s")`, text), int64(11), nil},
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // t.Setenv("EXPR_PATH", ".")
|
|
||||||
|
|
||||||
// var b bytes.Buffer
|
|
||||||
// ctx := NewSimpleStore()
|
|
||||||
// currentStdout := SetCtrl(ctx, ControlStdout, &b)
|
|
||||||
|
|
||||||
// runCtxTestSuite(t, ctx, section, inputs)
|
|
||||||
|
|
||||||
// SetCtrl(ctx, ControlStdout, currentStdout)
|
|
||||||
// if b.String() != text+"\n" {
|
|
||||||
// t.Errorf("println(): Got: %q, Want: %q", b.String(), text+"\n")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
@ -9,8 +9,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func _TestImportPlugin(t *testing.T) {
|
func _TestImportPlugin(t *testing.T) {
|
||||||
if err := importPlugin([]string{"test-resources"}, "json"); err != nil {
|
t.Setenv("PLUGINS", "${HOME}/go/src/git.portale-stac.it/go")
|
||||||
t.Errorf("importPlugin() failed: %v", err)
|
t.Setenv("EXPR_PLUGIN_PATH","${PLUGINS}/expr-json-plugin:${PLUGINS}/expr-csv-plugin")
|
||||||
|
|
||||||
|
gotCount, gotErr := importPluginFromSearchPath("json")
|
||||||
|
if gotCount != 1 {
|
||||||
|
t.Errorf("Import count: got=%d, want=1", gotCount)
|
||||||
|
}
|
||||||
|
if gotErr != nil {
|
||||||
|
t.Errorf("importPlugin() failed: %v", gotErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
38
utils.go
38
utils.go
@ -6,7 +6,11 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsString(v any) (ok bool) {
|
func IsString(v any) (ok bool) {
|
||||||
@ -221,3 +225,37 @@ func ForAll[T, V any](ts []T, fn func(T) V) []V {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExpandPath(sourcePath string) (expandedPath string, err error) {
|
||||||
|
for expandedPath = os.ExpandEnv(sourcePath); expandedPath != sourcePath; expandedPath = os.ExpandEnv(sourcePath) {
|
||||||
|
sourcePath = expandedPath
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(sourcePath, "~") {
|
||||||
|
var home, userName, remainder string
|
||||||
|
|
||||||
|
slashPos := strings.IndexRune(sourcePath, '/')
|
||||||
|
if slashPos > 0 {
|
||||||
|
userName = sourcePath[1:slashPos]
|
||||||
|
remainder = sourcePath[slashPos:]
|
||||||
|
} else {
|
||||||
|
userName = sourcePath[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(userName) == 0 {
|
||||||
|
home, err = os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var userInfo *user.User
|
||||||
|
userInfo, err = user.Lookup(userName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
home = userInfo.HomeDir
|
||||||
|
}
|
||||||
|
expandedPath = path.Join(home, remainder)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user