Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ac8cab275 | |||
| 6c5e9db34b | |||
| 78871641d0 | |||
| dacbec677a | |||
| 75ed88915d | |||
| f2d1f23774 | |||
| edd90054d7 | |||
| 610e2df5f5 | |||
| 32c0b45255 | |||
| 75a3f220df | |||
| 116b54836f | |||
| 8787973de0 | |||
| 4d910dd069 |
79
ast.go
79
ast.go
@ -5,7 +5,10 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- ast
|
||||
@ -19,33 +22,33 @@ func NewAst() *ast {
|
||||
return &ast{}
|
||||
}
|
||||
|
||||
func (expr *ast) TypeName() string {
|
||||
func (ast *ast) TypeName() string {
|
||||
return "Expression"
|
||||
}
|
||||
|
||||
func (expr *ast) ToForest() {
|
||||
if expr.root != nil {
|
||||
if expr.forest == nil {
|
||||
expr.forest = make([]*term, 0)
|
||||
func (ast *ast) ToForest() {
|
||||
if ast.root != nil {
|
||||
if ast.forest == nil {
|
||||
ast.forest = make([]*term, 0)
|
||||
}
|
||||
expr.forest = append(expr.forest, expr.root)
|
||||
expr.root = nil
|
||||
ast.forest = append(ast.forest, ast.root)
|
||||
ast.root = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (expr *ast) String() string {
|
||||
func (ast *ast) String() string {
|
||||
var sb strings.Builder
|
||||
if expr.root == nil {
|
||||
if ast.root == nil {
|
||||
sb.WriteString("(nil)")
|
||||
} else {
|
||||
expr.root.toString(&sb)
|
||||
ast.root.toString(&sb)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (expr *ast) addTokens(tokens ...*Token) (err error) {
|
||||
func (ast *ast) addTokens(tokens ...*Token) (err error) {
|
||||
for _, tk := range tokens {
|
||||
if _, err = expr.addToken(tk); err != nil {
|
||||
if _, err = ast.addToken(tk); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -57,31 +60,31 @@ func (expr *ast) addTokens(tokens ...*Token) (err error) {
|
||||
// return
|
||||
// }
|
||||
|
||||
func (expr *ast) addToken(tk *Token) (t *term, err error) {
|
||||
func (ast *ast) addToken(tk *Token) (t *term, err error) {
|
||||
if t = newTerm(tk); t != nil {
|
||||
err = expr.addTerm(t)
|
||||
err = ast.addTerm(t)
|
||||
} else {
|
||||
err = tk.Errorf("unexpected token %q", tk.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (expr *ast) addTerm(node *term) (err error) {
|
||||
if expr.root == nil {
|
||||
expr.root = node
|
||||
func (ast *ast) addTerm(node *term) (err error) {
|
||||
if ast.root == nil {
|
||||
ast.root = node
|
||||
} else {
|
||||
expr.root, err = expr.insert(expr.root, node)
|
||||
ast.root, err = ast.insert(ast.root, node)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (expr *ast) insert(tree, node *term) (root *term, err error) {
|
||||
func (ast *ast) insert(tree, node *term) (root *term, err error) {
|
||||
if tree.getPriority() < node.getPriority() {
|
||||
root = tree
|
||||
if tree.isComplete() {
|
||||
var subRoot *term
|
||||
last := tree.removeLastChild()
|
||||
if subRoot, err = expr.insert(last, node); err == nil {
|
||||
if subRoot, err = ast.insert(last, node); err == nil {
|
||||
subRoot.setParent(tree)
|
||||
}
|
||||
} else {
|
||||
@ -96,22 +99,32 @@ func (expr *ast) insert(tree, node *term) (root *term, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (expr *ast) Finish() {
|
||||
if expr.root == nil && expr.forest != nil && len(expr.forest) >= 1 {
|
||||
expr.root = expr.forest[len(expr.forest)-1]
|
||||
expr.forest = expr.forest[0 : len(expr.forest)-1]
|
||||
func (ast *ast) Finish() {
|
||||
if ast.root == nil && ast.forest != nil && len(ast.forest) >= 1 {
|
||||
ast.root = ast.forest[len(ast.forest)-1]
|
||||
ast.forest = ast.forest[0 : len(ast.forest)-1]
|
||||
}
|
||||
}
|
||||
|
||||
func (expr *ast) Eval(ctx ExprContext) (result any, err error) {
|
||||
expr.Finish()
|
||||
func (ast *ast) Eval(ctx kern.ExprContext) (result any, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if errVal, ok := r.(error); ok {
|
||||
err = errVal
|
||||
} else {
|
||||
err = errors.New("unexpected error while evaluating the expression")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if expr.root != nil {
|
||||
ast.Finish()
|
||||
|
||||
if ast.root != nil {
|
||||
// initDefaultVars(ctx)
|
||||
if expr.forest != nil {
|
||||
for _, root := range expr.forest {
|
||||
if result, err = root.compute(ctx); err == nil {
|
||||
ctx.UnsafeSetVar(ControlLastResult, result)
|
||||
if ast.forest != nil {
|
||||
for _, tree := range ast.forest {
|
||||
if result, err = tree.Compute(ctx); err == nil {
|
||||
ctx.UnsafeSetVar(kern.ControlLastResult, result)
|
||||
} else {
|
||||
//err = fmt.Errorf("error in expression nr %d: %v", i+1, err)
|
||||
break
|
||||
@ -119,8 +132,8 @@ func (expr *ast) Eval(ctx ExprContext) (result any, err error) {
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if result, err = expr.root.compute(ctx); err == nil {
|
||||
ctx.UnsafeSetVar(ControlLastResult, result)
|
||||
if result, err = ast.root.Compute(ctx); err == nil {
|
||||
ctx.UnsafeSetVar(kern.ControlLastResult, result)
|
||||
}
|
||||
}
|
||||
// } else {
|
||||
|
||||
@ -4,20 +4,24 @@
|
||||
// function.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// ---- Linking with Expr functions
|
||||
type exprFunctor struct {
|
||||
baseFunctor
|
||||
params []ExprFuncParam
|
||||
kern.BaseFunctor
|
||||
params []kern.ExprFuncParam
|
||||
expr Expr
|
||||
defCtx ExprContext
|
||||
defCtx kern.ExprContext
|
||||
}
|
||||
|
||||
func (functor *exprFunctor) GetParams() (params []ExprFuncParam) {
|
||||
func (functor *exprFunctor) GetParams() (params []kern.ExprFuncParam) {
|
||||
return functor.params
|
||||
}
|
||||
|
||||
func newExprFunctor(e Expr, params []ExprFuncParam, ctx ExprContext) *exprFunctor {
|
||||
var defCtx ExprContext
|
||||
func newExprFunctor(e Expr, params []kern.ExprFuncParam, ctx kern.ExprContext) *exprFunctor {
|
||||
var defCtx kern.ExprContext
|
||||
if ctx != nil {
|
||||
defCtx = ctx
|
||||
}
|
||||
@ -28,17 +32,17 @@ func (functor *exprFunctor) TypeName() string {
|
||||
return "ExprFunctor"
|
||||
}
|
||||
|
||||
func (functor *exprFunctor) GetDefinitionContext() ExprContext {
|
||||
func (functor *exprFunctor) GetDefinitionContext() kern.ExprContext {
|
||||
return functor.defCtx
|
||||
}
|
||||
|
||||
func (functor *exprFunctor) InvokeNamed(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func (functor *exprFunctor) InvokeNamed(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var missing []string
|
||||
for _, p := range functor.params {
|
||||
if arg, exists := args[p.Name()]; exists {
|
||||
if funcArg, ok := arg.(Functor); ok {
|
||||
if funcArg, ok := arg.(kern.Functor); ok {
|
||||
paramSpecs := funcArg.GetParams()
|
||||
ctx.RegisterFunc(p.Name(), funcArg, TypeAny, paramSpecs)
|
||||
ctx.RegisterFunc(p.Name(), funcArg, kern.TypeAny, paramSpecs)
|
||||
} else {
|
||||
ctx.UnsafeSetVar(p.Name(), arg)
|
||||
}
|
||||
@ -51,7 +55,7 @@ func (functor *exprFunctor) InvokeNamed(ctx ExprContext, name string, args map[s
|
||||
}
|
||||
}
|
||||
if missing != nil {
|
||||
err = ErrMissingParams(name, missing)
|
||||
err = kern.ErrMissingParams(name, missing)
|
||||
} else {
|
||||
result, err = functor.expr.Eval(ctx)
|
||||
}
|
||||
|
||||
208
builtin-base.go
208
builtin-base.go
@ -9,81 +9,83 @@ import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
const (
|
||||
ParamDenominator = "denominator"
|
||||
)
|
||||
|
||||
func isNilFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = args[ParamValue] == nil
|
||||
func isNilFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = args[kern.ParamValue] == nil
|
||||
return
|
||||
}
|
||||
|
||||
func isIntFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsInteger(args[ParamValue])
|
||||
func isIntFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsInteger(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isFloatFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsFloat(args[ParamValue])
|
||||
func isFloatFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsFloat(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isBoolFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsBool(args[ParamValue])
|
||||
func isBoolFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsBool(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isStringFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsString(args[ParamValue])
|
||||
func isStringFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsString(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isFractionFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsFract(args[ParamValue])
|
||||
func isFractionFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsFraction(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isRationalFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsRational(args[ParamValue])
|
||||
func isRationalFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsRational(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isListFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsList(args[ParamValue])
|
||||
func isListFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsList(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func isDictionaryFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = IsDict(args[ParamValue])
|
||||
func isDictionaryFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
result = kern.IsDict(args[kern.ParamValue])
|
||||
return
|
||||
}
|
||||
|
||||
func boolFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[ParamValue].(type) {
|
||||
func boolFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[kern.ParamValue].(type) {
|
||||
case int64:
|
||||
result = (v != 0)
|
||||
case *FractionType:
|
||||
result = v.num != 0
|
||||
case *kern.FractionType:
|
||||
result = v.N() != 0
|
||||
case float64:
|
||||
result = v != 0.0
|
||||
case bool:
|
||||
result = v
|
||||
case string:
|
||||
result = len(v) > 0
|
||||
case *ListType:
|
||||
case *kern.ListType:
|
||||
result = len(*v) > 0
|
||||
case *DictType:
|
||||
case *kern.DictType:
|
||||
result = len(*v) > 0
|
||||
default:
|
||||
err = ErrCantConvert(name, v, "bool")
|
||||
err = kern.ErrCantConvert(name, v, "bool")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func intFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[ParamValue].(type) {
|
||||
func intFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[kern.ParamValue].(type) {
|
||||
case int64:
|
||||
result = v
|
||||
case float64:
|
||||
@ -99,16 +101,16 @@ func intFunc(ctx ExprContext, name string, args map[string]any) (result any, err
|
||||
if i, err = strconv.Atoi(v); err == nil {
|
||||
result = int64(i)
|
||||
}
|
||||
case *FractionType:
|
||||
result = int64(v.num / v.den)
|
||||
case *kern.FractionType:
|
||||
result = int64(v.N() / v.D())
|
||||
default:
|
||||
err = ErrCantConvert(name, v, "int")
|
||||
err = kern.ErrCantConvert(name, v, "int")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func decFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[ParamValue].(type) {
|
||||
func decFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[kern.ParamValue].(type) {
|
||||
case int64:
|
||||
result = float64(v)
|
||||
case float64:
|
||||
@ -124,16 +126,16 @@ func decFunc(ctx ExprContext, name string, args map[string]any) (result any, err
|
||||
if f, err = strconv.ParseFloat(v, 64); err == nil {
|
||||
result = f
|
||||
}
|
||||
case *FractionType:
|
||||
result = v.toFloat()
|
||||
case *kern.FractionType:
|
||||
result = v.ToFloat()
|
||||
default:
|
||||
err = ErrCantConvert(name, v, "float")
|
||||
err = kern.ErrCantConvert(name, v, "float")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func stringFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[ParamValue].(type) {
|
||||
func stringFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[kern.ParamValue].(type) {
|
||||
case int64:
|
||||
result = strconv.FormatInt(v, 10)
|
||||
case float64:
|
||||
@ -146,118 +148,118 @@ func stringFunc(ctx ExprContext, name string, args map[string]any) (result any,
|
||||
}
|
||||
case string:
|
||||
result = v
|
||||
case *FractionType:
|
||||
case *kern.FractionType:
|
||||
result = v.ToString(0)
|
||||
case Formatter:
|
||||
case kern.Formatter:
|
||||
result = v.ToString(0)
|
||||
case fmt.Stringer:
|
||||
result = v.String()
|
||||
default:
|
||||
err = ErrCantConvert(name, v, "string")
|
||||
err = kern.ErrCantConvert(name, v, "string")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fractFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[ParamValue].(type) {
|
||||
func fractFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
switch v := args[kern.ParamValue].(type) {
|
||||
case int64:
|
||||
var den int64 = 1
|
||||
|
||||
var ok bool
|
||||
if den, ok = args[ParamDenominator].(int64); !ok {
|
||||
err = ErrExpectedGot(name, "integer", args[ParamDenominator])
|
||||
err = kern.ErrExpectedGot(name, "integer", args[ParamDenominator])
|
||||
} else if den == 0 {
|
||||
err = ErrFuncDivisionByZero(name)
|
||||
err = kern.ErrFuncDivisionByZero(name)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
result = newFraction(v, den)
|
||||
result = kern.NewFraction(v, den)
|
||||
}
|
||||
case float64:
|
||||
result, err = float64ToFraction(v)
|
||||
result, err = kern.Float64ToFraction(v)
|
||||
case bool:
|
||||
if v {
|
||||
result = newFraction(1, 1)
|
||||
result = kern.NewFraction(1, 1)
|
||||
} else {
|
||||
result = newFraction(0, 1)
|
||||
result = kern.NewFraction(0, 1)
|
||||
}
|
||||
case string:
|
||||
result, err = makeGeneratingFraction(v)
|
||||
case *FractionType:
|
||||
result, err = kern.MakeGeneratingFraction(v)
|
||||
case *kern.FractionType:
|
||||
result = v
|
||||
default:
|
||||
err = ErrCantConvert(name, v, "float")
|
||||
err = kern.ErrCantConvert(name, v, "float")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// func iteratorFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
||||
// func iteratorFunc(ctx expr.ExprContext, name string, args []any) (result any, err error) {
|
||||
// return
|
||||
// }
|
||||
|
||||
func evalFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[ParamSource].(string); ok {
|
||||
var expr Expr
|
||||
func evalFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[kern.ParamSource].(string); ok {
|
||||
var ast Expr
|
||||
|
||||
parser := NewParser()
|
||||
if ctx == nil {
|
||||
ctx = NewSimpleStore()
|
||||
ctx = NewSimpleStoreWithoutGlobalContext()
|
||||
}
|
||||
|
||||
r := strings.NewReader(source)
|
||||
scanner := NewScanner(r, DefaultTranslations())
|
||||
|
||||
if expr, err = parser.Parse(scanner); err == nil {
|
||||
CtrlEnable(ctx, control_export_all)
|
||||
result, err = expr.Eval(ctx)
|
||||
if ast, err = parser.Parse(scanner); err == nil {
|
||||
CtrlEnable(ctx, kern.ControlExportAll)
|
||||
result, err = ast.Eval(ctx)
|
||||
}
|
||||
} else {
|
||||
err = ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
err = kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func varFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func varFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var varName string
|
||||
var ok bool
|
||||
|
||||
if varName, ok = args[ParamName].(string); !ok {
|
||||
return nil, ErrWrongParamType(name, ParamName, TypeString, args[ParamName])
|
||||
if varName, ok = args[kern.ParamName].(string); !ok {
|
||||
return nil, kern.ErrWrongParamType(name, kern.ParamName, kern.TypeString, args[kern.ParamName])
|
||||
}
|
||||
|
||||
if result, ok = args[ParamValue]; ok && result != nil {
|
||||
if result, ok = args[kern.ParamValue]; ok && result != nil {
|
||||
ctx.GetParent().UnsafeSetVar(varName, result)
|
||||
// } else {
|
||||
// err = ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
// err = expr.ErrWrongParamType(name, expr.ParamSource, expr.TypeString, args[expr.ParamSource])
|
||||
// }
|
||||
} else if result, ok = ctx.GetVar(varName); !ok {
|
||||
err = ErrUnknownVar(name, varName)
|
||||
err = kern.ErrUnknownVar(name, varName)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func setFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var varName string
|
||||
var ok bool
|
||||
|
||||
if varName, ok = args[ParamName].(string); !ok {
|
||||
return nil, ErrWrongParamType(name, ParamName, TypeString, args[ParamName])
|
||||
if varName, ok = args[kern.ParamName].(string); !ok {
|
||||
return nil, kern.ErrWrongParamType(name, kern.ParamName, kern.TypeString, args[kern.ParamName])
|
||||
}
|
||||
|
||||
if result, ok = args[ParamValue]; ok {
|
||||
if result, ok = args[kern.ParamValue]; ok {
|
||||
ctx.GetParent().UnsafeSetVar(varName, result)
|
||||
} else {
|
||||
err = ErrWrongParamType(name, ParamValue, TypeAny, args[ParamValue])
|
||||
err = kern.ErrWrongParamType(name, kern.ParamValue, kern.TypeAny, args[kern.ParamValue])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func unsetFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func unsetFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var varName string
|
||||
var ok bool
|
||||
|
||||
if varName, ok = args[ParamName].(string); !ok {
|
||||
return nil, ErrWrongParamType(name, ParamName, TypeString, args[ParamName])
|
||||
if varName, ok = args[kern.ParamName].(string); !ok {
|
||||
return nil, kern.ErrWrongParamType(name, kern.ParamName, kern.TypeString, args[kern.ParamName])
|
||||
} else {
|
||||
ctx.GetParent().DeleteVar(varName)
|
||||
result = nil
|
||||
@ -267,47 +269,47 @@ func unsetFunc(ctx ExprContext, name string, args map[string]any) (result any, e
|
||||
|
||||
//// import
|
||||
|
||||
func ImportBuiltinsFuncs(ctx ExprContext) {
|
||||
anyParams := []ExprFuncParam{
|
||||
NewFuncParam(ParamValue),
|
||||
func ImportBuiltinsFuncs(ctx kern.ExprContext) {
|
||||
anyParams := []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamValue),
|
||||
}
|
||||
|
||||
ctx.RegisterFunc("isNil", NewGolangFunctor(isNilFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isInt", NewGolangFunctor(isIntFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isFloat", NewGolangFunctor(isFloatFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isBool", NewGolangFunctor(isBoolFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isString", NewGolangFunctor(isStringFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isFract", NewGolangFunctor(isFractionFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isRational", NewGolangFunctor(isRationalFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isList", NewGolangFunctor(isListFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isDict", NewGolangFunctor(isDictionaryFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isNil", kern.NewGolangFunctor(isNilFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isInt", kern.NewGolangFunctor(isIntFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isFloat", kern.NewGolangFunctor(isFloatFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isBool", kern.NewGolangFunctor(isBoolFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isString", kern.NewGolangFunctor(isStringFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isFract", kern.NewGolangFunctor(isFractionFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isRational", kern.NewGolangFunctor(isRationalFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isList", kern.NewGolangFunctor(isListFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("isDict", kern.NewGolangFunctor(isDictionaryFunc), kern.TypeBoolean, anyParams)
|
||||
|
||||
ctx.RegisterFunc("bool", NewGolangFunctor(boolFunc), TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("int", NewGolangFunctor(intFunc), TypeInt, anyParams)
|
||||
ctx.RegisterFunc("dec", NewGolangFunctor(decFunc), TypeFloat, anyParams)
|
||||
ctx.RegisterFunc("string", NewGolangFunctor(stringFunc), TypeString, anyParams)
|
||||
ctx.RegisterFunc("fract", NewGolangFunctor(fractFunc), TypeFraction, []ExprFuncParam{
|
||||
NewFuncParam(ParamValue),
|
||||
ctx.RegisterFunc("bool", kern.NewGolangFunctor(boolFunc), kern.TypeBoolean, anyParams)
|
||||
ctx.RegisterFunc("int", kern.NewGolangFunctor(intFunc), kern.TypeInt, anyParams)
|
||||
ctx.RegisterFunc("dec", kern.NewGolangFunctor(decFunc), kern.TypeFloat, anyParams)
|
||||
ctx.RegisterFunc("string", kern.NewGolangFunctor(stringFunc), kern.TypeString, anyParams)
|
||||
ctx.RegisterFunc("fract", kern.NewGolangFunctor(fractFunc), kern.TypeFraction, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamValue),
|
||||
NewFuncParamFlagDef(ParamDenominator, PfDefault, int64(1)),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("eval", NewGolangFunctor(evalFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
ctx.RegisterFunc("eval", kern.NewGolangFunctor(evalFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("var", NewGolangFunctor(varFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParam(ParamName),
|
||||
NewFuncParamFlagDef(ParamValue, PfDefault, nil),
|
||||
ctx.RegisterFunc("var", kern.NewGolangFunctor(varFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamName),
|
||||
NewFuncParamFlagDef(kern.ParamValue, PfDefault, nil),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("set", NewGolangFunctor(setFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParam(ParamName),
|
||||
NewFuncParam(ParamValue),
|
||||
ctx.RegisterFunc("set", kern.NewGolangFunctor(setFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamName),
|
||||
NewFuncParam(kern.ParamValue),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("unset", NewGolangFunctor(unsetFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParam(ParamName),
|
||||
NewFuncParam(ParamValue),
|
||||
ctx.RegisterFunc("unset", kern.NewGolangFunctor(unsetFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamName),
|
||||
NewFuncParam(kern.ParamValue),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -8,11 +8,13 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func getStdout(ctx ExprContext) io.Writer {
|
||||
func getStdout(ctx kern.ExprContext) io.Writer {
|
||||
var w io.Writer
|
||||
if wany, exists := ctx.GetVar(ControlStdout); exists && wany != nil {
|
||||
if wany, exists := ctx.GetVar(kern.ControlStdout); exists && wany != nil {
|
||||
w, _ = wany.(io.Writer)
|
||||
}
|
||||
if w == nil {
|
||||
@ -21,9 +23,9 @@ func getStdout(ctx ExprContext) io.Writer {
|
||||
return w
|
||||
}
|
||||
|
||||
func printFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func printFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var n int = 0
|
||||
if v, exists := args[ParamItem]; exists && v != nil {
|
||||
if v, exists := args[kern.ParamItem]; exists && v != nil {
|
||||
argv := v.([]any)
|
||||
n, err = fmt.Fprint(getStdout(ctx), argv...)
|
||||
}
|
||||
@ -31,9 +33,9 @@ func printFunc(ctx ExprContext, name string, args map[string]any) (result any, e
|
||||
return
|
||||
}
|
||||
|
||||
func printLnFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func printLnFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var n int = 0
|
||||
if v, exists := args[ParamItem]; exists && v != nil {
|
||||
if v, exists := args[kern.ParamItem]; exists && v != nil {
|
||||
argv := v.([]any)
|
||||
n, err = fmt.Fprintln(getStdout(ctx), argv...)
|
||||
} else {
|
||||
@ -43,12 +45,12 @@ func printLnFunc(ctx ExprContext, name string, args map[string]any) (result any,
|
||||
return
|
||||
}
|
||||
|
||||
func ImportFmtFuncs(ctx ExprContext) {
|
||||
ctx.RegisterFunc("print", NewGolangFunctor(printFunc), TypeInt, []ExprFuncParam{
|
||||
NewFuncParamFlag(ParamItem, PfRepeat),
|
||||
func ImportFmtFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("print", kern.NewGolangFunctor(printFunc), kern.TypeInt, []kern.ExprFuncParam{
|
||||
NewFuncParamFlag(kern.ParamItem, PfRepeat),
|
||||
})
|
||||
ctx.RegisterFunc("println", NewGolangFunctor(printLnFunc), TypeInt, []ExprFuncParam{
|
||||
NewFuncParamFlag(ParamItem, PfRepeat),
|
||||
ctx.RegisterFunc("println", kern.NewGolangFunctor(printLnFunc), kern.TypeInt, []kern.ExprFuncParam{
|
||||
NewFuncParamFlag(kern.ParamItem, PfRepeat),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -7,32 +7,34 @@ package expr
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func importFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func importFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
return importGeneral(ctx, name, args)
|
||||
}
|
||||
|
||||
func importAllFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
CtrlEnable(ctx, control_export_all)
|
||||
func importAllFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
CtrlEnable(ctx, kern.ControlExportAll)
|
||||
return importGeneral(ctx, name, args)
|
||||
}
|
||||
|
||||
func importGeneral(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
dirList := buildSearchDirList("sources", ENV_EXPR_SOURCE_PATH)
|
||||
if v, exists := args[ParamFilepath]; exists && v != nil {
|
||||
func importGeneral(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
dirList := buildSearchDirList(ctx, "sources", ENV_EXPR_SOURCE_PATH)
|
||||
if v, exists := args[kern.ParamFilepath]; exists && v != nil {
|
||||
argv := v.([]any)
|
||||
result, err = doImport(ctx, name, dirList, NewArrayIterator(argv))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func doImport(ctx ExprContext, name string, dirList []string, it Iterator) (result any, err error) {
|
||||
func doImport(ctx kern.ExprContext, name string, dirList []string, it kern.Iterator) (result any, err error) {
|
||||
var v any
|
||||
var sourceFilepath string
|
||||
|
||||
for v, err = it.Next(); err == nil; v, err = it.Next() {
|
||||
if err = checkStringParamExpected(name, v, it.Index()); err != nil {
|
||||
if err = checkStringParamExpected(name, v, int(it.Index())); err != nil {
|
||||
break
|
||||
}
|
||||
if sourceFilepath, err = makeFilepath(v.(string), dirList); err != nil {
|
||||
@ -64,12 +66,12 @@ func doImport(ctx ExprContext, name string, dirList []string, it Iterator) (resu
|
||||
return
|
||||
}
|
||||
|
||||
func ImportImportFuncs(ctx ExprContext) {
|
||||
ctx.RegisterFunc("import", NewGolangFunctor(importFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParamFlag(ParamFilepath, PfRepeat),
|
||||
func ImportImportFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("import", kern.NewGolangFunctor(importFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParamFlag(kern.ParamFilepath, PfRepeat),
|
||||
})
|
||||
ctx.RegisterFunc("importAll", NewGolangFunctor(importAllFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParamFlag(ParamFilepath, PfRepeat),
|
||||
ctx.RegisterFunc("importAll", kern.NewGolangFunctor(importAllFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParamFlag(kern.ParamFilepath, PfRepeat),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -15,24 +17,24 @@ const (
|
||||
iterVarStatus = "status"
|
||||
)
|
||||
|
||||
func parseRunArgs(localCtx ExprContext, args map[string]any) (it Iterator, op Functor, err error) {
|
||||
func parseRunArgs(localCtx kern.ExprContext, args map[string]any) (it kern.Iterator, op kern.Functor, err error) {
|
||||
var ok bool
|
||||
|
||||
if it, ok = args[ParamIterator].(Iterator); !ok {
|
||||
err = fmt.Errorf("paramter %q must be an iterator, passed %v [%s]", ParamIterator, args[ParamIterator], TypeName(args[ParamIterator]))
|
||||
if it, ok = args[kern.ParamIterator].(kern.Iterator); !ok {
|
||||
err = fmt.Errorf("paramter %q must be an iterator, passed %v [%s]", kern.ParamIterator, args[kern.ParamIterator], kern.TypeName(args[kern.ParamIterator]))
|
||||
return
|
||||
}
|
||||
|
||||
if args[iterParamOperator] != nil {
|
||||
if op, ok = args[iterParamOperator].(Functor); !ok || op == nil {
|
||||
err = fmt.Errorf("paramter %q must be a function, passed %v [%s]", iterParamOperator, args[iterParamOperator], TypeName(args[iterParamOperator]))
|
||||
if op, ok = args[iterParamOperator].(kern.Functor); !ok || op == nil {
|
||||
err = fmt.Errorf("paramter %q must be a function, passed %v [%s]", iterParamOperator, args[iterParamOperator], kern.TypeName(args[iterParamOperator]))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var vars *DictType
|
||||
if vars, ok = args[iterParamVars].(*DictType); !ok && args[iterParamVars] != nil {
|
||||
err = fmt.Errorf("paramter %q must be a dictionary, passed %v [%s]", iterParamVars, args[iterParamVars], TypeName(args[iterParamVars]))
|
||||
var vars *kern.DictType
|
||||
if vars, ok = args[iterParamVars].(*kern.DictType); !ok && args[iterParamVars] != nil {
|
||||
err = fmt.Errorf("paramter %q must be a dictionary, passed %v [%s]", iterParamVars, args[iterParamVars], kern.TypeName(args[iterParamVars]))
|
||||
return
|
||||
}
|
||||
|
||||
@ -48,10 +50,10 @@ func parseRunArgs(localCtx ExprContext, args map[string]any) (it Iterator, op Fu
|
||||
return
|
||||
}
|
||||
|
||||
func runFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var it Iterator
|
||||
func runFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var it kern.Iterator
|
||||
var ok bool
|
||||
var op Functor
|
||||
var op kern.Functor
|
||||
var v any
|
||||
// var usingDefaultOp = false
|
||||
var params map[string]any
|
||||
@ -62,25 +64,16 @@ func runFunc(ctx ExprContext, name string, args map[string]any) (result any, err
|
||||
|
||||
if it, op, err = parseRunArgs(localCtx, args); err != nil {
|
||||
return
|
||||
// } else if op == nil {
|
||||
// op = NewGolangFunctor(printLnFunc)
|
||||
// usingDefaultOp = true
|
||||
}
|
||||
|
||||
for item, err = it.Next(); err == nil; item, err = it.Next() {
|
||||
// if usingDefaultOp {
|
||||
// params = map[string]any{ParamItem: []any{item}}
|
||||
// } else {
|
||||
// params = map[string]any{ParamIndex: it.Index(), ParamItem: item}
|
||||
// }
|
||||
|
||||
if op != nil {
|
||||
params = map[string]any{ParamIndex: it.Index(), ParamItem: item}
|
||||
params = map[string]any{kern.ParamIndex: it.Index(), kern.ParamItem: item}
|
||||
if v, err = op.InvokeNamed(localCtx, iterParamOperator, params); err != nil {
|
||||
break
|
||||
} else {
|
||||
var success bool
|
||||
if success, ok = ToBool(v); !success || !ok {
|
||||
if success, ok = kern.ToBool(v); !success || !ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -99,9 +92,9 @@ func runFunc(ctx ExprContext, name string, args map[string]any) (result any, err
|
||||
return
|
||||
}
|
||||
|
||||
func ImportIterFuncs(ctx ExprContext) {
|
||||
ctx.RegisterFunc("run", NewGolangFunctor(runFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParam(ParamIterator),
|
||||
func ImportIterFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("run", kern.NewGolangFunctor(runFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamIterator),
|
||||
NewFuncParamFlag(iterParamOperator, PfOptional),
|
||||
NewFuncParamFlag(iterParamVars, PfOptional),
|
||||
})
|
||||
|
||||
@ -7,67 +7,69 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func checkNumberParamExpected(funcName string, paramValue any, paramPos, level, subPos int) (err error) {
|
||||
if !(IsNumber(paramValue) || isFraction(paramValue)) /*|| isList(paramValue)*/ {
|
||||
if !(kern.IsNumber(paramValue) || kern.IsFraction(paramValue)) /*|| isList(paramValue)*/ {
|
||||
err = fmt.Errorf("%s(): param nr %d (%d in %d) has wrong type %T, number expected",
|
||||
funcName, paramPos+1, subPos+1, level, paramValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func doAdd(ctx ExprContext, name string, it Iterator, count, level int) (result any, err error) {
|
||||
func doAdd(ctx kern.ExprContext, name string, it kern.Iterator, count, level int) (result any, err error) {
|
||||
var sumAsFloat, sumAsFract bool
|
||||
var floatSum float64 = 0.0
|
||||
var intSum int64 = 0
|
||||
var fractSum *FractionType
|
||||
var fractSum *kern.FractionType
|
||||
var v any
|
||||
|
||||
level++
|
||||
|
||||
for v, err = it.Next(); err == nil; v, err = it.Next() {
|
||||
if list, ok := v.(*ListType); ok {
|
||||
if list, ok := v.(*kern.ListType); ok {
|
||||
v = NewListIterator(list, nil)
|
||||
}
|
||||
if subIter, ok := v.(Iterator); ok {
|
||||
if subIter, ok := v.(kern.Iterator); ok {
|
||||
if v, err = doAdd(ctx, name, subIter, count, level); err != nil {
|
||||
break
|
||||
}
|
||||
if extIter, ok := v.(ExtIterator); ok && extIter.HasOperation(CleanName) {
|
||||
if _, err = extIter.CallOperation(CleanName, nil); err != nil {
|
||||
if extIter, ok := v.(kern.ExtIterator); ok && extIter.HasOperation(kern.CleanName) {
|
||||
if _, err = extIter.CallOperation(kern.CleanName, nil); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if err = checkNumberParamExpected(name, v, count, level, it.Index()); err != nil {
|
||||
} else if err = checkNumberParamExpected(name, v, count, level, int(it.Index())); err != nil {
|
||||
break
|
||||
}
|
||||
count++
|
||||
|
||||
if !sumAsFloat {
|
||||
if IsFloat(v) {
|
||||
if kern.IsFloat(v) {
|
||||
sumAsFloat = true
|
||||
if sumAsFract {
|
||||
floatSum = fractSum.toFloat()
|
||||
floatSum = fractSum.ToFloat()
|
||||
} else {
|
||||
floatSum = float64(intSum)
|
||||
}
|
||||
} else if !sumAsFract && isFraction(v) {
|
||||
fractSum = newFraction(intSum, 1)
|
||||
} else if !sumAsFract && kern.IsFraction(v) {
|
||||
fractSum = kern.NewFraction(intSum, 1)
|
||||
sumAsFract = true
|
||||
}
|
||||
}
|
||||
|
||||
if sumAsFloat {
|
||||
floatSum += numAsFloat(v)
|
||||
floatSum += kern.NumAsFloat(v)
|
||||
} else if sumAsFract {
|
||||
var item *FractionType
|
||||
var item *kern.FractionType
|
||||
var ok bool
|
||||
if item, ok = v.(*FractionType); !ok {
|
||||
if item, ok = v.(*kern.FractionType); !ok {
|
||||
iv, _ := v.(int64)
|
||||
item = newFraction(iv, 1)
|
||||
item = kern.NewFraction(iv, 1)
|
||||
}
|
||||
fractSum = sumFract(fractSum, item)
|
||||
fractSum = kern.SumFract(fractSum, item)
|
||||
} else {
|
||||
iv, _ := v.(int64)
|
||||
intSum += iv
|
||||
@ -86,64 +88,64 @@ func doAdd(ctx ExprContext, name string, it Iterator, count, level int) (result
|
||||
return
|
||||
}
|
||||
|
||||
func addFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
argv := args[ParamValue].([]any)
|
||||
func addFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
argv := args[kern.ParamValue].([]any)
|
||||
result, err = doAdd(ctx, name, NewArrayIterator(argv), 0, -1)
|
||||
return
|
||||
}
|
||||
|
||||
func doMul(ctx ExprContext, name string, it Iterator, count, level int) (result any, err error) {
|
||||
func doMul(ctx kern.ExprContext, name string, it kern.Iterator, count, level int) (result any, err error) {
|
||||
var mulAsFloat, mulAsFract bool
|
||||
var floatProd float64 = 1.0
|
||||
var intProd int64 = 1
|
||||
var fractProd *FractionType
|
||||
var fractProd *kern.FractionType
|
||||
var v any
|
||||
|
||||
level++
|
||||
for v, err = it.Next(); err == nil; v, err = it.Next() {
|
||||
if list, ok := v.(*ListType); ok {
|
||||
if list, ok := v.(*kern.ListType); ok {
|
||||
v = NewListIterator(list, nil)
|
||||
}
|
||||
if subIter, ok := v.(Iterator); ok {
|
||||
if subIter, ok := v.(kern.Iterator); ok {
|
||||
if v, err = doMul(ctx, name, subIter, count, level); err != nil {
|
||||
break
|
||||
}
|
||||
if extIter, ok := v.(ExtIterator); ok && extIter.HasOperation(CleanName) {
|
||||
if _, err = extIter.CallOperation(CleanName, nil); err != nil {
|
||||
if extIter, ok := v.(kern.ExtIterator); ok && extIter.HasOperation(kern.CleanName) {
|
||||
if _, err = extIter.CallOperation(kern.CleanName, nil); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err = checkNumberParamExpected(name, v, count, level, it.Index()); err != nil {
|
||||
if err = checkNumberParamExpected(name, v, count, level, int(it.Index())); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
count++
|
||||
|
||||
if !mulAsFloat {
|
||||
if IsFloat(v) {
|
||||
if kern.IsFloat(v) {
|
||||
mulAsFloat = true
|
||||
if mulAsFract {
|
||||
floatProd = fractProd.toFloat()
|
||||
floatProd = fractProd.ToFloat()
|
||||
} else {
|
||||
floatProd = float64(intProd)
|
||||
}
|
||||
} else if !mulAsFract && isFraction(v) {
|
||||
fractProd = newFraction(intProd, 1)
|
||||
} else if !mulAsFract && kern.IsFraction(v) {
|
||||
fractProd = kern.NewFraction(intProd, 1)
|
||||
mulAsFract = true
|
||||
}
|
||||
}
|
||||
|
||||
if mulAsFloat {
|
||||
floatProd *= numAsFloat(v)
|
||||
floatProd *= kern.NumAsFloat(v)
|
||||
} else if mulAsFract {
|
||||
var item *FractionType
|
||||
var item *kern.FractionType
|
||||
var ok bool
|
||||
if item, ok = v.(*FractionType); !ok {
|
||||
if item, ok = v.(*kern.FractionType); !ok {
|
||||
iv, _ := v.(int64)
|
||||
item = newFraction(iv, 1)
|
||||
item = kern.NewFraction(iv, 1)
|
||||
}
|
||||
fractProd = mulFract(fractProd, item)
|
||||
fractProd = kern.MulFract(fractProd, item)
|
||||
} else {
|
||||
iv, _ := v.(int64)
|
||||
intProd *= iv
|
||||
@ -162,19 +164,19 @@ func doMul(ctx ExprContext, name string, it Iterator, count, level int) (result
|
||||
return
|
||||
}
|
||||
|
||||
func mulFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
argv := args[ParamValue].([]any)
|
||||
func mulFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
argv := args[kern.ParamValue].([]any)
|
||||
result, err = doMul(ctx, name, NewArrayIterator(argv), 0, -1)
|
||||
return
|
||||
}
|
||||
|
||||
func ImportMathFuncs(ctx ExprContext) {
|
||||
ctx.RegisterFunc("add", NewGolangFunctor(addFunc), TypeNumber, []ExprFuncParam{
|
||||
NewFuncParamFlagDef(ParamValue, PfDefault|PfRepeat, int64(0)),
|
||||
func ImportMathFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("add", kern.NewGolangFunctor(addFunc), kern.TypeNumber, []kern.ExprFuncParam{
|
||||
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, int64(0)),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("mul", NewGolangFunctor(mulFunc), TypeNumber, []ExprFuncParam{
|
||||
NewFuncParamFlagDef(ParamValue, PfDefault|PfRepeat, int64(1)),
|
||||
ctx.RegisterFunc("mul", kern.NewGolangFunctor(mulFunc), kern.TypeNumber, []kern.ExprFuncParam{
|
||||
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, int64(1)),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
const paramHandleOrPath = "handle-or-path"
|
||||
@ -15,8 +17,8 @@ const fileReadTextIteratorType = "fileReadTextIterator"
|
||||
|
||||
type fileReadTextIterator struct {
|
||||
osReader *osReader
|
||||
index int
|
||||
count int
|
||||
index int64
|
||||
count int64
|
||||
line string
|
||||
autoClose bool
|
||||
}
|
||||
@ -36,7 +38,7 @@ func (it *fileReadTextIterator) String() string {
|
||||
return fmt.Sprintf("$(%s@<nil>)", fileReadTextIteratorType)
|
||||
}
|
||||
|
||||
func (it *fileReadTextIterator) Count() int {
|
||||
func (it *fileReadTextIterator) Count() int64 {
|
||||
return it.count
|
||||
}
|
||||
|
||||
@ -60,7 +62,7 @@ func (it *fileReadTextIterator) Current() (item any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (it *fileReadTextIterator) Index() int {
|
||||
func (it *fileReadTextIterator) Index() int64 {
|
||||
return it.index
|
||||
}
|
||||
|
||||
@ -74,7 +76,7 @@ func (it *fileReadTextIterator) Reset() (err error) {
|
||||
}
|
||||
|
||||
func (it *fileReadTextIterator) HasOperation(name string) bool {
|
||||
return slices.Contains([]string{NextName, ResetName, IndexName, CountName, CurrentName, CleanName}, name)
|
||||
return slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName}, name)
|
||||
}
|
||||
|
||||
func (it *fileReadTextIterator) Clean() (err error) {
|
||||
@ -88,25 +90,25 @@ func (it *fileReadTextIterator) Clean() (err error) {
|
||||
|
||||
func (it *fileReadTextIterator) CallOperation(name string, args map[string]any) (v any, err error) {
|
||||
switch name {
|
||||
case NextName:
|
||||
case kern.NextName:
|
||||
v, err = it.Next()
|
||||
case ResetName:
|
||||
case kern.ResetName:
|
||||
err = it.Reset()
|
||||
case CleanName:
|
||||
case kern.CleanName:
|
||||
err = it.Clean()
|
||||
case IndexName:
|
||||
case kern.IndexName:
|
||||
v = int64(it.Index())
|
||||
case CurrentName:
|
||||
case kern.CurrentName:
|
||||
v, err = it.Current()
|
||||
case CountName:
|
||||
case kern.CountName:
|
||||
v = it.count
|
||||
default:
|
||||
err = errNoOperation(name)
|
||||
err = kern.ErrNoOperation(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fileReadIteratorFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func fileReadIteratorFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var handle *osReader
|
||||
var invalidFileHandle any
|
||||
var ok, autoClose bool
|
||||
@ -115,7 +117,7 @@ func fileReadIteratorFunc(ctx ExprContext, name string, args map[string]any) (re
|
||||
if handle, ok = args[paramHandleOrPath].(*osReader); !ok {
|
||||
if fileName, ok := args[paramHandleOrPath].(string); ok && len(fileName) > 0 {
|
||||
var handleAny any
|
||||
if handleAny, err = openFileFunc(ctx, name, map[string]any{ParamFilepath: fileName}); err != nil {
|
||||
if handleAny, err = openFileFunc(ctx, name, map[string]any{kern.ParamFilepath: fileName}); err != nil {
|
||||
return
|
||||
}
|
||||
if handleAny != nil {
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -65,8 +67,8 @@ func errInvalidFileHandle(funcName string, v any) error {
|
||||
}
|
||||
}
|
||||
|
||||
func createFileFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if filePath, ok := args[ParamFilepath].(string); ok && len(filePath) > 0 {
|
||||
func createFileFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if filePath, ok := args[kern.ParamFilepath].(string); ok && len(filePath) > 0 {
|
||||
var fh *os.File
|
||||
if fh, err = os.Create(filePath); err == nil {
|
||||
result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)}
|
||||
@ -77,8 +79,8 @@ func createFileFunc(ctx ExprContext, name string, args map[string]any) (result a
|
||||
return
|
||||
}
|
||||
|
||||
func openFileFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if filePath, ok := args[ParamFilepath].(string); ok && len(filePath) > 0 {
|
||||
func openFileFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if filePath, ok := args[kern.ParamFilepath].(string); ok && len(filePath) > 0 {
|
||||
var fh *os.File
|
||||
if fh, err = os.Open(filePath); err == nil {
|
||||
result = &osReader{fh: fh, reader: bufio.NewReader(fh)}
|
||||
@ -89,8 +91,8 @@ func openFileFunc(ctx ExprContext, name string, args map[string]any) (result any
|
||||
return
|
||||
}
|
||||
|
||||
func appendFileFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if filePath, ok := args[ParamFilepath].(string); ok && len(filePath) > 0 {
|
||||
func appendFileFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if filePath, ok := args[kern.ParamFilepath].(string); ok && len(filePath) > 0 {
|
||||
var fh *os.File
|
||||
if fh, err = os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0660); err == nil {
|
||||
result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)}
|
||||
@ -101,13 +103,13 @@ func appendFileFunc(ctx ExprContext, name string, args map[string]any) (result a
|
||||
return
|
||||
}
|
||||
|
||||
func closeFileFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func closeFileFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var handle osHandle
|
||||
var invalidFileHandle any
|
||||
var ok bool
|
||||
|
||||
if handle, ok = args[ParamHandle].(osHandle); !ok {
|
||||
invalidFileHandle = args[ParamHandle]
|
||||
if handle, ok = args[kern.ParamHandle].(osHandle); !ok {
|
||||
invalidFileHandle = args[kern.ParamHandle]
|
||||
}
|
||||
|
||||
if handle != nil {
|
||||
@ -128,18 +130,18 @@ func closeFileFunc(ctx ExprContext, name string, args map[string]any) (result an
|
||||
return
|
||||
}
|
||||
|
||||
func fileWriteTextFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func fileWriteTextFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var handle osHandle
|
||||
var invalidFileHandle any
|
||||
var ok bool
|
||||
|
||||
if handle, ok = args[ParamHandle].(osHandle); !ok {
|
||||
invalidFileHandle = args[ParamHandle]
|
||||
if handle, ok = args[kern.ParamHandle].(osHandle); !ok {
|
||||
invalidFileHandle = args[kern.ParamHandle]
|
||||
}
|
||||
|
||||
if handle != nil {
|
||||
if w, ok := handle.(*osWriter); ok {
|
||||
if v, exists := args[ParamItem]; exists {
|
||||
if v, exists := args[kern.ParamItem]; exists {
|
||||
argv := v.([]any)
|
||||
result, err = fmt.Fprint(w.writer, argv...)
|
||||
}
|
||||
@ -154,14 +156,14 @@ func fileWriteTextFunc(ctx ExprContext, name string, args map[string]any) (resul
|
||||
return
|
||||
}
|
||||
|
||||
func fileReadTextFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func fileReadTextFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var handle osHandle
|
||||
var invalidFileHandle any
|
||||
var ok bool
|
||||
|
||||
result = nil
|
||||
if handle, ok = args[ParamHandle].(osHandle); !ok || args[ParamHandle] == nil {
|
||||
invalidFileHandle = args[ParamHandle]
|
||||
if handle, ok = args[kern.ParamHandle].(osHandle); !ok || args[kern.ParamHandle] == nil {
|
||||
invalidFileHandle = args[kern.ParamHandle]
|
||||
}
|
||||
|
||||
if handle != nil {
|
||||
@ -194,14 +196,14 @@ func fileReadTextFunc(ctx ExprContext, name string, args map[string]any) (result
|
||||
return
|
||||
}
|
||||
|
||||
func fileReadTextAllFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func fileReadTextAllFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var handle osHandle
|
||||
var invalidFileHandle any
|
||||
var ok bool
|
||||
|
||||
result = nil
|
||||
if handle, ok = args[ParamHandle].(osHandle); !ok || args[ParamHandle] == nil {
|
||||
invalidFileHandle = args[ParamHandle]
|
||||
if handle, ok = args[kern.ParamHandle].(osHandle); !ok || args[kern.ParamHandle] == nil {
|
||||
invalidFileHandle = args[kern.ParamHandle]
|
||||
}
|
||||
|
||||
if handle != nil {
|
||||
@ -220,38 +222,38 @@ func fileReadTextAllFunc(ctx ExprContext, name string, args map[string]any) (res
|
||||
return
|
||||
}
|
||||
|
||||
func ImportOsFuncs(ctx ExprContext) {
|
||||
ctx.RegisterFunc("fileOpen", NewGolangFunctor(openFileFunc), TypeFileHandle, []ExprFuncParam{
|
||||
NewFuncParam(ParamFilepath),
|
||||
func ImportOsFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("fileOpen", kern.NewGolangFunctor(openFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamFilepath),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileAppend", NewGolangFunctor(appendFileFunc), TypeFileHandle, []ExprFuncParam{
|
||||
NewFuncParam(ParamFilepath),
|
||||
ctx.RegisterFunc("fileAppend", kern.NewGolangFunctor(appendFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamFilepath),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileCreate", NewGolangFunctor(createFileFunc), TypeFileHandle, []ExprFuncParam{
|
||||
NewFuncParam(ParamFilepath),
|
||||
ctx.RegisterFunc("fileCreate", kern.NewGolangFunctor(createFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamFilepath),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileClose", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{
|
||||
NewFuncParam(ParamHandle),
|
||||
ctx.RegisterFunc("fileClose", kern.NewGolangFunctor(closeFileFunc), kern.TypeBoolean, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileWriteText", NewGolangFunctor(fileWriteTextFunc), TypeInt, []ExprFuncParam{
|
||||
NewFuncParam(ParamHandle),
|
||||
NewFuncParamFlagDef(ParamItem, PfDefault|PfRepeat, ""),
|
||||
ctx.RegisterFunc("fileWriteText", kern.NewGolangFunctor(fileWriteTextFunc), kern.TypeInt, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
NewFuncParamFlagDef(kern.ParamItem, PfDefault|PfRepeat, ""),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileReadText", NewGolangFunctor(fileReadTextFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamHandle),
|
||||
ctx.RegisterFunc("fileReadText", kern.NewGolangFunctor(fileReadTextFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
NewFuncParamFlagDef(osLimitCh, PfDefault, "\n"),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileReadTextAll", NewGolangFunctor(fileReadTextAllFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamHandle),
|
||||
ctx.RegisterFunc("fileReadTextAll", kern.NewGolangFunctor(fileReadTextAllFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileReadIterator", NewGolangFunctor(fileReadIteratorFunc), TypeIterator, []ExprFuncParam{
|
||||
ctx.RegisterFunc("fileReadIterator", kern.NewGolangFunctor(fileReadIteratorFunc), kern.TypeIterator, []kern.ExprFuncParam{
|
||||
NewFuncParam(paramHandleOrPath),
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -15,7 +17,7 @@ const (
|
||||
)
|
||||
|
||||
// --- Start of function definitions
|
||||
func doJoinStr(funcName string, sep string, it Iterator) (result any, err error) {
|
||||
func doJoinStr(funcName string, sep string, it kern.Iterator) (result any, err error) {
|
||||
var sb strings.Builder
|
||||
var v any
|
||||
for v, err = it.Next(); err == nil; v, err = it.Next() {
|
||||
@ -25,7 +27,7 @@ func doJoinStr(funcName string, sep string, it Iterator) (result any, err error)
|
||||
if s, ok := v.(string); ok {
|
||||
sb.WriteString(s)
|
||||
} else {
|
||||
err = ErrExpectedGot(funcName, TypeString, v)
|
||||
err = kern.ErrExpectedGot(funcName, kern.TypeString, v)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -36,45 +38,45 @@ func doJoinStr(funcName string, sep string, it Iterator) (result any, err error)
|
||||
return
|
||||
}
|
||||
|
||||
func joinStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if sep, ok := args[ParamSeparator].(string); ok {
|
||||
if v, exists := args[ParamItem]; exists {
|
||||
func joinStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if sep, ok := args[kern.ParamSeparator].(string); ok {
|
||||
if v, exists := args[kern.ParamItem]; exists {
|
||||
argv := v.([]any)
|
||||
if len(argv) == 1 {
|
||||
if ls, ok := argv[0].(*ListType); ok {
|
||||
if ls, ok := argv[0].(*kern.ListType); ok {
|
||||
result, err = doJoinStr(name, sep, NewListIterator(ls, nil))
|
||||
} else if it, ok := argv[0].(Iterator); ok {
|
||||
} else if it, ok := argv[0].(kern.Iterator); ok {
|
||||
result, err = doJoinStr(name, sep, it)
|
||||
} else if s, ok := argv[0].(string); ok {
|
||||
result = s
|
||||
} else {
|
||||
err = ErrInvalidParameterValue(name, ParamItem, v)
|
||||
err = kern.ErrInvalidParameterValue(name, kern.ParamItem, v)
|
||||
}
|
||||
} else {
|
||||
result, err = doJoinStr(name, sep, NewArrayIterator(argv))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = ErrWrongParamType(name, ParamSeparator, TypeString, args[ParamSeparator])
|
||||
err = kern.ErrWrongParamType(name, kern.ParamSeparator, kern.TypeString, args[kern.ParamSeparator])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func subStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func subStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var start = 0
|
||||
var count = -1
|
||||
var source string
|
||||
var ok bool
|
||||
|
||||
if source, ok = args[ParamSource].(string); !ok {
|
||||
return nil, ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
if source, ok = args[kern.ParamSource].(string); !ok {
|
||||
return nil, kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
|
||||
if start, err = ToGoInt(args[ParamStart], name+"()"); err != nil {
|
||||
if start, err = kern.ToGoInt(args[kern.ParamStart], name+"()"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if count, err = ToGoInt(args[ParamCount], name+"()"); err != nil {
|
||||
if count, err = kern.ToGoInt(args[kern.ParamCount], name+"()"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -90,29 +92,29 @@ func subStrFunc(ctx ExprContext, name string, args map[string]any) (result any,
|
||||
return
|
||||
}
|
||||
|
||||
func trimStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func trimStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var source string
|
||||
var ok bool
|
||||
|
||||
if source, ok = args[ParamSource].(string); !ok {
|
||||
return nil, ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
if source, ok = args[kern.ParamSource].(string); !ok {
|
||||
return nil, kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
result = strings.TrimSpace(source)
|
||||
return
|
||||
}
|
||||
|
||||
func startsWithStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func startsWithStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var source, prefix string
|
||||
var ok bool
|
||||
|
||||
result = false
|
||||
|
||||
if source, ok = args[ParamSource].(string); !ok {
|
||||
return result, ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
if source, ok = args[kern.ParamSource].(string); !ok {
|
||||
return result, kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
|
||||
if prefix, ok = args[ParamPrefix].(string); !ok {
|
||||
return result, ErrWrongParamType(name, ParamPrefix, TypeString, args[ParamPrefix])
|
||||
if prefix, ok = args[kern.ParamPrefix].(string); !ok {
|
||||
return result, kern.ErrWrongParamType(name, kern.ParamPrefix, kern.TypeString, args[kern.ParamPrefix])
|
||||
}
|
||||
if strings.HasPrefix(source, prefix) {
|
||||
result = true
|
||||
@ -125,7 +127,7 @@ func startsWithStrFunc(ctx ExprContext, name string, args map[string]any) (resul
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("target item nr %d is %s, string expected", i+1, TypeName(targetSpec))
|
||||
err = fmt.Errorf("target item nr %d is %s, string expected", i+1, kern.TypeName(targetSpec))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -133,18 +135,18 @@ func startsWithStrFunc(ctx ExprContext, name string, args map[string]any) (resul
|
||||
return
|
||||
}
|
||||
|
||||
func endsWithStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func endsWithStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var source, suffix string
|
||||
var ok bool
|
||||
|
||||
result = false
|
||||
|
||||
if source, ok = args[ParamSource].(string); !ok {
|
||||
return result, ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
if source, ok = args[kern.ParamSource].(string); !ok {
|
||||
return result, kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
|
||||
if suffix, ok = args[ParamSuffix].(string); !ok {
|
||||
return result, ErrWrongParamType(name, ParamSuffix, TypeString, args[ParamSuffix])
|
||||
if suffix, ok = args[kern.ParamSuffix].(string); !ok {
|
||||
return result, kern.ErrWrongParamType(name, kern.ParamSuffix, kern.TypeString, args[kern.ParamSuffix])
|
||||
}
|
||||
if strings.HasPrefix(source, suffix) {
|
||||
result = true
|
||||
@ -157,7 +159,7 @@ func endsWithStrFunc(ctx ExprContext, name string, args map[string]any) (result
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("target item nr %d is %s, string expected", i+1, TypeName(targetSpec))
|
||||
err = fmt.Errorf("target item nr %d is %s, string expected", i+1, kern.TypeName(targetSpec))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -165,24 +167,24 @@ func endsWithStrFunc(ctx ExprContext, name string, args map[string]any) (result
|
||||
return
|
||||
}
|
||||
|
||||
func splitStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func splitStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var source, sep string
|
||||
var count int = -1
|
||||
var parts []string
|
||||
var ok bool
|
||||
|
||||
if source, ok = args[ParamSource].(string); !ok {
|
||||
return result, ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
if source, ok = args[kern.ParamSource].(string); !ok {
|
||||
return result, kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
|
||||
if sep, ok = args[ParamSeparator].(string); !ok {
|
||||
return nil, fmt.Errorf("separator param must be string, got %s (%v)", TypeName(args[ParamSeparator]), args[ParamSeparator])
|
||||
if sep, ok = args[kern.ParamSeparator].(string); !ok {
|
||||
return nil, fmt.Errorf("separator param must be string, got %s (%v)", kern.TypeName(args[kern.ParamSeparator]), args[kern.ParamSeparator])
|
||||
}
|
||||
|
||||
if count64, ok := args[ParamCount].(int64); ok { // TODO replace type assertion with toInt()
|
||||
if count64, ok := args[kern.ParamCount].(int64); ok { // TODO replace type assertion with toInt()
|
||||
count = int(count64)
|
||||
} else {
|
||||
return nil, fmt.Errorf("part count must be integer, got %s (%v)", TypeName(args[ParamCount]), args[ParamCount])
|
||||
return nil, fmt.Errorf("part count must be integer, got %s (%v)", kern.TypeName(args[kern.ParamCount]), args[kern.ParamCount])
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
@ -192,7 +194,7 @@ func splitStrFunc(ctx ExprContext, name string, args map[string]any) (result any
|
||||
} else {
|
||||
parts = []string{}
|
||||
}
|
||||
list := make(ListType, len(parts))
|
||||
list := make(kern.ListType, len(parts))
|
||||
for i, part := range parts {
|
||||
list[i] = part
|
||||
}
|
||||
@ -200,20 +202,20 @@ func splitStrFunc(ctx ExprContext, name string, args map[string]any) (result any
|
||||
return
|
||||
}
|
||||
|
||||
func upperStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[ParamSource].(string); ok {
|
||||
func upperStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[kern.ParamSource].(string); ok {
|
||||
result = strings.ToUpper(source)
|
||||
} else {
|
||||
err = ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
err = kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lowerStrFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[ParamSource].(string); ok {
|
||||
func lowerStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[kern.ParamSource].(string); ok {
|
||||
result = strings.ToLower(source)
|
||||
} else {
|
||||
err = ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
err = kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource])
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -221,46 +223,46 @@ func lowerStrFunc(ctx ExprContext, name string, args map[string]any) (result any
|
||||
// --- End of function definitions
|
||||
|
||||
// Import above functions in the context
|
||||
func ImportStringFuncs(ctx ExprContext) {
|
||||
ctx.RegisterFunc("strJoin", NewGolangFunctor(joinStrFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamSeparator),
|
||||
NewFuncParamFlag(ParamItem, PfRepeat),
|
||||
func ImportStringFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("strJoin", kern.NewGolangFunctor(joinStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSeparator),
|
||||
NewFuncParamFlag(kern.ParamItem, PfRepeat),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strSub", NewGolangFunctor(subStrFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
NewFuncParamFlagDef(ParamStart, PfDefault, int64(0)),
|
||||
NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)),
|
||||
ctx.RegisterFunc("strSub", kern.NewGolangFunctor(subStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParamFlagDef(kern.ParamStart, PfDefault, int64(0)),
|
||||
NewFuncParamFlagDef(kern.ParamCount, PfDefault, int64(-1)),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strSplit", NewGolangFunctor(splitStrFunc), "list of "+TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
NewFuncParamFlagDef(ParamSeparator, PfDefault, ""),
|
||||
NewFuncParamFlagDef(ParamCount, PfDefault, int64(-1)),
|
||||
ctx.RegisterFunc("strSplit", kern.NewGolangFunctor(splitStrFunc), "list of "+kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParamFlagDef(kern.ParamSeparator, PfDefault, ""),
|
||||
NewFuncParamFlagDef(kern.ParamCount, PfDefault, int64(-1)),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strTrim", NewGolangFunctor(trimStrFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
ctx.RegisterFunc("strTrim", kern.NewGolangFunctor(trimStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strStartsWith", NewGolangFunctor(startsWithStrFunc), TypeBoolean, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
NewFuncParam(ParamPrefix),
|
||||
ctx.RegisterFunc("strStartsWith", kern.NewGolangFunctor(startsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParam(kern.ParamPrefix),
|
||||
NewFuncParamFlag(strParamOther, PfRepeat),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strEndsWith", NewGolangFunctor(endsWithStrFunc), TypeBoolean, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
NewFuncParam(ParamSuffix),
|
||||
ctx.RegisterFunc("strEndsWith", kern.NewGolangFunctor(endsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParam(kern.ParamSuffix),
|
||||
NewFuncParamFlag(strParamOther, PfRepeat),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strUpper", NewGolangFunctor(upperStrFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
ctx.RegisterFunc("strUpper", kern.NewGolangFunctor(upperStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strLower", NewGolangFunctor(lowerStrFunc), TypeString, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
ctx.RegisterFunc("strLower", kern.NewGolangFunctor(lowerStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -6,21 +6,23 @@ package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type builtinModule struct {
|
||||
importFunc func(ExprContext)
|
||||
importFunc func(kern.ExprContext)
|
||||
description string
|
||||
imported bool
|
||||
}
|
||||
|
||||
func newBuiltinModule(importFunc func(ExprContext), description string) *builtinModule {
|
||||
func newBuiltinModule(importFunc func(kern.ExprContext), description string) *builtinModule {
|
||||
return &builtinModule{importFunc, description, false}
|
||||
}
|
||||
|
||||
var builtinModuleRegister map[string]*builtinModule
|
||||
|
||||
func RegisterBuiltinModule(name string, importFunc func(ExprContext), description string) {
|
||||
func RegisterBuiltinModule(name string, importFunc func(kern.ExprContext), description string) {
|
||||
if builtinModuleRegister == nil {
|
||||
builtinModuleRegister = make(map[string]*builtinModule)
|
||||
}
|
||||
|
||||
@ -7,24 +7,26 @@ package expr
|
||||
import (
|
||||
"io"
|
||||
"slices"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type dataCursor struct {
|
||||
ds map[string]Functor
|
||||
ctx ExprContext
|
||||
ds map[string]kern.Functor
|
||||
ctx kern.ExprContext
|
||||
initState bool // true if no item has produced yet (this replace di initial Next() call in the contructor)
|
||||
// cursorValid bool // true if resource is nil or if clean has not yet been called
|
||||
index int
|
||||
count int
|
||||
index int64
|
||||
count int64
|
||||
current any
|
||||
lastErr error
|
||||
resource any
|
||||
nextFunc Functor
|
||||
cleanFunc Functor
|
||||
resetFunc Functor
|
||||
nextFunc kern.Functor
|
||||
cleanFunc kern.Functor
|
||||
resetFunc kern.Functor
|
||||
}
|
||||
|
||||
func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *dataCursor) {
|
||||
func NewDataCursor(ctx kern.ExprContext, ds map[string]kern.Functor, resource any) (dc *dataCursor) {
|
||||
dc = &dataCursor{
|
||||
ds: ds,
|
||||
initState: true,
|
||||
@ -35,14 +37,14 @@ func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *da
|
||||
lastErr: nil,
|
||||
resource: resource,
|
||||
ctx: ctx.Clone(),
|
||||
nextFunc: ds[NextName],
|
||||
cleanFunc: ds[CleanName],
|
||||
resetFunc: ds[ResetName],
|
||||
nextFunc: ds[kern.NextName],
|
||||
cleanFunc: ds[kern.CleanName],
|
||||
resetFunc: ds[kern.ResetName],
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (dc *dataCursor) Context() ExprContext {
|
||||
func (dc *dataCursor) Context() kern.ExprContext {
|
||||
return dc.ctx
|
||||
}
|
||||
|
||||
@ -79,27 +81,27 @@ func (dc *dataCursor) String() string {
|
||||
}
|
||||
|
||||
func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
||||
exists = slices.Contains([]string{CleanName, ResetName, CurrentName, IndexName}, name)
|
||||
exists = slices.Contains([]string{kern.CleanName, kern.ResetName, kern.CurrentName, kern.IndexName}, name)
|
||||
if !exists {
|
||||
f, ok := dc.ds[name]
|
||||
exists = ok && isFunctor(f)
|
||||
exists = ok && kern.IsFunctor(f)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (dc *dataCursor) CallOperation(name string, args map[string]any) (value any, err error) {
|
||||
if name == IndexName {
|
||||
if name == kern.IndexName {
|
||||
value = int64(dc.Index())
|
||||
} else if name == CleanName {
|
||||
} else if name == kern.CleanName {
|
||||
err = dc.Clean()
|
||||
} else if name == ResetName {
|
||||
} else if name == kern.ResetName {
|
||||
err = dc.Reset()
|
||||
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
} else if functor, ok := dc.ds[name]; ok && kern.IsFunctor(functor) {
|
||||
ctx := kern.CloneContext(dc.ctx)
|
||||
value, err = functor.InvokeNamed(ctx, name, args)
|
||||
exportObjects(dc.ctx, ctx)
|
||||
kern.ExportObjects(dc.ctx, ctx)
|
||||
} else {
|
||||
err = errNoOperation(name)
|
||||
err = kern.ErrNoOperation(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -127,10 +129,10 @@ func (dc *dataCursor) CallOperation(name string, args map[string]any) (value any
|
||||
|
||||
func (dc *dataCursor) Reset() (err error) {
|
||||
if dc.resetFunc != nil {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
actualParams := bindActualParams(dc.resetFunc, []any{dc.resource})
|
||||
_, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams)
|
||||
exportObjects(dc.ctx, ctx)
|
||||
ctx := kern.CloneContext(dc.ctx)
|
||||
actualParams := kern.BindActualParams(dc.resetFunc, []any{dc.resource})
|
||||
_, err = dc.resetFunc.InvokeNamed(ctx, kern.ResetName, actualParams)
|
||||
kern.ExportObjects(dc.ctx, ctx)
|
||||
}
|
||||
dc.index = -1
|
||||
dc.count = 0
|
||||
@ -142,10 +144,10 @@ func (dc *dataCursor) Reset() (err error) {
|
||||
|
||||
func (dc *dataCursor) Clean() (err error) {
|
||||
if dc.cleanFunc != nil {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource})
|
||||
_, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams)
|
||||
exportObjects(dc.ctx, ctx)
|
||||
ctx := kern.CloneContext(dc.ctx)
|
||||
actualParams := kern.BindActualParams(dc.cleanFunc, []any{dc.resource})
|
||||
_, err = dc.cleanFunc.InvokeNamed(ctx, kern.CleanName, actualParams)
|
||||
kern.ExportObjects(dc.ctx, ctx)
|
||||
}
|
||||
dc.lastErr = io.EOF
|
||||
return
|
||||
@ -178,13 +180,13 @@ func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at
|
||||
return
|
||||
}
|
||||
|
||||
func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err error) {
|
||||
func (dc *dataCursor) checkFilter(filter kern.Functor, item any) (accepted bool, err error) {
|
||||
var v any
|
||||
var ok bool
|
||||
ctx := cloneContext(dc.ctx)
|
||||
ctx := kern.CloneContext(dc.ctx)
|
||||
|
||||
actualParams := bindActualParams(filter, []any{item, dc.index})
|
||||
if v, err = filter.InvokeNamed(ctx, FilterName, actualParams); err == nil && v != nil {
|
||||
actualParams := kern.BindActualParams(filter, []any{item, dc.index})
|
||||
if v, err = filter.InvokeNamed(ctx, kern.FilterName, actualParams); err == nil && v != nil {
|
||||
if accepted, ok = v.(bool); !ok {
|
||||
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
|
||||
}
|
||||
@ -192,10 +194,10 @@ func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err
|
||||
return
|
||||
}
|
||||
|
||||
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
actualParams := bindActualParams(mapper, []any{item, dc.index})
|
||||
mappedItem, err = mapper.InvokeNamed(ctx, MapName, actualParams)
|
||||
func (dc *dataCursor) mapItem(mapper kern.Functor, item any) (mappedItem any, err error) {
|
||||
ctx := kern.CloneContext(dc.ctx)
|
||||
actualParams := kern.BindActualParams(mapper, []any{item, dc.index})
|
||||
mappedItem, err = mapper.InvokeNamed(ctx, kern.MapName, actualParams)
|
||||
return
|
||||
}
|
||||
|
||||
@ -213,15 +215,15 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
|
||||
return
|
||||
}
|
||||
current = dc.current
|
||||
filter := dc.ds[FilterName]
|
||||
mapper := dc.ds[MapName]
|
||||
filter := dc.ds[kern.FilterName]
|
||||
mapper := dc.ds[kern.MapName]
|
||||
var item any
|
||||
for item == nil && dc.lastErr == nil {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
ctx := kern.CloneContext(dc.ctx)
|
||||
dc.index++
|
||||
|
||||
actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
||||
if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil {
|
||||
actualParams := kern.BindActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
||||
if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, kern.NextName, actualParams); dc.lastErr == nil {
|
||||
if item == nil {
|
||||
dc.lastErr = io.EOF
|
||||
} else {
|
||||
@ -239,7 +241,7 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
|
||||
}
|
||||
}
|
||||
}
|
||||
exportObjects(dc.ctx, ctx)
|
||||
kern.ExportObjects(dc.ctx, ctx)
|
||||
}
|
||||
dc.current = item
|
||||
if dc.lastErr != nil {
|
||||
@ -296,10 +298,10 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
|
||||
// return
|
||||
// }
|
||||
|
||||
func (dc *dataCursor) Index() int {
|
||||
func (dc *dataCursor) Index() int64 {
|
||||
return dc.index - 1
|
||||
}
|
||||
|
||||
func (dc *dataCursor) Count() int {
|
||||
func (dc *dataCursor) Count() int64 {
|
||||
return dc.count
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"io"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type dictIterMode int
|
||||
@ -20,9 +22,9 @@ const (
|
||||
)
|
||||
|
||||
type DictIterator struct {
|
||||
a *DictType
|
||||
count int
|
||||
index int
|
||||
a *kern.DictType
|
||||
count int64
|
||||
index int64
|
||||
keys []any
|
||||
iterMode dictIterMode
|
||||
}
|
||||
@ -65,7 +67,7 @@ func (it *DictIterator) makeKeys(m map[any]any, sort sortType) {
|
||||
}
|
||||
}
|
||||
|
||||
func NewDictIterator(dict *DictType, args []any) (it *DictIterator, err error) {
|
||||
func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err error) {
|
||||
var sortType = sortTypeNone
|
||||
var s string
|
||||
var argAny any
|
||||
@ -76,7 +78,7 @@ func NewDictIterator(dict *DictType, args []any) (it *DictIterator, err error) {
|
||||
} else {
|
||||
argAny = "default"
|
||||
}
|
||||
if s, err = ToGoString(argAny, "sort type"); err == nil {
|
||||
if s, err = kern.ToGoString(argAny, "sort type"); err == nil {
|
||||
switch strings.ToLower(s) {
|
||||
case "a", "asc":
|
||||
sortType = sortTypeAsc
|
||||
@ -97,7 +99,7 @@ func NewDictIterator(dict *DictType, args []any) (it *DictIterator, err error) {
|
||||
argAny = "default"
|
||||
}
|
||||
|
||||
if s, err = ToGoString(argAny, "iteration mode"); err == nil {
|
||||
if s, err = kern.ToGoString(argAny, "iteration mode"); err == nil {
|
||||
switch strings.ToLower(s) {
|
||||
case "k", "key", "keys":
|
||||
dictIt.iterMode = dictIterModeKeys
|
||||
@ -119,15 +121,15 @@ func NewDictIterator(dict *DictType, args []any) (it *DictIterator, err error) {
|
||||
}
|
||||
|
||||
func NewMapIterator(m map[any]any) (it *DictIterator) {
|
||||
it = &DictIterator{a: (*DictType)(&m), count: 0, index: -1, keys: nil}
|
||||
it = &DictIterator{a: (*kern.DictType)(&m), count: 0, index: -1, keys: nil}
|
||||
it.makeKeys(m, sortTypeNone)
|
||||
return
|
||||
}
|
||||
|
||||
func (it *DictIterator) String() string {
|
||||
var l = 0
|
||||
var l = int64(0)
|
||||
if it.a != nil {
|
||||
l = len(*it.a)
|
||||
l = int64(len(*it.a))
|
||||
}
|
||||
return fmt.Sprintf("$({#%d})", l)
|
||||
}
|
||||
@ -138,45 +140,45 @@ func (it *DictIterator) TypeName() string {
|
||||
|
||||
func (it *DictIterator) HasOperation(name string) bool {
|
||||
// yes := name == NextName || name == ResetName || name == IndexName || name == CountName || name == CurrentName
|
||||
yes := slices.Contains([]string{NextName, ResetName, IndexName, CountName, CurrentName, CleanName, KeyName, ValueName}, name)
|
||||
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName, kern.KeyName, kern.ValueName}, name)
|
||||
return yes
|
||||
}
|
||||
|
||||
func (it *DictIterator) CallOperation(name string, args map[string]any) (v any, err error) {
|
||||
switch name {
|
||||
case NextName:
|
||||
case kern.NextName:
|
||||
v, err = it.Next()
|
||||
case ResetName:
|
||||
case kern.ResetName:
|
||||
err = it.Reset()
|
||||
case CleanName:
|
||||
case kern.CleanName:
|
||||
err = it.Clean()
|
||||
case IndexName:
|
||||
case kern.IndexName:
|
||||
v = int64(it.Index())
|
||||
case CurrentName:
|
||||
case kern.CurrentName:
|
||||
v, err = it.Current()
|
||||
case CountName:
|
||||
case kern.CountName:
|
||||
v = it.count
|
||||
case KeyName:
|
||||
if it.index >= 0 && it.index < len(it.keys) {
|
||||
case kern.KeyName:
|
||||
if it.index >= 0 && it.index < int64(len(it.keys)) {
|
||||
v = it.keys[it.index]
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
case ValueName:
|
||||
if it.index >= 0 && it.index < len(it.keys) {
|
||||
case kern.ValueName:
|
||||
if it.index >= 0 && it.index < int64(len(it.keys)) {
|
||||
a := *(it.a)
|
||||
v = a[it.keys[it.index]]
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
default:
|
||||
err = errNoOperation(name)
|
||||
err = kern.ErrNoOperation(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (it *DictIterator) Current() (item any, err error) {
|
||||
if it.index >= 0 && it.index < len(it.keys) {
|
||||
if it.index >= 0 && it.index < int64(len(it.keys)) {
|
||||
switch it.iterMode {
|
||||
case dictIterModeKeys:
|
||||
item = it.keys[it.index]
|
||||
@ -186,7 +188,7 @@ func (it *DictIterator) Current() (item any, err error) {
|
||||
case dictIterModeItems:
|
||||
a := *(it.a)
|
||||
pair := []any{it.keys[it.index], a[it.keys[it.index]]}
|
||||
item = newList(pair)
|
||||
item = kern.NewList(pair)
|
||||
}
|
||||
} else {
|
||||
err = io.EOF
|
||||
@ -202,11 +204,11 @@ func (it *DictIterator) Next() (item any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (it *DictIterator) Index() int {
|
||||
func (it *DictIterator) Index() int64 {
|
||||
return it.index
|
||||
}
|
||||
|
||||
func (it *DictIterator) Count() int {
|
||||
func (it *DictIterator) Count() int64 {
|
||||
return it.count
|
||||
}
|
||||
|
||||
|
||||
@ -1421,12 +1421,38 @@ Same as <<_add,add()>> but returns the product of the values of the parameters.
|
||||
[green]`24`
|
||||
|
||||
==== Module "os.file"
|
||||
The "os.file" module provides functions for working with files.
|
||||
|
||||
Activation: +
|
||||
`{4sp}builtin "os.file"`
|
||||
|
||||
Currently available functions:
|
||||
|
||||
* <<_fileOpen,fileOpen()>>
|
||||
* <<_fileAppend,fileAppend()>>
|
||||
* <<_fileCreate,fileCreate()>>
|
||||
* <<_fileClose,fileClose()>>
|
||||
* <<_fileWriteText,fileWriteText()>>
|
||||
* <<_fileReadText,fileReadText()>>
|
||||
* <<_fileReadTextAll,fileReadTextAll()>>
|
||||
|
||||
More functions will be added in the future.
|
||||
|
||||
---
|
||||
|
||||
===== fileOpen()
|
||||
Syntax: +
|
||||
`{4sp}fileOpen(<file-path>) -> file-handle`
|
||||
|
||||
Returns a file handle for the specified file path. The file is opened in read-write mode. If the file does not exist, it is created.
|
||||
|
||||
===== fileAppend()
|
||||
|
||||
===== fileCreate()
|
||||
Syntax: +
|
||||
`{4sp}fileCreate(<file-path>) -> file-handle`
|
||||
|
||||
Creates or truncates the named _<file-path>_. If the file already exists, it is truncated. If the file does not exist, it is created with mode 0o666 (before umask). The associated file descriptor has mode [O_RDWR]. The directory containing the file must already exist.
|
||||
|
||||
===== fileClose()
|
||||
|
||||
@ -1438,6 +1464,24 @@ Same as <<_add,add()>> but returns the product of the values of the parameters.
|
||||
|
||||
|
||||
==== Module "string"
|
||||
This module provides functions for working with strings.
|
||||
|
||||
Activation: +
|
||||
`{4sp}builtin "string"`
|
||||
|
||||
|
||||
Currently available functions:
|
||||
|
||||
* <<_strJoin,strJoin()>>
|
||||
* <<_strSub,strSub()>>
|
||||
* <<_strSplit,strSplit()>>
|
||||
* <<_strTrim,strTrim()>>
|
||||
* <<_strStartsWith,strStartsWith()>>
|
||||
* <<_strEndsWith,strEndsWith()>>
|
||||
* <<_strUpper,strUpper()>>
|
||||
* <<_strLower,strLower()>>
|
||||
|
||||
---
|
||||
|
||||
===== strJoin()
|
||||
Syntax: +
|
||||
|
||||
8
expr.go
8
expr.go
@ -4,9 +4,13 @@
|
||||
// expr.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
kern "git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// ----Expression interface
|
||||
type Expr interface {
|
||||
Typer
|
||||
Eval(ctx ExprContext) (result any, err error)
|
||||
kern.Typer
|
||||
Eval(ctx kern.ExprContext) (result any, err error)
|
||||
String() string
|
||||
}
|
||||
|
||||
201
function.go
201
function.go
@ -6,19 +6,20 @@ package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// ---- Function template
|
||||
type FuncTemplate func(ctx ExprContext, name string, args map[string]any) (result any, err error)
|
||||
// type FuncTemplate func(ctx expr.ExprContext, name string, args map[string]any) (result any, err error)
|
||||
|
||||
// ---- Common functor definition
|
||||
type baseFunctor struct {
|
||||
info ExprFunc
|
||||
type BaseFunctor struct {
|
||||
info kern.ExprFunc
|
||||
}
|
||||
|
||||
func (functor *baseFunctor) ToString(opt FmtOpt) (s string) {
|
||||
func (functor *BaseFunctor) ToString(opt kern.FmtOpt) (s string) {
|
||||
if functor.info != nil {
|
||||
s = functor.info.ToString(opt)
|
||||
} else {
|
||||
@ -27,23 +28,23 @@ func (functor *baseFunctor) ToString(opt FmtOpt) (s string) {
|
||||
return s
|
||||
}
|
||||
|
||||
func (functor *baseFunctor) GetParams() (params []ExprFuncParam) {
|
||||
func (functor *BaseFunctor) GetParams() (params []kern.ExprFuncParam) {
|
||||
if functor.info != nil {
|
||||
return functor.info.Params()
|
||||
} else {
|
||||
return []ExprFuncParam{}
|
||||
return []kern.ExprFuncParam{}
|
||||
}
|
||||
}
|
||||
|
||||
func (functor *baseFunctor) SetFunc(info ExprFunc) {
|
||||
func (functor *BaseFunctor) SetFunc(info kern.ExprFunc) {
|
||||
functor.info = info
|
||||
}
|
||||
|
||||
func (functor *baseFunctor) GetFunc() ExprFunc {
|
||||
func (functor *BaseFunctor) GetFunc() kern.ExprFunc {
|
||||
return functor.info
|
||||
}
|
||||
|
||||
func (functor *baseFunctor) GetDefinitionContext() ExprContext {
|
||||
func (functor *BaseFunctor) GetDefinitionContext() kern.ExprContext {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -62,11 +63,11 @@ type funcParamInfo struct {
|
||||
defaultValue any
|
||||
}
|
||||
|
||||
func NewFuncParam(name string) ExprFuncParam {
|
||||
func NewFuncParam(name string) kern.ExprFuncParam {
|
||||
return &funcParamInfo{name: name}
|
||||
}
|
||||
|
||||
func NewFuncParamFlag(name string, flags paramFlags) ExprFuncParam {
|
||||
func NewFuncParamFlag(name string, flags paramFlags) kern.ExprFuncParam {
|
||||
return &funcParamInfo{name: name, flags: flags}
|
||||
}
|
||||
|
||||
@ -79,7 +80,7 @@ func (param *funcParamInfo) Name() string {
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) Type() string {
|
||||
return TypeAny
|
||||
return kern.TypeAny
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) IsDefault() bool {
|
||||
@ -100,17 +101,17 @@ func (param *funcParamInfo) DefaultValue() any {
|
||||
|
||||
// --- Functions
|
||||
|
||||
// funcInfo implements ExprFunc
|
||||
// funcInfo implements expr.ExprFunc
|
||||
type funcInfo struct {
|
||||
name string
|
||||
minArgs int
|
||||
maxArgs int
|
||||
functor Functor
|
||||
formalParams []ExprFuncParam
|
||||
functor kern.Functor
|
||||
formalParams []kern.ExprFuncParam
|
||||
returnType string
|
||||
}
|
||||
|
||||
func newFuncInfo(name string, functor Functor, returnType string, params []ExprFuncParam) (info *funcInfo, err error) {
|
||||
func newFuncInfo(name string, functor kern.Functor, returnType string, params []kern.ExprFuncParam) (info *funcInfo, err error) {
|
||||
var minArgs = 0
|
||||
var maxArgs = 0
|
||||
for _, p := range params {
|
||||
@ -138,7 +139,7 @@ func newFuncInfo(name string, functor Functor, returnType string, params []ExprF
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (info *funcInfo) Params() []ExprFuncParam {
|
||||
func (info *funcInfo) Params() []kern.ExprFuncParam {
|
||||
return info.formalParams
|
||||
}
|
||||
|
||||
@ -146,7 +147,7 @@ func (info *funcInfo) ReturnType() string {
|
||||
return info.returnType
|
||||
}
|
||||
|
||||
func (info *funcInfo) ToString(opt FmtOpt) string {
|
||||
func (info *funcInfo) ToString(opt kern.FmtOpt) string {
|
||||
var sb strings.Builder
|
||||
if len(info.Name()) == 0 {
|
||||
sb.WriteString("func")
|
||||
@ -180,7 +181,7 @@ func (info *funcInfo) ToString(opt FmtOpt) string {
|
||||
if len(info.returnType) > 0 {
|
||||
sb.WriteString(info.returnType)
|
||||
} else {
|
||||
sb.WriteString(TypeAny)
|
||||
sb.WriteString(kern.TypeAny)
|
||||
}
|
||||
sb.WriteString("{}")
|
||||
return sb.String()
|
||||
@ -198,11 +199,11 @@ func (info *funcInfo) MaxArgs() int {
|
||||
return info.maxArgs
|
||||
}
|
||||
|
||||
func (info *funcInfo) Functor() Functor {
|
||||
func (info *funcInfo) Functor() kern.Functor {
|
||||
return info.functor
|
||||
}
|
||||
|
||||
func (info *funcInfo) AllocContext(parentCtx ExprContext) (ctx ExprContext) {
|
||||
func (info *funcInfo) AllocContext(parentCtx kern.ExprContext) (ctx kern.ExprContext) {
|
||||
if defCtx := info.functor.GetDefinitionContext(); defCtx != nil {
|
||||
ctx = defCtx.Clone()
|
||||
ctx.SetParent(defCtx)
|
||||
@ -213,7 +214,7 @@ func (info *funcInfo) AllocContext(parentCtx ExprContext) (ctx ExprContext) {
|
||||
return
|
||||
}
|
||||
|
||||
func (info *funcInfo) ParamSpec(paramName string) ExprFuncParam {
|
||||
func (info *funcInfo) ParamSpec(paramName string) kern.ExprFuncParam {
|
||||
for _, spec := range info.formalParams {
|
||||
if spec.Name() == paramName {
|
||||
return spec
|
||||
@ -222,7 +223,7 @@ func (info *funcInfo) ParamSpec(paramName string) ExprFuncParam {
|
||||
return nil
|
||||
}
|
||||
|
||||
func initActualParams(ctx ExprContext, info ExprFunc, callTerm *term) (actualParams map[string]any, err error) {
|
||||
func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *term) (actualParams map[string]any, err error) {
|
||||
var varArgs []any
|
||||
var varName string
|
||||
|
||||
@ -237,10 +238,10 @@ func initActualParams(ctx ExprContext, info ExprFunc, callTerm *term) (actualPar
|
||||
for i, tree := range callTerm.children {
|
||||
var paramValue any
|
||||
paramCtx := ctx.Clone()
|
||||
if paramValue, err = tree.compute(paramCtx); err != nil {
|
||||
if paramValue, err = tree.Compute(paramCtx); err != nil {
|
||||
break
|
||||
}
|
||||
if paramName, namedParam := getAssignVarName(tree); namedParam {
|
||||
if paramName, namedParam := kern.GetAssignVarName(tree); namedParam {
|
||||
if info.ParamSpec(paramName) == nil {
|
||||
err = fmt.Errorf("%s(): unknown param %q", info.Name(), paramName)
|
||||
break
|
||||
@ -260,7 +261,7 @@ func initActualParams(ctx ExprContext, info ExprFunc, callTerm *term) (actualPar
|
||||
actualParams[spec.Name()] = paramValue
|
||||
}
|
||||
} else {
|
||||
err = ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.children))
|
||||
err = kern.ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.children))
|
||||
break
|
||||
}
|
||||
} else {
|
||||
@ -279,7 +280,7 @@ func initActualParams(ctx ExprContext, info ExprFunc, callTerm *term) (actualPar
|
||||
func (info *funcInfo) PrepareCall(name string, actualParams map[string]any) (err error) {
|
||||
passedCount := len(actualParams)
|
||||
if info.MinArgs() > passedCount {
|
||||
err = ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount)
|
||||
err = kern.ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount)
|
||||
return
|
||||
}
|
||||
|
||||
@ -301,86 +302,86 @@ func (info *funcInfo) PrepareCall(name string, actualParams map[string]any) (err
|
||||
}
|
||||
|
||||
if info.MaxArgs() >= 0 && info.MaxArgs() < len(actualParams) {
|
||||
err = ErrTooManyParams(name, info.MaxArgs(), len(actualParams))
|
||||
err = kern.ErrTooManyParams(name, info.MaxArgs(), len(actualParams))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ----- Call a function ---
|
||||
|
||||
func getAssignVarName(t *term) (name string, ok bool) {
|
||||
if ok = t.symbol() == SymEqual; ok {
|
||||
name = t.children[0].source()
|
||||
}
|
||||
return
|
||||
}
|
||||
// func getAssignVarName(t *term) (name string, ok bool) {
|
||||
// if ok = t.symbol() == SymEqual; ok {
|
||||
// name = t.children[0].source()
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func CallFunctionByTerm(parentCtx ExprContext, name string, callTerm *term) (result any, err error) {
|
||||
var actualParams map[string]any
|
||||
if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
if actualParams, err = initActualParams(parentCtx, info, callTerm); err == nil {
|
||||
ctx := info.AllocContext(parentCtx)
|
||||
if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
functor := info.Functor()
|
||||
result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
exportObjectsToParent(ctx)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
// func CallFunctionByTerm(parentCtx expr.ExprContext, name string, callTerm *term) (result any, err error) {
|
||||
// var actualParams map[string]any
|
||||
// if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
// if actualParams, err = initActualParams(parentCtx, info, callTerm); err == nil {
|
||||
// ctx := info.AllocContext(parentCtx)
|
||||
// if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
// functor := info.Functor()
|
||||
// result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
// exportObjectsToParent(ctx)
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// err = fmt.Errorf("unknown function %s()", name)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func CallFunctionByArgs(parentCtx ExprContext, name string, args []any) (result any, err error) {
|
||||
var actualParams map[string]any
|
||||
if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
functor := info.Functor()
|
||||
actualParams = bindActualParams(functor, args)
|
||||
ctx := info.AllocContext(parentCtx)
|
||||
if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
exportObjectsToParent(ctx)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
// func CallFunctionByArgs(parentCtx expr.ExprContext, name string, args []any) (result any, err error) {
|
||||
// var actualParams map[string]any
|
||||
// if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
// functor := info.Functor()
|
||||
// actualParams = bindActualParams(functor, args)
|
||||
// ctx := info.AllocContext(parentCtx)
|
||||
// if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
// result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
// exportObjectsToParent(ctx)
|
||||
// }
|
||||
// } else {
|
||||
// err = fmt.Errorf("unknown function %s()", name)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func CallFunctionByParams(parentCtx ExprContext, name string, actualParams map[string]any) (result any, err error) {
|
||||
//var actualParams map[string]any
|
||||
if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
functor := info.Functor()
|
||||
ctx := info.AllocContext(parentCtx)
|
||||
if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
exportObjectsToParent(ctx)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
// func CallFunctionByParams(parentCtx expr.ExprContext, name string, actualParams map[string]any) (result any, err error) {
|
||||
// //var actualParams map[string]any
|
||||
// if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
// functor := info.Functor()
|
||||
// ctx := info.AllocContext(parentCtx)
|
||||
// if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
// result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
// exportObjectsToParent(ctx)
|
||||
// }
|
||||
// } else {
|
||||
// err = fmt.Errorf("unknown function %s()", name)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func GetParam(args map[string]any, paramName string, paramNum int) (value any, exists bool) {
|
||||
if value, exists = args[paramName]; !exists {
|
||||
if paramNum > 0 && paramNum <= len(args) {
|
||||
value, exists = args["arg"+strconv.Itoa(paramNum)]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// func GetParam(args map[string]any, paramName string, paramNum int) (value any, exists bool) {
|
||||
// if value, exists = args[paramName]; !exists {
|
||||
// if paramNum > 0 && paramNum <= len(args) {
|
||||
// value, exists = args["arg"+strconv.Itoa(paramNum)]
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func bindActualParams(functor Functor, args []any) (actualParams map[string]any) {
|
||||
formalParams := functor.GetParams()
|
||||
actualParams = make(map[string]any, len(args))
|
||||
for i, arg := range args {
|
||||
if i < len(formalParams) {
|
||||
actualParams[formalParams[i].Name()] = arg
|
||||
} else {
|
||||
actualParams["arg"+strconv.Itoa(i+1)] = arg
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// func bindActualParams(functor Functor, args []any) (actualParams map[string]any) {
|
||||
// formalParams := functor.GetParams()
|
||||
// actualParams = make(map[string]any, len(args))
|
||||
// for i, arg := range args {
|
||||
// if i < len(formalParams) {
|
||||
// actualParams[formalParams[i].Name()] = arg
|
||||
// } else {
|
||||
// actualParams["arg"+strconv.Itoa(i+1)] = arg
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
@ -7,101 +7,68 @@ package expr
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
var globalCtx *SimpleStore
|
||||
//var globalCtx *SimpleStore
|
||||
|
||||
func ImportInContext(name string) (exists bool) {
|
||||
var mod *builtinModule
|
||||
if mod, exists = builtinModuleRegister[name]; exists {
|
||||
mod.importFunc(globalCtx)
|
||||
mod.imported = true
|
||||
func ImportInContext(ctx kern.ExprContext, name string) (exists bool) {
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
var mod *builtinModule
|
||||
if mod, exists = builtinModuleRegister[name]; exists {
|
||||
mod.importFunc(globalCtx)
|
||||
mod.imported = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ImportInContextByGlobPattern(pattern string) (count int, err error) {
|
||||
var matched bool
|
||||
for name, mod := range builtinModuleRegister {
|
||||
if matched, err = filepath.Match(pattern, name); err == nil {
|
||||
if matched {
|
||||
count++
|
||||
mod.importFunc(globalCtx)
|
||||
mod.imported = true
|
||||
func ImportInContextByGlobPattern(ctx kern.ExprContext, pattern string) (count int, err error) {
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
var matched bool
|
||||
for name, mod := range builtinModuleRegister {
|
||||
if matched, err = filepath.Match(pattern, name); err == nil {
|
||||
if matched {
|
||||
count++
|
||||
mod.importFunc(globalCtx)
|
||||
mod.imported = true
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetVar(ctx ExprContext, name string) (value any, exists bool) {
|
||||
if value, exists = ctx.GetVar(name); !exists {
|
||||
value, exists = globalCtx.GetVar(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetLocalFuncInfo(ctx ExprContext, name string) (item ExprFunc, exists bool) {
|
||||
var v any
|
||||
if len(name) > 0 {
|
||||
if v, exists = ctx.GetVar(name); exists && isFunctor(v) {
|
||||
f, _ := v.(Functor)
|
||||
item = f.GetFunc()
|
||||
} else {
|
||||
item, exists = ctx.GetFuncInfo(name)
|
||||
func GlobalCtrlSet(ctx kern.ExprContext, name string, newValue any) (currentValue any) {
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
|
||||
currentValue, _ = globalCtx.GetVar(name)
|
||||
globalCtx.SetVar(name, newValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetFuncInfo(ctx ExprContext, name string) (item ExprFunc, exists bool) {
|
||||
// if len(name) > 0 {
|
||||
// if item, exists = GetLocalFuncInfo(ctx, name); exists {
|
||||
// ownerCtx = ctx
|
||||
// } else if item, exists = globalCtx.GetFuncInfo(name); exists {
|
||||
// ownerCtx = globalCtx
|
||||
// }
|
||||
// }
|
||||
item, exists, _ = GetFuncInfoAndOwner(ctx, name)
|
||||
return
|
||||
}
|
||||
|
||||
func GetFuncInfoAndOwner(ctx ExprContext, name string) (item ExprFunc, exists bool, ownerCtx ExprContext) {
|
||||
if len(name) > 0 {
|
||||
if item, exists = GetLocalFuncInfo(ctx, name); exists {
|
||||
ownerCtx = ctx
|
||||
} else if item, exists = globalCtx.GetFuncInfo(name); exists {
|
||||
ownerCtx = globalCtx
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GlobalCtrlSet(name string, newValue any) (currentValue any) {
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
currentValue, _ = globalCtx.GetVar(name)
|
||||
|
||||
globalCtx.SetVar(name, newValue)
|
||||
return currentValue
|
||||
}
|
||||
|
||||
func GlobalCtrlGet(name string) (currentValue any) {
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
func GlobalCtrlGet(ctx kern.ExprContext, name string) (currentValue any) {
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
currentValue, _ = globalCtx.GetVar(name)
|
||||
}
|
||||
currentValue, _ = globalCtx.GetVar(name)
|
||||
return currentValue
|
||||
}
|
||||
|
||||
func CtrlEnable(ctx ExprContext, name string) (currentStatus bool) {
|
||||
func CtrlEnable(ctx kern.ExprContext, name string) (currentStatus bool) {
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
if v, exists := ctx.GetVar(name); exists && IsBool(v) {
|
||||
if v, exists := ctx.GetVar(name); exists && kern.IsBool(v) {
|
||||
currentStatus, _ = v.(bool)
|
||||
}
|
||||
|
||||
@ -109,11 +76,11 @@ func CtrlEnable(ctx ExprContext, name string) (currentStatus bool) {
|
||||
return currentStatus
|
||||
}
|
||||
|
||||
func CtrlDisable(ctx ExprContext, name string) (currentStatus bool) {
|
||||
func CtrlDisable(ctx kern.ExprContext, name string) (currentStatus bool) {
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
if v, exists := ctx.GetVar(name); exists && IsBool(v) {
|
||||
if v, exists := ctx.GetVar(name); exists && kern.IsBool(v) {
|
||||
currentStatus, _ = v.(bool)
|
||||
}
|
||||
|
||||
@ -121,36 +88,39 @@ func CtrlDisable(ctx ExprContext, name string) (currentStatus bool) {
|
||||
return currentStatus
|
||||
}
|
||||
|
||||
func CtrlIsEnabled(ctx ExprContext, name string) (status bool) {
|
||||
var v any
|
||||
var exists bool
|
||||
// func CtrlIsEnabled(ctx ExprContext, name string) (status bool) {
|
||||
// var v any
|
||||
// var exists bool
|
||||
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
// if !strings.HasPrefix(name, "_") {
|
||||
// name = "_" + name
|
||||
// }
|
||||
|
||||
if v, exists = ctx.GetVar(name); !exists {
|
||||
v, exists = globalCtx.GetVar(name)
|
||||
}
|
||||
// if v, exists = ctx.GetVar(name); !exists {
|
||||
// v, exists = globalCtx.GetVar(name)
|
||||
// }
|
||||
|
||||
if exists {
|
||||
if b, ok := v.(bool); ok {
|
||||
status = b
|
||||
// if exists {
|
||||
// if b, ok := v.(bool); ok {
|
||||
// status = b
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func getControlString(ctx kern.ExprContext, name string) (s string, exists bool) {
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
var v any
|
||||
if v, exists = globalCtx.GetVar(name); exists {
|
||||
s, exists = v.(string)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getControlString(name string) (s string, exists bool) {
|
||||
var v any
|
||||
if v, exists = globalCtx.GetVar(name); exists {
|
||||
s, exists = v.(string)
|
||||
}
|
||||
func InitGlobal() (ctx kern.ExprContext) {
|
||||
ctx = NewSimpleStoreWithoutGlobalContext()
|
||||
kern.InitDefaultVars(ctx)
|
||||
ImportBuiltinsFuncs(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
func init() {
|
||||
globalCtx = NewSimpleStore()
|
||||
initDefaultVars(globalCtx)
|
||||
ImportBuiltinsFuncs(globalCtx)
|
||||
}
|
||||
|
||||
2
graph.go
2
graph.go
@ -53,7 +53,7 @@ func (r *Reticle) computeCharWidth() {
|
||||
if v := ref.node.value(); v != nil {
|
||||
ref.label = fmt.Sprintf("%v", v)
|
||||
} else {
|
||||
ref.label = ref.node.source()
|
||||
ref.label = ref.node.Source()
|
||||
}
|
||||
r.colsWidth[c] = max(r.colsWidth[c], len(ref.label)+2) // +2 to make room for brakets
|
||||
}
|
||||
|
||||
25
helpers.go
25
helpers.go
@ -9,9 +9,12 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
"git.portale-stac.it/go-pkg/expr/util"
|
||||
)
|
||||
|
||||
func EvalString(ctx ExprContext, source string) (result any, err error) {
|
||||
func EvalString(ctx kern.ExprContext, source string) (result any, err error) {
|
||||
var tree *ast
|
||||
|
||||
r := strings.NewReader(source)
|
||||
@ -34,21 +37,21 @@ func EvalStringA(source string, args ...Arg) (result any, err error) {
|
||||
}
|
||||
|
||||
func EvalStringV(source string, args []Arg) (result any, err error) {
|
||||
ctx := NewSimpleStore()
|
||||
ctx := NewSimpleStoreWithoutGlobalContext()
|
||||
for _, arg := range args {
|
||||
if isFunc(arg.Value) {
|
||||
if f, ok := arg.Value.(FuncTemplate); ok {
|
||||
functor := NewGolangFunctor(f)
|
||||
if util.IsFunc(arg.Value) {
|
||||
if f, ok := arg.Value.(kern.FuncTemplate); ok {
|
||||
functor := kern.NewGolangFunctor(f)
|
||||
// ctx.RegisterFunc(arg.Name, functor, 0, -1)
|
||||
ctx.RegisterFunc(arg.Name, functor, TypeAny, []ExprFuncParam{
|
||||
NewFuncParamFlagDef(ParamValue, PfDefault|PfRepeat, 0),
|
||||
ctx.RegisterFunc(arg.Name, functor, kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, 0),
|
||||
})
|
||||
} else {
|
||||
err = fmt.Errorf("invalid function specification: %q", arg.Name)
|
||||
}
|
||||
} else if integer, ok := anyInteger(arg.Value); ok {
|
||||
} else if integer, ok := kern.AnyInteger(arg.Value); ok {
|
||||
ctx.SetVar(arg.Name, integer)
|
||||
} else if float, ok := anyFloat(arg.Value); ok {
|
||||
} else if float, ok := kern.AnyFloat(arg.Value); ok {
|
||||
ctx.SetVar(arg.Name, float)
|
||||
} else if _, ok := arg.Value.(string); ok {
|
||||
ctx.SetVar(arg.Name, arg.Value)
|
||||
@ -65,7 +68,7 @@ func EvalStringV(source string, args []Arg) (result any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func EvalStream(ctx ExprContext, r io.Reader) (result any, err error) {
|
||||
func EvalStream(ctx kern.ExprContext, r io.Reader) (result any, err error) {
|
||||
var tree *ast
|
||||
scanner := NewScanner(r, DefaultTranslations())
|
||||
parser := NewParser()
|
||||
@ -76,7 +79,7 @@ func EvalStream(ctx ExprContext, r io.Reader) (result any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func EvalFile(ctx ExprContext, filePath string) (result any, err error) {
|
||||
func EvalFile(ctx kern.ExprContext, filePath string) (result any, err error) {
|
||||
var fh *os.File
|
||||
if fh, err = os.Open(filePath); err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -11,6 +11,9 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
"git.portale-stac.it/go-pkg/expr/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -19,8 +22,8 @@ const (
|
||||
)
|
||||
|
||||
func checkStringParamExpected(funcName string, paramValue any, paramPos int) (err error) {
|
||||
if !(IsString(paramValue) /*|| isList(paramValue)*/) {
|
||||
err = fmt.Errorf("%s(): param nr %d has wrong type %s, string expected", funcName, paramPos+1, TypeName(paramValue))
|
||||
if !(kern.IsString(paramValue) /*|| isList(paramValue)*/) {
|
||||
err = fmt.Errorf("%s(): param nr %d has wrong type %s, string expected", funcName, paramPos+1, kern.TypeName(paramValue))
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -45,8 +48,8 @@ func addEnvImportDirs(envVarName string, dirList []string) []string {
|
||||
return dirList
|
||||
}
|
||||
|
||||
func addSearchDirs(endingPath string, dirList []string) []string {
|
||||
if dirSpec, exists := getControlString(ControlSearchPath); exists {
|
||||
func addSearchDirs(ctx kern.ExprContext, endingPath string, dirList []string) []string {
|
||||
if dirSpec, exists := getControlString(ctx, kern.ControlSearchPath); exists {
|
||||
dirs := strings.Split(dirSpec, ":")
|
||||
if dirList == nil {
|
||||
dirList = dirs
|
||||
@ -63,9 +66,9 @@ func addSearchDirs(endingPath string, dirList []string) []string {
|
||||
return dirList
|
||||
}
|
||||
|
||||
func buildSearchDirList(endingPath, envVarName string) (dirList []string) {
|
||||
func buildSearchDirList(ctx kern.ExprContext, endingPath, envVarName string) (dirList []string) {
|
||||
dirList = addEnvImportDirs(envVarName, dirList)
|
||||
dirList = addSearchDirs(endingPath, dirList)
|
||||
dirList = addSearchDirs(ctx, endingPath, dirList)
|
||||
return
|
||||
}
|
||||
|
||||
@ -83,7 +86,7 @@ func searchAmongPath(filename string, dirList []string) (filePath string) {
|
||||
}
|
||||
|
||||
for _, dir := range dirList {
|
||||
if dir, err = ExpandPath(dir); err != nil {
|
||||
if dir, err = util.ExpandPath(dir); err != nil {
|
||||
continue
|
||||
}
|
||||
if fullPath := path.Join(dir, filename); isFile(fullPath) {
|
||||
@ -106,7 +109,7 @@ func isPathRelative(filePath string) bool {
|
||||
}
|
||||
|
||||
func makeFilepath(filename string, dirList []string) (filePath string, err error) {
|
||||
if filename, err = ExpandPath(filename); err != nil {
|
||||
if filename, err = util.ExpandPath(filename); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
137
int-iterator.go
Normal file
137
int-iterator.go
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// int-iterator.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type IntIterator struct {
|
||||
count int64
|
||||
index int64
|
||||
start int64
|
||||
stop int64
|
||||
step int64
|
||||
}
|
||||
|
||||
func NewIntIterator(args []any) (it *IntIterator, err error) {
|
||||
var argc int = 0
|
||||
if args != nil {
|
||||
argc = len(args)
|
||||
}
|
||||
it = &IntIterator{count: 0, index: -1, start: 0, stop: 0, step: 1}
|
||||
if argc >= 1 {
|
||||
if it.stop, err = kern.ToGoInt64(args[0], "start index"); err != nil {
|
||||
return
|
||||
}
|
||||
if argc >= 2 {
|
||||
it.start = it.stop
|
||||
if it.stop, err = kern.ToGoInt64(args[1], "stop index"); err != nil {
|
||||
return
|
||||
}
|
||||
if argc >= 3 {
|
||||
if it.step, err = kern.ToGoInt64(args[2], "step"); err != nil {
|
||||
return
|
||||
}
|
||||
} else if it.start > it.stop {
|
||||
it.step = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
if it.step == 0 {
|
||||
err = fmt.Errorf("step cannot be zero")
|
||||
return
|
||||
}
|
||||
if it.start < it.stop && it.step < 0 {
|
||||
err = fmt.Errorf("step cannot be negative when start < stop")
|
||||
return
|
||||
}
|
||||
if it.start > it.stop && it.step > 0 {
|
||||
err = fmt.Errorf("step cannot be positive when start > stop")
|
||||
return
|
||||
}
|
||||
it.Reset()
|
||||
return
|
||||
}
|
||||
|
||||
func (it *IntIterator) String() string {
|
||||
return fmt.Sprintf("$(%d..%d..%d)", it.start, it.stop, it.step)
|
||||
}
|
||||
|
||||
func (it *IntIterator) TypeName() string {
|
||||
return "IntIterator"
|
||||
}
|
||||
|
||||
func (it *IntIterator) HasOperation(name string) bool {
|
||||
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName}, name)
|
||||
return yes
|
||||
}
|
||||
|
||||
func (it *IntIterator) CallOperation(name string, args map[string]any) (v any, err error) {
|
||||
switch name {
|
||||
case kern.NextName:
|
||||
v, err = it.Next()
|
||||
case kern.ResetName:
|
||||
err = it.Reset()
|
||||
case kern.CleanName:
|
||||
err = it.Clean()
|
||||
case kern.IndexName:
|
||||
v = int64(it.Index())
|
||||
case kern.CurrentName:
|
||||
v, err = it.Current()
|
||||
case kern.CountName:
|
||||
v = it.count
|
||||
default:
|
||||
err = kern.ErrNoOperation(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (it *IntIterator) Current() (item any, err error) {
|
||||
if it.start <= it.stop {
|
||||
if it.index >= it.start && it.index < it.stop {
|
||||
item = it.index
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
} else {
|
||||
if it.index > it.stop && it.index <= it.start {
|
||||
item = it.index
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (it *IntIterator) Next() (item any, err error) {
|
||||
it.index += it.step
|
||||
if item, err = it.Current(); err != io.EOF {
|
||||
it.count++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (it *IntIterator) Index() int64 {
|
||||
return it.index
|
||||
}
|
||||
|
||||
func (it *IntIterator) Count() int64 {
|
||||
return it.count
|
||||
}
|
||||
|
||||
func (it *IntIterator) Reset() error {
|
||||
it.index = it.start - it.step
|
||||
it.count = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
func (it *IntIterator) Clean() error {
|
||||
return nil
|
||||
}
|
||||
@ -4,19 +4,23 @@
|
||||
// iter-factory.go
|
||||
package expr
|
||||
|
||||
func NewIterator(value any) (it Iterator, err error) {
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func NewIterator(value any) (it kern.Iterator, err error) {
|
||||
if value == nil {
|
||||
return NewArrayIterator([]any{}), nil
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case *ListType:
|
||||
case *kern.ListType:
|
||||
it = NewListIterator(v, nil)
|
||||
case *DictType:
|
||||
case *kern.DictType:
|
||||
it, err = NewDictIterator(v, nil)
|
||||
case []any:
|
||||
it = NewArrayIterator(v)
|
||||
case Iterator:
|
||||
case kern.Iterator:
|
||||
it = v
|
||||
default:
|
||||
it = NewArrayIterator([]any{value})
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
// All rights reserved.
|
||||
|
||||
// bind-go-function.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
// ---- Linking with Go functions
|
||||
type golangFunctor struct {
|
||||
baseFunctor
|
||||
BaseFunctor
|
||||
f FuncTemplate
|
||||
}
|
||||
|
||||
27
kern/bool.go
Normal file
27
kern/bool.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// string.go
|
||||
package kern
|
||||
|
||||
func IsBool(v any) (ok bool) {
|
||||
_, ok = v.(bool)
|
||||
return ok
|
||||
}
|
||||
|
||||
func ToBool(v any) (b bool, ok bool) {
|
||||
ok = true
|
||||
switch x := v.(type) {
|
||||
case string:
|
||||
b = len(x) > 0
|
||||
case float64:
|
||||
b = x != 0.0
|
||||
case int64:
|
||||
b = x != 0
|
||||
case bool:
|
||||
b = x
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// common-errors.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -86,6 +86,6 @@ func ErrUnknownVar(funcName, varName string) error {
|
||||
|
||||
// --- Operator errors
|
||||
|
||||
func ErrLeftOperandMustBeVariable(leftTerm, opTerm *term) error {
|
||||
return leftTerm.Errorf("left operand of %q must be a variable", opTerm.source())
|
||||
func ErrLeftOperandMustBeVariable(leftTerm, opTerm Term) error {
|
||||
return leftTerm.Errorf("left operand of %q must be a variable", opTerm.Source())
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// common-params.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
const (
|
||||
ParamArgs = "args"
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// common-type-names.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
const (
|
||||
TypeAny = "any"
|
||||
@ -2,9 +2,9 @@
|
||||
// All rights reserved.
|
||||
|
||||
// context-helpers.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
func cloneContext(sourceCtx ExprContext) (clonedCtx ExprContext) {
|
||||
func CloneContext(sourceCtx ExprContext) (clonedCtx ExprContext) {
|
||||
if sourceCtx != nil {
|
||||
clonedCtx = sourceCtx.Clone()
|
||||
}
|
||||
@ -25,8 +25,8 @@ func exportFunc(ctx ExprContext, name string, info ExprFunc) {
|
||||
ctx.RegisterFunc(name, info.Functor(), info.ReturnType(), info.Params())
|
||||
}
|
||||
|
||||
func exportObjects(destCtx, sourceCtx ExprContext) {
|
||||
exportAll := CtrlIsEnabled(sourceCtx, control_export_all)
|
||||
func ExportObjects(destCtx, sourceCtx ExprContext) {
|
||||
exportAll := CtrlIsEnabled(sourceCtx, ControlExportAll)
|
||||
// fmt.Printf("Exporting from sourceCtx [%p] to destCtx [%p] -- exportAll=%t\n", sourceCtx, destCtx, exportAll)
|
||||
// Export variables
|
||||
for _, refName := range sourceCtx.EnumVars(func(name string) bool { return (exportAll || name[0] == '@') && !(name[0] == '_') }) {
|
||||
@ -44,6 +44,6 @@ func exportObjects(destCtx, sourceCtx ExprContext) {
|
||||
|
||||
func exportObjectsToParent(sourceCtx ExprContext) {
|
||||
if parentCtx := sourceCtx.GetParent(); parentCtx != nil {
|
||||
exportObjects(parentCtx, sourceCtx)
|
||||
ExportObjects(parentCtx, sourceCtx)
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,9 @@
|
||||
// All rights reserved.
|
||||
|
||||
// control.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
import "strings"
|
||||
|
||||
// Preset control variables
|
||||
const (
|
||||
@ -16,7 +18,7 @@ const (
|
||||
|
||||
// Other control variables
|
||||
const (
|
||||
control_export_all = "_export_all"
|
||||
ControlExportAll = "_export_all"
|
||||
)
|
||||
|
||||
// Initial values
|
||||
@ -24,13 +26,34 @@ const (
|
||||
init_search_path = "~/.local/lib/go-pkg/expr:/usr/local/lib/go-pkg/expr:/usr/lib/go-pkg/expr"
|
||||
)
|
||||
|
||||
func CtrlIsEnabled(ctx ExprContext, name string) (status bool) {
|
||||
var v any
|
||||
var exists bool
|
||||
|
||||
if !strings.HasPrefix(name, "_") {
|
||||
name = "_" + name
|
||||
}
|
||||
|
||||
if v, exists = ctx.GetVar(name); !exists {
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
v, exists = globalCtx.GetVar(name)
|
||||
}
|
||||
}
|
||||
|
||||
if exists {
|
||||
if b, ok := v.(bool); ok {
|
||||
status = b
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func SetCtrl(ctx ExprContext, name string, value any) (current any) {
|
||||
current, _ = ctx.GetVar(name)
|
||||
ctx.UnsafeSetVar(name, value)
|
||||
return
|
||||
}
|
||||
|
||||
func initDefaultVars(ctx ExprContext) {
|
||||
func InitDefaultVars(ctx ExprContext) {
|
||||
if _, exists := ctx.GetVar(ControlPreset); exists {
|
||||
return
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// dict-type.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -12,6 +12,11 @@ import (
|
||||
|
||||
type DictType map[any]any
|
||||
|
||||
func IsDict(v any) (ok bool) {
|
||||
_, ok = v.(*DictType)
|
||||
return ok
|
||||
}
|
||||
|
||||
func MakeDict() (dict *DictType) {
|
||||
d := make(DictType)
|
||||
dict = &d
|
||||
@ -32,7 +37,7 @@ func NewDict(dictAny map[any]any) (dict *DictType) {
|
||||
return
|
||||
}
|
||||
|
||||
func newDict(dictAny map[any]*term) (dict *DictType) {
|
||||
func newDict(dictAny map[any]Term) (dict *DictType) {
|
||||
// TODO Change with a call to NewDict()
|
||||
var d DictType
|
||||
if dictAny != nil {
|
||||
@ -110,7 +115,7 @@ func (dict *DictType) ToString(opt FmtOpt) string {
|
||||
sb.WriteString(": ")
|
||||
if formatter, ok := value.(Formatter); ok {
|
||||
sb.WriteString(formatter.ToString(opt))
|
||||
} else if t, ok := value.(*term); ok {
|
||||
} else if t, ok := value.(Term); ok {
|
||||
sb.WriteString(t.String())
|
||||
} else {
|
||||
sb.WriteString(fmt.Sprintf("%#v", value))
|
||||
@ -129,7 +134,7 @@ func (dict *DictType) TypeName() string {
|
||||
return "dict"
|
||||
}
|
||||
|
||||
func (dict *DictType) hasKey(target any) (ok bool) {
|
||||
func (dict *DictType) HasKey(target any) (ok bool) {
|
||||
for key := range *dict {
|
||||
if ok = reflect.DeepEqual(key, target); ok {
|
||||
break
|
||||
@ -138,7 +143,17 @@ func (dict *DictType) hasKey(target any) (ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (dict *DictType) clone() (c *DictType) {
|
||||
func (dict *DictType) SetItem(key any, value any) (err error) {
|
||||
(*dict)[key] = value
|
||||
return
|
||||
}
|
||||
|
||||
func (dict *DictType) GetItem(key any) (value any, err error) {
|
||||
value = (*dict)[key]
|
||||
return
|
||||
}
|
||||
|
||||
func (dict *DictType) Clone() (c *DictType) {
|
||||
c = newDict(nil)
|
||||
for k, v := range *dict {
|
||||
(*c)[k] = v
|
||||
@ -146,7 +161,7 @@ func (dict *DictType) clone() (c *DictType) {
|
||||
return
|
||||
}
|
||||
|
||||
func (dict *DictType) merge(second *DictType) {
|
||||
func (dict *DictType) Merge(second *DictType) {
|
||||
if second != nil {
|
||||
for k, v := range *second {
|
||||
(*dict)[k] = v
|
||||
@ -154,11 +169,6 @@ func (dict *DictType) merge(second *DictType) {
|
||||
}
|
||||
}
|
||||
|
||||
func (dict *DictType) setItem(key any, value any) (err error) {
|
||||
(*dict)[key] = value
|
||||
return
|
||||
}
|
||||
|
||||
////////////////
|
||||
|
||||
type DictFormat interface {
|
||||
@ -2,13 +2,14 @@
|
||||
// All rights reserved.
|
||||
|
||||
// expr-context.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
// ----Expression Context
|
||||
type ExprContext interface {
|
||||
Clone() ExprContext
|
||||
SetParent(ctx ExprContext)
|
||||
GetParent() (ctx ExprContext)
|
||||
GetGlobal() (ctx ExprContext)
|
||||
GetVar(varName string) (value any, exists bool)
|
||||
GetLast() any
|
||||
SetVar(varName string, value any)
|
||||
@ -22,6 +23,7 @@ type ExprContext interface {
|
||||
FuncCount() int
|
||||
DeleteFunc(funcName string)
|
||||
|
||||
GetLocalFuncInfo(name string) (info ExprFunc, exists bool)
|
||||
GetFuncInfo(name string) (item ExprFunc, exists bool)
|
||||
Call(name string, args map[string]any) (result any, err error)
|
||||
RegisterFuncInfo(info ExprFunc)
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// expr-function.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
// ---- Functor interface
|
||||
type Functor interface {
|
||||
23
kern/float.go
Normal file
23
kern/float.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// float.go
|
||||
package kern
|
||||
|
||||
func IsFloat(v any) (ok bool) {
|
||||
_, ok = v.(float64)
|
||||
return ok
|
||||
}
|
||||
|
||||
func AnyFloat(v any) (float float64, ok bool) {
|
||||
ok = true
|
||||
switch floatval := v.(type) {
|
||||
case float32:
|
||||
float = float64(floatval)
|
||||
case float64:
|
||||
float = floatval
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// formatter.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
import "fmt"
|
||||
|
||||
@ -46,7 +46,7 @@ type Formatter interface {
|
||||
ToString(options FmtOpt) string
|
||||
}
|
||||
|
||||
func getFormatted(v any, opt FmtOpt) (text string) {
|
||||
func GetFormatted(v any, opt FmtOpt) (text string) {
|
||||
if v == nil {
|
||||
text = "(nil)"
|
||||
} else if s, ok := v.(string); ok {
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// fraction-type.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
//https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html
|
||||
|
||||
@ -18,12 +18,12 @@ type FractionType struct {
|
||||
num, den int64
|
||||
}
|
||||
|
||||
func newFraction(num, den int64) *FractionType {
|
||||
func NewFraction(num, den int64) *FractionType {
|
||||
num, den = simplifyIntegers(num, den)
|
||||
return &FractionType{num, den}
|
||||
}
|
||||
|
||||
func float64ToFraction(f float64) (fract *FractionType, err error) {
|
||||
func Float64ToFraction(f float64) (fract *FractionType, err error) {
|
||||
var sign string
|
||||
intPart, decPart := math.Modf(f)
|
||||
if decPart < 0.0 {
|
||||
@ -33,11 +33,11 @@ func float64ToFraction(f float64) (fract *FractionType, err error) {
|
||||
}
|
||||
dec := fmt.Sprintf("%.12f", decPart)
|
||||
s := fmt.Sprintf("%s%.f%s", sign, intPart, dec[1:])
|
||||
return makeGeneratingFraction(s)
|
||||
return MakeGeneratingFraction(s)
|
||||
}
|
||||
|
||||
// Based on https://cs.opensource.google/go/go/+/refs/tags/go1.22.3:src/math/big/rat.go;l=39
|
||||
func makeGeneratingFraction(s string) (f *FractionType, err error) {
|
||||
func MakeGeneratingFraction(s string) (f *FractionType, err error) {
|
||||
var num, den int64
|
||||
var sign int64 = 1
|
||||
var parts []string
|
||||
@ -59,7 +59,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) {
|
||||
return
|
||||
}
|
||||
if len(parts) == 1 {
|
||||
f = newFraction(sign*num, 1)
|
||||
f = NewFraction(sign*num, 1)
|
||||
} else if len(parts) == 2 {
|
||||
subParts := strings.SplitN(parts[1], "(", 2)
|
||||
if len(subParts) == 1 {
|
||||
@ -76,7 +76,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) {
|
||||
num = num*10 + int64(c-'0')
|
||||
den = den * 10
|
||||
}
|
||||
f = newFraction(sign*num, den)
|
||||
f = NewFraction(sign*num, den)
|
||||
} else if len(subParts) == 2 {
|
||||
sub := num
|
||||
mul := int64(1)
|
||||
@ -103,7 +103,7 @@ func makeGeneratingFraction(s string) (f *FractionType, err error) {
|
||||
den *= mul
|
||||
}
|
||||
num -= sub
|
||||
f = newFraction(sign*num, den)
|
||||
f = NewFraction(sign*num, den)
|
||||
}
|
||||
}
|
||||
exit:
|
||||
@ -113,7 +113,15 @@ exit:
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FractionType) toFloat() float64 {
|
||||
func (f *FractionType) N() int64 {
|
||||
return f.num
|
||||
}
|
||||
|
||||
func (f *FractionType) D() int64 {
|
||||
return f.den
|
||||
}
|
||||
|
||||
func (f *FractionType) ToFloat() float64 {
|
||||
return float64(f.num) / float64(f.den)
|
||||
}
|
||||
|
||||
@ -168,7 +176,7 @@ func (f *FractionType) TypeName() string {
|
||||
// -------- fraction utility functions
|
||||
|
||||
// greatest common divider
|
||||
func gcd(a, b int64) (g int64) {
|
||||
func Gcd(a, b int64) (g int64) {
|
||||
if a < 0 {
|
||||
a = -a
|
||||
}
|
||||
@ -189,21 +197,21 @@ func gcd(a, b int64) (g int64) {
|
||||
|
||||
// lower common multiple
|
||||
func lcm(a, b int64) (l int64) {
|
||||
g := gcd(a, b)
|
||||
g := Gcd(a, b)
|
||||
l = a * b / g
|
||||
return
|
||||
}
|
||||
|
||||
// Sum two fractions
|
||||
func sumFract(f1, f2 *FractionType) (sum *FractionType) {
|
||||
func SumFract(f1, f2 *FractionType) (sum *FractionType) {
|
||||
m := lcm(f1.den, f2.den)
|
||||
sum = newFraction(f1.num*(m/f1.den)+f2.num*(m/f2.den), m)
|
||||
sum = NewFraction(f1.num*(m/f1.den)+f2.num*(m/f2.den), m)
|
||||
return
|
||||
}
|
||||
|
||||
// Multiply two fractions
|
||||
func mulFract(f1, f2 *FractionType) (prod *FractionType) {
|
||||
prod = newFraction(f1.num*f2.num, f1.den*f2.den)
|
||||
func MulFract(f1, f2 *FractionType) (prod *FractionType) {
|
||||
prod = NewFraction(f1.num*f2.num, f1.den*f2.den)
|
||||
return
|
||||
}
|
||||
|
||||
@ -230,12 +238,12 @@ func anyPairToFract(v1, v2 any) (f1, f2 *FractionType, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func sumAnyFract(af1, af2 any) (sum any, err error) {
|
||||
func SumAnyFract(af1, af2 any) (sum any, err error) {
|
||||
var f1, f2 *FractionType
|
||||
if f1, f2, err = anyPairToFract(af1, af2); err != nil {
|
||||
return
|
||||
}
|
||||
f := sumFract(f1, f2)
|
||||
f := SumFract(f1, f2)
|
||||
if f.num == 0 {
|
||||
sum = 0
|
||||
} else {
|
||||
@ -250,7 +258,7 @@ func sumAnyFract(af1, af2 any) (sum any, err error) {
|
||||
// =0 if af1 == af2
|
||||
// >0 if af1 > af2
|
||||
// err if af1 or af2 is not convertible to fraction
|
||||
func cmpAnyFract(af1, af2 any) (result int, err error) {
|
||||
func CmpAnyFract(af1, af2 any) (result int, err error) {
|
||||
var f1, f2 *FractionType
|
||||
if f1, f2, err = anyPairToFract(af1, af2); err != nil {
|
||||
return
|
||||
@ -266,7 +274,7 @@ func cmpAnyFract(af1, af2 any) (result int, err error) {
|
||||
// >0 if af1 > af2
|
||||
func cmpFract(f1, f2 *FractionType) (result int) {
|
||||
f2.num = -f2.num
|
||||
f := sumFract(f1, f2)
|
||||
f := SumFract(f1, f2)
|
||||
if f.num < 0 {
|
||||
result = -1
|
||||
} else if f.num > 0 {
|
||||
@ -277,13 +285,13 @@ func cmpFract(f1, f2 *FractionType) (result int) {
|
||||
return
|
||||
}
|
||||
|
||||
func subAnyFract(af1, af2 any) (sum any, err error) {
|
||||
func SubAnyFract(af1, af2 any) (sum any, err error) {
|
||||
var f1, f2 *FractionType
|
||||
if f1, f2, err = anyPairToFract(af1, af2); err != nil {
|
||||
return
|
||||
}
|
||||
f2.num = -f2.num
|
||||
f := sumFract(f1, f2)
|
||||
f := SumFract(f1, f2)
|
||||
if f.num == 0 {
|
||||
sum = 0
|
||||
} else {
|
||||
@ -292,7 +300,7 @@ func subAnyFract(af1, af2 any) (sum any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func mulAnyFract(af1, af2 any) (prod any, err error) {
|
||||
func MulAnyFract(af1, af2 any) (prod any, err error) {
|
||||
var f1, f2 *FractionType
|
||||
if f1, f2, err = anyPairToFract(af1, af2); err != nil {
|
||||
return
|
||||
@ -306,7 +314,7 @@ func mulAnyFract(af1, af2 any) (prod any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func divAnyFract(af1, af2 any) (quot any, err error) {
|
||||
func DivAnyFract(af1, af2 any) (quot any, err error) {
|
||||
var f1, f2 *FractionType
|
||||
if f1, f2, err = anyPairToFract(af1, af2); err != nil {
|
||||
return
|
||||
@ -345,7 +353,7 @@ func simplifyIntegers(num, den int64) (a, b int64) {
|
||||
den = -den
|
||||
num = -num
|
||||
}
|
||||
g := gcd(num, den)
|
||||
g := Gcd(num, den)
|
||||
a = num / g
|
||||
b = den / g
|
||||
return
|
||||
@ -355,7 +363,19 @@ func intToFraction(n int64) *FractionType {
|
||||
return &FractionType{n, 1}
|
||||
}
|
||||
|
||||
func isFraction(v any) (ok bool) {
|
||||
func IsFraction(v any) (ok bool) {
|
||||
_, ok = v.(*FractionType)
|
||||
return ok
|
||||
}
|
||||
|
||||
// func IsFract(v any) (ok bool) {
|
||||
// _, ok = v.(*FractionType)
|
||||
// return ok
|
||||
// }
|
||||
|
||||
func IsRational(v any) (ok bool) {
|
||||
if _, ok = v.(*FractionType); !ok {
|
||||
_, ok = v.(int64)
|
||||
}
|
||||
return ok
|
||||
}
|
||||
278
kern/function.go
Normal file
278
kern/function.go
Normal file
@ -0,0 +1,278 @@
|
||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// function.go
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ---- Function templates
|
||||
type FuncTemplate func(ctx ExprContext, name string, args map[string]any) (result any, err error)
|
||||
|
||||
type DeepFuncTemplate func(a, b any) (eq bool, err error)
|
||||
|
||||
func IsFunctor(v any) (ok bool) {
|
||||
_, ok = v.(Functor)
|
||||
return
|
||||
}
|
||||
|
||||
// ---- Common functor definition
|
||||
type BaseFunctor struct {
|
||||
info ExprFunc
|
||||
}
|
||||
|
||||
func (functor *BaseFunctor) ToString(opt FmtOpt) (s string) {
|
||||
if functor.info != nil {
|
||||
s = functor.info.ToString(opt)
|
||||
} else {
|
||||
s = "func(){}"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (functor *BaseFunctor) GetParams() (params []ExprFuncParam) {
|
||||
if functor.info != nil {
|
||||
return functor.info.Params()
|
||||
} else {
|
||||
return []ExprFuncParam{}
|
||||
}
|
||||
}
|
||||
|
||||
func (functor *BaseFunctor) SetFunc(info ExprFunc) {
|
||||
functor.info = info
|
||||
}
|
||||
|
||||
func (functor *BaseFunctor) GetFunc() ExprFunc {
|
||||
return functor.info
|
||||
}
|
||||
|
||||
func (functor *BaseFunctor) GetDefinitionContext() ExprContext {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---- Function Parameters
|
||||
type paramFlags uint16
|
||||
|
||||
const (
|
||||
PfDefault paramFlags = 1 << iota
|
||||
PfOptional
|
||||
PfRepeat
|
||||
)
|
||||
|
||||
type funcParamInfo struct {
|
||||
name string
|
||||
flags paramFlags
|
||||
defaultValue any
|
||||
}
|
||||
|
||||
func NewFuncParam(name string) ExprFuncParam {
|
||||
return &funcParamInfo{name: name}
|
||||
}
|
||||
|
||||
func NewFuncParamFlag(name string, flags paramFlags) ExprFuncParam {
|
||||
return &funcParamInfo{name: name, flags: flags}
|
||||
}
|
||||
|
||||
func NewFuncParamFlagDef(name string, flags paramFlags, defValue any) *funcParamInfo {
|
||||
return &funcParamInfo{name: name, flags: flags, defaultValue: defValue}
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) Name() string {
|
||||
return param.name
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) Type() string {
|
||||
return TypeAny
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) IsDefault() bool {
|
||||
return (param.flags & PfDefault) != 0
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) IsOptional() bool {
|
||||
return (param.flags & PfOptional) != 0
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) IsRepeat() bool {
|
||||
return (param.flags & PfRepeat) != 0
|
||||
}
|
||||
|
||||
func (param *funcParamInfo) DefaultValue() any {
|
||||
return param.defaultValue
|
||||
}
|
||||
|
||||
func initActualParams(ctx ExprContext, info ExprFunc, callTerm Term) (actualParams map[string]any, err error) {
|
||||
var varArgs []any
|
||||
var varName string
|
||||
|
||||
namedParamsStarted := false
|
||||
|
||||
formalParams := info.Params()
|
||||
actualParams = make(map[string]any, len(formalParams))
|
||||
if callTerm == nil {
|
||||
return
|
||||
}
|
||||
|
||||
childCount := callTerm.GetChildCount()
|
||||
for i := range childCount {
|
||||
tree := callTerm.GetChild(i)
|
||||
// for i, tree := range callTerm.Children() {
|
||||
var paramValue any
|
||||
paramCtx := ctx.Clone()
|
||||
if paramValue, err = tree.Compute(paramCtx); err != nil {
|
||||
break
|
||||
}
|
||||
if paramName, namedParam := GetAssignVarName(tree); namedParam {
|
||||
if info.ParamSpec(paramName) == nil {
|
||||
err = fmt.Errorf("%s(): unknown param %q", info.Name(), paramName)
|
||||
break
|
||||
}
|
||||
actualParams[paramName] = paramValue
|
||||
namedParamsStarted = true
|
||||
} else if !namedParamsStarted {
|
||||
if varArgs != nil {
|
||||
varArgs = append(varArgs, paramValue)
|
||||
} else if i < len(formalParams) {
|
||||
spec := formalParams[i]
|
||||
if spec.IsRepeat() {
|
||||
varArgs = make([]any, 0, childCount-i)
|
||||
varArgs = append(varArgs, paramValue)
|
||||
varName = spec.Name()
|
||||
} else {
|
||||
actualParams[spec.Name()] = paramValue
|
||||
}
|
||||
} else {
|
||||
err = ErrTooManyParams(info.Name(), len(formalParams), childCount)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("%s(): positional param nr %d not allowed after named params", info.Name(), i+1)
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if varArgs != nil {
|
||||
actualParams[varName] = varArgs
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// func (info *funcInfo) PrepareCall(name string, actualParams map[string]any) (err error) {
|
||||
// passedCount := len(actualParams)
|
||||
// if info.MinArgs() > passedCount {
|
||||
// err = ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount)
|
||||
// return
|
||||
// }
|
||||
|
||||
// if passedCount < len(info.formalParams) {
|
||||
// for _, p := range info.formalParams {
|
||||
// if _, exists := actualParams[p.Name()]; !exists {
|
||||
// if !p.IsDefault() {
|
||||
// break
|
||||
// }
|
||||
// if p.IsRepeat() {
|
||||
// varArgs := make([]any, 1)
|
||||
// varArgs[0] = p.DefaultValue()
|
||||
// actualParams[p.Name()] = varArgs
|
||||
// } else {
|
||||
// actualParams[p.Name()] = p.DefaultValue()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if info.MaxArgs() >= 0 && info.MaxArgs() < len(actualParams) {
|
||||
// err = ErrTooManyParams(name, info.MaxArgs(), len(actualParams))
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
// ----- Call a function ---
|
||||
|
||||
// func getAssignVarName(t *term) (name string, ok bool) {
|
||||
// if ok = t.symbol() == SymEqual; ok {
|
||||
// name = t.children[0].source()
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func GetAssignVarName(t Term) (name string, ok bool) {
|
||||
if ok = t.IsAssign(); ok {
|
||||
name = t.GetChildSource(0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CallFunctionByTerm(parentCtx ExprContext, name string, callTerm Term) (result any, err error) {
|
||||
var actualParams map[string]any
|
||||
if info, exists := parentCtx.GetFuncInfo(name); exists {
|
||||
if actualParams, err = initActualParams(parentCtx, info, callTerm); err == nil {
|
||||
ctx := info.AllocContext(parentCtx)
|
||||
if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
functor := info.Functor()
|
||||
result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
exportObjectsToParent(ctx)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CallFunctionByArgs(parentCtx ExprContext, name string, args []any) (result any, err error) {
|
||||
var actualParams map[string]any
|
||||
if info, exists := parentCtx.GetFuncInfo(name); exists {
|
||||
functor := info.Functor()
|
||||
actualParams = BindActualParams(functor, args)
|
||||
ctx := info.AllocContext(parentCtx)
|
||||
if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
exportObjectsToParent(ctx)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CallFunctionByParams(parentCtx ExprContext, name string, actualParams map[string]any) (result any, err error) {
|
||||
//var actualParams map[string]any
|
||||
if info, exists := parentCtx.GetFuncInfo(name); exists {
|
||||
functor := info.Functor()
|
||||
ctx := info.AllocContext(parentCtx)
|
||||
if err = info.PrepareCall(name, actualParams); err == nil {
|
||||
result, err = functor.InvokeNamed(ctx, name, actualParams)
|
||||
exportObjectsToParent(ctx)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetParam(args map[string]any, paramName string, paramNum int) (value any, exists bool) {
|
||||
if value, exists = args[paramName]; !exists {
|
||||
if paramNum > 0 && paramNum <= len(args) {
|
||||
value, exists = args["arg"+strconv.Itoa(paramNum)]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func BindActualParams(functor Functor, args []any) (actualParams map[string]any) {
|
||||
formalParams := functor.GetParams()
|
||||
actualParams = make(map[string]any, len(args))
|
||||
for i, arg := range args {
|
||||
if i < len(formalParams) {
|
||||
actualParams[formalParams[i].Name()] = arg
|
||||
} else {
|
||||
actualParams["arg"+strconv.Itoa(i+1)] = arg
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// iterator.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
import (
|
||||
// "errors"
|
||||
@ -30,8 +30,8 @@ type Iterator interface {
|
||||
fmt.Stringer
|
||||
Next() (item any, err error) // must return io.EOF after the last item
|
||||
Current() (item any, err error)
|
||||
Index() int
|
||||
Count() int
|
||||
Index() int64
|
||||
Count() int64
|
||||
HasOperation(name string) bool
|
||||
CallOperation(name string, args map[string]any) (value any, err error)
|
||||
}
|
||||
@ -42,10 +42,11 @@ type ExtIterator interface {
|
||||
Clean() error
|
||||
}
|
||||
|
||||
func errNoOperation(name string) error {
|
||||
func ErrNoOperation(name string) error {
|
||||
return fmt.Errorf("no %s() function defined in the data-source", name)
|
||||
}
|
||||
|
||||
// func errInvalidDataSource() error {
|
||||
// return errors.New("invalid data-source")
|
||||
// }
|
||||
func IsIterator(v any) (ok bool) {
|
||||
_, ok = v.(Iterator)
|
||||
return
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// list-type.go
|
||||
package expr
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -12,23 +12,21 @@ import (
|
||||
|
||||
type ListType []any
|
||||
|
||||
func newListA(listAny ...any) (list *ListType) {
|
||||
func IsList(v any) (ok bool) {
|
||||
_, ok = v.(*ListType)
|
||||
return ok
|
||||
}
|
||||
|
||||
func NewListA(listAny ...any) (list *ListType) {
|
||||
if listAny == nil {
|
||||
listAny = []any{}
|
||||
}
|
||||
return newList(listAny)
|
||||
}
|
||||
|
||||
func newList(listAny []any) (list *ListType) {
|
||||
return NewList(listAny)
|
||||
}
|
||||
|
||||
func NewList(listAny []any) (list *ListType) {
|
||||
if listAny != nil {
|
||||
ls := make(ListType, len(listAny))
|
||||
// for i, item := range listAny {
|
||||
// ls[i] = item
|
||||
// }
|
||||
copy(ls, listAny)
|
||||
list = &ls
|
||||
}
|
||||
@ -106,22 +104,11 @@ func (ls *ListType) TypeName() string {
|
||||
return "list"
|
||||
}
|
||||
|
||||
// func (list *ListType) indexDeepCmp(target any) (index int) {
|
||||
// index = -1
|
||||
// for i, item := range *list {
|
||||
// if reflect.DeepEqual(item, target) {
|
||||
// index = i
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func (ls *ListType) contains(t *ListType) (answer bool) {
|
||||
func (ls *ListType) Contains(t *ListType) (answer bool) {
|
||||
if len(*ls) >= len(*t) {
|
||||
answer = true
|
||||
for _, item := range *t {
|
||||
if answer = ls.indexDeepSameCmp(item) >= 0; !answer {
|
||||
if answer = ls.IndexDeepSameCmp(item) >= 0; !answer {
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -143,12 +130,12 @@ func (ls1 *ListType) Equals(ls2 ListType) (answer bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (list *ListType) indexDeepSameCmp(target any) (index int) {
|
||||
func (list *ListType) IndexDeepSameCmp(target any) (index int) {
|
||||
var eq bool
|
||||
var err error
|
||||
index = -1
|
||||
for i, item := range *list {
|
||||
if eq, err = deepSame(item, target, sameContent); err != nil {
|
||||
if eq, err = deepSame(item, target, SameContent); err != nil {
|
||||
break
|
||||
} else if eq {
|
||||
index = i
|
||||
@ -158,13 +145,13 @@ func (list *ListType) indexDeepSameCmp(target any) (index int) {
|
||||
return
|
||||
}
|
||||
|
||||
func sameContent(a, b any) (same bool, err error) {
|
||||
func SameContent(a, b any) (same bool, err error) {
|
||||
la, _ := a.(*ListType)
|
||||
lb, _ := b.(*ListType)
|
||||
if len(*la) == len(*lb) {
|
||||
same = true
|
||||
for _, item := range *la {
|
||||
if pos := lb.indexDeepSameCmp(item); pos < 0 {
|
||||
if pos := lb.IndexDeepSameCmp(item); pos < 0 {
|
||||
same = false
|
||||
break
|
||||
}
|
||||
@ -173,19 +160,19 @@ func sameContent(a, b any) (same bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func deepSame(a, b any, deepCmp deepFuncTemplate) (eq bool, err error) {
|
||||
if isNumOrFract(a) && isNumOrFract(b) {
|
||||
func deepSame(a, b any, deepCmp DeepFuncTemplate) (eq bool, err error) {
|
||||
if IsNumOrFract(a) && IsNumOrFract(b) {
|
||||
if IsNumber(a) && IsNumber(b) {
|
||||
if IsInteger(a) && IsInteger(b) {
|
||||
li, _ := a.(int64)
|
||||
ri, _ := b.(int64)
|
||||
eq = li == ri
|
||||
} else {
|
||||
eq = numAsFloat(a) == numAsFloat(b)
|
||||
eq = NumAsFloat(a) == NumAsFloat(b)
|
||||
}
|
||||
} else {
|
||||
var cmp int
|
||||
if cmp, err = cmpAnyFract(a, b); err == nil {
|
||||
if cmp, err = CmpAnyFract(a, b); err == nil {
|
||||
eq = cmp == 0
|
||||
}
|
||||
}
|
||||
@ -198,7 +185,7 @@ func deepSame(a, b any, deepCmp deepFuncTemplate) (eq bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (list *ListType) setItem(index int64, value any) (err error) {
|
||||
func (list *ListType) SetItem(index int64, value any) (err error) {
|
||||
if index >= 0 && index < int64(len(*list)) {
|
||||
(*list)[index] = value
|
||||
} else {
|
||||
@ -207,6 +194,6 @@ func (list *ListType) setItem(index int64, value any) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (list *ListType) appendItem(value any) {
|
||||
func (list *ListType) AppendItem(value any) {
|
||||
*list = append(*list, value)
|
||||
}
|
||||
88
kern/number.go
Normal file
88
kern/number.go
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// number.go
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func IsInteger(v any) (ok bool) {
|
||||
_, ok = v.(int64)
|
||||
return ok
|
||||
}
|
||||
|
||||
func IsNumber(v any) (ok bool) {
|
||||
return IsFloat(v) || IsInteger(v)
|
||||
}
|
||||
|
||||
func IsNumOrFract(v any) (ok bool) {
|
||||
return IsFloat(v) || IsInteger(v) || IsFraction(v)
|
||||
}
|
||||
|
||||
func IsNumberString(v any) (ok bool) {
|
||||
return IsString(v) || IsNumber(v)
|
||||
}
|
||||
|
||||
func NumAsFloat(v any) (f float64) {
|
||||
var ok bool
|
||||
if f, ok = v.(float64); !ok {
|
||||
if fract, ok := v.(*FractionType); ok {
|
||||
f = fract.ToFloat()
|
||||
} else {
|
||||
i, _ := v.(int64)
|
||||
f = float64(i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func AnyInteger(v any) (i int64, ok bool) {
|
||||
ok = true
|
||||
switch intval := v.(type) {
|
||||
case int:
|
||||
i = int64(intval)
|
||||
case uint8:
|
||||
i = int64(intval)
|
||||
case uint16:
|
||||
i = int64(intval)
|
||||
case uint64:
|
||||
i = int64(intval)
|
||||
case uint32:
|
||||
i = int64(intval)
|
||||
case int8:
|
||||
i = int64(intval)
|
||||
case int16:
|
||||
i = int64(intval)
|
||||
case int32:
|
||||
i = int64(intval)
|
||||
case int64:
|
||||
i = intval
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ToGoInt(value any, description string) (i int, err error) {
|
||||
if valueInt64, ok := value.(int64); ok {
|
||||
i = int(valueInt64)
|
||||
} else if valueInt, ok := value.(int); ok {
|
||||
i = valueInt
|
||||
} else {
|
||||
err = fmt.Errorf("%s expected integer, got %s (%v)", description, TypeName(value), value)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ToGoInt64(value any, description string) (i int64, err error) {
|
||||
if valueInt64, ok := value.(int64); ok {
|
||||
i = valueInt64
|
||||
} else if valueInt, ok := value.(int); ok {
|
||||
i = int64(valueInt)
|
||||
} else {
|
||||
err = fmt.Errorf("%s expected integer, got %s (%v)", description, TypeName(value), value)
|
||||
}
|
||||
return
|
||||
}
|
||||
23
kern/string.go
Normal file
23
kern/string.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// string.go
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func IsString(v any) (ok bool) {
|
||||
_, ok = v.(string)
|
||||
return ok
|
||||
}
|
||||
|
||||
func ToGoString(value any, description string) (s string, err error) {
|
||||
if s, ok := value.(string); ok {
|
||||
return s, nil
|
||||
} else {
|
||||
err = fmt.Errorf("%s expected string, got %s (%v)", description, TypeName(value), value)
|
||||
}
|
||||
return
|
||||
}
|
||||
21
kern/term.go
Normal file
21
kern/term.go
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// term.go
|
||||
package kern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Term interface {
|
||||
fmt.Stringer
|
||||
// Children() []Term
|
||||
Source() string
|
||||
GetChildCount() (count int)
|
||||
GetChild(index int) Term
|
||||
GetChildSource(index int) string
|
||||
Compute(ctx ExprContext) (result any, err error)
|
||||
IsAssign() bool
|
||||
Errorf(template string, args ...any) (err error)
|
||||
}
|
||||
@ -7,40 +7,43 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type ListIterator struct {
|
||||
a *ListType
|
||||
count int
|
||||
index int
|
||||
start int
|
||||
stop int
|
||||
step int
|
||||
a *kern.ListType
|
||||
count int64
|
||||
index int64
|
||||
start int64
|
||||
stop int64
|
||||
step int64
|
||||
}
|
||||
|
||||
func NewListIterator(list *ListType, args []any) (it *ListIterator) {
|
||||
func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) {
|
||||
var argc int = 0
|
||||
listLen := len(([]any)(*list))
|
||||
listLen := int64(len(([]any)(*list)))
|
||||
if args != nil {
|
||||
argc = len(args)
|
||||
}
|
||||
it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1}
|
||||
if argc >= 1 {
|
||||
if i, err := ToGoInt(args[0], "start index"); err == nil {
|
||||
if i, err := kern.ToGoInt64(args[0], "start index"); err == nil {
|
||||
if i < 0 {
|
||||
i = listLen + i
|
||||
}
|
||||
it.start = i
|
||||
}
|
||||
if argc >= 2 {
|
||||
if i, err := ToGoInt(args[1], "stop index"); err == nil {
|
||||
if i, err := kern.ToGoInt64(args[1], "stop index"); err == nil {
|
||||
if i < 0 {
|
||||
i = listLen + i
|
||||
}
|
||||
it.stop = i
|
||||
}
|
||||
if argc >= 3 {
|
||||
if i, err := ToGoInt(args[2], "step"); err == nil {
|
||||
if i, err := kern.ToGoInt64(args[2], "step"); err == nil {
|
||||
if i < 0 {
|
||||
i = -i
|
||||
}
|
||||
@ -58,14 +61,14 @@ func NewListIterator(list *ListType, args []any) (it *ListIterator) {
|
||||
}
|
||||
|
||||
func NewArrayIterator(array []any) (it *ListIterator) {
|
||||
it = &ListIterator{a: (*ListType)(&array), count: 0, index: -1, start: 0, stop: len(array) - 1, step: 1}
|
||||
it = &ListIterator{a: (*kern.ListType)(&array), count: 0, index: -1, start: 0, stop: int64(len(array)) - 1, step: 1}
|
||||
return
|
||||
}
|
||||
|
||||
func (it *ListIterator) String() string {
|
||||
var l = 0
|
||||
var l = int64(0)
|
||||
if it.a != nil {
|
||||
l = len(*it.a)
|
||||
l = int64(len(*it.a))
|
||||
}
|
||||
return fmt.Sprintf("$([#%d])", l)
|
||||
}
|
||||
@ -75,26 +78,27 @@ func (it *ListIterator) TypeName() string {
|
||||
}
|
||||
|
||||
func (it *ListIterator) HasOperation(name string) bool {
|
||||
yes := name == NextName || name == ResetName || name == IndexName || name == CountName || name == CurrentName
|
||||
//yes := name == expr.NextName || name == expr.ResetName || name == expr.IndexName || name == expr.CountName || name == expr.CurrentName
|
||||
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName}, name)
|
||||
return yes
|
||||
}
|
||||
|
||||
func (it *ListIterator) CallOperation(name string, args map[string]any) (v any, err error) {
|
||||
switch name {
|
||||
case NextName:
|
||||
case kern.NextName:
|
||||
v, err = it.Next()
|
||||
case ResetName:
|
||||
case kern.ResetName:
|
||||
err = it.Reset()
|
||||
case CleanName:
|
||||
case kern.CleanName:
|
||||
err = it.Clean()
|
||||
case IndexName:
|
||||
case kern.IndexName:
|
||||
v = int64(it.Index())
|
||||
case CurrentName:
|
||||
case kern.CurrentName:
|
||||
v, err = it.Current()
|
||||
case CountName:
|
||||
case kern.CountName:
|
||||
v = it.count
|
||||
default:
|
||||
err = errNoOperation(name)
|
||||
err = kern.ErrNoOperation(name)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -102,13 +106,13 @@ func (it *ListIterator) CallOperation(name string, args map[string]any) (v any,
|
||||
func (it *ListIterator) Current() (item any, err error) {
|
||||
a := *(it.a)
|
||||
if it.start <= it.stop {
|
||||
if it.stop < len(a) && it.index >= it.start && it.index <= it.stop {
|
||||
if it.stop < int64(len(a)) && it.index >= it.start && it.index <= it.stop {
|
||||
item = a[it.index]
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
} else {
|
||||
if it.start < len(a) && it.index >= it.stop && it.index <= it.start {
|
||||
if it.start < int64(len(a)) && it.index >= it.stop && it.index <= it.start {
|
||||
item = a[it.index]
|
||||
} else {
|
||||
err = io.EOF
|
||||
@ -126,11 +130,11 @@ func (it *ListIterator) Next() (item any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (it *ListIterator) Index() int {
|
||||
func (it *ListIterator) Index() int64 {
|
||||
return it.index
|
||||
}
|
||||
|
||||
func (it *ListIterator) Count() int {
|
||||
func (it *ListIterator) Count() int64 {
|
||||
return it.count
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
// operand-dict.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- dict term
|
||||
func newDictTerm(args map[any]*term) *term {
|
||||
@ -18,12 +21,12 @@ func newDictTerm(args map[any]*term) *term {
|
||||
}
|
||||
|
||||
// -------- dict func
|
||||
func evalDict(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalDict(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
dict, _ := opTerm.value().(map[any]*term)
|
||||
items := make(DictType, len(dict))
|
||||
items := make(kern.DictType, len(dict))
|
||||
for key, tree := range dict {
|
||||
var param any
|
||||
if param, err = tree.compute(ctx); err != nil {
|
||||
if param, err = tree.Compute(ctx); err != nil {
|
||||
break
|
||||
}
|
||||
items[key] = param
|
||||
|
||||
@ -4,11 +4,15 @@
|
||||
// operand-expr.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- expr term
|
||||
func newExprTerm(root *term) *term {
|
||||
tk := NewValueToken(root.tk.row, root.tk.col, SymExpression, root.source(), root)
|
||||
tk := NewValueToken(root.tk.row, root.tk.col, SymExpression, root.Source(), root)
|
||||
return &term{
|
||||
tk: *tk,
|
||||
parent: nil,
|
||||
@ -20,9 +24,9 @@ func newExprTerm(root *term) *term {
|
||||
}
|
||||
|
||||
// -------- eval expr
|
||||
func evalExpr(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
if expr, ok := opTerm.value().(*term); ok {
|
||||
v, err = expr.compute(ctx)
|
||||
func evalExpr(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
if ast, ok := opTerm.value().(*term); ok {
|
||||
v, err = ast.Compute(ctx)
|
||||
} else {
|
||||
err = fmt.Errorf("expression expected, got %T", opTerm.value())
|
||||
}
|
||||
|
||||
@ -6,15 +6,21 @@ package expr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- function call term
|
||||
func newFuncCallTerm(tk *Token, args []*term) *term {
|
||||
var pos termPosition = posLeaf
|
||||
if len(args) > 0 {
|
||||
pos = posMultifix
|
||||
}
|
||||
return &term{
|
||||
tk: *tk,
|
||||
parent: nil,
|
||||
children: args,
|
||||
position: posLeaf,
|
||||
position: pos,
|
||||
priority: priValue,
|
||||
evalFunc: evalFuncCall,
|
||||
}
|
||||
@ -38,9 +44,9 @@ func newFuncCallTerm(tk *Token, args []*term) *term {
|
||||
// return
|
||||
// }
|
||||
|
||||
func evalFuncCall(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalFuncCall(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
name, _ := opTerm.tk.Value.(string)
|
||||
v, err = CallFunctionByTerm(ctx, name, opTerm)
|
||||
v, err = kern.CallFunctionByTerm(ctx, name, opTerm)
|
||||
return
|
||||
}
|
||||
|
||||
@ -57,23 +63,23 @@ func newFuncDefTerm(tk *Token, args []*term) *term {
|
||||
}
|
||||
|
||||
// -------- eval func def
|
||||
func evalFuncDef(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalFuncDef(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
bodySpec := opTerm.value()
|
||||
if expr, ok := bodySpec.(*ast); ok {
|
||||
paramList := make([]ExprFuncParam, 0, len(opTerm.children))
|
||||
if ast, ok := bodySpec.(*ast); ok {
|
||||
paramList := make([]kern.ExprFuncParam, 0, len(opTerm.children))
|
||||
for _, param := range opTerm.children {
|
||||
var defValue any
|
||||
flags := paramFlags(0)
|
||||
if len(param.children) > 0 {
|
||||
flags |= PfDefault
|
||||
if defValue, err = param.children[0].compute(ctx); err != nil {
|
||||
if defValue, err = param.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
info := NewFuncParamFlagDef(param.source(), flags, defValue)
|
||||
info := NewFuncParamFlagDef(param.Source(), flags, defValue)
|
||||
paramList = append(paramList, info)
|
||||
}
|
||||
v = newExprFunctor(expr, paramList, ctx)
|
||||
v = newExprFunctor(ast, paramList, ctx)
|
||||
} else {
|
||||
err = errors.New("invalid function definition: the body specification must be an expression")
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- iterator term
|
||||
@ -25,11 +27,11 @@ func newIteratorTerm(tk *Token, args []*term) *term {
|
||||
|
||||
// -------- eval iterator
|
||||
|
||||
func evalTermArray(ctx ExprContext, terms []*term) (values []any, err error) {
|
||||
func evalTermArray(ctx kern.ExprContext, terms []*term) (values []any, err error) {
|
||||
values = make([]any, len(terms))
|
||||
for i, t := range terms {
|
||||
var value any
|
||||
if value, err = t.compute(ctx); err == nil {
|
||||
if value, err = t.Compute(ctx); err == nil {
|
||||
values[i] = value
|
||||
} else {
|
||||
break
|
||||
@ -38,25 +40,25 @@ func evalTermArray(ctx ExprContext, terms []*term) (values []any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalFirstChild(ctx ExprContext, iteratorTerm *term) (value any, err error) {
|
||||
func evalFirstChild(ctx kern.ExprContext, iteratorTerm *term) (value any, err error) {
|
||||
if len(iteratorTerm.children) < 1 || iteratorTerm.children[0] == nil {
|
||||
err = iteratorTerm.Errorf("missing the data-source parameter")
|
||||
return
|
||||
}
|
||||
|
||||
value, err = iteratorTerm.children[0].compute(ctx)
|
||||
value, err = iteratorTerm.children[0].Compute(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]Functor, err error) {
|
||||
if dictAny, ok := firstChildValue.(*DictType); ok {
|
||||
requiredFields := []string{NextName}
|
||||
func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]kern.Functor, err error) {
|
||||
if dictAny, ok := firstChildValue.(*kern.DictType); ok {
|
||||
requiredFields := []string{kern.NextName}
|
||||
fieldsMask := 0b1
|
||||
foundFields := 0
|
||||
ds = make(map[string]Functor)
|
||||
ds = make(map[string]kern.Functor)
|
||||
for keyAny, item := range *dictAny {
|
||||
if key, ok := keyAny.(string); ok {
|
||||
if functor, ok := item.(Functor); ok {
|
||||
if functor, ok := item.(kern.Functor); ok {
|
||||
ds[key] = functor
|
||||
if index := slices.Index(requiredFields, key); index >= 0 {
|
||||
foundFields |= 1 << index
|
||||
@ -78,9 +80,9 @@ func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]F
|
||||
return
|
||||
}
|
||||
|
||||
func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalIterator(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var firstChildValue any
|
||||
var ds map[string]Functor
|
||||
var ds map[string]kern.Functor
|
||||
|
||||
if firstChildValue, err = evalFirstChild(ctx, opTerm); err != nil {
|
||||
return
|
||||
@ -95,7 +97,7 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
if len(ds) > 0 {
|
||||
var dc *dataCursor
|
||||
dcCtx := ctx.Clone()
|
||||
if initFunc, exists := ds[InitName]; exists && initFunc != nil {
|
||||
if initFunc, exists := ds[kern.InitName]; exists && initFunc != nil {
|
||||
var args []any
|
||||
var resource any
|
||||
if len(opTerm.children) > 1 {
|
||||
@ -106,13 +108,13 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
args = []any{}
|
||||
}
|
||||
|
||||
actualParams := bindActualParams(initFunc, args)
|
||||
actualParams := kern.BindActualParams(initFunc, args)
|
||||
|
||||
initCtx := ctx.Clone()
|
||||
if resource, err = initFunc.InvokeNamed(initCtx, InitName, actualParams); err != nil {
|
||||
if resource, err = initFunc.InvokeNamed(initCtx, kern.InitName, actualParams); err != nil {
|
||||
return
|
||||
}
|
||||
exportObjects(dcCtx, initCtx)
|
||||
kern.ExportObjects(dcCtx, initCtx)
|
||||
dc = NewDataCursor(dcCtx, ds, resource)
|
||||
} else {
|
||||
dc = NewDataCursor(dcCtx, ds, nil)
|
||||
@ -120,7 +122,7 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
|
||||
v = dc
|
||||
} else {
|
||||
if dictIt, ok := firstChildValue.(*DictType); ok {
|
||||
if dictIt, ok := firstChildValue.(*kern.DictType); ok {
|
||||
var args []any
|
||||
if args, err = evalSibling(ctx, opTerm.children, nil); err == nil {
|
||||
v, err = NewDictIterator(dictIt, args)
|
||||
@ -129,11 +131,16 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
err = opTerm.children[0].Errorf("the data-source must be a dictionary")
|
||||
}
|
||||
}
|
||||
} else if list, ok := firstChildValue.(*ListType); ok {
|
||||
} else if list, ok := firstChildValue.(*kern.ListType); ok {
|
||||
var args []any
|
||||
if args, err = evalSibling(ctx, opTerm.children, nil); err == nil {
|
||||
v = NewListIterator(list, args)
|
||||
}
|
||||
} else if intVal, ok := firstChildValue.(int64); ok {
|
||||
var args []any
|
||||
if args, err = evalSibling(ctx, opTerm.children, intVal); err == nil {
|
||||
v, err = NewIntIterator(args)
|
||||
}
|
||||
} else {
|
||||
var list []any
|
||||
if list, err = evalSibling(ctx, opTerm.children, firstChildValue); err == nil {
|
||||
@ -143,7 +150,7 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalSibling(ctx ExprContext, terms []*term, firstChildValue any) (list []any, err error) {
|
||||
func evalSibling(ctx kern.ExprContext, terms []*term, firstChildValue any) (list []any, err error) {
|
||||
items := make([]any, 0, len(terms))
|
||||
for i, tree := range terms {
|
||||
var param any
|
||||
@ -152,7 +159,7 @@ func evalSibling(ctx ExprContext, terms []*term, firstChildValue any) (list []an
|
||||
continue
|
||||
}
|
||||
param = firstChildValue
|
||||
} else if param, err = tree.compute(ctx); err != nil {
|
||||
} else if param, err = tree.Compute(ctx); err != nil {
|
||||
break
|
||||
}
|
||||
items = append(items, param)
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operand-list.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- list term
|
||||
func newListTermA(args ...*term) *term {
|
||||
return newListTerm(0, 0, args)
|
||||
@ -21,12 +25,12 @@ func newListTerm(row, col int, args []*term) *term {
|
||||
}
|
||||
|
||||
// -------- list func
|
||||
func evalList(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalList(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
list, _ := opTerm.value().([]*term)
|
||||
items := make(ListType, len(list))
|
||||
items := make(kern.ListType, len(list))
|
||||
for i, tree := range list {
|
||||
var param any
|
||||
if param, err = tree.compute(ctx); err != nil {
|
||||
if param, err = tree.Compute(ctx); err != nil {
|
||||
break
|
||||
}
|
||||
items[i] = param
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operand-literal.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- literal term
|
||||
func newLiteralTerm(tk *Token) *term {
|
||||
return &term{
|
||||
@ -17,7 +21,7 @@ func newLiteralTerm(tk *Token) *term {
|
||||
}
|
||||
|
||||
// -------- eval func
|
||||
func evalLiteral(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalLiteral(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
v = opTerm.tk.Value
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- selector case term
|
||||
@ -41,7 +43,7 @@ func newSelectorCaseTerm(row, col int, filterList *term, caseExpr Expr) *term {
|
||||
}
|
||||
|
||||
// -------- eval selector case
|
||||
func evalSelectorCase(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalSelectorCase(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var ok bool
|
||||
if v, ok = opTerm.value().(*selectorCase); !ok {
|
||||
err = fmt.Errorf("selector-case expected, got %T", opTerm.value())
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operand-var.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- variable term
|
||||
func newVarTerm(tk *Token) *term {
|
||||
@ -21,11 +25,11 @@ func newVarTerm(tk *Token) *term {
|
||||
}
|
||||
|
||||
// -------- eval func
|
||||
func evalVar(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalVar(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var exists bool
|
||||
name := opTerm.source()
|
||||
if v, exists = GetVar(ctx, name); !exists {
|
||||
if info, exists := GetFuncInfo(ctx, name); exists {
|
||||
name := opTerm.Source()
|
||||
if v, exists = ctx.GetVar(name); !exists {
|
||||
if info, exists := ctx.GetFuncInfo(name); exists {
|
||||
v = info.Functor()
|
||||
} else {
|
||||
err = fmt.Errorf("undefined variable or function %q", name)
|
||||
|
||||
@ -4,6 +4,11 @@
|
||||
// operator-assign.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
"git.portale-stac.it/go-pkg/expr/util"
|
||||
)
|
||||
|
||||
//-------- assign term
|
||||
|
||||
func newAssignTerm(tk *Token) (inst *term) {
|
||||
@ -16,19 +21,19 @@ func newAssignTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func assignCollectionItem(ctx ExprContext, collectionTerm, keyListTerm *term, value any) (err error) {
|
||||
func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *term, value any) (err error) {
|
||||
var collectionValue, keyListValue, keyValue any
|
||||
var keyList *ListType
|
||||
var keyList *kern.ListType
|
||||
var ok bool
|
||||
|
||||
if collectionValue, err = collectionTerm.compute(ctx); err != nil {
|
||||
if collectionValue, err = collectionTerm.Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if keyListValue, err = keyListTerm.compute(ctx); err != nil {
|
||||
if keyListValue, err = keyListTerm.Compute(ctx); err != nil {
|
||||
return
|
||||
} else if keyList, ok = keyListValue.(*ListType); !ok || len(*keyList) != 1 {
|
||||
err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, TypeName(keyListValue))
|
||||
} else if keyList, ok = keyListValue.(*kern.ListType); !ok || len(*keyList) != 1 {
|
||||
err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, kern.TypeName(keyListValue))
|
||||
return
|
||||
}
|
||||
if keyValue = (*keyList)[0]; keyValue == nil {
|
||||
@ -37,30 +42,30 @@ func assignCollectionItem(ctx ExprContext, collectionTerm, keyListTerm *term, va
|
||||
}
|
||||
|
||||
switch collection := collectionValue.(type) {
|
||||
case *ListType:
|
||||
case *kern.ListType:
|
||||
if index, ok := keyValue.(int64); ok {
|
||||
err = collection.setItem(index, value)
|
||||
err = collection.SetItem(index, value)
|
||||
} else {
|
||||
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, TypeName(keyValue))
|
||||
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue))
|
||||
}
|
||||
case *DictType:
|
||||
err = collection.setItem(keyValue, value)
|
||||
case *kern.DictType:
|
||||
err = collection.SetItem(keyValue, value)
|
||||
default:
|
||||
err = collectionTerm.Errorf("collection expected")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func assignValue(ctx ExprContext, leftTerm *term, v any) (err error) {
|
||||
func assignValue(ctx kern.ExprContext, leftTerm *term, v any) (err error) {
|
||||
if leftTerm.symbol() == SymIndex {
|
||||
err = assignCollectionItem(ctx, leftTerm.children[0], leftTerm.children[1], v)
|
||||
} else {
|
||||
ctx.UnsafeSetVar(leftTerm.source(), v)
|
||||
ctx.UnsafeSetVar(leftTerm.Source(), v)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
@ -74,17 +79,17 @@ func evalAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
|
||||
rightChild := opTerm.children[1]
|
||||
|
||||
if v, err = rightChild.compute(ctx); err == nil {
|
||||
if functor, ok := v.(Functor); ok {
|
||||
if v, err = rightChild.Compute(ctx); err == nil {
|
||||
if functor, ok := v.(kern.Functor); ok {
|
||||
if leftSym == SymVariable {
|
||||
if info := functor.GetFunc(); info != nil {
|
||||
ctx.RegisterFunc(leftTerm.source(), info.Functor(), info.ReturnType(), info.Params())
|
||||
ctx.RegisterFunc(leftTerm.Source(), info.Functor(), info.ReturnType(), info.Params())
|
||||
} else if funcDef, ok := functor.(*exprFunctor); ok {
|
||||
paramSpecs := ForAll(funcDef.params, func(p ExprFuncParam) ExprFuncParam { return p })
|
||||
paramSpecs := util.ForAll(funcDef.params, func(p kern.ExprFuncParam) kern.ExprFuncParam { return p })
|
||||
|
||||
ctx.RegisterFunc(leftTerm.source(), functor, TypeAny, paramSpecs)
|
||||
ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, paramSpecs)
|
||||
} else {
|
||||
err = opTerm.Errorf("unknown function %s()", rightChild.source())
|
||||
err = opTerm.Errorf("unknown function %s()", rightChild.Source())
|
||||
}
|
||||
} else {
|
||||
err = assignValue(ctx, leftTerm, v)
|
||||
@ -111,19 +116,19 @@ func newOpAssignTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func getCollectionItemValue(ctx ExprContext, collectionTerm, keyListTerm *term) (value any, err error) {
|
||||
func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *term) (value any, err error) {
|
||||
var collectionValue, keyListValue, keyValue any
|
||||
var keyList *ListType
|
||||
var keyList *kern.ListType
|
||||
var ok bool
|
||||
|
||||
if collectionValue, err = collectionTerm.compute(ctx); err != nil {
|
||||
if collectionValue, err = collectionTerm.Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if keyListValue, err = keyListTerm.compute(ctx); err != nil {
|
||||
if keyListValue, err = keyListTerm.Compute(ctx); err != nil {
|
||||
return
|
||||
} else if keyList, ok = keyListValue.(*ListType); !ok || len(*keyList) != 1 {
|
||||
err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, TypeName(keyListValue))
|
||||
} else if keyList, ok = keyListValue.(*kern.ListType); !ok || len(*keyList) != 1 {
|
||||
err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, kern.TypeName(keyListValue))
|
||||
return
|
||||
}
|
||||
if keyValue = (*keyList)[0]; keyValue == nil {
|
||||
@ -132,13 +137,13 @@ func getCollectionItemValue(ctx ExprContext, collectionTerm, keyListTerm *term)
|
||||
}
|
||||
|
||||
switch collection := collectionValue.(type) {
|
||||
case *ListType:
|
||||
case *kern.ListType:
|
||||
if index, ok := keyValue.(int64); ok {
|
||||
value = (*collection)[index]
|
||||
} else {
|
||||
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, TypeName(keyValue))
|
||||
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue))
|
||||
}
|
||||
case *DictType:
|
||||
case *kern.DictType:
|
||||
value = (*collection)[keyValue]
|
||||
default:
|
||||
err = collectionTerm.Errorf("collection expected")
|
||||
@ -146,16 +151,16 @@ func getCollectionItemValue(ctx ExprContext, collectionTerm, keyListTerm *term)
|
||||
return
|
||||
}
|
||||
|
||||
func getAssignValue(ctx ExprContext, leftTerm *term) (value any, err error) {
|
||||
func getAssignValue(ctx kern.ExprContext, leftTerm *term) (value any, err error) {
|
||||
if leftTerm.symbol() == SymIndex {
|
||||
value, err = getCollectionItemValue(ctx, leftTerm.children[0], leftTerm.children[1])
|
||||
} else {
|
||||
value, _ = ctx.GetVar(leftTerm.source())
|
||||
value, _ = ctx.GetVar(leftTerm.Source())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalOpAssign(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var rightValue, leftValue any
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
@ -170,7 +175,7 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
|
||||
rightChild := opTerm.children[1]
|
||||
|
||||
if rightValue, err = rightChild.compute(ctx); err == nil {
|
||||
if rightValue, err = rightChild.Compute(ctx); err == nil {
|
||||
if leftValue, err = getAssignValue(ctx, leftTerm); err == nil {
|
||||
switch opTerm.symbol() {
|
||||
case SymPlusEqual:
|
||||
@ -194,7 +199,7 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
case SymDoubleGreaterEqual:
|
||||
v, err = bitRightShift(opTerm, leftValue, rightValue)
|
||||
default:
|
||||
err = opTerm.Errorf("unsupported assign operator %q", opTerm.source())
|
||||
err = opTerm.Errorf("unsupported assign operator %q", opTerm.Source())
|
||||
}
|
||||
if err == nil {
|
||||
err = assignValue(ctx, leftTerm, v)
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-bitwise.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- Bitwise NOT term
|
||||
|
||||
func newBitwiseNotTerm(tk *Token) (inst *term) {
|
||||
@ -16,18 +20,18 @@ func newBitwiseNotTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalBitwiseNot(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalBitwiseNot(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var value any
|
||||
|
||||
if value, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsInteger(value) {
|
||||
if kern.IsInteger(value) {
|
||||
i, _ := value.(int64)
|
||||
v = ^i
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(value)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(value)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -59,7 +63,7 @@ func bitwiseAnd(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalBitwiseAnd(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalBitwiseAnd(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -96,7 +100,7 @@ func bitwiseOr(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalBitwiseOr(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalBitwiseOr(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -134,7 +138,7 @@ func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalBitwiseXor(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalBitwiseXor(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operator-bool.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- NOT term
|
||||
|
||||
@ -18,17 +22,17 @@ func newNotTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalNot(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalNot(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var rightValue any
|
||||
|
||||
if rightValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if b, ok := ToBool(rightValue); ok {
|
||||
if b, ok := kern.ToBool(rightValue); ok {
|
||||
v = !b
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(rightValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(rightValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -45,8 +49,8 @@ func newAndTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalAnd(ctx ExprContext, self *term) (v any, err error) {
|
||||
if CtrlIsEnabled(ctx, ControlBoolShortcut) {
|
||||
func evalAnd(ctx kern.ExprContext, self *term) (v any, err error) {
|
||||
if kern.CtrlIsEnabled(ctx, kern.ControlBoolShortcut) {
|
||||
v, err = evalAndWithShortcut(ctx, self)
|
||||
} else {
|
||||
v, err = evalAndWithoutShortcut(ctx, self)
|
||||
@ -54,7 +58,7 @@ func evalAnd(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalAndWithoutShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
func evalAndWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var leftBool, rightBool bool
|
||||
var lok, rok bool
|
||||
@ -63,8 +67,8 @@ func evalAndWithoutShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
leftBool, lok = ToBool(leftValue)
|
||||
rightBool, rok = ToBool(rightValue)
|
||||
leftBool, lok = kern.ToBool(leftValue)
|
||||
rightBool, rok = kern.ToBool(rightValue)
|
||||
|
||||
if lok && rok {
|
||||
v = leftBool && rightBool
|
||||
@ -74,24 +78,25 @@ func evalAndWithoutShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalAndWithShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
func evalAndWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if err = self.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = self.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = self.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftBool, lok := ToBool(leftValue); !lok {
|
||||
err = fmt.Errorf("got %s as left operand type of 'AND' operator, it must be bool", TypeName(leftValue))
|
||||
return
|
||||
if leftBool, lok := kern.ToBool(leftValue); !lok {
|
||||
// err = fmt.Errorf("got %s as left operand type of 'AND' operator, it must be bool", expr.TypeName(leftValue))
|
||||
// return
|
||||
err = self.errIncompatibleType(leftValue, "left")
|
||||
} else if !leftBool {
|
||||
v = false
|
||||
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
|
||||
if rightBool, rok := ToBool(rightValue); rok {
|
||||
} else if rightValue, err = self.children[1].Compute(ctx); err == nil {
|
||||
if rightBool, rok := kern.ToBool(rightValue); rok {
|
||||
v = rightBool
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
@ -112,8 +117,8 @@ func newOrTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalOr(ctx ExprContext, self *term) (v any, err error) {
|
||||
if CtrlIsEnabled(ctx, ControlBoolShortcut) {
|
||||
func evalOr(ctx kern.ExprContext, self *term) (v any, err error) {
|
||||
if kern.CtrlIsEnabled(ctx, kern.ControlBoolShortcut) {
|
||||
v, err = evalOrWithShortcut(ctx, self)
|
||||
} else {
|
||||
v, err = evalOrWithoutShortcut(ctx, self)
|
||||
@ -121,7 +126,7 @@ func evalOr(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalOrWithoutShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
func evalOrWithoutShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var leftBool, rightBool bool
|
||||
var lok, rok bool
|
||||
@ -130,8 +135,8 @@ func evalOrWithoutShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
leftBool, lok = ToBool(leftValue)
|
||||
rightBool, rok = ToBool(rightValue)
|
||||
leftBool, lok = kern.ToBool(leftValue)
|
||||
rightBool, rok = kern.ToBool(rightValue)
|
||||
|
||||
if lok && rok {
|
||||
v = leftBool || rightBool
|
||||
@ -141,24 +146,24 @@ func evalOrWithoutShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalOrWithShortcut(ctx ExprContext, self *term) (v any, err error) {
|
||||
func evalOrWithShortcut(ctx kern.ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if err = self.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = self.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = self.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftBool, lok := ToBool(leftValue); !lok {
|
||||
err = fmt.Errorf("got %s as left operand type of 'OR' operator, it must be bool", TypeName(leftValue))
|
||||
if leftBool, lok := kern.ToBool(leftValue); !lok {
|
||||
err = fmt.Errorf("got %s as left operand type of 'OR' operator, it must be bool", kern.TypeName(leftValue))
|
||||
return
|
||||
} else if leftBool {
|
||||
v = true
|
||||
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
|
||||
if rightBool, rok := ToBool(rightValue); rok {
|
||||
} else if rightValue, err = self.children[1].Compute(ctx); err == nil {
|
||||
if rightBool, rok := kern.ToBool(rightValue); rok {
|
||||
v = rightBool
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operator-builtin.go
|
||||
package expr
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- builtin term
|
||||
|
||||
@ -18,7 +22,7 @@ func newBuiltinTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalBuiltin(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalBuiltin(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
@ -26,25 +30,25 @@ func evalBuiltin(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
}
|
||||
|
||||
count := 0
|
||||
if IsString(childValue) {
|
||||
if kern.IsString(childValue) {
|
||||
module, _ := childValue.(string)
|
||||
count, err = ImportInContextByGlobPattern(module)
|
||||
count, err = ImportInContextByGlobPattern(ctx, module)
|
||||
} else {
|
||||
var moduleSpec any
|
||||
var it Iterator
|
||||
var it kern.Iterator
|
||||
if it, err = NewIterator(childValue); err != nil {
|
||||
return
|
||||
}
|
||||
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
||||
if module, ok := moduleSpec.(string); ok {
|
||||
if ImportInContext(module) {
|
||||
if ImportInContext(ctx, module) {
|
||||
count++
|
||||
} else {
|
||||
err = opTerm.Errorf("unknown builtin module %q", module)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = opTerm.Errorf("expected string at item nr %d, got %s", it.Index()+1, TypeName(moduleSpec))
|
||||
err = opTerm.Errorf("expected string at item nr %d, got %s", it.Index()+1, kern.TypeName(moduleSpec))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-but.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- but term
|
||||
|
||||
func newButTerm(tk *Token) (inst *term) {
|
||||
@ -16,7 +20,7 @@ func newButTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalBut(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalBut(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
_, v, err = opTerm.evalInfix(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-context-value.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- context term
|
||||
|
||||
func newContextTerm(tk *Token) (inst *term) {
|
||||
@ -16,14 +20,14 @@ func newContextTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalContextValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalContextValue(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
|
||||
var sourceCtx ExprContext
|
||||
var sourceCtx kern.ExprContext
|
||||
if len(opTerm.children) == 0 {
|
||||
sourceCtx = ctx
|
||||
} else if opTerm.children[0].symbol() == SymVariable && opTerm.children[0].source() == "global" {
|
||||
sourceCtx = globalCtx
|
||||
} else if opTerm.children[0].symbol() == SymVariable && opTerm.children[0].Source() == "global" {
|
||||
sourceCtx = ctx.GetGlobal()
|
||||
} else if childValue, err = opTerm.evalPrefix(ctx); err == nil {
|
||||
if dc, ok := childValue.(*dataCursor); ok {
|
||||
sourceCtx = dc.ctx
|
||||
@ -31,9 +35,9 @@ func evalContextValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
}
|
||||
|
||||
if sourceCtx != nil {
|
||||
if formatter, ok := sourceCtx.(DictFormat); ok {
|
||||
if formatter, ok := sourceCtx.(kern.DictFormat); ok {
|
||||
v = formatter.ToDict()
|
||||
} else if formatter, ok := sourceCtx.(Formatter); ok {
|
||||
} else if formatter, ok := sourceCtx.(kern.Formatter); ok {
|
||||
v = formatter.ToString(0)
|
||||
} else {
|
||||
// keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
|
||||
@ -49,7 +53,7 @@ func evalContextValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
v = d
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-ctrl.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- export all term
|
||||
|
||||
func newExportAllTerm(tk *Token) (inst *term) {
|
||||
@ -16,8 +20,8 @@ func newExportAllTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalExportAll(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
CtrlEnable(ctx, control_export_all)
|
||||
func evalExportAll(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
CtrlEnable(ctx, kern.ControlExportAll)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-default.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- default term
|
||||
|
||||
func newDefaultTerm(tk *Token) (inst *term) {
|
||||
@ -16,7 +20,7 @@ func newDefaultTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalDefault(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var rightValue any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
@ -26,13 +30,13 @@ func evalDefault(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
leftTerm := opTerm.children[0]
|
||||
if leftTerm.tk.Sym != SymVariable {
|
||||
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||
err = ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, exists := ctx.GetVar(leftTerm.source()); exists {
|
||||
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists {
|
||||
v = leftValue
|
||||
} else if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
} else if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
v = rightValue
|
||||
}
|
||||
return
|
||||
@ -50,7 +54,7 @@ func newAlternateTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalAlternate(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalAlternate(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var rightValue any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
@ -60,12 +64,12 @@ func evalAlternate(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
leftTerm := opTerm.children[0]
|
||||
if leftTerm.tk.Sym != SymVariable {
|
||||
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||
err = ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, exists := ctx.GetVar(leftTerm.source()); exists && leftValue != nil {
|
||||
if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists && leftValue != nil {
|
||||
if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
v = rightValue
|
||||
}
|
||||
} else {
|
||||
@ -86,7 +90,7 @@ func newDefaultAssignTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalAssignDefault(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalAssignDefault(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var rightValue any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
@ -96,21 +100,21 @@ func evalAssignDefault(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
leftTerm := opTerm.children[0]
|
||||
if leftTerm.tk.Sym != SymVariable {
|
||||
// err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||
err = ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||
err = kern.ErrLeftOperandMustBeVariable(leftTerm, opTerm)
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, exists := ctx.GetVar(leftTerm.source()); exists {
|
||||
if leftValue, exists := ctx.GetVar(leftTerm.Source()); exists {
|
||||
v = leftValue
|
||||
} else if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
if functor, ok := rightValue.(Functor); ok {
|
||||
} else if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
if functor, ok := rightValue.(kern.Functor); ok {
|
||||
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
||||
ctx.RegisterFunc(leftTerm.source(), functor, TypeAny, []ExprFuncParam{
|
||||
NewFuncParamFlag(ParamValue, PfDefault|PfRepeat),
|
||||
ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParamFlag(kern.ParamValue, PfDefault|PfRepeat),
|
||||
})
|
||||
} else {
|
||||
v = rightValue
|
||||
ctx.UnsafeSetVar(leftTerm.source(), rightValue)
|
||||
ctx.UnsafeSetVar(leftTerm.Source(), rightValue)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- digest term
|
||||
@ -21,21 +23,21 @@ func newDigestTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalDigest(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalDigest(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var it Iterator
|
||||
var it kern.Iterator
|
||||
var item, lastValue any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if it, err = NewIterator(leftValue); err != nil {
|
||||
return nil, fmt.Errorf("left operand of DIGEST must be an iterable data-source; got %s", TypeName(leftValue))
|
||||
return nil, fmt.Errorf("left operand of DIGEST must be an iterable data-source; got %s", kern.TypeName(leftValue))
|
||||
}
|
||||
|
||||
lastValue = nil
|
||||
@ -43,7 +45,7 @@ func evalDigest(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
ctx.SetVar("_", item)
|
||||
ctx.SetVar("_index", it.Index())
|
||||
ctx.SetVar("_count", it.Count())
|
||||
if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
if rightValue == nil {
|
||||
break
|
||||
} else {
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-dot.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- dot term
|
||||
func newDotTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
@ -15,22 +19,22 @@ func newDotTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalDot(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalDot(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
indexTerm := opTerm.children[1]
|
||||
|
||||
switch unboxedValue := leftValue.(type) {
|
||||
case ExtIterator:
|
||||
case kern.ExtIterator:
|
||||
if indexTerm.symbol() == SymVariable /*|| indexTerm.symbol() == SymString */ {
|
||||
opName := indexTerm.source()
|
||||
opName := indexTerm.Source()
|
||||
if unboxedValue.HasOperation(opName) {
|
||||
v, err = unboxedValue.CallOperation(opName, map[string]any{})
|
||||
} else {
|
||||
@ -40,8 +44,19 @@ func evalDot(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
} else {
|
||||
err = indexTerm.tk.ErrorExpectedGot("identifier")
|
||||
}
|
||||
case *kern.DictType:
|
||||
s := opTerm.children[1].symbol()
|
||||
if s == SymVariable || s == SymString {
|
||||
src := opTerm.children[1].Source()
|
||||
if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
|
||||
src = src[1 : len(src)-1]
|
||||
}
|
||||
v, err = unboxedValue.GetItem(src)
|
||||
} else if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
v, err = unboxedValue.GetItem(rightValue)
|
||||
}
|
||||
default:
|
||||
if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operator-fact.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- fact term
|
||||
|
||||
@ -18,14 +22,14 @@ func newFactTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalFact(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalFact(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue any
|
||||
|
||||
if leftValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsInteger(leftValue) {
|
||||
if kern.IsInteger(leftValue) {
|
||||
if i, _ := leftValue.(int64); i >= 0 {
|
||||
f := int64(1)
|
||||
for k := int64(1); k <= i; k++ {
|
||||
@ -36,7 +40,7 @@ func evalFact(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
err = fmt.Errorf("factorial of a negative integer (%d) is not allowed", i)
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(leftValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(leftValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- map term
|
||||
@ -21,32 +23,32 @@ func newFilterTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalFilter(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalFilter(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var it Iterator
|
||||
var it kern.Iterator
|
||||
var item any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if it, err = NewIterator(leftValue); err != nil {
|
||||
return nil, fmt.Errorf("left operand of FILTER must be an iterable data-source; got %s", TypeName(leftValue))
|
||||
return nil, fmt.Errorf("left operand of FILTER must be an iterable data-source; got %s", kern.TypeName(leftValue))
|
||||
}
|
||||
|
||||
values := newListA()
|
||||
values := kern.NewListA()
|
||||
for item, err = it.Next(); err == nil; item, err = it.Next() {
|
||||
ctx.SetVar("_", item)
|
||||
ctx.SetVar("_index", it.Index())
|
||||
ctx.SetVar("_count", it.Count())
|
||||
if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
if success, valid := ToBool(rightValue); valid {
|
||||
if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
if success, valid := kern.ToBool(rightValue); valid {
|
||||
if success {
|
||||
values.appendItem(item)
|
||||
values.AppendItem(item)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("filter expression must return a boolean or a castable to boolean, got %v [%T]", rightValue, rightValue)
|
||||
|
||||
@ -8,6 +8,8 @@ package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- fraction term
|
||||
@ -23,7 +25,7 @@ func newFractionTerm(tk *Token) *term {
|
||||
}
|
||||
|
||||
// -------- eval func
|
||||
func evalFraction(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalFraction(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var numValue, denValue any
|
||||
var num, den int64
|
||||
var ok bool
|
||||
@ -49,16 +51,19 @@ func evalFraction(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
num = -num
|
||||
}
|
||||
if num != 0 {
|
||||
g := gcd(num, den)
|
||||
num = num / g
|
||||
den = den / g
|
||||
if g := kern.Gcd(num, den); g != 1 {
|
||||
num = num / g
|
||||
den = den / g
|
||||
}
|
||||
if den == 1 {
|
||||
v = num
|
||||
} else {
|
||||
v = &FractionType{num, den}
|
||||
// v = &expr.FractionType{num, den}
|
||||
v = kern.NewFraction(num, den)
|
||||
}
|
||||
} else {
|
||||
v = &FractionType{0, den}
|
||||
// v = &FractionType{0, den}
|
||||
v = kern.NewFraction(0, den)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-in.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- in term
|
||||
|
||||
func newInTerm(tk *Token) (inst *term) {
|
||||
@ -21,19 +25,19 @@ func newInTerm(tk *Token) (inst *term) {
|
||||
// return
|
||||
// }
|
||||
|
||||
func evalIn(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalIn(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsList(rightValue) {
|
||||
list, _ := rightValue.(*ListType)
|
||||
v = list.indexDeepSameCmp(leftValue) >= 0
|
||||
} else if IsDict(rightValue) {
|
||||
dict, _ := rightValue.(*DictType)
|
||||
v = dict.hasKey(leftValue)
|
||||
if kern.IsList(rightValue) {
|
||||
list, _ := rightValue.(*kern.ListType)
|
||||
v = list.IndexDeepSameCmp(leftValue) >= 0
|
||||
} else if kern.IsDict(rightValue) {
|
||||
dict, _ := rightValue.(*kern.DictType)
|
||||
v = dict.HasKey(leftValue)
|
||||
} else {
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-include.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- include term
|
||||
|
||||
func newIncludeTerm(tk *Token) (inst *term) {
|
||||
@ -16,7 +20,7 @@ func newIncludeTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalInclude(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalInclude(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
@ -24,8 +28,8 @@ func evalInclude(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
}
|
||||
|
||||
count := 0
|
||||
if IsList(childValue) {
|
||||
list, _ := childValue.(*ListType)
|
||||
if kern.IsList(childValue) {
|
||||
list, _ := childValue.(*kern.ListType)
|
||||
for i, filePathSpec := range *list {
|
||||
if filePath, ok := filePathSpec.(string); ok {
|
||||
if v, err = EvalFile(ctx, filePath); err == nil {
|
||||
@ -39,13 +43,13 @@ func evalInclude(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if IsString(childValue) {
|
||||
} else if kern.IsString(childValue) {
|
||||
filePath, _ := childValue.(string)
|
||||
if v, err = EvalFile(ctx, filePath); err == nil {
|
||||
count++
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
if err != nil {
|
||||
//v = count
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-index.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- index term
|
||||
func newIndexTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
@ -15,15 +19,15 @@ func newIndexTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func verifyKey(indexList *ListType) (index any, err error) {
|
||||
func verifyKey(indexList *kern.ListType) (index any, err error) {
|
||||
index = (*indexList)[0]
|
||||
return
|
||||
}
|
||||
|
||||
func verifyIndex(indexTerm *term, indexList *ListType, maxValue int) (index int, err error) {
|
||||
func verifyIndex(indexTerm *term, indexList *kern.ListType, maxValue int) (index int, err error) {
|
||||
var v int
|
||||
|
||||
if v, err = ToGoInt((*indexList)[0], "index expression"); err == nil {
|
||||
if v, err = kern.ToGoInt((*indexList)[0], "index expression"); err == nil {
|
||||
if v < 0 && v >= -maxValue {
|
||||
v = maxValue + v
|
||||
}
|
||||
@ -36,11 +40,11 @@ func verifyIndex(indexTerm *term, indexList *ListType, maxValue int) (index int,
|
||||
return
|
||||
}
|
||||
|
||||
func verifyRange(indexTerm *term, indexList *ListType, maxValue int) (startIndex, endIndex int, err error) {
|
||||
func verifyRange(indexTerm *term, indexList *kern.ListType, maxValue int) (startIndex, endIndex int, err error) {
|
||||
v, _ := ((*indexList)[0]).(*intPair)
|
||||
startIndex = v.a
|
||||
endIndex = v.b
|
||||
if endIndex == ConstLastIndex {
|
||||
if endIndex == kern.ConstLastIndex {
|
||||
endIndex = maxValue
|
||||
}
|
||||
if startIndex < 0 && startIndex >= -maxValue {
|
||||
@ -59,9 +63,9 @@ func verifyRange(indexTerm *term, indexList *ListType, maxValue int) (startIndex
|
||||
return
|
||||
}
|
||||
|
||||
func evalIndex(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalIndex(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var indexList *ListType
|
||||
var indexList *kern.ListType
|
||||
var ok bool
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -69,7 +73,7 @@ func evalIndex(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
}
|
||||
|
||||
indexTerm := opTerm.children[1]
|
||||
if indexList, ok = rightValue.(*ListType); !ok {
|
||||
if indexList, ok = rightValue.(*kern.ListType); !ok {
|
||||
err = opTerm.Errorf("invalid index expression")
|
||||
return
|
||||
} else if len(*indexList) != 1 {
|
||||
@ -77,9 +81,9 @@ func evalIndex(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if IsInteger((*indexList)[0]) {
|
||||
if kern.IsInteger((*indexList)[0]) {
|
||||
switch unboxedValue := leftValue.(type) {
|
||||
case *ListType:
|
||||
case *kern.ListType:
|
||||
var index int
|
||||
if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil {
|
||||
v = (*unboxedValue)[index]
|
||||
@ -89,17 +93,17 @@ func evalIndex(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil {
|
||||
v = string(unboxedValue[index])
|
||||
}
|
||||
case *DictType:
|
||||
case *kern.DictType:
|
||||
v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue)
|
||||
default:
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
} else if isIntPair((*indexList)[0]) {
|
||||
switch unboxedValue := leftValue.(type) {
|
||||
case *ListType:
|
||||
case *kern.ListType:
|
||||
var start, end int
|
||||
if start, end, err = verifyRange(indexTerm, indexList, len(*unboxedValue)); err == nil {
|
||||
sublist := ListType((*unboxedValue)[start:end])
|
||||
sublist := kern.ListType((*unboxedValue)[start:end])
|
||||
v = &sublist
|
||||
}
|
||||
case string:
|
||||
@ -110,8 +114,8 @@ func evalIndex(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
default:
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
} else if IsDict(leftValue) {
|
||||
d := leftValue.(*DictType)
|
||||
} else if kern.IsDict(leftValue) {
|
||||
d := leftValue.(*kern.DictType)
|
||||
v, err = getDictItem(d, indexTerm, indexList, rightValue)
|
||||
} else {
|
||||
rightChild := opTerm.children[1]
|
||||
@ -120,7 +124,7 @@ func evalIndex(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func getDictItem(d *DictType, indexTerm *term, indexList *ListType, rightValue any) (v any, err error) {
|
||||
func getDictItem(d *kern.DictType, indexTerm *term, indexList *kern.ListType, rightValue any) (v any, err error) {
|
||||
var ok bool
|
||||
var indexValue any
|
||||
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-insert.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- prepend term
|
||||
|
||||
func newPrependTerm(tk *Token) (inst *term) {
|
||||
@ -26,19 +30,19 @@ func newAppendTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalPrepend(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalPrepend(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsList(rightValue) {
|
||||
list, _ := rightValue.(*ListType)
|
||||
newList := append(ListType{leftValue}, *list...)
|
||||
if kern.IsList(rightValue) {
|
||||
list, _ := rightValue.(*kern.ListType)
|
||||
newList := append(kern.ListType{leftValue}, *list...)
|
||||
v = &newList
|
||||
if opTerm.children[1].symbol() == SymVariable {
|
||||
ctx.UnsafeSetVar(opTerm.children[1].source(), v)
|
||||
ctx.UnsafeSetVar(opTerm.children[1].Source(), v)
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
@ -46,19 +50,19 @@ func evalPrepend(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalAppend(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalAppend(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsList(leftValue) {
|
||||
list, _ := leftValue.(*ListType)
|
||||
if kern.IsList(leftValue) {
|
||||
list, _ := leftValue.(*kern.ListType)
|
||||
newList := append(*list, rightValue)
|
||||
v = &newList
|
||||
if opTerm.children[0].symbol() == SymVariable {
|
||||
ctx.UnsafeSetVar(opTerm.children[0].source(), v)
|
||||
ctx.UnsafeSetVar(opTerm.children[0].Source(), v)
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-iter-value.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- iter value term
|
||||
|
||||
func newIterValueTerm(tk *Token) (inst *term) {
|
||||
@ -16,17 +20,17 @@ func newIterValueTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalIterValue(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if it, ok := childValue.(Iterator); ok {
|
||||
if it, ok := childValue.(kern.Iterator); ok {
|
||||
v, err = it.Current()
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- join term
|
||||
@ -21,35 +23,35 @@ func newJoinTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalJoin(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalJoin(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var itLeft, itRight Iterator
|
||||
var itLeft, itRight kern.Iterator
|
||||
var item any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if rightValue, err = opTerm.children[1].compute(ctx); err != nil {
|
||||
if rightValue, err = opTerm.children[1].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if itLeft, err = NewIterator(leftValue); err != nil {
|
||||
return nil, fmt.Errorf("left operand of JOIN must be an iterable data-source; got %s", TypeName(leftValue))
|
||||
return nil, fmt.Errorf("left operand of JOIN must be an iterable data-source; got %s", kern.TypeName(leftValue))
|
||||
}
|
||||
|
||||
if itRight, err = NewIterator(rightValue); err != nil {
|
||||
return nil, fmt.Errorf("right operand of JOIN must be an iterable data-source; got %s", TypeName(rightValue))
|
||||
return nil, fmt.Errorf("right operand of JOIN must be an iterable data-source; got %s", kern.TypeName(rightValue))
|
||||
}
|
||||
|
||||
values := newListA()
|
||||
for _, it := range []Iterator{itLeft, itRight} {
|
||||
values := kern.NewListA()
|
||||
for _, it := range []kern.Iterator{itLeft, itRight} {
|
||||
for item, err = it.Next(); err == nil; item, err = it.Next() {
|
||||
values.appendItem(item)
|
||||
values.AppendItem(item)
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-length.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- length term
|
||||
|
||||
func newLengthTerm(tk *Token) (inst *term) {
|
||||
@ -16,23 +20,23 @@ func newLengthTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalLength(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalLength(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsList(childValue) {
|
||||
ls, _ := childValue.(*ListType)
|
||||
if kern.IsList(childValue) {
|
||||
ls, _ := childValue.(*kern.ListType)
|
||||
v = int64(len(*ls))
|
||||
} else if IsString(childValue) {
|
||||
} else if kern.IsString(childValue) {
|
||||
s, _ := childValue.(string)
|
||||
v = int64(len(s))
|
||||
} else if IsDict(childValue) {
|
||||
m, _ := childValue.(*DictType)
|
||||
} else if kern.IsDict(childValue) {
|
||||
m, _ := childValue.(*kern.DictType)
|
||||
v = int64(len(*m))
|
||||
} else if it, ok := childValue.(Iterator); ok {
|
||||
} else if it, ok := childValue.(kern.Iterator); ok {
|
||||
v = int64(it.Count())
|
||||
// if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(CountName) {
|
||||
// count, _ := extIt.CallOperation(CountName, nil)
|
||||
@ -41,7 +45,7 @@ func evalLength(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
// v = int64(it.Index() + 1)
|
||||
// }
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- map term
|
||||
@ -21,30 +23,30 @@ func newMapTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalMap(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalMap(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var it Iterator
|
||||
var it kern.Iterator
|
||||
var item any
|
||||
|
||||
if err = opTerm.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if it, err = NewIterator(leftValue); err != nil {
|
||||
return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", TypeName(leftValue))
|
||||
return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue))
|
||||
}
|
||||
|
||||
values := newListA()
|
||||
values := kern.NewListA()
|
||||
for item, err = it.Next(); err == nil; item, err = it.Next() {
|
||||
ctx.SetVar("_", item)
|
||||
ctx.SetVar("_index", it.Index())
|
||||
ctx.SetVar("_count", it.Count())
|
||||
if rightValue, err = opTerm.children[1].compute(ctx); err == nil {
|
||||
values.appendItem(rightValue)
|
||||
if rightValue, err = opTerm.children[1].Compute(ctx); err == nil {
|
||||
values.AppendItem(rightValue)
|
||||
}
|
||||
ctx.DeleteVar("_count")
|
||||
ctx.DeleteVar("_index")
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-plugin.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- plugin term
|
||||
|
||||
func newPluginTerm(tk *Token) (inst *term) {
|
||||
@ -16,7 +20,7 @@ func newPluginTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalPlugin(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalPlugin(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
var count int
|
||||
|
||||
@ -24,7 +28,7 @@ func evalPlugin(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if count, err = importPluginFromSearchPath(childValue); err == nil {
|
||||
if count, err = importPluginFromSearchPath(ctx, childValue); err == nil {
|
||||
v = int64(count)
|
||||
}
|
||||
return
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-post-inc-dec.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- post increment term
|
||||
|
||||
func newPostIncTerm(tk *Token) *term {
|
||||
@ -17,40 +21,40 @@ func newPostIncTerm(tk *Token) *term {
|
||||
}
|
||||
}
|
||||
|
||||
func evalPostInc(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalPostInc(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if it, ok := childValue.(Iterator); ok {
|
||||
if it, ok := childValue.(kern.Iterator); ok {
|
||||
var namePrefix string
|
||||
v, err = it.Next()
|
||||
|
||||
if opTerm.children[0].symbol() == SymVariable {
|
||||
namePrefix = opTerm.children[0].source()
|
||||
namePrefix = opTerm.children[0].Source()
|
||||
}
|
||||
ctx.UnsafeSetVar(namePrefix+"_index", it.Index())
|
||||
if c, err1 := it.Current(); err1 == nil {
|
||||
ctx.UnsafeSetVar(namePrefix+"_current", c)
|
||||
}
|
||||
|
||||
if it.HasOperation(KeyName) {
|
||||
if k, err1 := it.CallOperation(KeyName, nil); err1 == nil {
|
||||
if it.HasOperation(kern.KeyName) {
|
||||
if k, err1 := it.CallOperation(kern.KeyName, nil); err1 == nil {
|
||||
ctx.UnsafeSetVar(namePrefix+"_key", k)
|
||||
}
|
||||
}
|
||||
if it.HasOperation(ValueName) {
|
||||
if v1, err1 := it.CallOperation(ValueName, nil); err1 == nil {
|
||||
if it.HasOperation(kern.ValueName) {
|
||||
if v1, err1 := it.CallOperation(kern.ValueName, nil); err1 == nil {
|
||||
ctx.UnsafeSetVar(namePrefix+"_value", v1)
|
||||
}
|
||||
}
|
||||
} else if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
} else if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
v = childValue
|
||||
i, _ := childValue.(int64)
|
||||
ctx.SetVar(opTerm.children[0].source(), i+1)
|
||||
ctx.SetVar(opTerm.children[0].Source(), i+1)
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -68,7 +72,7 @@ func newPostDecTerm(tk *Token) *term {
|
||||
}
|
||||
}
|
||||
|
||||
func evalPostDec(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalPostDec(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
@ -76,12 +80,12 @@ func evalPostDec(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
|
||||
/* if it, ok := childValue.(Iterator); ok {
|
||||
v, err = it.Next()
|
||||
} else */if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
} else */if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
v = childValue
|
||||
i, _ := childValue.(int64)
|
||||
ctx.SetVar(opTerm.children[0].source(), i-1)
|
||||
ctx.SetVar(opTerm.children[0].Source(), i-1)
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-pre-inc-dec.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- pre increment term
|
||||
|
||||
func newPreIncTerm(tk *Token) *term {
|
||||
@ -17,18 +21,18 @@ func newPreIncTerm(tk *Token) *term {
|
||||
}
|
||||
}
|
||||
|
||||
func evalPreInc(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalPreInc(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
i := childValue.(int64) + 1
|
||||
ctx.SetVar(opTerm.children[0].source(), i)
|
||||
ctx.SetVar(opTerm.children[0].Source(), i)
|
||||
v = i
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -46,18 +50,18 @@ func newPreDecTerm(tk *Token) *term {
|
||||
}
|
||||
}
|
||||
|
||||
func evalPreDec(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalPreDec(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
if kern.IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
|
||||
i := childValue.(int64) - 1
|
||||
ctx.SetVar(opTerm.children[0].source(), i)
|
||||
ctx.SetVar(opTerm.children[0].Source(), i)
|
||||
v = i
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(childValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(childValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ package expr
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- multiply term
|
||||
@ -21,15 +23,15 @@ func newMultiplyTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func mulValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if IsString(leftValue) && IsInteger(rightValue) {
|
||||
if kern.IsString(leftValue) && kern.IsInteger(rightValue) {
|
||||
s, _ := leftValue.(string)
|
||||
n, _ := rightValue.(int64)
|
||||
v = strings.Repeat(s, int(n))
|
||||
} else if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
|
||||
if IsFloat(leftValue) || IsFloat(rightValue) {
|
||||
v = numAsFloat(leftValue) * numAsFloat(rightValue)
|
||||
} else if isFraction(leftValue) || isFraction(rightValue) {
|
||||
v, err = mulAnyFract(leftValue, rightValue)
|
||||
} else if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||
v = kern.NumAsFloat(leftValue) * kern.NumAsFloat(rightValue)
|
||||
} else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) {
|
||||
v, err = kern.MulAnyFract(leftValue, rightValue)
|
||||
} else {
|
||||
leftInt, _ := leftValue.(int64)
|
||||
rightInt, _ := rightValue.(int64)
|
||||
@ -41,7 +43,7 @@ func mulValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalMultiply(ctx ExprContext, prodTerm *term) (v any, err error) {
|
||||
func evalMultiply(ctx kern.ExprContext, prodTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = prodTerm.evalInfix(ctx); err != nil {
|
||||
@ -64,16 +66,16 @@ func newDivideTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
|
||||
if IsFloat(leftValue) || IsFloat(rightValue) {
|
||||
d := numAsFloat(rightValue)
|
||||
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||
d := kern.NumAsFloat(rightValue)
|
||||
if d == 0.0 {
|
||||
err = opTerm.errDivisionByZero()
|
||||
} else {
|
||||
v = numAsFloat(leftValue) / d
|
||||
v = kern.NumAsFloat(leftValue) / d
|
||||
}
|
||||
} else if isFraction(leftValue) || isFraction(rightValue) {
|
||||
v, err = divAnyFract(leftValue, rightValue)
|
||||
} else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) {
|
||||
v, err = kern.DivAnyFract(leftValue, rightValue)
|
||||
} else {
|
||||
leftInt, _ := leftValue.(int64)
|
||||
if rightInt, _ := rightValue.(int64); rightInt == 0 {
|
||||
@ -82,11 +84,11 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
v = leftInt / rightInt
|
||||
}
|
||||
}
|
||||
} else if IsString(leftValue) && IsString(rightValue) {
|
||||
} else if kern.IsString(leftValue) && kern.IsString(rightValue) {
|
||||
source := leftValue.(string)
|
||||
sep := rightValue.(string)
|
||||
v = ListFromStrings(strings.Split(source, sep))
|
||||
} else if IsString(leftValue) && IsInteger(rightValue) {
|
||||
v = kern.ListFromStrings(strings.Split(source, sep))
|
||||
} else if kern.IsString(leftValue) && kern.IsInteger(rightValue) {
|
||||
source := leftValue.(string)
|
||||
partSize := int(rightValue.(int64))
|
||||
if partSize == 0 {
|
||||
@ -105,7 +107,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if remainder > 0 {
|
||||
parts = append(parts, source[len(source)-remainder:])
|
||||
}
|
||||
v = newList(parts)
|
||||
v = kern.NewList(parts)
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
@ -113,7 +115,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalDivide(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalDivide(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -135,19 +137,19 @@ func newDivideAsFloatTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalDivideAsFloat(ctx ExprContext, floatDivTerm *term) (v any, err error) {
|
||||
func evalDivideAsFloat(ctx kern.ExprContext, floatDivTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = floatDivTerm.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
|
||||
d := numAsFloat(rightValue)
|
||||
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||
d := kern.NumAsFloat(rightValue)
|
||||
if d == 0.0 {
|
||||
err = floatDivTerm.errDivisionByZero()
|
||||
} else {
|
||||
v = numAsFloat(leftValue) / d
|
||||
v = kern.NumAsFloat(leftValue) / d
|
||||
}
|
||||
} else {
|
||||
err = floatDivTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
@ -167,7 +169,7 @@ func newRemainderTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
func remainderValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||
if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) {
|
||||
rightInt, _ := rightValue.(int64)
|
||||
if rightInt == 0 {
|
||||
err = opTerm.errDivisionByZero()
|
||||
@ -181,7 +183,7 @@ func remainderValues(opTerm *term, leftValue, rightValue any) (v any, err error)
|
||||
return
|
||||
}
|
||||
|
||||
func evalRemainder(ctx ExprContext, remainderTerm *term) (v any, err error) {
|
||||
func evalRemainder(ctx kern.ExprContext, remainderTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = remainderTerm.evalInfix(ctx); err != nil {
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operator-range.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
// -------- range term
|
||||
type intPair struct {
|
||||
@ -12,10 +16,10 @@ type intPair struct {
|
||||
}
|
||||
|
||||
func (p *intPair) TypeName() string {
|
||||
return TypePair
|
||||
return kern.TypePair
|
||||
}
|
||||
|
||||
func (p *intPair) ToString(opt FmtOpt) string {
|
||||
func (p *intPair) ToString(opt kern.FmtOpt) string {
|
||||
return fmt.Sprintf("(%d, %d)", p.a, p.b)
|
||||
}
|
||||
|
||||
@ -41,21 +45,21 @@ func changeColonToRange(t *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalRange(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalRange(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if len(opTerm.children) == 0 {
|
||||
leftValue = int64(0)
|
||||
rightValue = int64(-1)
|
||||
} else if len(opTerm.children) == 1 {
|
||||
if leftValue, err = opTerm.children[0].compute(ctx); err != nil {
|
||||
if leftValue, err = opTerm.children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
rightValue = int64(ConstLastIndex)
|
||||
rightValue = int64(kern.ConstLastIndex)
|
||||
} else if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if !(IsInteger(leftValue) && IsInteger(rightValue)) {
|
||||
if !(kern.IsInteger(leftValue) && kern.IsInteger(rightValue)) {
|
||||
// err = opTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
err = errRangeInvalidSpecification(opTerm)
|
||||
return
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operator-rel.go
|
||||
package expr
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- equal term
|
||||
|
||||
@ -18,25 +22,25 @@ func newEqualTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
type deepFuncTemplate func(a, b any) (eq bool, err error)
|
||||
// type deepFuncTemplate func(a, b any) (eq bool, err error)
|
||||
|
||||
func equals(a, b any, deepCmp deepFuncTemplate) (eq bool, err error) {
|
||||
if isNumOrFract(a) && isNumOrFract(b) {
|
||||
if IsNumber(a) && IsNumber(b) {
|
||||
if IsInteger(a) && IsInteger(b) {
|
||||
func equals(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) {
|
||||
if kern.IsNumOrFract(a) && kern.IsNumOrFract(b) {
|
||||
if kern.IsNumber(a) && kern.IsNumber(b) {
|
||||
if kern.IsInteger(a) && kern.IsInteger(b) {
|
||||
li, _ := a.(int64)
|
||||
ri, _ := b.(int64)
|
||||
eq = li == ri
|
||||
} else {
|
||||
eq = numAsFloat(a) == numAsFloat(b)
|
||||
eq = kern.NumAsFloat(a) == kern.NumAsFloat(b)
|
||||
}
|
||||
} else {
|
||||
var cmp int
|
||||
if cmp, err = cmpAnyFract(a, b); err == nil {
|
||||
if cmp, err = kern.CmpAnyFract(a, b); err == nil {
|
||||
eq = cmp == 0
|
||||
}
|
||||
}
|
||||
} else if deepCmp != nil && IsList(a) && IsList(b) {
|
||||
} else if deepCmp != nil && kern.IsList(a) && kern.IsList(b) {
|
||||
eq, err = deepCmp(a, b)
|
||||
} else {
|
||||
eq = reflect.DeepEqual(a, b)
|
||||
@ -45,7 +49,7 @@ func equals(a, b any, deepCmp deepFuncTemplate) (eq bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalEqual(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -68,9 +72,9 @@ func newNotEqualTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalNotEqual(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalNotEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
if v, err = evalEqual(ctx, opTerm); err == nil {
|
||||
b, _ := ToBool(v)
|
||||
b, _ := kern.ToBool(v)
|
||||
v = !b
|
||||
}
|
||||
return
|
||||
@ -89,37 +93,37 @@ func newLessTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func lessThan(self *term, a, b any) (isLess bool, err error) {
|
||||
if isNumOrFract(a) && isNumOrFract(b) {
|
||||
if IsNumber(a) && IsNumber(b) {
|
||||
if IsInteger(a) && IsInteger(b) {
|
||||
if kern.IsNumOrFract(a) && kern.IsNumOrFract(b) {
|
||||
if kern.IsNumber(a) && kern.IsNumber(b) {
|
||||
if kern.IsInteger(a) && kern.IsInteger(b) {
|
||||
li, _ := a.(int64)
|
||||
ri, _ := b.(int64)
|
||||
isLess = li < ri
|
||||
} else {
|
||||
isLess = numAsFloat(a) < numAsFloat(b)
|
||||
isLess = kern.NumAsFloat(a) < kern.NumAsFloat(b)
|
||||
}
|
||||
} else {
|
||||
var cmp int
|
||||
if cmp, err = cmpAnyFract(a, b); err == nil {
|
||||
if cmp, err = kern.CmpAnyFract(a, b); err == nil {
|
||||
isLess = cmp < 0
|
||||
}
|
||||
}
|
||||
} else if IsString(a) && IsString(b) {
|
||||
} else if kern.IsString(a) && kern.IsString(b) {
|
||||
ls, _ := a.(string)
|
||||
rs, _ := b.(string)
|
||||
isLess = ls < rs
|
||||
// Inclusion test
|
||||
} else if IsList(a) && IsList(b) {
|
||||
aList, _ := a.(*ListType)
|
||||
bList, _ := b.(*ListType)
|
||||
isLess = len(*aList) < len(*bList) && bList.contains(aList)
|
||||
} else if kern.IsList(a) && kern.IsList(b) {
|
||||
aList, _ := a.(*kern.ListType)
|
||||
bList, _ := b.(*kern.ListType)
|
||||
isLess = len(*aList) < len(*bList) && bList.Contains(aList)
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(a, b)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalLess(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalLess(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -144,8 +148,8 @@ func newLessEqualTerm(tk *Token) (inst *term) {
|
||||
func lessThanOrEqual(self *term, a, b any) (isLessEq bool, err error) {
|
||||
if isLessEq, err = lessThan(self, a, b); err == nil {
|
||||
if !isLessEq {
|
||||
if IsList(a) && IsList(b) {
|
||||
isLessEq, err = sameContent(a, b)
|
||||
if kern.IsList(a) && kern.IsList(b) {
|
||||
isLessEq, err = kern.SameContent(a, b)
|
||||
} else {
|
||||
isLessEq, err = equals(a, b, nil)
|
||||
}
|
||||
@ -154,7 +158,7 @@ func lessThanOrEqual(self *term, a, b any) (isLessEq bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalLessEqual(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalLessEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -178,7 +182,7 @@ func newGreaterTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalGreater(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalGreater(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -201,7 +205,7 @@ func newGreaterEqualTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalGreaterEqual(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalGreaterEqual(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-selector.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- selector term
|
||||
|
||||
func newSelectorTerm(tk *Token) (inst *term) {
|
||||
@ -16,7 +20,7 @@ func newSelectorTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func trySelectorCase(ctx ExprContext, exprValue, caseSel any, caseIndex int) (match bool, selectedValue any, err error) {
|
||||
func trySelectorCase(ctx kern.ExprContext, exprValue, caseSel any, caseIndex int) (match bool, selectedValue any, err error) {
|
||||
caseData, _ := caseSel.(*selectorCase)
|
||||
if caseData.filterList == nil {
|
||||
selectedValue, err = caseData.caseExpr.Eval(ctx)
|
||||
@ -38,7 +42,7 @@ func trySelectorCase(ctx ExprContext, exprValue, caseSel any, caseIndex int) (ma
|
||||
} else {
|
||||
var caseValue any
|
||||
for _, caseTerm := range filterList {
|
||||
if caseValue, err = caseTerm.compute(ctx); err != nil || caseValue == exprValue {
|
||||
if caseValue, err = caseTerm.Compute(ctx); err != nil || caseValue == exprValue {
|
||||
selectedValue, err = caseData.caseExpr.Eval(ctx)
|
||||
match = true
|
||||
break
|
||||
@ -49,7 +53,7 @@ func trySelectorCase(ctx ExprContext, exprValue, caseSel any, caseIndex int) (ma
|
||||
return
|
||||
}
|
||||
|
||||
func evalSelector(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalSelector(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var exprValue any
|
||||
var match bool
|
||||
|
||||
@ -57,7 +61,7 @@ func evalSelector(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
exprTerm := opTerm.children[0]
|
||||
if exprValue, err = exprTerm.compute(ctx); err != nil {
|
||||
if exprValue, err = exprTerm.Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-shift.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- bit right shift term
|
||||
|
||||
func newRightShiftTerm(tk *Token) (inst *term) {
|
||||
@ -17,7 +21,7 @@ func newRightShiftTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||
if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) {
|
||||
leftInt := leftValue.(int64)
|
||||
rightInt := rightValue.(int64)
|
||||
v = leftInt >> rightInt
|
||||
@ -27,7 +31,7 @@ func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalRightShift(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
@ -49,7 +53,7 @@ func newLeftShiftTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||
if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) {
|
||||
leftInt := leftValue.(int64)
|
||||
rightInt := rightValue.(int64)
|
||||
v = leftInt << rightInt
|
||||
@ -59,7 +63,7 @@ func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalLeftShift(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
// operator-sign.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- plus sign term
|
||||
|
||||
func newPlusSignTerm(tk *Token) (inst *term) {
|
||||
@ -28,21 +32,21 @@ func newMinusSignTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalSign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalSign(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var rightValue any
|
||||
|
||||
if rightValue, err = opTerm.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsFloat(rightValue) {
|
||||
if kern.IsFloat(rightValue) {
|
||||
if opTerm.tk.Sym == SymChangeSign {
|
||||
f, _ := rightValue.(float64)
|
||||
v = -f
|
||||
} else {
|
||||
v = rightValue
|
||||
}
|
||||
} else if IsInteger(rightValue) {
|
||||
} else if kern.IsInteger(rightValue) {
|
||||
if opTerm.tk.Sym == SymChangeSign {
|
||||
i, _ := rightValue.(int64)
|
||||
v = -i
|
||||
@ -50,7 +54,7 @@ func evalSign(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
v = rightValue
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(rightValue)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(rightValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- plus term
|
||||
@ -22,46 +24,46 @@ func newPlusTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func sumValues(plusTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if (IsString(leftValue) && isNumberString(rightValue)) || (IsString(rightValue) && isNumberString(leftValue)) {
|
||||
if (kern.IsString(leftValue) && kern.IsNumberString(rightValue)) || (kern.IsString(rightValue) && kern.IsNumberString(leftValue)) {
|
||||
v = fmt.Sprintf("%v%v", leftValue, rightValue)
|
||||
} else if IsNumber(leftValue) && IsNumber(rightValue) {
|
||||
if IsFloat(leftValue) || IsFloat(rightValue) {
|
||||
v = numAsFloat(leftValue) + numAsFloat(rightValue)
|
||||
} else if kern.IsNumber(leftValue) && kern.IsNumber(rightValue) {
|
||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||
v = kern.NumAsFloat(leftValue) + kern.NumAsFloat(rightValue)
|
||||
} else {
|
||||
leftInt, _ := leftValue.(int64)
|
||||
rightInt, _ := rightValue.(int64)
|
||||
v = leftInt + rightInt
|
||||
}
|
||||
} else if IsList(leftValue) && IsList(rightValue) {
|
||||
var leftList, rightList *ListType
|
||||
leftList, _ = leftValue.(*ListType)
|
||||
rightList, _ = rightValue.(*ListType)
|
||||
} else if kern.IsList(leftValue) && kern.IsList(rightValue) {
|
||||
var leftList, rightList *kern.ListType
|
||||
leftList, _ = leftValue.(*kern.ListType)
|
||||
rightList, _ = rightValue.(*kern.ListType)
|
||||
|
||||
sumList := make(ListType, 0, len(*leftList)+len(*rightList))
|
||||
sumList := make(kern.ListType, 0, len(*leftList)+len(*rightList))
|
||||
sumList = append(sumList, *leftList...)
|
||||
sumList = append(sumList, *rightList...)
|
||||
v = &sumList
|
||||
} else if (isFraction(leftValue) && IsNumber(rightValue)) || (isFraction(rightValue) && IsNumber(leftValue)) {
|
||||
if IsFloat(leftValue) || IsFloat(rightValue) {
|
||||
v = numAsFloat(leftValue) + numAsFloat(rightValue)
|
||||
} else if (kern.IsFraction(leftValue) && kern.IsNumber(rightValue)) || (kern.IsFraction(rightValue) && kern.IsNumber(leftValue)) {
|
||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||
v = kern.NumAsFloat(leftValue) + kern.NumAsFloat(rightValue)
|
||||
} else {
|
||||
v, err = sumAnyFract(leftValue, rightValue)
|
||||
v, err = kern.SumAnyFract(leftValue, rightValue)
|
||||
}
|
||||
} else if IsDict(leftValue) && IsDict(rightValue) {
|
||||
leftDict, _ := leftValue.(*DictType)
|
||||
rightDict, _ := rightValue.(*DictType)
|
||||
c := leftDict.clone()
|
||||
c.merge(rightDict)
|
||||
} else if kern.IsDict(leftValue) && kern.IsDict(rightValue) {
|
||||
leftDict, _ := leftValue.(*kern.DictType)
|
||||
rightDict, _ := rightValue.(*kern.DictType)
|
||||
c := leftDict.Clone()
|
||||
c.Merge(rightDict)
|
||||
v = c
|
||||
} else if isFraction(leftValue) && isFraction(rightValue) {
|
||||
v, err = sumAnyFract(leftValue, rightValue)
|
||||
} else if kern.IsFraction(leftValue) && kern.IsFraction(rightValue) {
|
||||
v, err = kern.SumAnyFract(leftValue, rightValue)
|
||||
} else {
|
||||
err = plusTerm.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
return v, err
|
||||
}
|
||||
|
||||
func evalPlus(ctx ExprContext, plusTerm *term) (v any, err error) {
|
||||
func evalPlus(ctx kern.ExprContext, plusTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = plusTerm.evalInfix(ctx); err != nil {
|
||||
@ -84,20 +86,20 @@ func newMinusTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func diffValues(minusTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
|
||||
if IsFloat(leftValue) || IsFloat(rightValue) {
|
||||
v = numAsFloat(leftValue) - numAsFloat(rightValue)
|
||||
} else if isFraction(leftValue) || isFraction(rightValue) {
|
||||
v, err = subAnyFract(leftValue, rightValue)
|
||||
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) {
|
||||
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) {
|
||||
v = kern.NumAsFloat(leftValue) - kern.NumAsFloat(rightValue)
|
||||
} else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) {
|
||||
v, err = kern.SubAnyFract(leftValue, rightValue)
|
||||
} else {
|
||||
leftInt, _ := leftValue.(int64)
|
||||
rightInt, _ := rightValue.(int64)
|
||||
v = leftInt - rightInt
|
||||
}
|
||||
} else if IsList(leftValue) && IsList(rightValue) {
|
||||
leftList, _ := leftValue.(*ListType)
|
||||
rightList, _ := rightValue.(*ListType)
|
||||
diffList := make(ListType, 0, len(*leftList)-len(*rightList))
|
||||
} else if kern.IsList(leftValue) && kern.IsList(rightValue) {
|
||||
leftList, _ := leftValue.(*kern.ListType)
|
||||
rightList, _ := rightValue.(*kern.ListType)
|
||||
diffList := make(kern.ListType, 0, len(*leftList)-len(*rightList))
|
||||
for _, item := range *leftList {
|
||||
if slices.Index(*rightList, item) < 0 {
|
||||
diffList = append(diffList, item)
|
||||
@ -110,7 +112,7 @@ func diffValues(minusTerm *term, leftValue, rightValue any) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalMinus(ctx ExprContext, minusTerm *term) (v any, err error) {
|
||||
func evalMinus(ctx kern.ExprContext, minusTerm *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = minusTerm.evalInfix(ctx); err != nil {
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
// operator-unset.go
|
||||
package expr
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
//-------- unset term
|
||||
|
||||
@ -18,7 +22,7 @@ func newUnsetTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func deleteContextItem(ctx ExprContext, opTerm *term, item any) (deleted bool, err error) {
|
||||
func deleteContextItem(ctx kern.ExprContext, opTerm *term, item any) (deleted bool, err error) {
|
||||
if name, ok := item.(string); ok {
|
||||
var size int
|
||||
if strings.HasSuffix(name, "()") {
|
||||
@ -31,12 +35,12 @@ func deleteContextItem(ctx ExprContext, opTerm *term, item any) (deleted bool, e
|
||||
deleted = ctx.VarCount() < size
|
||||
}
|
||||
} else {
|
||||
err = opTerm.errIncompatibleType(item)
|
||||
err = opTerm.errIncompatiblePrefixPostfixType(item)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalUnset(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
func evalUnset(ctx kern.ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
var deleted bool
|
||||
|
||||
@ -45,8 +49,8 @@ func evalUnset(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
}
|
||||
|
||||
count := 0
|
||||
if IsList(childValue) {
|
||||
list, _ := childValue.(*ListType)
|
||||
if kern.IsList(childValue) {
|
||||
list, _ := childValue.(*kern.ListType)
|
||||
for _, item := range *list {
|
||||
if deleted, err = deleteContextItem(ctx, opTerm, item); err != nil {
|
||||
break
|
||||
|
||||
37
parser.go
37
parser.go
@ -104,7 +104,7 @@ func (parser *parser) parseFuncDef(scanner *scanner) (tree *term, err error) {
|
||||
param := newTerm(tk)
|
||||
if len(args) > 0 {
|
||||
if pos := paramAlreadyDefined(args, param); pos > 0 {
|
||||
err = tk.Errorf("parameter %q at position %d already defined at position %d", param.source(), len(args)+1, pos)
|
||||
err = tk.Errorf("parameter %q at position %d already defined at position %d", param.Source(), len(args)+1, pos)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -155,7 +155,7 @@ func (parser *parser) parseFuncDef(scanner *scanner) (tree *term, err error) {
|
||||
func paramAlreadyDefined(args []*term, param *term) (position int) {
|
||||
position = 0
|
||||
for i, arg := range args {
|
||||
if arg.source() == param.source() {
|
||||
if arg.Source() == param.Source() {
|
||||
position = i + 1
|
||||
}
|
||||
}
|
||||
@ -382,6 +382,15 @@ func (parser *parser) parseItem(scanner *scanner, ctx parserContext, termSymbols
|
||||
}
|
||||
|
||||
func (parser *parser) Parse(scanner *scanner, termSymbols ...Symbol) (tree *ast, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if errVal, ok := r.(error); ok {
|
||||
err = errVal
|
||||
} else {
|
||||
err = errors.New("unexpected error while parsing the expression")
|
||||
}
|
||||
}
|
||||
}()
|
||||
termSymbols = append(termSymbols, SymEos)
|
||||
return parser.parseGeneral(scanner, allowMultiExpr, termSymbols...)
|
||||
}
|
||||
@ -397,7 +406,7 @@ func couldBeACollection(t *term) bool {
|
||||
func listSubTree(tree *ast, listTerm *term, allowIndeces bool) (root *term, err error) {
|
||||
var tk *Token
|
||||
if allowIndeces {
|
||||
tk = NewToken(listTerm.tk.row, listTerm.tk.col, SymIndex, listTerm.source())
|
||||
tk = NewToken(listTerm.tk.row, listTerm.tk.col, SymIndex, listTerm.Source())
|
||||
root = newTerm(tk)
|
||||
if err = tree.addTerm(root); err == nil {
|
||||
err = tree.addTerm(listTerm)
|
||||
@ -455,15 +464,6 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
||||
//fmt.Println("Token:", tk)
|
||||
if firstToken {
|
||||
changePrefix(tk)
|
||||
// if tk.Sym == SymMinus {
|
||||
// tk.Sym = SymChangeSign
|
||||
// } else if tk.Sym == SymPlus {
|
||||
// tk.Sym = SymUnchangeSign
|
||||
// } else if tk.IsSymbol(SymStar) {
|
||||
// tk.SetSymbol(SymDereference)
|
||||
// } else if tk.IsSymbol(SymExclamation) {
|
||||
// tk.SetSymbol(SymNot)
|
||||
// }
|
||||
firstToken = false
|
||||
}
|
||||
|
||||
@ -471,12 +471,13 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
||||
case SymOpenRound:
|
||||
var subTree *ast
|
||||
if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil {
|
||||
exprTerm := newExprTerm(subTree.root)
|
||||
err = tree.addTerm(exprTerm)
|
||||
currentTerm = exprTerm
|
||||
// subTree.root.priority = priValue
|
||||
// err = tree.addTerm(newExprTerm(subTree.root))
|
||||
// currentTerm = subTree.root
|
||||
if subTree.root == nil {
|
||||
err = tk.ErrorExpectedGotString("expression", "()")
|
||||
} else {
|
||||
exprTerm := newExprTerm(subTree.root)
|
||||
err = tree.addTerm(exprTerm)
|
||||
currentTerm = exprTerm
|
||||
}
|
||||
}
|
||||
case SymFuncCall:
|
||||
var funcCallTerm *term
|
||||
|
||||
30
plugins.go
30
plugins.go
@ -10,6 +10,8 @@ import (
|
||||
"os"
|
||||
"plugin"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
var pluginRegister map[string]*plugin.Plugin
|
||||
@ -39,12 +41,12 @@ func makePluginName(name string) (decorated string) {
|
||||
return
|
||||
}
|
||||
|
||||
func importPlugin( /*ctx ExprContext,*/ dirList []string, name string) (err error) {
|
||||
func importPlugin(ctx kern.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 importFunc func(kern.ExprContext)
|
||||
var ok bool
|
||||
|
||||
decoratedName := makePluginName(name)
|
||||
@ -71,7 +73,7 @@ func importPlugin( /*ctx ExprContext,*/ dirList []string, name string) (err erro
|
||||
}
|
||||
if deps := *sym.(*[]string); len(deps) > 0 {
|
||||
// var count int
|
||||
if err = loadModules(dirList, deps); err != nil {
|
||||
if err = loadModules(ctx, dirList, deps); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -80,33 +82,35 @@ func importPlugin( /*ctx ExprContext,*/ dirList []string, name string) (err erro
|
||||
return
|
||||
}
|
||||
|
||||
if importFunc, ok = sym.(func(ExprContext)); !ok {
|
||||
if importFunc, ok = sym.(func(kern.ExprContext)); !ok {
|
||||
err = fmt.Errorf("plugin %q does not provide a valid import function", decoratedName)
|
||||
return
|
||||
}
|
||||
|
||||
registerPlugin(moduleName, p)
|
||||
importFunc(globalCtx)
|
||||
if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
importFunc(globalCtx)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func importPluginFromSearchPath(name any) (count int, err error) {
|
||||
func importPluginFromSearchPath(ctx kern.ExprContext, name any) (count int, err error) {
|
||||
var moduleSpec any
|
||||
var it Iterator
|
||||
dirList := buildSearchDirList("plugin", ENV_EXPR_PLUGIN_PATH)
|
||||
var it kern.Iterator
|
||||
dirList := buildSearchDirList(ctx, "plugin", ENV_EXPR_PLUGIN_PATH)
|
||||
count = 0
|
||||
if it, err = NewIterator(name); err != nil {
|
||||
return
|
||||
}
|
||||
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
||||
if module, ok := moduleSpec.(string); ok {
|
||||
if err = importPlugin(dirList, module); err != nil {
|
||||
if err = importPlugin(ctx, dirList, module); err != nil {
|
||||
break
|
||||
}
|
||||
count++
|
||||
} else {
|
||||
err = fmt.Errorf("expected string as item nr %d, got %s", it.Index()+1, TypeName(moduleSpec))
|
||||
err = fmt.Errorf("expected string as item nr %d, got %s", it.Index()+1, kern.TypeName(moduleSpec))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -116,10 +120,10 @@ func importPluginFromSearchPath(name any) (count int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func loadModules(dirList []string, moduleNames []string) (err error) {
|
||||
func loadModules(ctx kern.ExprContext, dirList []string, moduleNames []string) (err error) {
|
||||
for _, name := range moduleNames {
|
||||
if err1 := importPlugin(dirList, name); err1 != nil {
|
||||
if !ImportInContext(name) {
|
||||
if err1 := importPlugin(ctx, dirList, name); err1 != nil {
|
||||
if !ImportInContext(ctx, name) {
|
||||
err = err1
|
||||
break
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ import (
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type scanner struct {
|
||||
@ -503,7 +505,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) {
|
||||
if sym == SymFloat {
|
||||
value, err = strconv.ParseFloat(txt, 64)
|
||||
} else if sym == SymFraction {
|
||||
value, err = makeGeneratingFraction(txt)
|
||||
value, err = kern.MakeGeneratingFraction(txt)
|
||||
} else {
|
||||
value, err = strconv.ParseInt(txt, numBase, 64)
|
||||
}
|
||||
|
||||
107
simple-store.go
107
simple-store.go
@ -7,43 +7,63 @@ package expr
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
"git.portale-stac.it/go-pkg/expr/util"
|
||||
// "strings"
|
||||
)
|
||||
|
||||
type SimpleStore struct {
|
||||
parent ExprContext
|
||||
global kern.ExprContext
|
||||
parent kern.ExprContext
|
||||
varStore map[string]any
|
||||
funcStore map[string]ExprFunc
|
||||
funcStore map[string]kern.ExprFunc
|
||||
}
|
||||
|
||||
func NewSimpleStore() *SimpleStore {
|
||||
global := InitGlobal()
|
||||
ctx := &SimpleStore{
|
||||
global: global,
|
||||
varStore: make(map[string]any),
|
||||
funcStore: make(map[string]kern.ExprFunc),
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func NewSimpleStoreWithoutGlobalContext() *SimpleStore {
|
||||
ctx := &SimpleStore{
|
||||
varStore: make(map[string]any),
|
||||
funcStore: make(map[string]ExprFunc),
|
||||
funcStore: make(map[string]kern.ExprFunc),
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (ss *SimpleStore) Init() {
|
||||
ss.varStore = make(map[string]any)
|
||||
ss.funcStore = make(map[string]ExprFunc)
|
||||
ss.funcStore = make(map[string]kern.ExprFunc)
|
||||
}
|
||||
|
||||
func filterRefName(name string) bool { return name[0] != '@' }
|
||||
func filterRefName(name string) bool { return name[0] != '@' }
|
||||
|
||||
//func filterPrivName(name string) bool { return name[0] != '_' }
|
||||
|
||||
func (ctx *SimpleStore) SetParent(parentCtx ExprContext) {
|
||||
func (ctx *SimpleStore) SetParent(parentCtx kern.ExprContext) {
|
||||
ctx.parent = parentCtx
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) GetParent() ExprContext {
|
||||
func (ctx *SimpleStore) GetParent() kern.ExprContext {
|
||||
return ctx.parent
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) Clone() ExprContext {
|
||||
func (ctx *SimpleStore) GetGlobal() (globalCtx kern.ExprContext) {
|
||||
return ctx.global
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) Clone() kern.ExprContext {
|
||||
clone := &SimpleStore{
|
||||
varStore: CloneFilteredMap(ctx.varStore, filterRefName),
|
||||
funcStore: CloneFilteredMap(ctx.funcStore, filterRefName),
|
||||
global: ctx.global,
|
||||
varStore: util.CloneFilteredMap(ctx.varStore, filterRefName),
|
||||
funcStore: util.CloneFilteredMap(ctx.funcStore, filterRefName),
|
||||
}
|
||||
return clone
|
||||
}
|
||||
@ -57,19 +77,19 @@ func (ctx *SimpleStore) Clone() ExprContext {
|
||||
// }
|
||||
// }
|
||||
|
||||
func (ctx *SimpleStore) ToString(opt FmtOpt) string {
|
||||
func (ctx *SimpleStore) ToString(opt kern.FmtOpt) string {
|
||||
dict := ctx.ToDict()
|
||||
return dict.ToString(opt)
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) varsToDict(dict *DictType) *DictType {
|
||||
func (ctx *SimpleStore) varsToDict(dict *kern.DictType) *kern.DictType {
|
||||
names := ctx.EnumVars(nil)
|
||||
slices.Sort(names)
|
||||
for _, name := range ctx.EnumVars(nil) {
|
||||
value, _ := ctx.GetVar(name)
|
||||
if f, ok := value.(Formatter); ok {
|
||||
if f, ok := value.(kern.Formatter); ok {
|
||||
(*dict)[name] = f.ToString(0)
|
||||
} else if _, ok = value.(Functor); ok {
|
||||
} else if _, ok = value.(kern.Functor); ok {
|
||||
(*dict)[name] = "func(){}"
|
||||
} else {
|
||||
(*dict)[name] = fmt.Sprintf("%v", value)
|
||||
@ -78,12 +98,12 @@ func (ctx *SimpleStore) varsToDict(dict *DictType) *DictType {
|
||||
return dict
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) funcsToDict(dict *DictType) *DictType {
|
||||
func (ctx *SimpleStore) funcsToDict(dict *kern.DictType) *kern.DictType {
|
||||
names := ctx.EnumFuncs(func(name string) bool { return true })
|
||||
slices.Sort(names)
|
||||
for _, name := range names {
|
||||
value, _ := ctx.GetFuncInfo(name)
|
||||
if formatter, ok := value.(Formatter); ok {
|
||||
if formatter, ok := value.(kern.Formatter); ok {
|
||||
(*dict)[name] = formatter.ToString(0)
|
||||
} else {
|
||||
(*dict)[name] = fmt.Sprintf("%v", value)
|
||||
@ -92,20 +112,23 @@ func (ctx *SimpleStore) funcsToDict(dict *DictType) *DictType {
|
||||
return dict
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) ToDict() (dict *DictType) {
|
||||
dict = MakeDict()
|
||||
(*dict)["variables"] = ctx.varsToDict(MakeDict())
|
||||
(*dict)["functions"] = ctx.funcsToDict(MakeDict())
|
||||
func (ctx *SimpleStore) ToDict() (dict *kern.DictType) {
|
||||
dict = kern.MakeDict()
|
||||
(*dict)["variables"] = ctx.varsToDict(kern.MakeDict())
|
||||
(*dict)["functions"] = ctx.funcsToDict(kern.MakeDict())
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) {
|
||||
v, exists = ctx.varStore[varName]
|
||||
func (ctx *SimpleStore) GetVar(varName string) (value any, exists bool) {
|
||||
if value, exists = ctx.varStore[varName]; !exists && ctx.global != nil {
|
||||
value, exists = ctx.global.GetVar(varName)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) GetLast() (v any) {
|
||||
v = ctx.varStore["last"]
|
||||
v = ctx.varStore[kern.ControlLastResult]
|
||||
return
|
||||
}
|
||||
|
||||
@ -116,7 +139,7 @@ func (ctx *SimpleStore) UnsafeSetVar(varName string, value any) {
|
||||
|
||||
func (ctx *SimpleStore) SetVar(varName string, value any) {
|
||||
// fmt.Printf("[%p] SetVar(%v, %v)\n", ctx, varName, value)
|
||||
if allowedValue, ok := fromGenericAny(value); ok {
|
||||
if allowedValue, ok := util.FromGenericAny(value); ok {
|
||||
ctx.varStore[varName] = allowedValue
|
||||
} else {
|
||||
panic(fmt.Errorf("unsupported type %T of value %v", value, value))
|
||||
@ -145,16 +168,42 @@ func (ctx *SimpleStore) DeleteVar(varName string) {
|
||||
delete(ctx.varStore, varName)
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) GetFuncInfo(name string) (info ExprFunc, exists bool) {
|
||||
info, exists = ctx.funcStore[name]
|
||||
func (ctx *SimpleStore) GetFuncInfo(name string) (info kern.ExprFunc, exists bool) {
|
||||
info, exists, _ = ctx.GetFuncInfoAndOwner(name)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) RegisterFuncInfo(info ExprFunc) {
|
||||
func (ctx *SimpleStore) GetFuncInfoAndOwner(name string) (info kern.ExprFunc, exists bool, ownerCtx kern.ExprContext) {
|
||||
if len(name) > 0 {
|
||||
if info, exists = ctx.GetLocalFuncInfo(name); exists {
|
||||
ownerCtx = ctx
|
||||
} else if globalCtx := ctx.GetGlobal(); globalCtx != nil {
|
||||
if info, exists = globalCtx.GetFuncInfo(name); exists {
|
||||
ownerCtx = globalCtx
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) GetLocalFuncInfo(name string) (info kern.ExprFunc, exists bool) {
|
||||
var v any
|
||||
if len(name) > 0 {
|
||||
if v, exists = ctx.GetVar(name); exists && kern.IsFunctor(v) {
|
||||
f, _ := v.(kern.Functor)
|
||||
info = f.GetFunc()
|
||||
} else {
|
||||
info, exists = ctx.funcStore[name]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) RegisterFuncInfo(info kern.ExprFunc) {
|
||||
ctx.funcStore[info.Name()], _ = info.(*funcInfo)
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) RegisterFunc(name string, functor Functor, returnType string, params []ExprFuncParam) (exprFunc ExprFunc, err error) {
|
||||
func (ctx *SimpleStore) RegisterFunc(name string, functor kern.Functor, returnType string, params []kern.ExprFuncParam) (exprFunc kern.ExprFunc, err error) {
|
||||
var info *funcInfo
|
||||
if info, err = newFuncInfo(name, functor, returnType, params); err == nil {
|
||||
ctx.funcStore[name] = info
|
||||
@ -186,7 +235,7 @@ func (ctx *SimpleStore) DeleteFunc(funcName string) {
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) Call(name string, args map[string]any) (result any, err error) {
|
||||
if info, exists := GetLocalFuncInfo(ctx, name); exists {
|
||||
if info, exists := ctx.GetLocalFuncInfo(name); exists {
|
||||
functor := info.Functor()
|
||||
result, err = functor.InvokeNamed(ctx, name, args)
|
||||
} else {
|
||||
|
||||
@ -182,21 +182,49 @@ func StringEndsWithOperator(s string) bool {
|
||||
return endingOperator(s) != SymNone
|
||||
}
|
||||
|
||||
// func endingOperator(s string) (sym Symbol) {
|
||||
// var matchLength = 0
|
||||
// sym = SymNone
|
||||
// lower := strings.TrimRight(strings.ToLower(s), " \t")
|
||||
// for symbol, spec := range symbolMap {
|
||||
// if strings.HasSuffix(lower, spec.repr) {
|
||||
// if len(spec.repr) > matchLength {
|
||||
// matchLength = len(spec.repr)
|
||||
// if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) {
|
||||
// sym = symbol
|
||||
// } else {
|
||||
// sym = SymNone
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func endingOperator(s string) (sym Symbol) {
|
||||
var matchLength = 0
|
||||
var repr string
|
||||
sym = SymNone
|
||||
lower := strings.TrimRight(strings.ToLower(s), " \t")
|
||||
for symbol, spec := range symbolMap {
|
||||
if strings.HasSuffix(lower, spec.repr) {
|
||||
if len(spec.repr) > matchLength {
|
||||
matchLength = len(spec.repr)
|
||||
if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) {
|
||||
if len(spec.repr) > matchLength || repr == spec.repr {
|
||||
if strings.HasSuffix(lower, spec.repr) {
|
||||
if isNotEndingSymbol(spec) && repr != spec.repr {
|
||||
repr = spec.repr
|
||||
matchLength = len(spec.repr)
|
||||
sym = symbol
|
||||
} else {
|
||||
sym = SymNone
|
||||
break
|
||||
// matchLength = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func isNotEndingSymbol(spec symbolSpec) bool {
|
||||
return (spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix)) ||
|
||||
(spec.kind == symClassParenthesis && spec.opType == posPrefix)
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ package expr
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestBool(t *testing.T) {
|
||||
@ -19,10 +21,10 @@ func TestBool(t *testing.T) {
|
||||
/* 5 */ {`not "true"`, false, nil},
|
||||
/* 6 */ {`not "false"`, false, nil},
|
||||
/* 7 */ {`not ""`, true, nil},
|
||||
/* 8 */ {`not []`, nil, errors.New(`[1:4] prefix/postfix operator "NOT" do not support operand '[]' [list]`)},
|
||||
/* 8 */ {`not []`, nil, errors.New(`[1:4] prefix/postfix operator "NOT" does not support operand '[]' [list]`)},
|
||||
/* 9 */ {`true and false`, false, nil},
|
||||
/* 10 */ {`true and []`, nil, errors.New(`[1:9] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "AND"`)},
|
||||
/* 11 */ {`[] and false`, nil, errors.New(`got list as left operand type of 'AND' operator, it must be bool`)},
|
||||
/* 11 */ {`[] and false`, nil, errors.New(`[1:7] operator "AND" does not support operand '[]' [list] on its left side`)},
|
||||
/* 12 */ {`true or false`, true, nil},
|
||||
/* 13 */ {`true or []`, true, nil},
|
||||
/* 14 */ {`[] or false`, nil, errors.New(`got list as left operand type of 'OR' operator, it must be bool`)},
|
||||
@ -32,7 +34,7 @@ func TestBool(t *testing.T) {
|
||||
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 15)
|
||||
// runTestSuiteSpec(t, section, inputs, 13)
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
@ -46,7 +48,7 @@ func TestBoolNoShortcut(t *testing.T) {
|
||||
/* 5 */ {`not "true"`, false, nil},
|
||||
/* 6 */ {`not "false"`, false, nil},
|
||||
/* 7 */ {`not ""`, true, nil},
|
||||
/* 8 */ {`not []`, nil, `[1:4] prefix/postfix operator "NOT" do not support operand '[]' [list]`},
|
||||
/* 8 */ {`not []`, nil, `[1:4] prefix/postfix operator "NOT" does not support operand '[]' [list]`},
|
||||
/* 9 */ {`true and false`, false, nil},
|
||||
/* 10 */ {`true and []`, nil, `[1:9] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "AND"`},
|
||||
/* 11 */ {`[] and false`, nil, `[1:7] left operand '[]' [list] and right operand 'false' [bool] are not compatible with operator "AND"`},
|
||||
@ -58,10 +60,10 @@ func TestBoolNoShortcut(t *testing.T) {
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
current := SetCtrl(ctx, ControlBoolShortcut, false)
|
||||
current := kern.SetCtrl(ctx, kern.ControlBoolShortcut, false)
|
||||
|
||||
// runCtxTestSuiteSpec(t, ctx, section, inputs, 1)
|
||||
runCtxTestSuite(t, ctx, section, inputs)
|
||||
|
||||
SetCtrl(ctx, ControlBoolShortcut, current)
|
||||
kern.SetCtrl(ctx, kern.ControlBoolShortcut, current)
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ package expr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestFuncBase(t *testing.T) {
|
||||
@ -33,10 +35,10 @@ func TestFuncBase(t *testing.T) {
|
||||
/* 19 */ {`isFract(1:3)`, true, nil},
|
||||
/* 20 */ {`isFract(3:1)`, false, nil},
|
||||
/* 21 */ {`isRational(3:1)`, true, nil},
|
||||
/* 22 */ {`fract("2.2(3)")`, newFraction(67, 30), nil},
|
||||
/* 23 */ {`fract("1.21(3)")`, newFraction(91, 75), nil},
|
||||
/* 24 */ {`fract(1.21(3))`, newFraction(91, 75), nil},
|
||||
/* 25 */ {`fract(1.21)`, newFraction(121, 100), nil},
|
||||
/* 22 */ {`fract("2.2(3)")`, kern.NewFraction(67, 30), nil},
|
||||
/* 23 */ {`fract("1.21(3)")`, kern.NewFraction(91, 75), nil},
|
||||
/* 24 */ {`fract(1.21(3))`, kern.NewFraction(91, 75), nil},
|
||||
/* 25 */ {`fract(1.21)`, kern.NewFraction(121, 100), nil},
|
||||
/* 26 */ {`dec(2)`, float64(2), nil},
|
||||
/* 27 */ {`dec(2.0)`, float64(2), nil},
|
||||
/* 28 */ {`dec("2.0")`, float64(2), nil},
|
||||
@ -45,8 +47,8 @@ func TestFuncBase(t *testing.T) {
|
||||
/* 31 */ {`dec()`, nil, `dec(): too few params -- expected 1, got 0`},
|
||||
/* 32 */ {`dec(1,2,3)`, nil, `dec(): too many params -- expected 1, got 3`},
|
||||
/* 33 */ {`isBool(false)`, true, nil},
|
||||
/* 34 */ {`fract(1:2)`, newFraction(1, 2), nil},
|
||||
/* 35 */ {`fract(12,2)`, newFraction(6, 1), nil},
|
||||
/* 34 */ {`fract(1:2)`, kern.NewFraction(1, 2), nil},
|
||||
/* 35 */ {`fract(12,2)`, kern.NewFraction(6, 1), nil},
|
||||
/* 36 */ {`bool(2)`, true, nil},
|
||||
/* 37 */ {`bool(1:2)`, true, nil},
|
||||
/* 38 */ {`bool(1.0)`, true, nil},
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestFuncFmt(t *testing.T) {
|
||||
@ -37,11 +39,11 @@ func TestFmt(t *testing.T) {
|
||||
|
||||
var b bytes.Buffer
|
||||
ctx := NewSimpleStore()
|
||||
currentStdout := SetCtrl(ctx, ControlStdout, &b)
|
||||
currentStdout := kern.SetCtrl(ctx, kern.ControlStdout, &b)
|
||||
|
||||
runCtxTestSuite(t, ctx, section, inputs)
|
||||
|
||||
SetCtrl(ctx, ControlStdout, currentStdout)
|
||||
kern.SetCtrl(ctx, kern.ControlStdout, currentStdout)
|
||||
if b.String() != text+"\n" {
|
||||
t.Errorf("println(): Got: %q, Want: %q", b.String(), text+"\n")
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ func TestFuncRun(t *testing.T) {
|
||||
inputs := []inputType{
|
||||
/* 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},
|
||||
/* 3 */ {`builtin "iterator"; run($(1,2,3), func(index,item){status=status+item; true}, {"status":0})`, int64(6), nil},
|
||||
/* 3 */ {`builtin "iterator"; run($(4), 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},
|
||||
/* 5 */ {`builtin "iterator"; run(nil)`, nil, `paramter "iterator" must be an iterator, passed <nil> [nil]`},
|
||||
/* 6 */ {`builtin "iterator"; run($(1,2,3), nil)`, nil, nil},
|
||||
@ -26,6 +26,6 @@ func TestFuncRun(t *testing.T) {
|
||||
|
||||
//t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
runTestSuiteSpec(t, section, inputs, 10)
|
||||
// runTestSuite(t, section, inputs)
|
||||
// runTestSuiteSpec(t, section, inputs, 3)
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ package expr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestFuncString(t *testing.T) {
|
||||
@ -28,7 +30,7 @@ func TestFuncString(t *testing.T) {
|
||||
/* 14 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "789")`, true, nil},
|
||||
/* 15 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "0125")`, false, nil},
|
||||
/* 16 */ {`builtin "string"; strEndsWith("0123456789")`, nil, `strEndsWith(): too few params -- expected 2 or more, got 1`},
|
||||
/* 17 */ {`builtin "string"; strSplit("one-two-three", "-")`, newListA("one", "two", "three"), nil},
|
||||
/* 17 */ {`builtin "string"; strSplit("one-two-three", "-")`, kern.NewListA("one", "two", "three"), nil},
|
||||
/* 18 */ {`builtin "string"; strJoin("-", [1, "two", "three"])`, nil, `strJoin(): expected string, got integer (1)`},
|
||||
/* 19 */ {`builtin "string"; strJoin()`, nil, `strJoin(): too few params -- expected 1 or more, got 0`},
|
||||
/* 20 */ {`builtin "string"; strUpper("StOp")`, "STOP", nil},
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type inputType struct {
|
||||
@ -17,7 +19,7 @@ type inputType struct {
|
||||
wantErr any
|
||||
}
|
||||
|
||||
func runCtxTestSuiteSpec(t *testing.T, ctx ExprContext, section string, inputs []inputType, spec ...int) {
|
||||
func runCtxTestSuiteSpec(t *testing.T, ctx kern.ExprContext, section string, inputs []inputType, spec ...int) {
|
||||
succeeded := 0
|
||||
failed := 0
|
||||
for _, count := range spec {
|
||||
@ -36,7 +38,7 @@ func runTestSuiteSpec(t *testing.T, section string, inputs []inputType, spec ...
|
||||
runCtxTestSuiteSpec(t, nil, section, inputs, spec...)
|
||||
}
|
||||
|
||||
func runCtxTestSuite(t *testing.T, ctx ExprContext, section string, inputs []inputType) {
|
||||
func runCtxTestSuite(t *testing.T, ctx kern.ExprContext, section string, inputs []inputType) {
|
||||
|
||||
succeeded := 0
|
||||
failed := 0
|
||||
@ -68,8 +70,8 @@ func getWantedError(input *inputType) error {
|
||||
return wantErr
|
||||
}
|
||||
|
||||
func doTest(t *testing.T, ctx ExprContext, section string, input *inputType, count int) (good bool) {
|
||||
var expr Expr
|
||||
func doTest(t *testing.T, ctx kern.ExprContext, section string, input *inputType, count int) (good bool) {
|
||||
var ast Expr
|
||||
var gotResult any
|
||||
var gotErr error
|
||||
var eq, eqDone bool
|
||||
@ -87,13 +89,13 @@ func doTest(t *testing.T, ctx ExprContext, section string, input *inputType, cou
|
||||
scanner := NewScanner(r, DefaultTranslations())
|
||||
|
||||
good = true
|
||||
if expr, gotErr = parser.Parse(scanner); gotErr == nil {
|
||||
gotResult, gotErr = expr.Eval(ctx)
|
||||
if ast, gotErr = parser.Parse(scanner); gotErr == nil {
|
||||
gotResult, gotErr = ast.Eval(ctx)
|
||||
}
|
||||
|
||||
if input.wantResult != nil && gotResult != nil {
|
||||
if ls1, ok := input.wantResult.(*ListType); ok {
|
||||
if ls2, ok := gotResult.(*ListType); ok {
|
||||
if ls1, ok := input.wantResult.(*kern.ListType); ok {
|
||||
if ls2, ok := gotResult.(*kern.ListType); ok {
|
||||
eq = ls1.Equals(*ls2)
|
||||
eqDone = true
|
||||
}
|
||||
@ -105,13 +107,13 @@ func doTest(t *testing.T, ctx ExprContext, section string, input *inputType, cou
|
||||
}
|
||||
|
||||
if !eq /*gotResult != input.wantResult*/ {
|
||||
t.Errorf("%d: `%s` -> result = %v [%s], want = %v [%s]", count, input.source, gotResult, TypeName(gotResult), input.wantResult, TypeName(input.wantResult))
|
||||
t.Errorf(">>>%s/%d: `%s` -> result = %v [%s], want = %v [%s]", section, count, input.source, gotResult, kern.TypeName(gotResult), input.wantResult, kern.TypeName(input.wantResult))
|
||||
good = false
|
||||
}
|
||||
|
||||
if gotErr != wantErr {
|
||||
if wantErr == nil || gotErr == nil || (gotErr.Error() != wantErr.Error()) {
|
||||
t.Errorf("%d: %s -> got-err = <%v>, expected-err = <%v>", count, input.source, gotErr, wantErr)
|
||||
t.Errorf(">>>%s/%d: %s -> got-err = <%v>, expected-err = <%v>", section, count, input.source, gotErr, wantErr)
|
||||
good = false
|
||||
}
|
||||
}
|
||||
|
||||
60
t_context_test.go
Normal file
60
t_context_test.go
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// t_context_test.go
|
||||
package expr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCtrlSet(t *testing.T) {
|
||||
section := "Context"
|
||||
varName := "_test_var"
|
||||
varValue := "test-value"
|
||||
prevValue := "test-prev"
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
GlobalCtrlSet(ctx, varName, prevValue)
|
||||
if v := GlobalCtrlSet(ctx, varName, varValue); v != nil {
|
||||
if s, ok := v.(string); ok {
|
||||
if s != prevValue {
|
||||
t.Errorf(`%s -- CtrlSet(%q, %q) should have returned %q, got %q`, section, varName, varValue, varValue, s)
|
||||
}
|
||||
} else {
|
||||
t.Errorf(`%s -- CtrlSet(%q, %q) should have returned a string, got %v [%T]`, section, varName, varValue, v, v)
|
||||
}
|
||||
} else {
|
||||
t.Errorf(`%s -- CtrlSet(%q, %q) should have returned a value, got nil`, section, varName, varValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCtrlGet(t *testing.T) {
|
||||
section := "Context"
|
||||
varName := "_test_var"
|
||||
varValue := "test-value"
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
GlobalCtrlSet(ctx, varName, varValue)
|
||||
if v := GlobalCtrlGet(ctx, varName); v != nil {
|
||||
if s, ok := v.(string); ok {
|
||||
if s != "test-value" {
|
||||
t.Errorf(`%s -- CtrlGet(%q) should have returned %q, got %q`, section, varName, varValue, s)
|
||||
}
|
||||
} else {
|
||||
t.Errorf(`%s -- CtrlGet(%q) should have returned a string, got %v [%T]`, section, varName, v, v)
|
||||
}
|
||||
} else {
|
||||
t.Errorf(`%s -- CtrlGet(%q) should have returned a value, got nil`, section, varName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCtrlGetNotDefined(t *testing.T) {
|
||||
section := "Context"
|
||||
varName := "_test_var"
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
if v := GlobalCtrlGet(ctx, varName); v != nil {
|
||||
t.Errorf(`%s -- CtrlGet(%q) should have returned nil, got %v`, section, varName, v)
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,8 @@ import (
|
||||
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestDictParser(t *testing.T) {
|
||||
@ -37,7 +39,10 @@ func TestDictParser(t *testing.T) {
|
||||
//"b":2,
|
||||
"c":3
|
||||
}`, map[any]any{"a": 1, "c": 3}, nil},
|
||||
}
|
||||
/* 13 */ {`D={"a":1, "b":2}; D."a"`, int64(1), nil},
|
||||
/* 14 */ {`D={"a":1, "b":2}; D.a`, int64(1), nil},
|
||||
/* 15 */ {`D={1:"a", 2:"b", 3:"c"}; D.(1+2)`, "c", nil},
|
||||
}
|
||||
|
||||
succeeded := 0
|
||||
failed := 0
|
||||
@ -51,7 +56,7 @@ func TestDictParser(t *testing.T) {
|
||||
var gotResult any
|
||||
var gotErr error
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
ctx := NewSimpleStoreWithoutGlobalContext()
|
||||
ctx.SetVar("var1", int64(123))
|
||||
ctx.SetVar("var2", "abc")
|
||||
ImportMathFuncs(ctx)
|
||||
@ -118,11 +123,11 @@ func TestDictToStringMultiLine(t *testing.T) {
|
||||
want := `{
|
||||
"first": 1
|
||||
}`
|
||||
args := map[any]*term{
|
||||
args := map[any]any{
|
||||
"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)),
|
||||
}
|
||||
dict := newDict(args)
|
||||
got := dict.ToString(MultiLine)
|
||||
dict := kern.NewDict(args)
|
||||
got := dict.ToString(kern.MultiLine)
|
||||
// fmt.Printf("got=%q\n", got)
|
||||
|
||||
if good = got == want; !good {
|
||||
@ -140,10 +145,10 @@ func TestDictToString(t *testing.T) {
|
||||
var good bool
|
||||
section := "dict-ToString-SL"
|
||||
want := `{"first": 1}`
|
||||
args := map[any]*term{
|
||||
args := map[any]any{
|
||||
"first": newLiteralTerm(NewValueToken(0, 0, SymInteger, "1", 1)),
|
||||
}
|
||||
dict := newDict(args)
|
||||
dict := kern.NewDict(args)
|
||||
got := dict.ToString(0)
|
||||
// fmt.Printf("got=%q\n", got)
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ package expr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestExpr(t *testing.T) {
|
||||
@ -29,7 +31,7 @@ func TestExpr(t *testing.T) {
|
||||
/* 15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`},
|
||||
/* 16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil},
|
||||
/* 17 */ {`true ? {"a"} :: {"b"}`, "a", nil},
|
||||
/* 18 */ {`$$`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil},
|
||||
/* 18 */ {`$$`, kern.NewDict(map[any]any{"variables": kern.NewDict(nil), "functions": kern.NewDict(nil)}), nil},
|
||||
///* 19 */ {`$$global`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil},
|
||||
/* 19 */ {`
|
||||
ds={
|
||||
|
||||
@ -6,43 +6,45 @@ package expr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestFractionsParser(t *testing.T) {
|
||||
section := "Fraction"
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`1:2`, newFraction(1, 2), nil},
|
||||
/* 2 */ {`1:2 + 1`, newFraction(3, 2), nil},
|
||||
/* 3 */ {`1:2 - 1`, newFraction(-1, 2), nil},
|
||||
/* 4 */ {`1:2 * 1`, newFraction(1, 2), nil},
|
||||
/* 5 */ {`1:2 * 2:3`, newFraction(2, 6), nil},
|
||||
/* 6 */ {`1:2 / 2:3`, newFraction(3, 4), nil},
|
||||
/* 1 */ {`1:2`, kern.NewFraction(1, 2), nil},
|
||||
/* 2 */ {`1:2 + 1`, kern.NewFraction(3, 2), nil},
|
||||
/* 3 */ {`1:2 - 1`, kern.NewFraction(-1, 2), nil},
|
||||
/* 4 */ {`1:2 * 1`, kern.NewFraction(1, 2), nil},
|
||||
/* 5 */ {`1:2 * 2:3`, kern.NewFraction(2, 6), nil},
|
||||
/* 6 */ {`1:2 / 2:3`, kern.NewFraction(3, 4), nil},
|
||||
/* 7 */ {`1:"5"`, nil, `denominator must be integer, got string (5)`},
|
||||
/* 8 */ {`"1":5`, nil, `numerator must be integer, got string (1)`},
|
||||
/* 9 */ {`1:+5`, newFraction(1, 5), nil},
|
||||
/* 10 */ {`1:(-2)`, newFraction(-1, 2), nil},
|
||||
/* 11 */ {`builtin "math.arith"; add(1:2, 2:3)`, newFraction(7, 6), nil},
|
||||
/* 9 */ {`1:+5`, kern.NewFraction(1, 5), nil},
|
||||
/* 10 */ {`1:(-2)`, kern.NewFraction(-1, 2), nil},
|
||||
/* 11 */ {`builtin "math.arith"; add(1:2, 2:3)`, kern.NewFraction(7, 6), nil},
|
||||
/* 12 */ {`builtin "math.arith"; add(1:2, 1.0, 2)`, float64(3.5), nil},
|
||||
/* 13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, newFraction(2, 6), nil},
|
||||
/* 13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, kern.NewFraction(2, 6), nil},
|
||||
/* 14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil},
|
||||
/* 15 */ {`1:0`, nil, `[1:3] division by zero`},
|
||||
/* 16 */ {`fract(-0.5)`, newFraction(-1, 2), nil},
|
||||
/* 17 */ {`fract("")`, (*FractionType)(nil), `bad syntax`},
|
||||
/* 18 */ {`fract("-1")`, newFraction(-1, 1), nil},
|
||||
/* 19 */ {`fract("+1")`, newFraction(1, 1), nil},
|
||||
/* 20 */ {`fract("1a")`, (*FractionType)(nil), `strconv.ParseInt: parsing "1a": invalid syntax`},
|
||||
/* 16 */ {`fract(-0.5)`, kern.NewFraction(-1, 2), nil},
|
||||
/* 17 */ {`fract("")`, (*kern.FractionType)(nil), `bad syntax`},
|
||||
/* 18 */ {`fract("-1")`, kern.NewFraction(-1, 1), nil},
|
||||
/* 19 */ {`fract("+1")`, kern.NewFraction(1, 1), nil},
|
||||
/* 20 */ {`fract("1a")`, (*kern.FractionType)(nil), `strconv.ParseInt: parsing "1a": invalid syntax`},
|
||||
/* 21 */ {`fract(1,0)`, nil, `fract(): division by zero`},
|
||||
/* 22 */ {`string(1:2)`, "1:2", nil},
|
||||
/* 23 */ {`1+1:2+0.5`, float64(2), nil},
|
||||
/* 24 */ {`1:(2-2)`, nil, `[1:3] division by zero`},
|
||||
/* 25 */ {`[0,1][1-1]:1`, newFraction(0, 1), nil},
|
||||
/* 25 */ {`[0,1][1-1]:1`, kern.NewFraction(0, 1), nil},
|
||||
}
|
||||
// runTestSuiteSpec(t, section, inputs, 25)
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func TestFractionToStringSimple(t *testing.T) {
|
||||
source := newFraction(1, 2)
|
||||
source := kern.NewFraction(1, 2)
|
||||
want := "1:2"
|
||||
got := source.ToString(0)
|
||||
if got != want {
|
||||
@ -51,18 +53,18 @@ func TestFractionToStringSimple(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFractionToStringMultiline(t *testing.T) {
|
||||
source := newFraction(1, 2)
|
||||
source := kern.NewFraction(1, 2)
|
||||
want := "1\n-\n2"
|
||||
got := source.ToString(MultiLine)
|
||||
got := source.ToString(kern.MultiLine)
|
||||
if got != want {
|
||||
t.Errorf(`(1,2) -> result = %v [%T], want = %v [%T]`, got, got, want, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToStringMultilineTty(t *testing.T) {
|
||||
source := newFraction(-1, 2)
|
||||
source := kern.NewFraction(-1, 2)
|
||||
want := "\x1b[4m-1\x1b[0m\n 2"
|
||||
got := source.ToString(MultiLine | TTY)
|
||||
got := source.ToString(kern.MultiLine | kern.TTY)
|
||||
if got != want {
|
||||
t.Errorf(`(1,2) -> result = %#v [%T], want = %#v [%T]`, got, got, want, want)
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ package expr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestFuncs(t *testing.T) {
|
||||
@ -47,12 +49,12 @@ func TestFuncs(t *testing.T) {
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func dummy(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
func dummy(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func TestFunctionToStringSimple(t *testing.T) {
|
||||
source := NewGolangFunctor(dummy)
|
||||
source := kern.NewGolangFunctor(dummy)
|
||||
want := "func(){}"
|
||||
got := source.ToString(0)
|
||||
if got != want {
|
||||
@ -61,8 +63,8 @@ func TestFunctionToStringSimple(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFunctionGetFunc(t *testing.T) {
|
||||
source := NewGolangFunctor(dummy)
|
||||
want := ExprFunc(nil)
|
||||
source := kern.NewGolangFunctor(dummy)
|
||||
want := kern.ExprFunc(nil)
|
||||
got := source.GetFunc()
|
||||
if got != want {
|
||||
t.Errorf(`(func() -> result = %v [%T], want = %v [%T]`, got, got, want, want)
|
||||
@ -76,16 +78,16 @@ func TestGoFunction(t *testing.T) {
|
||||
/* 2 */ {`myName("Peppino")`, "Peppino", nil},
|
||||
}
|
||||
|
||||
myName := func(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
myName := func(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
var ok bool
|
||||
if result, ok = args["name"].(string); !ok {
|
||||
err = ErrWrongParamType(name, "name", TypeString, args["name"])
|
||||
err = kern.ErrWrongParamType(name, "name", kern.TypeString, args["name"])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
ctx.RegisterFunc("myName", NewGolangFunctor(myName), TypeString, []ExprFuncParam{
|
||||
ctx := NewSimpleStoreWithoutGlobalContext()
|
||||
ctx.RegisterFunc("myName", kern.NewGolangFunctor(myName), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParamFlagDef("name", PfOptional|PfDefault, "Celestino Amoroso"),
|
||||
})
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ import (
|
||||
|
||||
func TestEvalString(t *testing.T) {
|
||||
|
||||
ctx := NewSimpleStore()
|
||||
ctx := NewSimpleStoreWithoutGlobalContext()
|
||||
ctx.SetVar("a", uint8(1))
|
||||
ctx.SetVar("b", int8(2))
|
||||
ctx.SetVar("f", 2.0)
|
||||
|
||||
@ -7,10 +7,12 @@ package expr
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
func TestNewListIterator(t *testing.T) {
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, 3, 1})
|
||||
if item, err := it.Next(); err != nil {
|
||||
t.Errorf("error: %v", err)
|
||||
@ -22,7 +24,7 @@ func TestNewListIterator(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewListIterator2(t *testing.T) {
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{3, 1, -1})
|
||||
if item, err := it.Next(); err != nil {
|
||||
t.Errorf("error: %v", err)
|
||||
@ -34,7 +36,7 @@ func TestNewListIterator2(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewListIterator3(t *testing.T) {
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, -1, 1})
|
||||
if item, err := it.Next(); err != nil {
|
||||
t.Errorf("error: %v", err)
|
||||
@ -90,7 +92,7 @@ func TestNewIterList5(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewIterList6(t *testing.T) {
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it1, _ := NewIterator(list)
|
||||
it, _ := NewIterator(it1)
|
||||
if item, err := it.Next(); err != nil {
|
||||
@ -101,6 +103,7 @@ func TestNewIterList6(t *testing.T) {
|
||||
t.Logf("Next: %v", item)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewString(t *testing.T) {
|
||||
list := "123"
|
||||
it, _ := NewIterator(list)
|
||||
@ -111,7 +114,7 @@ func TestNewString(t *testing.T) {
|
||||
|
||||
func TestHasOperation(t *testing.T) {
|
||||
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, 3, 1})
|
||||
hasOp := it.HasOperation("reset")
|
||||
if !hasOp {
|
||||
@ -121,7 +124,7 @@ func TestHasOperation(t *testing.T) {
|
||||
|
||||
func TestCallOperationReset(t *testing.T) {
|
||||
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, 3, 1})
|
||||
if v, err := it.CallOperation("reset", nil); err != nil {
|
||||
t.Errorf("Error on CallOperation(reset): %v", err)
|
||||
@ -132,7 +135,7 @@ func TestCallOperationReset(t *testing.T) {
|
||||
|
||||
func TestCallOperationIndex(t *testing.T) {
|
||||
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, 3, 1})
|
||||
if v, err := it.CallOperation("index", nil); err != nil {
|
||||
t.Errorf("Error on CallOperation(index): %v", err)
|
||||
@ -143,7 +146,7 @@ func TestCallOperationIndex(t *testing.T) {
|
||||
|
||||
func TestCallOperationCount(t *testing.T) {
|
||||
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, 3, 1})
|
||||
if v, err := it.CallOperation("count", nil); err != nil {
|
||||
t.Errorf("Error on CallOperation(count): %v", err)
|
||||
@ -154,7 +157,7 @@ func TestCallOperationCount(t *testing.T) {
|
||||
|
||||
func TestCallOperationUnknown(t *testing.T) {
|
||||
|
||||
list := newListA("a", "b", "c", "d")
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it := NewListIterator(list, []any{1, 3, 1})
|
||||
if v, err := it.CallOperation("unknown", nil); err == nil {
|
||||
t.Errorf("Expected error on CallOperation(unknown), got %v", v)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user