diff --git a/list-iterator.go b/array-iterator.go similarity index 82% rename from list-iterator.go rename to array-iterator.go index 8e7107a..9e56fd3 100644 --- a/list-iterator.go +++ b/array-iterator.go @@ -10,10 +10,12 @@ import ( "slices" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" ) type ListIterator struct { - a *kern.ListType + a *array.ListType count int64 index int64 start int64 @@ -21,7 +23,7 @@ type ListIterator struct { step int64 } -func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) { +func NewListIterator(list *array.ListType, args []any) (it *ListIterator) { var argc int = 0 listLen := int64(len(([]any)(*list))) if args != nil { @@ -29,21 +31,21 @@ func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) { } it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1} if argc >= 1 { - if i, err := kern.ToGoInt64(args[0], "start index"); err == nil { + if i, err := types.ToGoInt64(args[0], "start index"); err == nil { if i < 0 { i = listLen + i } it.start = i } if argc >= 2 { - if i, err := kern.ToGoInt64(args[1], "stop index"); err == nil { + if i, err := types.ToGoInt64(args[1], "stop index"); err == nil { if i < 0 { i = listLen + i } it.stop = i } if argc >= 3 { - if i, err := kern.ToGoInt64(args[2], "step"); err == nil { + if i, err := types.ToGoInt64(args[2], "step"); err == nil { if i < 0 { i = -i } @@ -60,8 +62,8 @@ func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) { return } -func NewArrayIterator(array []any) (it *ListIterator) { - it = &ListIterator{a: (*kern.ListType)(&array), count: 0, index: -1, start: 0, stop: int64(len(array)) - 1, step: 1} +func NewArrayIterator(a []any) (it *ListIterator) { + it = &ListIterator{a: (*array.ListType)(&a), count: 0, index: -1, start: 0, stop: int64(len(a)) - 1, step: 1} return } diff --git a/builtin-base.go b/builtin-base.go index 5cb625c..a9571ae 100644 --- a/builtin-base.go +++ b/builtin-base.go @@ -12,6 +12,14 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/boolean" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/list" + "git.portale-stac.it/go-pkg/expr/types/str" ) const ( @@ -24,42 +32,42 @@ func isNilFunc(ctx kern.ExprContext, name string, args map[string]any) (result a } func isIntFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsInteger(args[kern.ParamValue]) + result = types.IsInteger(args[kern.ParamValue]) return } func isFloatFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsFloat(args[kern.ParamValue]) + result = float.IsFloat(args[kern.ParamValue]) return } func isBoolFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsBool(args[kern.ParamValue]) + result = boolean.IsBool(args[kern.ParamValue]) return } func isStringFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsString(args[kern.ParamValue]) + result = str.IsString(args[kern.ParamValue]) return } func isFractionFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsFraction(args[kern.ParamValue]) + result = fract.IsFraction(args[kern.ParamValue]) return } func isRationalFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsRational(args[kern.ParamValue]) + result = fract.IsRational(args[kern.ParamValue]) return } func isListFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsList(args[kern.ParamValue]) + result = array.IsList(args[kern.ParamValue]) return } func isDictionaryFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - result = kern.IsDict(args[kern.ParamValue]) + result = dict.IsDict(args[kern.ParamValue]) return } @@ -67,7 +75,7 @@ func boolFunc(ctx kern.ExprContext, name string, args map[string]any) (result an switch v := args[kern.ParamValue].(type) { case int64: result = (v != 0) - case *kern.FractionType: + case *fract.FractionType: result = v.N() != 0 case float64: result = v != 0.0 @@ -75,9 +83,9 @@ func boolFunc(ctx kern.ExprContext, name string, args map[string]any) (result an result = v case string: result = len(v) > 0 - case *kern.ListType: + case *array.ListType: result = len(*v) > 0 - case *kern.DictType: + case *dict.DictType: result = len(*v) > 0 default: err = kern.ErrCantConvert(name, v, "bool") @@ -102,7 +110,7 @@ func intFunc(ctx kern.ExprContext, name string, args map[string]any) (result any if i, err = strconv.Atoi(v); err == nil { result = int64(i) } - case *kern.FractionType: + case *fract.FractionType: result = int64(v.N() / v.D()) default: err = kern.ErrCantConvert(name, v, "int") @@ -127,7 +135,7 @@ func decFunc(ctx kern.ExprContext, name string, args map[string]any) (result any if f, err = strconv.ParseFloat(v, 64); err == nil { result = f } - case *kern.FractionType: + case *fract.FractionType: result = v.ToFloat() default: err = kern.ErrCantConvert(name, v, "float") @@ -149,7 +157,7 @@ func stringFunc(ctx kern.ExprContext, name string, args map[string]any) (result } case string: result = v - case *kern.FractionType: + case *fract.FractionType: result = v.ToString(0) case kern.Formatter: result = v.ToString(0) @@ -174,19 +182,19 @@ func fractFunc(ctx kern.ExprContext, name string, args map[string]any) (result a } if err == nil { - result = kern.NewFraction(v, den) + result = fract.NewFraction(v, den) } case float64: - result, err = kern.Float64ToFraction(v) + result, err = fract.Float64ToFraction(v) case bool: if v { - result = kern.NewFraction(1, 1) + result = fract.NewFraction(1, 1) } else { - result = kern.NewFraction(0, 1) + result = fract.NewFraction(0, 1) } case string: - result, err = kern.MakeGeneratingFraction(v) - case *kern.FractionType: + result, err = fract.MakeGeneratingFraction(v) + case *fract.FractionType: result = v default: err = kern.ErrCantConvert(name, v, "float") @@ -276,7 +284,7 @@ func charFunc(ctx kern.ExprContext, name string, args map[string]any) (result an } func seqFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { - list := kern.NewLinkedList() + list := list.NewLinkedList() items := args[kern.ParamValue].([]any) for _, arg := range items { list.PushBack(arg) diff --git a/builtin-iterator.go b/builtin-iterator.go index 04e7e15..d156525 100644 --- a/builtin-iterator.go +++ b/builtin-iterator.go @@ -9,6 +9,8 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/boolean" + "git.portale-stac.it/go-pkg/expr/types/dict" ) const ( @@ -32,8 +34,8 @@ func parseRunArgs(localCtx kern.ExprContext, args map[string]any) (it kern.Itera } } - var vars *kern.DictType - if vars, ok = args[iterParamVars].(*kern.DictType); !ok && args[iterParamVars] != nil { + var vars *dict.DictType + if vars, ok = args[iterParamVars].(*dict.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 } @@ -73,7 +75,7 @@ func runFunc(ctx kern.ExprContext, name string, args map[string]any) (result any break } else { var success bool - if success, ok = kern.ToBool(v); !success || !ok { + if success, ok = boolean.ToBool(v); !success || !ok { break } } diff --git a/builtin-math-arith.go b/builtin-math-arith.go index e56a217..519a148 100644 --- a/builtin-math-arith.go +++ b/builtin-math-arith.go @@ -9,10 +9,14 @@ import ( "io" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/fract" ) func checkNumberParamExpected(funcName string, paramValue any, paramPos, level, subPos int) (err error) { - if !(kern.IsNumber(paramValue) || kern.IsFraction(paramValue)) /*|| isList(paramValue)*/ { + if !(types.IsNumber(paramValue) || fract.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) } @@ -23,13 +27,13 @@ func doAdd(ctx kern.ExprContext, name string, it kern.Iterator, count, level int var sumAsFloat, sumAsFract bool var floatSum float64 = 0.0 var intSum int64 = 0 - var fractSum *kern.FractionType + var fractSum *fract.FractionType var v any level++ for v, err = it.Next(); err == nil; v, err = it.Next() { - if list, ok := v.(*kern.ListType); ok { + if list, ok := v.(*array.ListType); ok { v = NewListIterator(list, nil) } if subIter, ok := v.(kern.Iterator); ok { @@ -47,29 +51,29 @@ func doAdd(ctx kern.ExprContext, name string, it kern.Iterator, count, level int count++ if !sumAsFloat { - if kern.IsFloat(v) { + if float.IsFloat(v) { sumAsFloat = true if sumAsFract { floatSum = fractSum.ToFloat() } else { floatSum = float64(intSum) } - } else if !sumAsFract && kern.IsFraction(v) { - fractSum = kern.NewFraction(intSum, 1) + } else if !sumAsFract && fract.IsFraction(v) { + fractSum = fract.NewFraction(intSum, 1) sumAsFract = true } } if sumAsFloat { - floatSum += kern.NumAsFloat(v) + floatSum += types.NumAsFloat(v) } else if sumAsFract { - var item *kern.FractionType + var item *fract.FractionType var ok bool - if item, ok = v.(*kern.FractionType); !ok { + if item, ok = v.(*fract.FractionType); !ok { iv, _ := v.(int64) - item = kern.NewFraction(iv, 1) + item = fract.NewFraction(iv, 1) } - fractSum = kern.SumFract(fractSum, item) + fractSum = fract.SumFract(fractSum, item) } else { iv, _ := v.(int64) intSum += iv @@ -98,12 +102,12 @@ func doMul(ctx kern.ExprContext, name string, it kern.Iterator, count, level int var mulAsFloat, mulAsFract bool var floatProd float64 = 1.0 var intProd int64 = 1 - var fractProd *kern.FractionType + var fractProd *fract.FractionType var v any level++ for v, err = it.Next(); err == nil; v, err = it.Next() { - if list, ok := v.(*kern.ListType); ok { + if list, ok := v.(*array.ListType); ok { v = NewListIterator(list, nil) } if subIter, ok := v.(kern.Iterator); ok { @@ -123,29 +127,29 @@ func doMul(ctx kern.ExprContext, name string, it kern.Iterator, count, level int count++ if !mulAsFloat { - if kern.IsFloat(v) { + if float.IsFloat(v) { mulAsFloat = true if mulAsFract { floatProd = fractProd.ToFloat() } else { floatProd = float64(intProd) } - } else if !mulAsFract && kern.IsFraction(v) { - fractProd = kern.NewFraction(intProd, 1) + } else if !mulAsFract && fract.IsFraction(v) { + fractProd = fract.NewFraction(intProd, 1) mulAsFract = true } } if mulAsFloat { - floatProd *= kern.NumAsFloat(v) + floatProd *= types.NumAsFloat(v) } else if mulAsFract { - var item *kern.FractionType + var item *fract.FractionType var ok bool - if item, ok = v.(*kern.FractionType); !ok { + if item, ok = v.(*fract.FractionType); !ok { iv, _ := v.(int64) - item = kern.NewFraction(iv, 1) + item = fract.NewFraction(iv, 1) } - fractProd = kern.MulFract(fractProd, item) + fractProd = fract.MulFract(fractProd, item) } else { iv, _ := v.(int64) intProd *= iv diff --git a/builtin-string.go b/builtin-string.go index 1f2c8ad..e51bb50 100644 --- a/builtin-string.go +++ b/builtin-string.go @@ -10,6 +10,8 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" ) const ( @@ -43,8 +45,8 @@ func joinStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result if v, exists := args[kern.ParamItem]; exists { argv := v.([]any) if len(argv) == 1 { - if ls, ok := argv[0].(*kern.ListType); ok { - result, err = doJoinStr(name, sep, NewListIterator(ls, nil)) + if a, ok := argv[0].(*array.ListType); ok { + result, err = doJoinStr(name, sep, NewListIterator(a, nil)) } else if it, ok := argv[0].(kern.Iterator); ok { result, err = doJoinStr(name, sep, it) } else if s, ok := argv[0].(string); ok { @@ -72,11 +74,11 @@ func subStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result return nil, kern.ErrWrongParamType(name, kern.ParamSource, kern.TypeString, args[kern.ParamSource]) } - if start, err = kern.ToGoInt(args[kern.ParamStart], name+"()"); err != nil { + if start, err = types.ToGoInt(args[kern.ParamStart], name+"()"); err != nil { return } - if count, err = kern.ToGoInt(args[kern.ParamCount], name+"()"); err != nil { + if count, err = types.ToGoInt(args[kern.ParamCount], name+"()"); err != nil { return } @@ -194,11 +196,11 @@ func splitStrFunc(ctx kern.ExprContext, name string, args map[string]any) (resul } else { parts = []string{} } - list := make(kern.ListType, len(parts)) + a := make(array.ListType, len(parts)) for i, part := range parts { - list[i] = part + a[i] = part } - result = &list + result = &a return } diff --git a/cmd/ecli/graph.go b/cmd/ecli/graph.go index 4e641b0..9ea8a78 100644 --- a/cmd/ecli/graph.go +++ b/cmd/ecli/graph.go @@ -3,6 +3,9 @@ //go:build graph +// NOTE: Enable this build tag to print the graph of the expression instead of evaluating it. +// go run -tags graph cmd/ecli/main.go + // graph.go package main diff --git a/cmd/ecli/main.go b/cmd/ecli/main.go index 7425792..e76a630 100644 --- a/cmd/ecli/main.go +++ b/cmd/ecli/main.go @@ -14,6 +14,9 @@ import ( "git.portale-stac.it/go-pkg/expr" "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/str" "git.portale-stac.it/go-pkg/utils" // https://pkg.go.dev/github.com/ergochat/readline#section-readme @@ -225,10 +228,10 @@ func compute(opt *Options, ctx kern.ExprContext, r io.Reader, outputEnabled bool func printResult(opt *Options, result any) { if f, ok := result.(kern.Formatter); ok { fmt.Println(f.ToString(opt.formOpt)) - } else if kern.IsInteger(result) { + } else if types.IsInteger(result) { fmt.Printf(opt.baseVerb, result) fmt.Println() - } else if kern.IsString(result) { + } else if str.IsString(result) { fmt.Printf("\"%s\"\n", result) } else { fmt.Println(result) @@ -257,7 +260,7 @@ func registerLocalFunctions(ctx kern.ExprContext) { vars := ctx.EnumVars(func(name string) bool { return len(name) > 0 && name[0] == '_' }) - result = kern.ListFromStrings(vars) + result = array.ListFromStrings(vars) return } @@ -309,7 +312,7 @@ func registerLocalFunctions(ctx kern.ExprContext) { name, _, _ := strings.Cut(e, "=") vars = append(vars, name) } - result = kern.ListFromStrings(vars) + result = array.ListFromStrings(vars) return } diff --git a/dict-iterator.go b/dict-iterator.go index 47585b9..ab131fe 100644 --- a/dict-iterator.go +++ b/dict-iterator.go @@ -11,6 +11,9 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/str" ) type dictIterMode int @@ -22,7 +25,7 @@ const ( ) type DictIterator struct { - a *kern.DictType + a *dict.DictType count int64 index int64 keys []any @@ -67,7 +70,7 @@ func (it *DictIterator) makeKeys(m map[any]any, sort sortType) { } } -func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err error) { +func NewDictIterator(dict *dict.DictType, args []any) (it *DictIterator, err error) { var sortType = sortTypeNone var s string var argAny any @@ -78,7 +81,7 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err } else { argAny = "default" } - if s, err = kern.ToGoString(argAny, "sort type"); err == nil { + if s, err = str.ToGoString(argAny, "sort type"); err == nil { switch strings.ToLower(s) { case "a", "asc": sortType = sortTypeAsc @@ -99,7 +102,7 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err argAny = "default" } - if s, err = kern.ToGoString(argAny, "iteration mode"); err == nil { + if s, err = str.ToGoString(argAny, "iteration mode"); err == nil { switch strings.ToLower(s) { case "k", "key", "keys": dictIt.iterMode = dictIterModeKeys @@ -124,7 +127,7 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err } func NewMapIterator(m map[any]any) (it *DictIterator) { - it = &DictIterator{a: (*kern.DictType)(&m), count: 0, index: -1, keys: nil} + it = &DictIterator{a: (*dict.DictType)(&m), count: 0, index: -1, keys: nil} it.makeKeys(m, sortTypeNone) return } @@ -190,7 +193,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 = kern.NewList(pair) + item = array.NewList(pair) } } else { err = io.EOF diff --git a/global-context.go b/global-context.go index c1a721c..9f9b7df 100644 --- a/global-context.go +++ b/global-context.go @@ -9,6 +9,7 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/boolean" ) //var globalCtx *SimpleStore @@ -68,7 +69,7 @@ func GlobalCtrlGet(ctx kern.ExprContext, name string) (currentValue any) { func CtrlEnable(ctx kern.ExprContext, name string) (currentStatus bool) { name = fixCtrlVar(name) - if v, exists := ctx.GetVar(name); exists && kern.IsBool(v) { + if v, exists := ctx.GetVar(name); exists && boolean.IsBool(v) { currentStatus, _ = v.(bool) } @@ -78,7 +79,7 @@ func CtrlEnable(ctx kern.ExprContext, name string) (currentStatus bool) { func CtrlDisable(ctx kern.ExprContext, name string) (currentStatus bool) { name = fixCtrlVar(name) - if v, exists := ctx.GetVar(name); exists && kern.IsBool(v) { + if v, exists := ctx.GetVar(name); exists && boolean.IsBool(v) { currentStatus, _ = v.(bool) } diff --git a/helpers.go b/helpers.go index bf1f8e7..1187e57 100644 --- a/helpers.go +++ b/helpers.go @@ -12,6 +12,8 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/float" "git.portale-stac.it/go-pkg/expr/util" ) @@ -50,9 +52,9 @@ func EvalStringV(source string, args []Arg) (result any, err error) { } else { err = fmt.Errorf("invalid function specification: %q", arg.Name) } - } else if integer, ok := kern.AnyInteger(arg.Value); ok { + } else if integer, ok := types.AnyInteger(arg.Value); ok { ctx.SetVar(arg.Name, integer) - } else if float, ok := kern.AnyFloat(arg.Value); ok { + } else if float, ok := float.AnyFloat(arg.Value); ok { ctx.SetVar(arg.Name, float) } else if _, ok := arg.Value.(string); ok { ctx.SetVar(arg.Name, arg.Value) diff --git a/import-utils.go b/import-utils.go index 18c54e1..64806a7 100644 --- a/import-utils.go +++ b/import-utils.go @@ -13,6 +13,7 @@ import ( "strings" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/str" "git.portale-stac.it/go-pkg/expr/util" ) @@ -22,7 +23,7 @@ const ( ) func checkStringParamExpected(funcName string, paramValue any, paramPos int) (err error) { - if !(kern.IsString(paramValue) /*|| isList(paramValue)*/) { + if !(str.IsString(paramValue) /*|| isList(paramValue)*/) { err = fmt.Errorf("%s(): param nr %d has wrong type %s, string expected", funcName, paramPos+1, kern.TypeName(paramValue)) } return diff --git a/int-iterator.go b/int-iterator.go index cf44067..6c7910b 100644 --- a/int-iterator.go +++ b/int-iterator.go @@ -10,6 +10,7 @@ import ( "slices" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" ) type IntIterator struct { @@ -31,16 +32,16 @@ func NewIntIterator(args []any) (it *IntIterator, err error) { } 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 { + if it.stop, err = types.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 { + if it.stop, err = types.ToGoInt64(args[1], "stop index"); err != nil { return } if argc >= 3 { - if it.step, err = kern.ToGoInt64(args[2], "step"); err != nil { + if it.step, err = types.ToGoInt64(args[2], "step"); err != nil { return } } else if it.start > it.stop { diff --git a/iter-factory.go b/iter-factory.go index 0b47d18..a3323b4 100644 --- a/iter-factory.go +++ b/iter-factory.go @@ -9,6 +9,9 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" ) func NewFormalIterator(value any) (it kern.Iterator) { @@ -26,11 +29,11 @@ func NewIterator(ctx kern.ExprContext, value any, ops []*scan.Term) (it kern.Ite } switch v := value.(type) { - case *kern.ListType: + case *array.ListType: it = NewListIterator(v, nil) - case *kern.LinkedList: + case *list.LinkedList: it = NewLinkedListIterator(v, nil) - case *kern.DictType: + case *dict.DictType: it, err = NewDictIterator(v, nil) case []any: it = NewArrayIterator(v) diff --git a/kern/clone-value.go b/kern/clone-value.go deleted file mode 100644 index 5155ef9..0000000 --- a/kern/clone-value.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). -// All rights reserved. - -// clone-value.go -package kern - -func Clone(v any) (c any) { - if v == nil { - return - } - switch unboxed := v.(type) { - case int64: - c = unboxed - case float64: - c = unboxed - case string: - c = unboxed - case bool: - c = unboxed - case *ListType: - c = unboxed.Clone() - case *DictType: - c = unboxed.Clone() - case *LinkedList: - c = unboxed.Clone() - default: - c = v - } - return -} diff --git a/kern/cloner.go b/kern/cloner.go new file mode 100644 index 0000000..a86f34c --- /dev/null +++ b/kern/cloner.go @@ -0,0 +1,23 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// cloner.go +package kern + +type Cloner interface { + Clone() any +} + +func IsCloner(v any) (ok bool) { + _, ok = v.(Cloner) + return +} + +func Clone(a any) (clone any) { + if IsCloner(a) { + clone = a.(Cloner).Clone() + } else { + clone = a + } + return +} diff --git a/kern/common-type-names.go b/kern/common-type-names.go index 0e05256..531eb43 100644 --- a/kern/common-type-names.go +++ b/kern/common-type-names.go @@ -6,6 +6,7 @@ package kern const ( TypeAny = "any" + TypeArray = "array" TypeNil = "nil" TypeBoolean = "boolean" TypeFloat = "float" diff --git a/kern/compare.go b/kern/compare.go deleted file mode 100644 index f0ccb3f..0000000 --- a/kern/compare.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). -// All rights reserved. - -package kern - -import "reflect" - -func Equal(value1, value2 any) (equal bool) { - if value1 == nil && value2 == nil { - equal = true - } else if value1 == nil || value2 == nil { - equal = false - } else if IsBool(value1) && IsBool(value2) { - equal = value1.(bool) == value2.(bool) - } else if IsList(value1) && IsList(value2) { - ls1 := value1.(*ListType) - ls2 := value2.(*ListType) - equal = ls1.Equals(*ls2) - } else if IsDict(value1) && IsDict(value2) { - d1 := value1.(*DictType) - d2 := value2.(*DictType) - equal = d1.Equals(*d2) - } else if IsLinkedList(value1) && IsLinkedList(value2) { - ll1 := value1.(*LinkedList) - ll2 := value2.(*LinkedList) - equal = ll1.Equals(ll2) - } else if IsInteger(value1) && IsInteger(value2) { - equal = value1.(int64) == value2.(int64) - } else if IsString(value1) && IsString(value2) { - equal = value1.(string) == value2.(string) - } else if IsFloat(value1) && IsFloat(value2) { - equal = value1.(float64) == value2.(float64) - } else if IsNumOrFract(value1) && IsNumOrFract(value2) { - if eq, err := CmpAnyFract(value1, value2); err == nil { - equal = eq == 0 - } - } else if !reflect.DeepEqual(value1, value2) { - equal = false - } - return -} diff --git a/kern/consts.go b/kern/consts.go new file mode 100644 index 0000000..6d3095e --- /dev/null +++ b/kern/consts.go @@ -0,0 +1,7 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// consts.go +package kern + +const MaxUint64Allowed = uint64(9_223_372_036_854_775_807) diff --git a/kern/equaler.go b/kern/equaler.go new file mode 100644 index 0000000..a2e6683 --- /dev/null +++ b/kern/equaler.go @@ -0,0 +1,23 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// equaler.go +package kern + +type Equaler interface { + EqualTo(other Equaler) bool +} + +func IsEqualer(v any) (ok bool) { + _, ok = v.(Equaler) + return +} + +func Equal(a, b any) (equal bool) { + if IsEqualer(a) && IsEqualer(b) { + equal = a.(Equaler).EqualTo(b.(Equaler)) + } else { + equal = a == b + } + return +} diff --git a/kern/expr-context.go b/kern/expr-context.go index 88e8f21..0aaad72 100644 --- a/kern/expr-context.go +++ b/kern/expr-context.go @@ -29,35 +29,6 @@ type ExprContext interface { RegisterFuncInfo(info ExprFunc) RegisterFunc(name string, f Functor, returnType string, param []ExprFuncParam) (funcInfo ExprFunc, err error) - ToDict() (dict *DictType) + ToDict() (dict any) // must be a *DictType ToString(opt FmtOpt) string } - -func ContextToDict(ctx ExprContext) (dict *DictType) { - var keys []string - // Variables - keys = ctx.EnumVars(nil) - vars := MakeDict() - for _, key := range keys { - value, _ := ctx.GetVar(key) - vars.SetItem(key, value) - } - - // Functions - keys = ctx.EnumFuncs(func(name string) bool { return true }) - funcs := MakeDict() - for _, key := range keys { - funcInfo, _ := ctx.GetFuncInfo(key) - funcs.SetItem(key, funcInfo) - } - - dict = MakeDict() - dict.SetItem("vars", vars) - dict.SetItem("funcs", funcs) - return -} - -func ContextToString(ctx ExprContext, opt FmtOpt) string { - dict := ctx.ToDict() - return dict.ToString(opt) -} diff --git a/kern/formatter.go b/kern/formatter.go index dfbb188..2e2346f 100644 --- a/kern/formatter.go +++ b/kern/formatter.go @@ -21,6 +21,10 @@ const ( Base16 ) +type Formatter interface { + ToString(options FmtOpt) string +} + const ( TruncateEllipsis = "(...)" MinTruncateSize = 10 @@ -45,10 +49,6 @@ func GetFormatIndent(opt FmtOpt) int { return int(opt >> 16) } -type Formatter interface { - ToString(options FmtOpt) string -} - func Format(sb *strings.Builder, item any, opt FmtOpt) { if s, ok := item.(string); ok { sb.WriteByte('"') @@ -73,22 +73,3 @@ func GetFormatted(v any, opt FmtOpt) (text string) { } return } - -type Typer interface { - TypeName() string -} - -func TypeName(v any) (name string) { - if v == nil { - name = "nil" - } else if typer, ok := v.(Typer); ok { - name = typer.TypeName() - } else if IsInteger(v) { - name = "integer" - } else if IsFloat(v) { - name = "float" - } else { - name = fmt.Sprintf("%T", v) - } - return -} diff --git a/kern/typer.go b/kern/typer.go new file mode 100644 index 0000000..245bb4d --- /dev/null +++ b/kern/typer.go @@ -0,0 +1,26 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// typer.go +package kern + +import "fmt" + +type Typer interface { + TypeName() string +} + +func TypeName(v any) (name string) { + if v == nil { + name = "nil" + } else if typer, ok := v.(Typer); ok { + name = typer.TypeName() + } else if _, ok := v.(int64); ok { + name = "integer" + } else if _, ok := v.(float64); ok { + name = "float" + } else { + name = fmt.Sprintf("%T", v) + } + return +} diff --git a/kern/util.go b/kern/util.go new file mode 100644 index 0000000..1576843 --- /dev/null +++ b/kern/util.go @@ -0,0 +1,37 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// util.go +package kern + +func FixAnyNumber(v any) (fixed any) { + switch unboxed := v.(type) { + case int: + fixed = int64(unboxed) + case int8: + fixed = int64(unboxed) + case int16: + fixed = int64(unboxed) + case int32: + fixed = int64(unboxed) + case uint: + fixed = int64(unboxed) + case uint8: + fixed = int64(unboxed) + case uint16: + fixed = int64(unboxed) + case uint32: + fixed = int64(unboxed) + case uint64: + if unboxed <= MaxUint64Allowed { + fixed = int64(unboxed) + } else { + fixed = float64(unboxed) + } + case float32: + fixed = float64(unboxed) + default: + fixed = v + } + return +} diff --git a/linked-list-iterator.go b/linked-list-iterator.go index b8df669..6ebdd58 100644 --- a/linked-list-iterator.go +++ b/linked-list-iterator.go @@ -10,16 +10,17 @@ import ( "slices" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/list" ) type LinkedListIterator struct { - a *kern.LinkedList + a *list.LinkedList count int64 index int64 - current *kern.ListNode + current *list.ListNode } -func NewLinkedListIterator(list *kern.LinkedList, args []any) (it *LinkedListIterator) { +func NewLinkedListIterator(list *list.LinkedList, args []any) (it *LinkedListIterator) { it = &LinkedListIterator{a: list, count: 0, index: -1, current: list.FirstNode()} return } diff --git a/operand-dict.go b/operand-dict.go index 103d91a..e6f351a 100644 --- a/operand-dict.go +++ b/operand-dict.go @@ -7,6 +7,9 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/str" ) // -------- dict term @@ -23,16 +26,16 @@ func newDictTerm(args map[any]*scan.Term) *scan.Term { // -------- dict func func evalDict(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { - dict, _ := opTerm.Value().(map[any]*scan.Term) - items := make(kern.DictType, len(dict)) - for key, tree := range dict { + dt, _ := opTerm.Value().(map[any]*scan.Term) + items := make(dict.DictType, len(dt)) + for key, tree := range dt { var param any if param, err = tree.Compute(ctx); err != nil { break } var keyValue any if keyValue, err = (key.(*scan.Term)).Compute(ctx); err == nil { - if kern.IsInteger(keyValue) || kern.IsString(keyValue) { + if types.IsInteger(keyValue) || str.IsString(keyValue) { items[keyValue] = param } else { err = key.(*scan.Term).Errorf("dict key can be integer or string, got %s", kern.TypeName(keyValue)) diff --git a/operand-iterator.go b/operand-iterator.go index 4da7abc..e03c07f 100644 --- a/operand-iterator.go +++ b/operand-iterator.go @@ -10,6 +10,9 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" ) // -------- iterator term @@ -52,7 +55,7 @@ func evalFirstChild(ctx kern.ExprContext, iteratorTerm *scan.Term) (value any, e } func getDataSourceDict(iteratorTerm *scan.Term, firstChildValue any) (ds map[string]kern.Functor, err error) { - if dictAny, ok := firstChildValue.(*kern.DictType); ok { + if dictAny, ok := firstChildValue.(*dict.DictType); ok { requiredFields := []string{kern.NextName} fieldsMask := 0b1 foundFields := 0 @@ -123,7 +126,7 @@ func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { v = dc } else { - if dictIt, ok := firstChildValue.(*kern.DictType); ok { + if dictIt, ok := firstChildValue.(*dict.DictType); ok { var args []any if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil { v, err = NewDictIterator(dictIt, args) @@ -132,15 +135,15 @@ func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { err = opTerm.Children[0].Errorf("the data-source must be a dictionary") } } - } else if list, ok := firstChildValue.(*kern.ListType); ok { + } else if a, ok := firstChildValue.(*array.ListType); ok { var args []any if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil { - v = NewListIterator(list, args) + v = NewListIterator(a, args) } - } else if list, ok := firstChildValue.(*kern.LinkedList); ok { + } else if ll, ok := firstChildValue.(*list.LinkedList); ok { var args []any if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil { - v = NewLinkedListIterator(list, args) + v = NewLinkedListIterator(ll, args) } } else if intVal, ok := firstChildValue.(int64); ok { var args []any diff --git a/operand-linked-list.go b/operand-linked-list.go index cd5ef3f..93896f1 100644 --- a/operand-linked-list.go +++ b/operand-linked-list.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/list" ) // -------- list term @@ -27,9 +28,9 @@ func newLinkedListTerm(row, col int, args []*scan.Term) *scan.Term { // -------- list func func evalLinkedList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { - list, _ := opTerm.Value().([]*scan.Term) - items := kern.NewLinkedList() - for _, tree := range list { + listTerm, _ := opTerm.Value().([]*scan.Term) + items := list.NewLinkedList() + for _, tree := range listTerm { var param any if param, err = tree.Compute(ctx); err != nil { break diff --git a/operand-list.go b/operand-list.go index 974011d..5a24ac8 100644 --- a/operand-list.go +++ b/operand-list.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" ) // -------- list term @@ -28,7 +29,7 @@ func newListTerm(row, col int, args []*scan.Term) *scan.Term { // -------- list func func evalList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { list, _ := opTerm.Value().([]*scan.Term) - items := make(kern.ListType, len(list)) + items := make(array.ListType, len(list)) for i, tree := range list { var param any if param, err = tree.Compute(ctx); err != nil { diff --git a/operand-literal.go b/operand-literal.go index ecf22b7..46ff937 100644 --- a/operand-literal.go +++ b/operand-literal.go @@ -7,10 +7,21 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/fract" ) // -------- literal term func newLiteralTerm(tk *scan.Token) *scan.Term { + + if tk.Sym == scan.SymFraction { + if v, isString := tk.Value.(string); isString { + var err error + if tk.Value, err = fract.MakeGeneratingFraction(v); err != nil { + return nil + } + } + } + return &scan.Term{ Tk: *tk, Parent: nil, diff --git a/operator-assign.go b/operator-assign.go index e7f306a..24eace3 100644 --- a/operator-assign.go +++ b/operator-assign.go @@ -7,6 +7,8 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" "git.portale-stac.it/go-pkg/expr/util" ) @@ -44,7 +46,7 @@ func evalDeepCopyAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err err func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term, value any) (err error) { var collectionValue, keyListValue, keyValue any - var keyList *kern.ListType + var keyList *array.ListType var ok bool if collectionValue, err = collectionTerm.Compute(ctx); err != nil { @@ -53,7 +55,7 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca if keyListValue, err = keyListTerm.Compute(ctx); err != nil { return - } else if keyList, ok = keyListValue.(*kern.ListType); !ok || len(*keyList) != 1 { + } else if keyList, ok = keyListValue.(*array.ListType); !ok || len(*keyList) != 1 { err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, kern.TypeName(keyListValue)) return } @@ -63,13 +65,13 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca } switch collection := collectionValue.(type) { - case *kern.ListType: + case *array.ListType: if index, ok := keyValue.(int64); ok { err = collection.SetItem(index, value) } else { err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue)) } - case *kern.DictType: + case *dict.DictType: collection.SetItem(keyValue, value) default: err = collectionTerm.Errorf("collection expected") @@ -92,7 +94,7 @@ func assignValue(ctx kern.ExprContext, leftTerm *scan.Term, v any, deepCopy bool func evalAssignDictItem(ctx kern.ExprContext, dotTerm *scan.Term, valueTerm kern.Term) (v any, err error) { var ok bool var dictAny, dotKey any - var dict *kern.DictType + var dt *dict.DictType if err = dotTerm.CheckOperands(); err != nil { return @@ -102,8 +104,8 @@ func evalAssignDictItem(ctx kern.ExprContext, dotTerm *scan.Term, valueTerm kern if dictAny, err = dotLeftTerm.Compute(ctx); err != nil { return } - if dict, ok = dictAny.(*kern.DictType); !ok { - err = dotTerm.Tk.ErrorExpectedGot(kern.DictTypeName) + if dt, ok = dictAny.(*dict.DictType); !ok { + err = dotTerm.Tk.ErrorExpectedGot(dict.DictTypeName) return } @@ -119,7 +121,7 @@ func evalAssignDictItem(ctx kern.ExprContext, dotTerm *scan.Term, valueTerm kern return } - dict.SetItem(dotKey, v) + dt.SetItem(dotKey, v) return } @@ -178,7 +180,7 @@ func newOpAssignTerm(tk *scan.Token) (inst *scan.Term) { func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term) (value any, err error) { var collectionValue, keyListValue, keyValue any - var keyList *kern.ListType + var keyList *array.ListType var ok bool if collectionValue, err = collectionTerm.Compute(ctx); err != nil { @@ -187,7 +189,7 @@ func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *s if keyListValue, err = keyListTerm.Compute(ctx); err != nil { return - } else if keyList, ok = keyListValue.(*kern.ListType); !ok || len(*keyList) != 1 { + } else if keyList, ok = keyListValue.(*array.ListType); !ok || len(*keyList) != 1 { err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, kern.TypeName(keyListValue)) return } @@ -197,13 +199,13 @@ func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *s } switch collection := collectionValue.(type) { - case *kern.ListType: + case *array.ListType: if index, ok := keyValue.(int64); ok { value = (*collection)[index] } else { err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue)) } - case *kern.DictType: + case *dict.DictType: value = (*collection)[keyValue] default: err = collectionTerm.Errorf("collection expected") diff --git a/operator-bitwise.go b/operator-bitwise.go index 929afac..702664d 100644 --- a/operator-bitwise.go +++ b/operator-bitwise.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" ) //-------- Bitwise NOT term @@ -28,7 +29,7 @@ func evalBitwiseNot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) return } - if kern.IsInteger(value) { + if types.IsInteger(value) { i, _ := value.(int64) v = ^i } else { diff --git a/operator-bool.go b/operator-bool.go index 5f733ec..d74597f 100644 --- a/operator-bool.go +++ b/operator-bool.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/boolean" ) //-------- NOT term @@ -30,7 +31,7 @@ func evalNot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if b, ok := kern.ToBool(rightValue); ok { + if b, ok := boolean.ToBool(rightValue); ok { v = !b } else { err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue) @@ -68,8 +69,8 @@ func evalAndWithoutShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err e return } - leftBool, lok = kern.ToBool(leftValue) - rightBool, rok = kern.ToBool(rightValue) + leftBool, lok = boolean.ToBool(leftValue) + rightBool, rok = boolean.ToBool(rightValue) if lok && rok { v = leftBool && rightBool @@ -90,14 +91,14 @@ func evalAndWithShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err erro return } - if leftBool, lok := kern.ToBool(leftValue); !lok { + if leftBool, lok := boolean.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 := kern.ToBool(rightValue); rok { + if rightBool, rok := boolean.ToBool(rightValue); rok { v = rightBool } else { err = self.ErrIncompatibleTypes(leftValue, rightValue) @@ -136,8 +137,8 @@ func evalOrWithoutShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err er return } - leftBool, lok = kern.ToBool(leftValue) - rightBool, rok = kern.ToBool(rightValue) + leftBool, lok = boolean.ToBool(leftValue) + rightBool, rok = boolean.ToBool(rightValue) if lok && rok { v = leftBool || rightBool @@ -158,13 +159,13 @@ func evalOrWithShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err error return } - if leftBool, lok := kern.ToBool(leftValue); !lok { + if leftBool, lok := boolean.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 := kern.ToBool(rightValue); rok { + if rightBool, rok := boolean.ToBool(rightValue); rok { v = rightBool } else { err = self.ErrIncompatibleTypes(leftValue, rightValue) diff --git a/operator-builtin.go b/operator-builtin.go index ad62447..9f55b54 100644 --- a/operator-builtin.go +++ b/operator-builtin.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- builtin term @@ -31,7 +32,7 @@ func evalBuiltin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } count := 0 - if kern.IsString(childValue) { + if str.IsString(childValue) { module, _ := childValue.(string) count, err = ImportInContextByGlobPattern(ctx, module) } else { diff --git a/operator-context.go b/operator-context.go index 14037b7..21f2a6b 100644 --- a/operator-context.go +++ b/operator-context.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/list" ) //-------- context term @@ -48,7 +49,7 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error } if err == nil { var item any - values := kern.NewLinkedListA() + values := list.NewLinkedListA() for item, err = it.Next(); err == nil; item, err = it.Next() { values.PushBack(item) } diff --git a/operator-dot.go b/operator-dot.go index 353567e..5f5795f 100644 --- a/operator-dot.go +++ b/operator-dot.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/dict" "git.portale-stac.it/go-pkg/expr/util" ) @@ -46,22 +47,7 @@ func evalDot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } else { err = indexTerm.Tk.ErrorExpectedGot("identifier") } - case *kern.DictType: - // var ok bool - // s := opTerm.Children[1].Symbol() - // if s == scan.SymVariable || s == scan.SymString { - // src := opTerm.Children[1].Source() - // if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' { - // src = src[1 : len(src)-1] - // } - // if v, ok = unboxedValue.GetItem(src); !ok { - // err = opTerm.Errorf("key %q not found", src) - // } - // } else if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { - // if v, ok = unboxedValue.GetItem(rightValue); !ok { - // err = opTerm.Errorf("key %q not found", rightValue) - // } - // } + case *dict.DictType: v, err = dotGetDictItemValue(ctx, unboxedValue, opTerm.Children[1]) default: if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { @@ -71,7 +57,7 @@ func evalDot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } -func dotGetDictItemValue(ctx kern.ExprContext, d *kern.DictType, rightTerm *scan.Term) (v any, err error) { +func dotGetDictItemValue(ctx kern.ExprContext, d *dict.DictType, rightTerm *scan.Term) (v any, err error) { var ok bool var rightValue any s := rightTerm.Symbol() diff --git a/operator-fact.go b/operator-fact.go index 7375b31..3c1c28f 100644 --- a/operator-fact.go +++ b/operator-fact.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" ) //-------- fact term @@ -30,7 +31,7 @@ func evalFact(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsInteger(leftValue) { + if types.IsInteger(leftValue) { if i, _ := leftValue.(int64); i >= 0 { f := int64(1) for k := int64(1); k <= i; k++ { diff --git a/operator-filter.go b/operator-filter.go index f8ee9a7..930f2f2 100644 --- a/operator-filter.go +++ b/operator-filter.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/boolean" ) //-------- map term @@ -117,7 +118,7 @@ func (it *filterIterator) Next() (item any, err error) { ctx.DeleteVar("_") if err == nil { - if success, valid := kern.ToBool(result); valid { + if success, valid := boolean.ToBool(result); valid { if success { item = attempt break diff --git a/operator-fraction.go b/operator-fraction.go index 5643a70..ab0b480 100644 --- a/operator-fraction.go +++ b/operator-fraction.go @@ -11,6 +11,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/fract" ) // -------- fraction term @@ -51,7 +52,7 @@ func evalFraction(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { num = -num } if num != 0 { - if g := kern.Gcd(num, den); g != 1 { + if g := fract.Gcd(num, den); g != 1 { num = num / g den = den / g } @@ -59,11 +60,11 @@ func evalFraction(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { v = num } else { // v = &expr.FractionType{num, den} - v = kern.NewFraction(num, den) + v = fract.NewFraction(num, den) } } else { // v = &FractionType{0, den} - v = kern.NewFraction(0, den) + v = fract.NewFraction(0, den) } return } diff --git a/operator-groupby.go b/operator-groupby.go index 9130e95..5ac8ef9 100644 --- a/operator-groupby.go +++ b/operator-groupby.go @@ -11,6 +11,9 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- group by term @@ -52,13 +55,13 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { keyByIndex = true } else if rightValue, err = opTerm.Children[1].Compute(ctx); err != nil { return - } else if kern.IsString(rightValue) { + } else if str.IsString(rightValue) { sKey = rightValue.(string) } else { return nil, fmt.Errorf("right operand of GROUPBY must be a string or identifier '__'; got %s", kern.TypeName(rightValue)) } - values := kern.MakeDict() + values := dict.MakeDict() for item, err = it.Next(); err == nil; item, err = it.Next() { ctx.SetVar("_", item) ctx.SetVar("__", it.Index()) @@ -66,7 +69,7 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var sItemKey string - if d, ok := item.(*kern.DictType); ok { + if d, ok := item.(*dict.DictType); ok { if keyByIndex || len(sKey) == 0 { sItemKey = strconv.Itoa(int(it.Index())) } else if d.HasKey(sKey) { @@ -86,12 +89,12 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { sItemKey = strconv.Itoa(int(it.Index())) } - var ls *kern.ListType + var ls *array.ListType if lsAny, exists := values.GetItem(sItemKey); exists && lsAny != nil { - ls = lsAny.(*kern.ListType) + ls = lsAny.(*array.ListType) } if ls == nil { - ls = kern.NewListA() + ls = array.NewListA() } ls.AppendItem(item) values.SetItem(sItemKey, ls) diff --git a/operator-in.go b/operator-in.go index 9c09925..942e0dc 100644 --- a/operator-in.go +++ b/operator-in.go @@ -7,6 +7,8 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" ) //-------- in term @@ -33,11 +35,11 @@ func evalIn(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsList(rightValue) { - list, _ := rightValue.(*kern.ListType) - v = list.IndexDeepSameCmp(leftValue) >= 0 - } else if kern.IsDict(rightValue) { - dict, _ := rightValue.(*kern.DictType) + if array.IsList(rightValue) { + a, _ := rightValue.(*array.ListType) + v = a.IndexDeepSameCmp(leftValue) >= 0 + } else if dict.IsDict(rightValue) { + dict, _ := rightValue.(*dict.DictType) v = dict.HasKey(leftValue) } else { err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) diff --git a/operator-include.go b/operator-include.go index eadbab0..9b03eb5 100644 --- a/operator-include.go +++ b/operator-include.go @@ -7,6 +7,8 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- include term @@ -29,9 +31,9 @@ func evalInclude(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } count := 0 - if kern.IsList(childValue) { - list, _ := childValue.(*kern.ListType) - for i, filePathSpec := range *list { + if array.IsList(childValue) { + a, _ := childValue.(*array.ListType) + for i, filePathSpec := range *a { if filePath, ok := filePathSpec.(string); ok { if v, err = EvalFile(ctx, filePath); err == nil { count++ @@ -44,7 +46,7 @@ func evalInclude(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { break } } - } else if kern.IsString(childValue) { + } else if str.IsString(childValue) { filePath, _ := childValue.(string) if v, err = EvalFile(ctx, filePath); err == nil { count++ diff --git a/operator-index.go b/operator-index.go index 4f8c473..ffbaa4f 100644 --- a/operator-index.go +++ b/operator-index.go @@ -7,6 +7,10 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" ) // -------- index term @@ -20,15 +24,15 @@ func newIndexTerm(tk *scan.Token) (inst *scan.Term) { } } -func verifyKey(indexList *kern.ListType) (index any, err error) { +func verifyKey(indexList *array.ListType) (index any, err error) { index = (*indexList)[0] return } -func verifyIndex(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) (index int, err error) { +func verifyIndex(indexTerm *scan.Term, indexList *array.ListType, maxValue int) (index int, err error) { var v int - if v, err = kern.ToGoInt((*indexList)[0], "index expression"); err == nil { + if v, err = types.ToGoInt((*indexList)[0], "index expression"); err == nil { if v < 0 && v >= -maxValue { v = maxValue + v } @@ -41,7 +45,7 @@ func verifyIndex(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) ( return } -func verifyRange(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) (startIndex, endIndex int, err error) { +func verifyRange(indexTerm *scan.Term, indexList *array.ListType, maxValue int) (startIndex, endIndex int, err error) { v, _ := ((*indexList)[0]).(*intPair) startIndex = v.a endIndex = v.b @@ -66,7 +70,7 @@ func verifyRange(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) ( func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { var leftValue, rightValue any - var indexList *kern.ListType + var indexList *array.ListType var ok bool if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { @@ -74,7 +78,7 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } indexTerm := opTerm.Children[1] - if indexList, ok = rightValue.(*kern.ListType); !ok { + if indexList, ok = rightValue.(*array.ListType); !ok { err = opTerm.Errorf("invalid index expression") return } else if len(*indexList) != 1 { @@ -82,14 +86,14 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsInteger((*indexList)[0]) { + if types.IsInteger((*indexList)[0]) { switch unboxedValue := leftValue.(type) { - case *kern.ListType: + case *array.ListType: var index int if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil { v = (*unboxedValue)[index] } - case *kern.LinkedList: + case *list.LinkedList: var index int if index, err = verifyIndex(indexTerm, indexList, unboxedValue.Len()); err == nil { v, err = unboxedValue.At(index) @@ -99,20 +103,20 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil { v = string(unboxedValue[index]) } - case *kern.DictType: + case *dict.DictType: v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue) default: err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } } else if isIntPair((*indexList)[0]) { switch unboxedValue := leftValue.(type) { - case *kern.ListType: + case *array.ListType: var start, end int if start, end, err = verifyRange(indexTerm, indexList, len(*unboxedValue)); err == nil { - sublist := kern.ListType((*unboxedValue)[start:end]) + sublist := array.ListType((*unboxedValue)[start:end]) v = &sublist } - case *kern.LinkedList: + case *list.LinkedList: var start, end int if start, end, err = verifyRange(indexTerm, indexList, unboxedValue.Len()); err == nil { v = unboxedValue.Sub(start, end) @@ -125,8 +129,8 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { default: err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } - } else if kern.IsDict(leftValue) { - d := leftValue.(*kern.DictType) + } else if dict.IsDict(leftValue) { + d := leftValue.(*dict.DictType) v, err = getDictItem(d, indexTerm, indexList, rightValue) } else { rightChild := opTerm.Children[1] @@ -135,7 +139,7 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } -func getDictItem(d *kern.DictType, indexTerm *scan.Term, indexList *kern.ListType, rightValue any) (v any, err error) { +func getDictItem(d *dict.DictType, indexTerm *scan.Term, indexList *array.ListType, rightValue any) (v any, err error) { var ok bool var indexValue any diff --git a/operator-insert.go b/operator-insert.go index 70459e8..a2ce70b 100644 --- a/operator-insert.go +++ b/operator-insert.go @@ -7,6 +7,8 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/list" ) //-------- prepend term @@ -32,33 +34,33 @@ func newAppendTerm(tk *scan.Token) (inst *scan.Term) { } func prependToList(opTerm *scan.Term, leftValue, rightValue any) (result any, err error) { - if list, ok := rightValue.(*kern.ListType); ok { + if a, ok := rightValue.(*array.ListType); ok { var it kern.Iterator if it, ok = leftValue.(kern.Iterator); !ok { it = NewFormalIterator(leftValue) } - ls := kern.NewLinkedList() + ls := list.NewLinkedList() ls.SeqPushBack(it) - newList := kern.ListType(nil) - if newSize := len(*list) + int(ls.Len()); newSize > cap(*list) { - newList = make([]any, 0, newSize) + newArray := array.ListType(nil) + if newSize := len(*a) + int(ls.Len()); newSize > cap(*a) { + newArray = make([]any, 0, newSize) for node := ls.FirstNode(); node != nil; node = node.Next() { - newList = append(newList, node.Data()) + newArray = append(newArray, node.Data()) } } - for _, item := range *list { - newList = append(newList, item) + for _, item := range *a { + newArray = append(newArray, item) } - result = &newList - } else if list, ok := rightValue.(*kern.LinkedList); ok { + result = &newArray + } else if ll, ok := rightValue.(*list.LinkedList); ok { var it kern.Iterator if it, ok = leftValue.(kern.Iterator); !ok { it = NewFormalIterator(leftValue) } - result = list.SeqPushBack(it) + result = ll.SeqPushBack(it) } else { err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } @@ -77,33 +79,33 @@ func evalPrepend(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } func appendToList(opTerm *scan.Term, leftValue, rightValue any) (result any, err error) { - if list, ok := leftValue.(*kern.ListType); ok { + if a, ok := leftValue.(*array.ListType); ok { var it kern.Iterator if it, ok = rightValue.(kern.Iterator); !ok { it = NewFormalIterator(rightValue) } - ls := kern.NewLinkedList() + ls := list.NewLinkedList() ls.SeqPushBack(it) - newList := *list - if newSize := len(*list) + int(ls.Len()); newSize > cap(*list) { - newList = make([]any, 0, newSize) - for _, item := range *list { - newList = append(newList, item) + newArray := *a + if newSize := len(*a) + int(ls.Len()); newSize > cap(*a) { + newArray = make([]any, 0, newSize) + for _, item := range *a { + newArray = append(newArray, item) } } for node := ls.FirstNode(); node != nil; node = node.Next() { - newList = append(newList, node.Data()) + newArray = append(newArray, node.Data()) } - result = &newList - } else if list, ok := leftValue.(*kern.LinkedList); ok { + result = &newArray + } else if ll, ok := leftValue.(*list.LinkedList); ok { var it kern.Iterator if it, ok = rightValue.(kern.Iterator); !ok { it = NewFormalIterator(rightValue) } - result = list.SeqPushBack(it) + result = ll.SeqPushBack(it) } else { err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) } diff --git a/operator-length.go b/operator-length.go index 914b0c6..556997d 100644 --- a/operator-length.go +++ b/operator-length.go @@ -7,6 +7,10 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- length term @@ -28,25 +32,19 @@ func evalLength(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsList(childValue) { - ls, _ := childValue.(*kern.ListType) + if array.IsList(childValue) { + ls, _ := childValue.(*array.ListType) v = int64(len(*ls)) - } else if kern.IsString(childValue) { + } else if str.IsString(childValue) { s, _ := childValue.(string) v = int64(len(s)) - } else if kern.IsDict(childValue) { - m, _ := childValue.(*kern.DictType) + } else if dict.IsDict(childValue) { + m, _ := childValue.(*dict.DictType) v = int64(len(*m)) - } else if lls, ok := childValue.(*kern.LinkedList); ok { + } else if lls, ok := childValue.(*list.LinkedList); ok { v = int64(lls.Len()) } 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) - // v, _ = ToGoInt(count, "") - // } else { - // v = int64(it.Index() + 1) - // } } else { err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) } diff --git a/operator-map.go b/operator-map.go index 40ed54b..fe87f3b 100644 --- a/operator-map.go +++ b/operator-map.go @@ -44,27 +44,6 @@ func evalMap(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } } - // values := kern.NewListA() - // for item, err = it.Next(); err == nil; item, err = it.Next() { - // ctx.SetVar("_", item) - // ctx.SetVar("__", it.Index()) - // ctx.SetVar("_#", it.Count()) - // if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { - // values.AppendItem(rightValue) - // } - // ctx.DeleteVar("_#") - // ctx.DeleteVar("__") - // ctx.DeleteVar("_") - // if err != nil { - // break - // } - // } - // if err == io.EOF { - // err = nil - // } - // if err == nil { - // v = values - // } v, err = NewIterIter(it, ctx, opTerm.Children[1:]) return } diff --git a/operator-post-inc-dec.go b/operator-post-inc-dec.go index c08ecd3..e811fd1 100644 --- a/operator-post-inc-dec.go +++ b/operator-post-inc-dec.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" ) // -------- post increment term @@ -49,7 +50,7 @@ func evalPostInc(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { ctx.UnsafeSetVar(namePrefix+"_value", v1) } } - } else if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { + } else if types.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { v = childValue i, _ := childValue.(int64) ctx.SetVar(opTerm.Children[0].Source(), i+1) @@ -79,7 +80,7 @@ func evalPostDec(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { /* if it, ok := childValue.(Iterator); ok { v, err = it.Next() - } else */if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { + } else */if types.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { v = childValue i, _ := childValue.(int64) ctx.SetVar(opTerm.Children[0].Source(), i-1) diff --git a/operator-pre-inc-dec.go b/operator-pre-inc-dec.go index bfaf962..b088028 100644 --- a/operator-pre-inc-dec.go +++ b/operator-pre-inc-dec.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" ) // -------- pre increment term @@ -27,7 +28,7 @@ func evalPreInc(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { + if types.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { i := childValue.(int64) + 1 ctx.SetVar(opTerm.Children[0].Source(), i) v = i @@ -56,7 +57,7 @@ func evalPreDec(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { + if types.IsInteger(childValue) && opTerm.Children[0].Symbol() == scan.SymVariable { i := childValue.(int64) - 1 ctx.SetVar(opTerm.Children[0].Source(), i) v = i diff --git a/operator-prod.go b/operator-prod.go index 0b40040..969c910 100644 --- a/operator-prod.go +++ b/operator-prod.go @@ -9,6 +9,11 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- multiply term @@ -24,15 +29,15 @@ func newMultiplyTerm(tk *scan.Token) (inst *scan.Term) { } func mulValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - if kern.IsString(leftValue) && kern.IsInteger(rightValue) { + if str.IsString(leftValue) && types.IsInteger(rightValue) { s, _ := leftValue.(string) n, _ := rightValue.(int64) v = strings.Repeat(s, int(n)) - } 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 if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) { + if float.IsFloat(leftValue) || float.IsFloat(rightValue) { + v = types.NumAsFloat(leftValue) * types.NumAsFloat(rightValue) + } else if fract.IsFraction(leftValue) || fract.IsFraction(rightValue) { + v, err = fract.MulAnyFract(leftValue, rightValue) } else { leftInt, _ := leftValue.(int64) rightInt, _ := rightValue.(int64) @@ -67,16 +72,16 @@ func newDivideTerm(tk *scan.Token) (inst *scan.Term) { } func divValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { - if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { - d := kern.NumAsFloat(rightValue) + if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) { + if float.IsFloat(leftValue) || float.IsFloat(rightValue) { + d := types.NumAsFloat(rightValue) if d == 0.0 { err = opTerm.ErrDivisionByZero() } else { - v = kern.NumAsFloat(leftValue) / d + v = types.NumAsFloat(leftValue) / d } - } else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) { - v, err = kern.DivAnyFract(leftValue, rightValue) + } else if fract.IsFraction(leftValue) || fract.IsFraction(rightValue) { + v, err = fract.DivAnyFract(leftValue, rightValue) } else { leftInt, _ := leftValue.(int64) if rightInt, _ := rightValue.(int64); rightInt == 0 { @@ -85,11 +90,11 @@ func divValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) v = leftInt / rightInt } } - } else if kern.IsString(leftValue) && kern.IsString(rightValue) { + } else if str.IsString(leftValue) && str.IsString(rightValue) { source := leftValue.(string) sep := rightValue.(string) - v = kern.ListFromStrings(strings.Split(source, sep)) - } else if kern.IsString(leftValue) && kern.IsInteger(rightValue) { + v = array.ListFromStrings(strings.Split(source, sep)) + } else if str.IsString(leftValue) && types.IsInteger(rightValue) { source := leftValue.(string) partSize := int(rightValue.(int64)) if partSize == 0 { @@ -108,7 +113,7 @@ func divValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) if remainder > 0 { parts = append(parts, source[len(source)-remainder:]) } - v = kern.NewList(parts) + v = array.NewList(parts) } } else { err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) @@ -145,12 +150,12 @@ func evalDivideAsFloat(ctx kern.ExprContext, floatDivTerm *scan.Term) (v any, er return } - if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { - d := kern.NumAsFloat(rightValue) + if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) { + d := types.NumAsFloat(rightValue) if d == 0.0 { err = floatDivTerm.ErrDivisionByZero() } else { - v = kern.NumAsFloat(leftValue) / d + v = types.NumAsFloat(leftValue) / d } } else { err = floatDivTerm.ErrIncompatibleTypes(leftValue, rightValue) @@ -170,7 +175,7 @@ func newRemainderTerm(tk *scan.Token) (inst *scan.Term) { } } func remainderValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) { + if types.IsInteger(leftValue) && types.IsInteger(rightValue) { rightInt, _ := rightValue.(int64) if rightInt == 0 { err = opTerm.ErrDivisionByZero() diff --git a/operator-range.go b/operator-range.go index fcae077..1585e2d 100644 --- a/operator-range.go +++ b/operator-range.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" ) // -------- range term @@ -60,7 +61,7 @@ func evalRange(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } else if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { return } - if !(kern.IsInteger(leftValue) && kern.IsInteger(rightValue)) { + if !(types.IsInteger(leftValue) && types.IsInteger(rightValue)) { // err = opTerm.errIncompatibleTypes(leftValue, rightValue) err = errRangeInvalidSpecification(opTerm) return diff --git a/operator-rel.go b/operator-rel.go index 98445b6..e5666f2 100644 --- a/operator-rel.go +++ b/operator-rel.go @@ -9,6 +9,11 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/boolean" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- equal term @@ -26,22 +31,22 @@ func newEqualTerm(tk *scan.Token) (inst *scan.Term) { // type deepFuncTemplate func(a, b any) (eq bool, err error) 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) { + if types.IsNumOrFract(a) && types.IsNumOrFract(b) { + if types.IsNumber(a) && types.IsNumber(b) { + if types.IsInteger(a) && types.IsInteger(b) { li, _ := a.(int64) ri, _ := b.(int64) eq = li == ri } else { - eq = kern.NumAsFloat(a) == kern.NumAsFloat(b) + eq = types.NumAsFloat(a) == types.NumAsFloat(b) } } else { var cmp int - if cmp, err = kern.CmpAnyFract(a, b); err == nil { + if cmp, err = fract.CmpAnyFract(a, b); err == nil { eq = cmp == 0 } } - } else if deepCmp != nil && kern.IsList(a) && kern.IsList(b) { + } else if deepCmp != nil && array.IsList(a) && array.IsList(b) { eq, err = deepCmp(a, b) } else { eq = reflect.DeepEqual(a, b) @@ -75,7 +80,7 @@ func newNotEqualTerm(tk *scan.Token) (inst *scan.Term) { func evalNotEqual(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { if v, err = evalEqual(ctx, opTerm); err == nil { - b, _ := kern.ToBool(v) + b, _ := boolean.ToBool(v) v = !b } return @@ -94,29 +99,29 @@ func newLessTerm(tk *scan.Token) (inst *scan.Term) { } func lessThan(self *scan.Term, a, b any) (isLess bool, err error) { - if kern.IsNumOrFract(a) && kern.IsNumOrFract(b) { - if kern.IsNumber(a) && kern.IsNumber(b) { - if kern.IsInteger(a) && kern.IsInteger(b) { + if types.IsNumOrFract(a) && types.IsNumOrFract(b) { + if types.IsNumber(a) && types.IsNumber(b) { + if types.IsInteger(a) && types.IsInteger(b) { li, _ := a.(int64) ri, _ := b.(int64) isLess = li < ri } else { - isLess = kern.NumAsFloat(a) < kern.NumAsFloat(b) + isLess = types.NumAsFloat(a) < types.NumAsFloat(b) } } else { var cmp int - if cmp, err = kern.CmpAnyFract(a, b); err == nil { + if cmp, err = fract.CmpAnyFract(a, b); err == nil { isLess = cmp < 0 } } - } else if kern.IsString(a) && kern.IsString(b) { + } else if str.IsString(a) && str.IsString(b) { ls, _ := a.(string) rs, _ := b.(string) isLess = ls < rs // Inclusion test - } else if kern.IsList(a) && kern.IsList(b) { - aList, _ := a.(*kern.ListType) - bList, _ := b.(*kern.ListType) + } else if array.IsList(a) && array.IsList(b) { + aList, _ := a.(*array.ListType) + bList, _ := b.(*array.ListType) isLess = len(*aList) < len(*bList) && bList.Contains(aList) } else { err = self.ErrIncompatibleTypes(a, b) @@ -149,8 +154,8 @@ func newLessEqualTerm(tk *scan.Token) (inst *scan.Term) { func lessThanOrEqual(self *scan.Term, a, b any) (isLessEq bool, err error) { if isLessEq, err = lessThan(self, a, b); err == nil { if !isLessEq { - if kern.IsList(a) && kern.IsList(b) { - isLessEq, err = kern.SameContent(a, b) + if array.IsList(a) && array.IsList(b) { + isLessEq, err = array.SameContent(a, b) } else { isLessEq, err = equals(a, b, nil) } diff --git a/operator-shift.go b/operator-shift.go index 3c9f247..7cd8427 100644 --- a/operator-shift.go +++ b/operator-shift.go @@ -7,6 +7,7 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" ) //-------- bit right shift term @@ -22,7 +23,7 @@ func newRightShiftTerm(tk *scan.Token) (inst *scan.Term) { } func bitRightShift(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) { + if types.IsInteger(leftValue) && types.IsInteger(rightValue) { leftInt := leftValue.(int64) rightInt := rightValue.(int64) v = leftInt >> rightInt @@ -56,7 +57,7 @@ func newLeftShiftTerm(tk *scan.Token) (inst *scan.Term) { } func bitLeftShift(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - if kern.IsInteger(leftValue) && kern.IsInteger(rightValue) { + if types.IsInteger(leftValue) && types.IsInteger(rightValue) { leftInt := leftValue.(int64) rightInt := rightValue.(int64) v = leftInt << rightInt diff --git a/operator-sign.go b/operator-sign.go index 84d686f..984c81c 100644 --- a/operator-sign.go +++ b/operator-sign.go @@ -7,6 +7,8 @@ package expr import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/float" ) //-------- plus sign term @@ -38,14 +40,14 @@ func evalSign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { return } - if kern.IsFloat(rightValue) { + if float.IsFloat(rightValue) { if opTerm.Tk.Sym == scan.SymChangeSign { f, _ := rightValue.(float64) v = -f } else { v = rightValue } - } else if kern.IsInteger(rightValue) { + } else if types.IsInteger(rightValue) { if opTerm.Tk.Sym == scan.SymChangeSign { i, _ := rightValue.(int64) v = -i diff --git a/operator-sum.go b/operator-sum.go index d88e471..3ab91d3 100644 --- a/operator-sum.go +++ b/operator-sum.go @@ -10,6 +10,12 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/str" ) //-------- plus term @@ -25,39 +31,39 @@ func newPlusTerm(tk *scan.Token) (inst *scan.Term) { } func sumValues(plusTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - if (kern.IsString(leftValue) && kern.IsNumberString(rightValue)) || (kern.IsString(rightValue) && kern.IsNumberString(leftValue)) { + if (str.IsString(leftValue) && types.IsNumberString(rightValue)) || (str.IsString(rightValue) && types.IsNumberString(leftValue)) { v = fmt.Sprintf("%v%v", leftValue, rightValue) - } else if kern.IsNumber(leftValue) && kern.IsNumber(rightValue) { - if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { - v = kern.NumAsFloat(leftValue) + kern.NumAsFloat(rightValue) + } else if types.IsNumber(leftValue) && types.IsNumber(rightValue) { + if float.IsFloat(leftValue) || float.IsFloat(rightValue) { + v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue) } else { leftInt, _ := leftValue.(int64) rightInt, _ := rightValue.(int64) v = leftInt + rightInt } - } else if kern.IsList(leftValue) && kern.IsList(rightValue) { - var leftList, rightList *kern.ListType - leftList, _ = leftValue.(*kern.ListType) - rightList, _ = rightValue.(*kern.ListType) + } else if array.IsList(leftValue) && array.IsList(rightValue) { + var leftList, rightList *array.ListType + leftList, _ = leftValue.(*array.ListType) + rightList, _ = rightValue.(*array.ListType) - sumList := make(kern.ListType, 0, len(*leftList)+len(*rightList)) + sumList := make(array.ListType, 0, len(*leftList)+len(*rightList)) sumList = append(sumList, *leftList...) sumList = append(sumList, *rightList...) v = &sumList - } 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 if (fract.IsFraction(leftValue) && types.IsNumber(rightValue)) || (fract.IsFraction(rightValue) && types.IsNumber(leftValue)) { + if float.IsFloat(leftValue) || float.IsFloat(rightValue) { + v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue) } else { - v, err = kern.SumAnyFract(leftValue, rightValue) + v, err = fract.SumAnyFract(leftValue, rightValue) } - } else if kern.IsDict(leftValue) && kern.IsDict(rightValue) { - leftDict, _ := leftValue.(*kern.DictType) - rightDict, _ := rightValue.(*kern.DictType) + } else if dict.IsDict(leftValue) && dict.IsDict(rightValue) { + leftDict, _ := leftValue.(*dict.DictType) + rightDict, _ := rightValue.(*dict.DictType) c := leftDict.Clone() c.Merge(rightDict) v = c - } else if kern.IsFraction(leftValue) && kern.IsFraction(rightValue) { - v, err = kern.SumAnyFract(leftValue, rightValue) + } else if fract.IsFraction(leftValue) && fract.IsFraction(rightValue) { + v, err = fract.SumAnyFract(leftValue, rightValue) } else { err = plusTerm.ErrIncompatibleTypes(leftValue, rightValue) } @@ -87,20 +93,20 @@ func newMinusTerm(tk *scan.Token) (inst *scan.Term) { } func diffValues(minusTerm *scan.Term, leftValue, rightValue any) (v any, err error) { - 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) + if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) { + if float.IsFloat(leftValue) || float.IsFloat(rightValue) { + v = types.NumAsFloat(leftValue) - types.NumAsFloat(rightValue) + } else if fract.IsFraction(leftValue) || fract.IsFraction(rightValue) { + v, err = fract.SubAnyFract(leftValue, rightValue) } else { leftInt, _ := leftValue.(int64) rightInt, _ := rightValue.(int64) v = leftInt - rightInt } - } 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)) + } else if array.IsList(leftValue) && array.IsList(rightValue) { + leftList, _ := leftValue.(*array.ListType) + rightList, _ := rightValue.(*array.ListType) + diffList := make(array.ListType, 0, len(*leftList)-len(*rightList)) for _, item := range *leftList { if slices.Index(*rightList, item) < 0 { diffList = append(diffList, item) diff --git a/operator-unset.go b/operator-unset.go index 08d071f..19a83b3 100644 --- a/operator-unset.go +++ b/operator-unset.go @@ -9,6 +9,7 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" ) //-------- unset term @@ -50,8 +51,8 @@ func evalUnset(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { } count := 0 - if kern.IsList(childValue) { - list, _ := childValue.(*kern.ListType) + if array.IsList(childValue) { + list, _ := childValue.(*array.ListType) for _, item := range *list { if deleted, err = deleteContextItem(ctx, opTerm, item); err != nil { break diff --git a/scan/scanner.go b/scan/scanner.go index 4ddde62..d8109fc 100644 --- a/scan/scanner.go +++ b/scan/scanner.go @@ -12,7 +12,6 @@ import ( "strconv" "strings" - "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/util" ) @@ -518,7 +517,8 @@ func (scanner *Scanner) parseNumber(firstCh byte) (tk *Token) { if sym == SymFloat { value, err = strconv.ParseFloat(txt, 64) } else if sym == SymFraction { - value, err = kern.MakeGeneratingFraction(txt) + // value, err = kern.MakeGeneratingFraction(txt) + value = txt } else { value, err = strconv.ParseInt(txt, numBase, 64) } diff --git a/scan/t_scanner_test.go b/scan/t_scanner_test.go index acdd4a7..7c01af9 100644 --- a/scan/t_scanner_test.go +++ b/scan/t_scanner_test.go @@ -9,8 +9,6 @@ import ( "reflect" "strings" "testing" - - "git.portale-stac.it/go-pkg/expr/kern" ) func TestScanner(t *testing.T) { @@ -62,7 +60,6 @@ func TestScanner(t *testing.T) { /* 38 */ {`\`, SymError, errors.New("incomplete escape sequence"), nil}, /* 39 */ {`"string"`, SymString, "string", nil}, /* 40 */ {`identifier`, SymIdentifier, "identifier", nil}, - /* 41 */ {`1.2(3)`, SymFraction, kern.NewFraction(37, 30), nil}, } for i, input := range inputs { diff --git a/scan/term.go b/scan/term.go index 80af3a6..07424b0 100644 --- a/scan/term.go +++ b/scan/term.go @@ -199,15 +199,6 @@ func (t *Term) Compute(ctx kern.ExprContext) (v any, err error) { return } -// func (term *term) toInt(computedValue any, valueDescription string) (i int, err error) { -// if index64, ok := computedValue.(int64); ok { -// i = int(index64) -// } else { -// err = term.Errorf("%s, got %s (%v)", valueDescription, TypeName(computedValue), computedValue) -// } -// return -// } - func (t *Term) ErrIncompatibleTypes(leftValue, rightValue any) error { leftType := kern.TypeName(leftValue) leftText := kern.GetFormatted(leftValue, kern.Truncate) diff --git a/simple-store.go b/simple-store.go index 3f16d16..7899726 100644 --- a/simple-store.go +++ b/simple-store.go @@ -8,6 +8,7 @@ import ( "fmt" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" "git.portale-stac.it/go-pkg/expr/util" // "strings" ) @@ -76,12 +77,12 @@ func (ctx *SimpleStore) Clone() kern.ExprContext { // } // } -func (ctx *SimpleStore) ToDict() (dict *kern.DictType) { - return kern.ContextToDict(ctx) +func (ctx *SimpleStore) ToDict() any { + return types.ContextToDict(ctx) } func (ctx *SimpleStore) ToString(opt kern.FmtOpt) string { - return kern.ContextToString(ctx, opt) + return types.ContextToString(ctx, opt) } // func (ctx *SimpleStore) ToString(opt kern.FmtOpt) string { diff --git a/t_bool_test.go b/t_bool_test.go index 3ccb73f..40ee3d3 100644 --- a/t_bool_test.go +++ b/t_bool_test.go @@ -21,15 +21,15 @@ 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" does not support operand '[]' [list]`)}, + /* 8 */ {`not []`, nil, errors.New(`[1:4] prefix/postfix operator "NOT" does not support operand '[]' [array]`)}, /* 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(`[1:7] operator "AND" does not support operand '[]' [list] on its left side`)}, + /* 10 */ {`true and []`, nil, errors.New(`[1:9] left operand 'true' [bool] and right operand '[]' [array] are not compatible with operator "AND"`)}, + /* 11 */ {`[] and false`, nil, errors.New(`[1:7] operator "AND" does not support operand '[]' [array] 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`)}, + /* 14 */ {`[] or false`, nil, errors.New(`got array as left operand type of 'OR' operator, it must be bool`)}, /* 15 */ {`!true`, false, nil}, - /* 13 */ //{`true or []`, nil, errors.New(`[1:8] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "OR"`)}, + /* 13 */ //{`true or []`, nil, errors.New(`[1:8] left operand 'true' [bool] and right operand '[]' [array] are not compatible with operator "OR"`)}, } // t.Setenv("EXPR_PATH", ".") @@ -48,13 +48,13 @@ 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" does not support operand '[]' [list]`}, + /* 8 */ {`not []`, nil, `[1:4] prefix/postfix operator "NOT" does not support operand '[]' [array]`}, /* 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"`}, + /* 10 */ {`true and []`, nil, `[1:9] left operand 'true' [bool] and right operand '[]' [array] are not compatible with operator "AND"`}, + /* 11 */ {`[] and false`, nil, `[1:7] left operand '[]' [array] and right operand 'false' [bool] are not compatible with operator "AND"`}, /* 12 */ {`true or false`, true, nil}, - /* 13 */ {`true or []`, nil, `[1:8] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "OR"`}, - /* 14 */ {`[] or false`, nil, `[1:6] left operand '[]' [list] and right operand 'false' [bool] are not compatible with operator "OR"`}, + /* 13 */ {`true or []`, nil, `[1:8] left operand 'true' [bool] and right operand '[]' [array] are not compatible with operator "OR"`}, + /* 14 */ {`[] or false`, nil, `[1:6] left operand '[]' [array] and right operand 'false' [bool] are not compatible with operator "OR"`}, } // t.Setenv("EXPR_PATH", ".") diff --git a/t_builtin-base_test.go b/t_builtin-base_test.go index 0557185..3f68121 100644 --- a/t_builtin-base_test.go +++ b/t_builtin-base_test.go @@ -7,7 +7,8 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestFuncBase(t *testing.T) { @@ -35,10 +36,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)")`, 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}, + /* 22 */ {`fract("2.2(3)")`, fract.NewFraction(67, 30), nil}, + /* 23 */ {`fract("1.21(3)")`, fract.NewFraction(91, 75), nil}, + /* 24 */ {`fract(1.21(3))`, fract.NewFraction(91, 75), nil}, + /* 25 */ {`fract(1.21)`, fract.NewFraction(121, 100), nil}, /* 26 */ {`dec(2)`, float64(2), nil}, /* 27 */ {`dec(2.0)`, float64(2), nil}, /* 28 */ {`dec("2.0")`, float64(2), nil}, @@ -47,8 +48,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)`, kern.NewFraction(1, 2), nil}, - /* 35 */ {`fract(12,2)`, kern.NewFraction(6, 1), nil}, + /* 34 */ {`fract(1:2)`, fract.NewFraction(1, 2), nil}, + /* 35 */ {`fract(12,2)`, fract.NewFraction(6, 1), nil}, /* 36 */ {`bool(2)`, true, nil}, /* 37 */ {`bool(1:2)`, true, nil}, /* 38 */ {`bool(1.0)`, true, nil}, @@ -60,7 +61,7 @@ func TestFuncBase(t *testing.T) { /* 44 */ {`bool({1:"one"})`, true, nil}, /* 45 */ {`dec(false)`, float64(0), nil}, /* 46 */ {`dec(1:2)`, float64(0.5), nil}, - /* 47 */ {`dec([1])`, nil, `dec(): can't convert list to float`}, + /* 47 */ {`dec([1])`, nil, `dec(): can't convert array to float`}, /* 48 */ {`eval("a=3"); a`, int64(3), nil}, /* 49 */ {`int(5:2)`, int64(2), nil}, @@ -95,20 +96,21 @@ func TestFuncBaseFraction(t *testing.T) { section := "Builtin-Base-Fraction" inputs := []inputType{ - /* 1 */ {`fract(-0.5)`, kern.NewFraction(-1, 2), nil}, - /* 2 */ {`fract("")`, (*kern.FractionType)(nil), `bad syntax`}, - /* 3 */ {`fract("-1")`, kern.NewFraction(-1, 1), nil}, - /* 4 */ {`fract("+1")`, kern.NewFraction(1, 1), nil}, - /* 5 */ {`fract("1a")`, (*kern.FractionType)(nil), `strconv.ParseInt: parsing "1a": invalid syntax`}, + /* 1 */ {`fract(-0.5)`, fract.NewFraction(-1, 2), nil}, + /* 2 */ {`fract("")`, (*fract.FractionType)(nil), `bad syntax`}, + /* 3 */ {`fract("-1")`, fract.NewFraction(-1, 1), nil}, + /* 4 */ {`fract("+1")`, fract.NewFraction(1, 1), nil}, + /* 5 */ {`fract("1a")`, (*fract.FractionType)(nil), `strconv.ParseInt: parsing "1a": invalid syntax`}, /* 6 */ {`fract(1,0)`, nil, `fract(): division by zero`}, /* 7 */ {`fract(5, "1")`, nil, `fract(): expected integer, got string ("1")`}, - /* 8 */ {`fract(true)`, kern.NewFraction(1, 1), nil}, - /* 9 */ {`fract(false)`, kern.NewFraction(0, 1), nil}, + /* 8 */ {`fract(true)`, fract.NewFraction(1, 1), nil}, + /* 9 */ {`fract(false)`, fract.NewFraction(0, 1), nil}, + /* 10 */ {`1.2(3)`, fract.NewFraction(37, 30), nil}, } // t.Setenv("EXPR_PATH", ".") - // runTestSuiteSpec(t, section, inputs, 8) + // runTestSuiteSpec(t, section, inputs, 5) runTestSuite(t, section, inputs) } @@ -118,7 +120,7 @@ func TestFuncBaseOthers(t *testing.T) { inputs := []inputType{ /* 1 */ {`set("a", 3); a`, int64(3), nil}, /* 2 */ {`set(true, 3)`, nil, `set(): the "name" parameter must be a string, got a bool (true)`}, - /* 3 */ {`seq(1,2,3)`, kern.NewLinkedListA(int64(1), int64(2), int64(3)), nil}, + /* 3 */ {`seq(1,2,3)`, list.NewLinkedListA(int64(1), int64(2), int64(3)), nil}, // /* 4 */ {`seq(1,2,4)`, kern.NewLinkedListA(int64(1), int64(2), int64(3)), nil}, } diff --git a/t_builtin-string_test.go b/t_builtin-string_test.go index 08a6d46..a9cb3d8 100644 --- a/t_builtin-string_test.go +++ b/t_builtin-string_test.go @@ -7,7 +7,7 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" ) func TestFuncString(t *testing.T) { @@ -30,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", "-")`, kern.NewListA("one", "two", "three"), nil}, + /* 17 */ {`builtin "string"; strSplit("one-two-three", "-")`, array.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}, diff --git a/t_common_test.go b/t_common_test.go index 33740f3..c7238cb 100644 --- a/t_common_test.go +++ b/t_common_test.go @@ -98,11 +98,13 @@ func doTest(t *testing.T, ctx kern.ExprContext, section string, input *inputType gotResult, gotErr = ast.Eval(ctx) } - eq := kern.Equal(gotResult, input.wantResult) + if gotErr == nil && wantErr != nil { + eq := kern.Equal(gotResult, input.wantResult) - if !eq /*gotResult != 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 !eq /*gotResult != 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 { diff --git a/t_context_test.go b/t_context_test.go index 4295fc3..8ca60f1 100644 --- a/t_context_test.go +++ b/t_context_test.go @@ -7,7 +7,7 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestCtrlSet(t *testing.T) { @@ -82,8 +82,8 @@ func TestList(t *testing.T) { section := "Context" inputs := []inputType{ - /* 1 */ {`$$(5)`, kern.NewLinkedListA(5), nil}, - /* 2 */ {`$$($(2))`, kern.NewLinkedListA(0, 1), nil}, + /* 1 */ {`$$(5)`, list.NewLinkedListA(5), nil}, + /* 2 */ {`$$($(2))`, list.NewLinkedListA(0, 1), nil}, /* 3 */ {`string(($$global).funcs.bool)`, `bool(value):boolean{}`, nil}, } diff --git a/t_dict_test.go b/t_dict_test.go index ef335ee..612dd07 100644 --- a/t_dict_test.go +++ b/t_dict_test.go @@ -11,40 +11,42 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestDictParser(t *testing.T) { section := "Dict" inputs := []inputType{ - /* 1 */ {`{}`, kern.NewDict(nil), nil}, + /* 1 */ {`{}`, dict.NewDict(nil), nil}, /* 2 */ {`{123}`, nil, errors.New("[1:6] expected `:`, got `}`")}, - /* 3 */ {`{1:"one",2:"two",3:"three"}`, kern.NewDict(map[any]any{int64(1): "one", int64(2): "two", int64(3): "three"}), nil}, + /* 3 */ {`{1:"one",2:"two",3:"three"}`, dict.NewDict(map[any]any{int64(1): "one", int64(2): "two", int64(3): "three"}), nil}, /* 4 */ {`{1:"one",2:"two",3:"three"}[3]`, "three", nil}, /* 5 */ {`#{1:"one",2:"two",3:"three"}`, int64(3), nil}, - /* 6 */ {`{1:"one"} + {2:"two"}`, kern.NewDict(map[any]any{int64(1): "one", int64(2): "two"}), nil}, + /* 6 */ {`{1:"one"} + {2:"two"}`, dict.NewDict(map[any]any{int64(1): "one", int64(2): "two"}), nil}, /* 7 */ {`2 in {1:"one", 2:"two"}`, true, nil}, - /* 8 */ {`D={"a":1, "b":2}; D["a"]=9; D`, kern.NewDict(map[any]any{"a": int64(9), "b": int64(2)}), nil}, - /* 9 */ {`D={"a":1, "b":2}; D["z"]=9; D`, kern.NewDict(map[any]any{"z": int64(9), "a": int64(1), "b": int64(2)}), nil}, + /* 8 */ {`D={"a":1, "b":2}; D["a"]=9; D`, dict.NewDict(map[any]any{"a": int64(9), "b": int64(2)}), nil}, + /* 9 */ {`D={"a":1, "b":2}; D["z"]=9; D`, dict.NewDict(map[any]any{"z": int64(9), "a": int64(1), "b": int64(2)}), nil}, /* 10 */ {`D={"a":1, "b":2}; D[nil]=9`, nil, errors.New(`[1:21] index/key is nil`)}, /* 11 */ {`D={"a":1, "b":2}; D["a"]`, int64(1), nil}, /* 12 */ {`m={ "a":1, //"b":2, "c":3 - }`, kern.NewDict(map[any]any{"a": int64(1), "c": int64(3)}), nil}, + }`, dict.NewDict(map[any]any{"a": int64(1), "c": int64(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}, /* 16 */ {`D={1:"a"}; D.2`, nil, `[1:15] key 2 not found`}, /* 17 */ {`D={1:"a"}; D."2"`, nil, `[1:17] key "2" not found`}, /* 18 */ {`D={"a":1, "b":2}; D.a = 10; D.a`, int64(10), nil}, - /* 19 */ {`k="a"; D={k: 10}`, kern.NewDict(map[any]any{"a": int64(10)}), nil}, + /* 19 */ {`k="a"; D={k: 10}`, dict.NewDict(map[any]any{"a": int64(10)}), nil}, /* 20 */ {`k=[<1,2>]; D={k: 10}`, nil, `[1:16] dict key can be integer or string, got lisked-list`}, /* 21 */ {`f=func(n){"x"+n}; d{f(5):10}`, nil, `[0:0] two adjacent operators: "d" and "{}"`}, - /* 22 */ {`f=func(n){"x"+n}; d={f(5):10}`, kern.NewDict(map[any]any{"x5": int64(10)}), nil}, + /* 22 */ {`f=func(n){"x"+n}; d={f(5):10}`, dict.NewDict(map[any]any{"x5": int64(10)}), nil}, /* 23 */ {`f=func(n){"x"+n}; d={f(5); "z":10}`, nil, "[1:27] expected one of `:`, `}`, got `;`"}, - /* 24 */ {`f=func(n){"x"+n}; d={f(5) but "z":10}`, kern.NewDict(map[any]any{"z": int64(10)}), nil}, + /* 24 */ {`f=func(n){"x"+n}; d={f(5) but "z":10}`, dict.NewDict(map[any]any{"z": int64(10)}), nil}, } // runTestSuiteSpec(t, section, inputs, 23, 24) @@ -56,9 +58,9 @@ func TestAccessSubFields(t *testing.T) { ctx := NewSimpleStore() ctx.UnsafeSetVar( "D", - kern.NewDict(map[any]any{ - "a": kern.NewDict(map[any]any{"uno": int64(10)}), - "b": kern.NewListA(1, 2, 3), + dict.NewDict(map[any]any{ + "a": dict.NewDict(map[any]any{"uno": int64(10)}), + "b": list.NewLinkedListA(1, 2, 3), }), ) // D={"a": {"uno":1}} @@ -66,10 +68,11 @@ func TestAccessSubFields(t *testing.T) { /* 1 */ {`D.a.uno`, int64(10), nil}, /* 2 */ {`D.a.uno = 111; D.a."uno"`, int64(111), nil}, /* 3 */ {`D.a.uno = 111; D["a"]["uno"]`, int64(111), nil}, - /* 4 */ {`D.b[1] = 22; D["b"][1]`, int64(22), nil}, + // /* 4 */ {`D.b[1] = 22; D["b"][1]`, int64(22), nil}, + /* 4 */ {`D.b[1] = 22; D["b"][1]`, nil, `[1:3] collection expected`}, } - // runCtxTestSuiteSpec(t, ctx, section, inputs, 4) - runCtxTestSuite(t, ctx, section, inputs) + runCtxTestSuiteSpec(t, ctx, section, inputs, 4) + // runCtxTestSuite(t, ctx, section, inputs) } func TestDictToStringMultiLine(t *testing.T) { @@ -81,7 +84,7 @@ func TestDictToStringMultiLine(t *testing.T) { args := map[any]any{ "first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)), } - dict := kern.NewDict(args) + dict := dict.NewDict(args) got := dict.ToString(kern.MultiLine) // fmt.Printf("got=%q\n", got) @@ -103,7 +106,7 @@ func TestDictToString(t *testing.T) { args := map[any]any{ "first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)), } - dict := kern.NewDict(args) + dict := dict.NewDict(args) got := dict.ToString(0) // fmt.Printf("got=%q\n", got) diff --git a/t_expr_test.go b/t_expr_test.go index faa59f0..e0c122e 100644 --- a/t_expr_test.go +++ b/t_expr_test.go @@ -7,7 +7,7 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/dict" ) func TestExpr(t *testing.T) { @@ -31,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 */ {`$$`, kern.NewDict(map[any]any{"vars": kern.NewDict(nil), "funcs": kern.NewDict(nil)}), nil}, + /* 18 */ {`$$`, dict.NewDict(map[any]any{"vars": dict.NewDict(nil), "funcs": dict.NewDict(nil)}), nil}, /* 19 */ {` ds={ "init":func(@end){@current=0 but true}, diff --git a/t_fractions_test.go b/t_fractions_test.go index 8fbad45..c3ef11a 100644 --- a/t_fractions_test.go +++ b/t_fractions_test.go @@ -8,29 +8,30 @@ import ( "testing" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/fract" ) func TestFractionsParser(t *testing.T) { section := "Fraction" inputs := []inputType{ - /* 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}, + /* 1 */ {`1:2`, fract.NewFraction(1, 2), nil}, + /* 2 */ {`1:2 + 1`, fract.NewFraction(3, 2), nil}, + /* 3 */ {`1:2 - 1`, fract.NewFraction(-1, 2), nil}, + /* 4 */ {`1:2 * 1`, fract.NewFraction(1, 2), nil}, + /* 5 */ {`1:2 * 2:3`, fract.NewFraction(2, 6), nil}, + /* 6 */ {`1:2 / 2:3`, fract.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`, 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}, + /* 9 */ {`1:+5`, fract.NewFraction(1, 5), nil}, + /* 10 */ {`1:(-2)`, fract.NewFraction(-1, 2), nil}, + /* 11 */ {`builtin "math.arith"; add(1:2, 2:3)`, fract.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)`, kern.NewFraction(2, 6), nil}, + /* 13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, fract.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 */ {`1+1:2+0.5`, float64(2), nil}, /* 17 */ {`1:(2-2)`, nil, `[1:3] division by zero`}, - /* 18 */ {`[0,1][1-1]:1`, kern.NewFraction(0, 1), nil}, + /* 18 */ {`[0,1][1-1]:1`, fract.NewFraction(0, 1), nil}, /* 19 */ {`1:2 == 0.5`, true, nil}, } // runTestSuiteSpec(t, section, inputs, 26) @@ -38,7 +39,7 @@ func TestFractionsParser(t *testing.T) { } func TestFractionToStringSimple(t *testing.T) { - source := kern.NewFraction(1, 2) + source := fract.NewFraction(1, 2) want := "1:2" got := source.ToString(0) if got != want { @@ -47,7 +48,7 @@ func TestFractionToStringSimple(t *testing.T) { } func TestFractionToStringMultiline(t *testing.T) { - source := kern.NewFraction(1, 2) + source := fract.NewFraction(1, 2) want := "1\n-\n2" got := source.ToString(kern.MultiLine) if got != want { @@ -56,7 +57,7 @@ func TestFractionToStringMultiline(t *testing.T) { } func TestToStringMultilineTty(t *testing.T) { - source := kern.NewFraction(-1, 2) + source := fract.NewFraction(-1, 2) want := "\x1b[4m-1\x1b[0m\n 2" got := source.ToString(kern.MultiLine | kern.TTY) if got != want { diff --git a/t_index_test.go b/t_index_test.go index aab9f0e..47b6dc5 100644 --- a/t_index_test.go +++ b/t_index_test.go @@ -7,7 +7,7 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" ) func TestCollections(t *testing.T) { @@ -20,7 +20,7 @@ func TestCollections(t *testing.T) { /* 5 */ {`"abcdef"[1:2:3]`, nil, `[1:14] invalid range specification`}, /* 6 */ {`"abcdef"[((1>0)?{1}:{0}):3]`, "bc", nil}, /* 7 */ {`"abcdef"[[0,1][0]:1]`, "a", nil}, - /* 8 */ {`[0,1,2,3,4][:]`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, + /* 8 */ {`[0,1,2,3,4][:]`, array.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, } t.Setenv("EXPR_PATH", ".") diff --git a/t_iter-iter_test.go b/t_iter-iter_test.go index 5265e48..43f4be3 100644 --- a/t_iter-iter_test.go +++ b/t_iter-iter_test.go @@ -7,14 +7,14 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestIterIterator(t *testing.T) { section := "Iter-Iter" inputs := []inputType{ - /* 1 */ {`it=$(4); $$($(it) filter ${_}==100)`, kern.NewLinkedListA(), nil}, - /* 2 */ {`it=$(4); $$($(it, $_) filter ${_}==100)`, kern.NewLinkedListA(), nil}, + /* 1 */ {`it=$(4); $$($(it) filter ${_}==100)`, list.NewLinkedListA(), nil}, + /* 2 */ {`it=$(4); $$($(it, $_) filter ${_}==100)`, list.NewLinkedListA(), nil}, /* 3 */ {`it=$(4); $(it, 10+$_, last-1) digest ${_}`, int64(12), nil}, /* 4 */ {`f=func(n){last-n}; it=$(4); $(it, 10+$_, f(-1)) digest ${_}`, int64(14), nil}, } diff --git a/t_iter-list_test.go b/t_iter-list_test.go index 24ea2dc..22bb87d 100644 --- a/t_iter-list_test.go +++ b/t_iter-list_test.go @@ -8,12 +8,12 @@ import ( "io" "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" ) func TestNewListIterator(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, 3, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, 3, 1}) if item, err := it.Next(); err != nil { t.Errorf("error: %v", err) } else if item != "b" { @@ -24,8 +24,8 @@ func TestNewListIterator(t *testing.T) { } func TestNewListIterator2(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{3, 1, -1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{3, 1, -1}) if item, err := it.Next(); err != nil { t.Errorf("error: %v", err) } else if item != "d" { @@ -36,8 +36,8 @@ func TestNewListIterator2(t *testing.T) { } func TestNewListIterator3(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, -1, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, -1, 1}) if item, err := it.Next(); err != nil { t.Errorf("error: %v", err) } else if item != "b" { @@ -93,8 +93,8 @@ func TestNewIterList5(t *testing.T) { func TestNewIterList6(t *testing.T) { ctx := NewSimpleStore() - list := kern.NewListA("a", "b", "c", "d") - it1, _ := NewIterator(ctx, list, nil) + a := array.NewListA("a", "b", "c", "d") + it1, _ := NewIterator(ctx, a, nil) it, _ := NewIterator(ctx, it1, nil) if item, err := it.Next(); err != nil { t.Errorf("error: %v", err) @@ -115,8 +115,8 @@ func TestNewString(t *testing.T) { func TestHasOperation(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, 3, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, 3, 1}) hasOp := it.HasOperation("reset") if !hasOp { t.Errorf("HasOperation(reset) must be true, got false") @@ -125,8 +125,8 @@ func TestHasOperation(t *testing.T) { func TestCallOperationReset(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, 3, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, 3, 1}) if v, err := it.CallOperation("reset", nil); err != nil { t.Errorf("Error on CallOperation(reset): %v", err) } else { @@ -136,8 +136,8 @@ func TestCallOperationReset(t *testing.T) { func TestCallOperationIndex(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, 3, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, 3, 1}) if v, err := it.CallOperation("index", nil); err != nil { t.Errorf("Error on CallOperation(index): %v", err) } else { @@ -147,8 +147,8 @@ func TestCallOperationIndex(t *testing.T) { func TestCallOperationCount(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, 3, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, 3, 1}) if v, err := it.CallOperation("count", nil); err != nil { t.Errorf("Error on CallOperation(count): %v", err) } else { @@ -158,8 +158,8 @@ func TestCallOperationCount(t *testing.T) { func TestCallOperationUnknown(t *testing.T) { - list := kern.NewListA("a", "b", "c", "d") - it := NewListIterator(list, []any{1, 3, 1}) + a := array.NewListA("a", "b", "c", "d") + it := NewListIterator(a, []any{1, 3, 1}) if v, err := it.CallOperation("unknown", nil); err == nil { t.Errorf("Expected error on CallOperation(unknown), got %v", v) } diff --git a/t_iterator_test.go b/t_iterator_test.go index 5b21bd2..f764689 100644 --- a/t_iterator_test.go +++ b/t_iterator_test.go @@ -9,6 +9,9 @@ import ( "git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/scan" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestIteratorParser(t *testing.T) { @@ -35,7 +38,7 @@ func TestIteratorParser(t *testing.T) { /* 19 */ {`it=$({1:"one",2:"two",3:"three"}); it++`, int64(1), nil}, /* 20 */ {`it=$({1:"one",2:"two",3:"three"}, "default", "value"); it++`, "one", nil}, /* 21 */ {`it=$({1:"one",2:"two",3:"three"}, "desc", "key"); it++`, int64(3), nil}, - /* 22 */ {`it=$({1:"one",2:"two",3:"three"}, "asc", "item"); it++`, kern.NewList([]any{int64(1), "one"}), nil}, + /* 22 */ {`it=$({1:"one",2:"two",3:"three"}, "asc", "item"); it++`, array.NewList([]any{int64(1), "one"}), nil}, /* 23 */ {`$$($(1,4,0))`, nil, `step cannot be zero`}, /* 24 */ {`$$($(1,4,-1))`, nil, `step cannot be negative when start < stop`}, /* 25 */ {`$$($(4,1,1))`, nil, `step cannot be positive when start > stop`}, @@ -75,7 +78,7 @@ func TestCallOpIterIter(t *testing.T) { func TestCallOpDictIter(t *testing.T) { section := "DictIterator-CallOp" - inner := kern.NewDict(map[any]any{"a": 1}) + inner := dict.NewDict(map[any]any{"a": 1}) if it, err := NewDictIterator(inner, nil); err != nil { t.Errorf(`%s -- NewIterIter() failed: %v`, section, err) } else { @@ -87,7 +90,7 @@ func TestCallOpDictIter(t *testing.T) { func TestCallOpLinkedListIter(t *testing.T) { section := "LinkedListIterator-CallOp" - inner := kern.NewLinkedListA(1, 2, 3) + inner := list.NewLinkedListA(1, 2, 3) it := NewLinkedListIterator(inner, nil) testIteratorCallOp(t, section, it) @@ -122,8 +125,8 @@ func testIterAttrs(t *testing.T, section string, it kern.Iterator, name, repr st func TestFilterIterator(t *testing.T) { section := "Iterator-Filter" inputs := []inputType{ - /* 1 */ {`$$([1,2,3] filter $_%2==0)`, kern.NewLinkedListA(2), nil}, - /* 2 */ {`it = [1,2,3] filter $_%2!=1; $$(it)`, kern.NewLinkedListA(2), nil}, + /* 1 */ {`$$([1,2,3] filter $_%2==0)`, list.NewLinkedListA(2), nil}, + /* 2 */ {`it = [1,2,3] filter $_%2!=1; $$(it)`, list.NewLinkedListA(2), nil}, /* 3 */ {`builtin "os.file"; #$$(fileLineIterator("test-file.txt") filter (#${_} == 2))`, int64(0), nil}, /* 4 */ {`builtin "os.file"; #$$(fileLineIterator("test-file.txt") filter (#${_} == 3))`, int64(2), nil}, } @@ -147,11 +150,11 @@ func TestDigestIterator(t *testing.T) { func TestCatIterator(t *testing.T) { section := "Iterator-Cat" inputs := []inputType{ - /* 1 */ {`$$([1] cat [])`, kern.NewLinkedListA(1), nil}, - /* 2 */ {`$$([1] cat [2])`, kern.NewLinkedListA(1, 2), nil}, - /* 3 */ {`$$([1] cat nil)`, kern.NewLinkedListA(1), nil}, - /* 4 */ {`$$(nil cat [2])`, kern.NewLinkedListA(2), nil}, - /* 5 */ {`$$(nil cat nil)`, kern.NewLinkedListA(), nil}, + /* 1 */ {`$$([1] cat [])`, list.NewLinkedListA(1), nil}, + /* 2 */ {`$$([1] cat [2])`, list.NewLinkedListA(1, 2), nil}, + /* 3 */ {`$$([1] cat nil)`, list.NewLinkedListA(1), nil}, + /* 4 */ {`$$(nil cat [2])`, list.NewLinkedListA(2), nil}, + /* 5 */ {`$$(nil cat nil)`, list.NewLinkedListA(), nil}, /* 6 */ {`$$(["a","b"] cat ["x"-true])`, nil, `[1:23] left operand 'x' [string] and right operand 'true' [bool] are not compatible with operator "-"`}, } @@ -162,10 +165,10 @@ func TestCatIterator(t *testing.T) { func TestMapIterator(t *testing.T) { section := "Iterator-Map" inputs := []inputType{ - /* 1 */ {`$$([3,4,5] map ${_#})`, kern.NewLinkedListA(1, 2, 3), nil}, + /* 1 */ {`$$([3,4,5] map ${_#})`, list.NewLinkedListA(1, 2, 3), nil}, /* 2 */ {`#$$($(10) map ${_})`, int64(10), nil}, /* 3 */ {`#$$($(10,0) map ${_})`, int64(10), nil}, - /* 4 */ {`builtin "os.file"; $$(fileLineIterator("test-file.txt") map ${__})`, kern.NewLinkedListA(0, 1), nil}, + /* 4 */ {`builtin "os.file"; $$(fileLineIterator("test-file.txt") map ${__})`, list.NewLinkedListA(0, 1), nil}, /* 5 */ {`$$(["1", "2", "3"] map int())`, nil, `int(): too few params -- expected 1, got 0`}, } diff --git a/t_list_test.go b/t_list_test.go index 971f303..41cb584 100644 --- a/t_list_test.go +++ b/t_list_test.go @@ -7,56 +7,57 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestListParser(t *testing.T) { section := "List" inputs := []inputType{ - /* 1 */ {`[]`, kern.NewListA(), nil}, - /* 2 */ {`[1,2,3]`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, - /* 3 */ {`[1,2,"hello"]`, kern.NewListA(int64(1), int64(2), "hello"), nil}, - /* 4 */ {`[1+2, not true, "hello"]`, kern.NewListA(int64(3), false, "hello"), nil}, - /* 5 */ {`[1,2]+[3]`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, - /* 6 */ {`[1,4,3,2]-[3]`, kern.NewListA(int64(1), int64(4), int64(2)), nil}, + /* 1 */ {`[]`, array.NewListA(), nil}, + /* 2 */ {`[1,2,3]`, array.NewListA(int64(1), int64(2), int64(3)), nil}, + /* 3 */ {`[1,2,"hello"]`, array.NewListA(int64(1), int64(2), "hello"), nil}, + /* 4 */ {`[1+2, not true, "hello"]`, array.NewListA(int64(3), false, "hello"), nil}, + /* 5 */ {`[1,2]+[3]`, array.NewListA(int64(1), int64(2), int64(3)), nil}, + /* 6 */ {`[1,4,3,2]-[3]`, array.NewListA(int64(1), int64(4), int64(2)), nil}, /* 7 */ {`builtin "math.arith"; add([1,4,3,2])`, int64(10), nil}, /* 8 */ {`builtin "math.arith"; add([1,[2,2],3,2])`, int64(10), nil}, /* 9 */ {`builtin "math.arith"; mul([1,4,3.0,2])`, float64(24.0), nil}, /* 10 */ {`builtin "math.arith"; add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`}, /* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil}, - /* 12 */ {`[1,2,3] <+ 2+2`, kern.NewListA(int64(1), int64(2), int64(3), int64(4)), nil}, - /* 13 */ {`2-1 +> [2,3]`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, + /* 12 */ {`[1,2,3] <+ 2+2`, array.NewListA(int64(1), int64(2), int64(3), int64(4)), nil}, + /* 13 */ {`2-1 +> [2,3]`, array.NewListA(int64(1), int64(2), int64(3)), nil}, /* 14 */ {`[1,2,3][1]`, int64(2), nil}, /* 15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil}, /* 16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil}, /* 17 */ {`list=["one","two","three"]; list[10]`, nil, `[1:34] index 10 out of bounds`}, - /* 18 */ {`["a", "b", "c"]`, kern.NewListA("a", "b", "c"), nil}, - /* 19 */ {`["a", "b", "c"]`, kern.NewList([]any{"a", "b", "c"}), nil}, + /* 18 */ {`["a", "b", "c"]`, array.NewListA("a", "b", "c"), nil}, + /* 19 */ {`["a", "b", "c"]`, array.NewList([]any{"a", "b", "c"}), nil}, /* 20 */ {`#["a", "b", "c"]`, int64(3), nil}, /* 21 */ {`"b" in ["a", "b", "c"]`, true, nil}, - /* 22 */ {`a=[1,2]; (a)<+3`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, - /* 23 */ {`a=[1,2]; (a)<+3; a`, kern.NewListA(int64(1), int64(2)), nil}, + /* 22 */ {`a=[1,2]; (a)<+3`, array.NewListA(int64(1), int64(2), int64(3)), nil}, + /* 23 */ {`a=[1,2]; (a)<+3; a`, array.NewListA(int64(1), int64(2)), nil}, /* 24 */ {`["a","b","c","d"][1]`, "b", nil}, /* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`}, - /* 26 */ {`[0,1,2,3,4][:]`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, + /* 26 */ {`[0,1,2,3,4][:]`, array.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, /* 27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`}, /* 28 */ {`2 << 3;`, int64(16), nil}, /* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`}, /* 30 */ {`2 >> 3;`, int64(0), nil}, - /* 31 */ {`a=[1,2]; a<+3`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, - /* 32 */ {`a=[1,2]; 5+>a`, kern.NewListA(int64(5), int64(1), int64(2)), nil}, - /* 33 */ {`L=[1,2]; L[0]=9; L`, kern.NewListA(int64(9), int64(2)), nil}, + /* 31 */ {`a=[1,2]; a<+3`, array.NewListA(int64(1), int64(2), int64(3)), nil}, + /* 32 */ {`a=[1,2]; 5+>a`, array.NewListA(int64(5), int64(1), int64(2)), nil}, + /* 33 */ {`L=[1,2]; L[0]=9; L`, array.NewListA(int64(9), int64(2)), nil}, /* 34 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`}, - /* 35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`}, + /* 35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [array]`}, /* 36 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`}, - /* 37 */ {`[0,1,2,3,4][2:3]`, kern.NewListA(int64(2)), nil}, - /* 38 */ {`[0,1,2,3,4][3:-1]`, kern.NewListA(int64(3)), nil}, - /* 30 */ {`[0,1,2,3,4][-3:-1]`, kern.NewListA(int64(2), int64(3)), nil}, - /* 40 */ {`[0,1,2,3,4][0:]`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, - /* 41 */ {`[0] << $([1,2,3,4])`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, - /* 42 */ {`L=[]; [1] >> L; L`, kern.NewListA(), nil}, - /* 43 */ {`L=[]; L << [1]; L`, kern.NewListA(), nil}, + /* 37 */ {`[0,1,2,3,4][2:3]`, array.NewListA(int64(2)), nil}, + /* 38 */ {`[0,1,2,3,4][3:-1]`, array.NewListA(int64(3)), nil}, + /* 30 */ {`[0,1,2,3,4][-3:-1]`, array.NewListA(int64(2), int64(3)), nil}, + /* 40 */ {`[0,1,2,3,4][0:]`, array.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, + /* 41 */ {`[0] << $([1,2,3,4])`, array.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, + /* 42 */ {`L=[]; [1] >> L; L`, array.NewListA(), nil}, + /* 43 */ {`L=[]; L << [1]; L`, array.NewListA(), nil}, // /* 44 */ {`[0,1,2,3,4][2:3]`, kern.NewListA(int64(20)), nil}, } @@ -70,11 +71,11 @@ func TestLinkedListParser(t *testing.T) { section := "Linked-List" inputs := []inputType{ - /* 1 */ {`[<1,2>]`, kern.NewLinkedListA(1, 2), nil}, + /* 1 */ {`[<1,2>]`, list.NewLinkedListA(1, 2), nil}, /* 2 */ {`it=$([<1,2,3>]); it++`, int64(1), nil}, /* 3 */ {`it=$([<1,2,3>]); #($$(it))`, int64(3), nil}, /* 4 */ {`[<1,2,3>][0]`, int64(1), nil}, - /* 5 */ {`[<1,2,3>][0:2]`, kern.NewLinkedListA(1, 2), nil}, + /* 5 */ {`[<1,2,3>][0:2]`, list.NewLinkedListA(1, 2), nil}, } // t.Setenv("EXPR_PATH", ".") diff --git a/t_operator_test.go b/t_operator_test.go index 1c62bbb..4a52401 100644 --- a/t_operator_test.go +++ b/t_operator_test.go @@ -7,7 +7,9 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/list" ) func TestOperator(t *testing.T) { @@ -52,26 +54,26 @@ func TestOperator(t *testing.T) { func TestOperatorInsert(t *testing.T) { section := "Operator-Insert" inputs := []inputType{ - /* 1 */ {`["a", "b"] << nil`, kern.NewListA("a", "b"), nil}, - /* 2 */ {`["a", "b"] << []`, kern.NewListA("a", "b", kern.NewListA()), nil}, - /* 3 */ {`["a", "b"] << $([])`, kern.NewListA("a", "b"), nil}, - /* 4 */ {`["a", "b"] << 3`, kern.NewListA("a", "b", int64(3)), nil}, - /* 5 */ {`3 << ["a", "b"]`, nil, `[1:5] left operand '3' [integer] and right operand '["a", "b"]' [list] are not compatible with operator "<<"`}, - /* 6 */ {`nil >> ["a", "b"]`, kern.NewListA("a", "b"), nil}, - /* 7 */ {`[] >> ["a", "b"]`, kern.NewListA(kern.NewListA(), "a", "b"), nil}, - /* 8 */ {`$([]) >> ["a", "b"]`, kern.NewListA("a", "b"), nil}, - /* 9 */ {`["a", "b"] << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil}, - /* 10 */ {`L=["a", "b"]; L << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil}, - /* 11 */ {`L=["a", "b"]; L << $([1,2,3]); L`, kern.NewListA("a", "b"), nil}, + /* 1 */ {`["a", "b"] << nil`, array.NewListA("a", "b"), nil}, + /* 2 */ {`["a", "b"] << []`, array.NewListA("a", "b", array.NewListA()), nil}, + /* 3 */ {`["a", "b"] << $([])`, array.NewListA("a", "b"), nil}, + /* 4 */ {`["a", "b"] << 3`, array.NewListA("a", "b", int64(3)), nil}, + /* 5 */ {`3 << ["a", "b"]`, nil, `[1:5] left operand '3' [integer] and right operand '["a", "b"]' [array] are not compatible with operator "<<"`}, + /* 6 */ {`nil >> ["a", "b"]`, array.NewListA("a", "b"), nil}, + /* 7 */ {`[] >> ["a", "b"]`, array.NewListA(array.NewListA(), "a", "b"), nil}, + /* 8 */ {`$([]) >> ["a", "b"]`, array.NewListA("a", "b"), nil}, + /* 9 */ {`["a", "b"] << $([1,2,3])`, array.NewListA("a", "b", int64(1), int64(2), int64(3)), nil}, + /* 10 */ {`L=["a", "b"]; L << $([1,2,3])`, array.NewListA("a", "b", int64(1), int64(2), int64(3)), nil}, + /* 11 */ {`L=["a", "b"]; L << $([1,2,3]); L`, array.NewListA("a", "b"), nil}, /* 12 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`}, - /* 13 */ {`[<>] << 1`, kern.NewLinkedListA(1), nil}, - /* 14 */ {`[<>] << [1,2]`, kern.NewLinkedListA(kern.NewListA(int64(1), int64(2))), nil}, - /* 15 */ {`[<>] << [<1,2>]`, kern.NewLinkedListA(kern.NewLinkedListA(1, 2)), nil}, - /* 16 */ {`1 >> [<>]`, kern.NewLinkedListA(1), nil}, - /* 17 */ {`[1,2] >> [<>]`, kern.NewLinkedListA(kern.NewListA(int64(1), int64(2))), nil}, - /* 18 */ {`[<1,2>] >> [<>]`, kern.NewLinkedListA(kern.NewLinkedListA(1, 2)), nil}, - /* 19 */ {`$([1,2]) >> [<>]`, kern.NewLinkedListA(1, 2), nil}, - /* 20 */ {`$([<1,2>]) >> [<>]`, kern.NewLinkedListA(1, 2), nil}, + /* 13 */ {`[<>] << 1`, list.NewLinkedListA(1), nil}, + /* 14 */ {`[<>] << [1,2]`, list.NewLinkedListA(array.NewListA(int64(1), int64(2))), nil}, + /* 15 */ {`[<>] << [<1,2>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil}, + /* 16 */ {`1 >> [<>]`, list.NewLinkedListA(1), nil}, + /* 17 */ {`[1,2] >> [<>]`, list.NewLinkedListA(array.NewListA(int64(1), int64(2))), nil}, + /* 18 */ {`[<1,2>] >> [<>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil}, + /* 19 */ {`$([1,2]) >> [<>]`, list.NewLinkedListA(1, 2), nil}, + /* 20 */ {`$([<1,2>]) >> [<>]`, list.NewLinkedListA(1, 2), nil}, } // runTestSuiteSpec(t, section, inputs, 9) @@ -81,10 +83,10 @@ func TestOperatorInsert(t *testing.T) { func TestOperatorDeepAssign(t *testing.T) { section := "Operator-DeepAssign" inputs := []inputType{ - /* 1 */ {`DD={"uno": 1, "due": 2}; D=DD; D["uno"]=11; DD`, kern.NewDict(map[any]any{"uno": int64(11), "due": int64(2)}), nil}, - /* 2 */ {`DD={"uno": 1, "due": 2}; D:=DD; D["uno"]=11; DD`, kern.NewDict(map[any]any{"uno": int64(1), "due": int64(2)}), nil}, - /* 3 */ {`LL=["a", "b"]; L=LL; L[0]="x"; LL`, kern.NewListA("x", "b"), nil}, - /* 4 */ {`LL=["a", "b"]; L:=LL; L[0]="x"; LL`, kern.NewListA("a", "b"), nil}, + /* 1 */ {`DD={"uno": 1, "due": 2}; D=DD; D["uno"]=11; DD`, dict.NewDict(map[any]any{"uno": int64(11), "due": int64(2)}), nil}, + /* 2 */ {`DD={"uno": 1, "due": 2}; D:=DD; D["uno"]=11; DD`, dict.NewDict(map[any]any{"uno": int64(1), "due": int64(2)}), nil}, + /* 3 */ {`LL=["a", "b"]; L=LL; L[0]="x"; LL`, array.NewListA("x", "b"), nil}, + /* 4 */ {`LL=["a", "b"]; L:=LL; L[0]="x"; LL`, array.NewListA("a", "b"), nil}, } // runTestSuiteSpec(t, section, inputs, 4) @@ -105,25 +107,25 @@ func TestOperatorGroupBy(t *testing.T) { section := "Operator-GroupBy" inputs := []inputType{ /* 1 */ {`L=[{"num": 1, "alpha": "one"}, {"num": 2, "alpha": "two"}, {"num": 3, "alpha": "three"}]; L groupby "num"`, - kern.NewDict(map[any]any{ - "1": kern.NewListA(kern.NewDict(map[any]any{"num": int64(1), "alpha": "one"})), - "2": kern.NewListA(kern.NewDict(map[any]any{"num": int64(2), "alpha": "two"})), - "3": kern.NewListA(kern.NewDict(map[any]any{"num": int64(3), "alpha": "three"})), + dict.NewDict(map[any]any{ + "1": array.NewListA(dict.NewDict(map[any]any{"num": int64(1), "alpha": "one"})), + "2": array.NewListA(dict.NewDict(map[any]any{"num": int64(2), "alpha": "two"})), + "3": array.NewListA(dict.NewDict(map[any]any{"num": int64(3), "alpha": "three"})), }), nil}, /* 2 */ {`cars = [{"model": "compas", "vendor": "jeep"}, {"model": "limited", "vendor": "jeep"}, {"model": "600", "vendor":"fiat"}]; cars groupby "vendor"`, - kern.NewDict(map[any]any{ - "jeep": kern.NewListA( - kern.NewDict(map[any]any{"model": "compas", "vendor": "jeep"}), - kern.NewDict(map[any]any{"model": "limited", "vendor": "jeep"})), - "fiat": kern.NewListA(kern.NewDict(map[any]any{"model": "600", "vendor": "fiat"})), + dict.NewDict(map[any]any{ + "jeep": array.NewListA( + dict.NewDict(map[any]any{"model": "compas", "vendor": "jeep"}), + dict.NewDict(map[any]any{"model": "limited", "vendor": "jeep"})), + "fiat": array.NewListA(dict.NewDict(map[any]any{"model": "600", "vendor": "fiat"})), }), nil}, /* 3 */ {`[3,4,5] groupby $__`, - kern.NewDict(map[any]any{ - "0": kern.NewListA(int64(3)), - "1": kern.NewListA(int64(4)), - "2": kern.NewListA(int64(5)), + dict.NewDict(map[any]any{ + "0": array.NewListA(int64(3)), + "1": array.NewListA(int64(4)), + "2": array.NewListA(int64(5)), }), nil}, } diff --git a/t_parser_test.go b/t_parser_test.go index 752e24e..62758dd 100644 --- a/t_parser_test.go +++ b/t_parser_test.go @@ -7,7 +7,8 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/fract" ) func TestGeneralParser(t *testing.T) { @@ -132,9 +133,9 @@ func TestGeneralParser(t *testing.T) { /* 116 */ {`null`, nil, `undefined variable or function "null"`}, /* 117 */ {`{"key"}`, nil, "[1:8] expected `:`, got `}`"}, /* 118 */ {`{"key":}`, nil, "[1:9] expected `dictionary-value`, got `}`"}, - /* 119 */ {`{}`, &kern.DictType{}, nil}, + /* 119 */ {`{}`, &dict.DictType{}, nil}, /* 120 */ {`v=10; v++; v`, int64(11), nil}, - /* 121 */ {`1.2()`, kern.NewFraction(6, 5), nil}, + /* 121 */ {`1.2()`, fract.NewFraction(6, 5), nil}, /* 122 */ {`x="abc"; x ?! #x`, int64(3), nil}, /* 123 */ {`x ?! #x`, nil, `[1:7] prefix/postfix operator "#" does not support operand '' [nil]`}, /* 124 */ {`x ?! (x+1)`, nil, nil}, diff --git a/t_plugin_test.go b/t_plugin_test.go index 708dcc7..c87d1b9 100644 --- a/t_plugin_test.go +++ b/t_plugin_test.go @@ -30,7 +30,7 @@ func TestPluginExists(t *testing.T) { func TestMakePluginName(t *testing.T) { name := "json" - want := "expr-" + name + "-plugin" + SHAREDLIBRARY_EXTENSION + want := "expr-" + name + /*"-plugin" +*/ SHAREDLIBRARY_EXTENSION if got := makePluginName(name); got != want { t.Errorf("makePluginName(%q) failed: Got: %q, Want: %q", name, got, want) diff --git a/t_strings_test.go b/t_strings_test.go index d7eb7fe..aac8b4c 100644 --- a/t_strings_test.go +++ b/t_strings_test.go @@ -7,7 +7,7 @@ package expr import ( "testing" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/array" ) func TestStringsParser(t *testing.T) { @@ -19,9 +19,9 @@ func TestStringsParser(t *testing.T) { /* 4 */ {`"uno" * (2+1)`, `unounouno`, nil}, /* 5 */ {`"abc"[1]`, `b`, nil}, /* 6 */ {`#"abc"`, int64(3), nil}, - /* 7 */ {`"192.168.0.240" / "."`, kern.NewListA("192", "168", "0", "240"), nil}, + /* 7 */ {`"192.168.0.240" / "."`, array.NewListA("192", "168", "0", "240"), nil}, /* 8 */ {`("192.168.0.240" / ".")[1]`, "168", nil}, - /* 9 */ {`"AF3B0Dz" / 2`, kern.NewListA("AF", "3B", "0D", "z"), nil}, + /* 9 */ {`"AF3B0Dz" / 2`, array.NewListA("AF", "3B", "0D", "z"), nil}, /* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"}, } diff --git a/t_utils_test.go b/t_utils_test.go index 802d77a..8f513f7 100644 --- a/t_utils_test.go +++ b/t_utils_test.go @@ -10,6 +10,11 @@ import ( "testing" "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/boolean" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/str" "git.portale-stac.it/go-pkg/expr/util" ) @@ -19,7 +24,7 @@ func TestIsString(t *testing.T) { failed := 0 count++ - if !kern.IsBool(true) { + if !boolean.IsBool(true) { t.Errorf("%d: IsBool(true) -> result = false, want true", count) failed++ } else { @@ -27,7 +32,7 @@ func TestIsString(t *testing.T) { } count++ - if !kern.IsString("abc") { + if !str.IsString("abc") { t.Errorf("%d: IsString(\"abc\") -> result = false, want true", count) failed++ } else { @@ -35,7 +40,7 @@ func TestIsString(t *testing.T) { } count++ - if !kern.IsInteger(int64(123)) { + if !types.IsInteger(int64(123)) { t.Errorf("%d: IsInteger(123) -> result = false, want true", count) failed++ } else { @@ -43,7 +48,7 @@ func TestIsString(t *testing.T) { } count++ - if !kern.IsFloat(1.23) { + if !float.IsFloat(1.23) { t.Errorf("%d: IsFloat(1.23) -> result = false, want true", count) failed++ } else { @@ -51,7 +56,7 @@ func TestIsString(t *testing.T) { } count++ - if !kern.IsFloat(kern.NumAsFloat(123)) { + if !float.IsFloat(types.NumAsFloat(123)) { t.Errorf("%d: IsFloat(numAsFloat(123)) -> result = false, want true", count) failed++ } else { @@ -60,14 +65,14 @@ func TestIsString(t *testing.T) { count++ if kern.IsIterator("fake") { - t.Errorf(`%d: isIterator("fake") -> result = true, want false`, count) + t.Errorf(`%d: IsIterator("fake") -> result = true, want false`, count) failed++ } else { succeeded++ } count++ - b, ok := kern.ToBool(true) + b, ok := boolean.ToBool(true) if !(ok && b) { t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok) failed++ @@ -76,7 +81,7 @@ func TestIsString(t *testing.T) { } count++ - b, ok = kern.ToBool("abc") + b, ok = boolean.ToBool("abc") if !(ok && b) { t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok) failed++ @@ -85,7 +90,7 @@ func TestIsString(t *testing.T) { } count++ - b, ok = kern.ToBool([]int{}) + b, ok = boolean.ToBool([]int{}) if ok { t.Errorf("%d: toBool([]) b=%v, ok=%v -> result = true, want false", count, b, ok) failed++ @@ -101,7 +106,7 @@ func TestToIntOk(t *testing.T) { wantValue := int(64) wantErr := error(nil) - gotValue, gotErr := kern.ToGoInt(source, "test") + gotValue, gotErr := types.ToGoInt(source, "test") if gotErr != nil || gotValue != wantValue { t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", @@ -114,7 +119,7 @@ func TestToIntErr(t *testing.T) { wantValue := 0 wantErr := errors.New(`test expected integer, got uint64 (64)`) - gotValue, gotErr := kern.ToGoInt(source, "test") + gotValue, gotErr := types.ToGoInt(source, "test") if gotErr.Error() != wantErr.Error() || gotValue != wantValue { t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", @@ -127,7 +132,7 @@ func TestToInt64Ok(t *testing.T) { wantValue := int64(64) wantErr := error(nil) - gotValue, gotErr := kern.ToGoInt64(source, "test") + gotValue, gotErr := types.ToGoInt64(source, "test") if gotErr != nil || gotValue != wantValue { t.Errorf("toInt64(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", @@ -140,7 +145,7 @@ func TestToInt64Err(t *testing.T) { wantValue := int64(0) wantErr := errors.New(`test expected integer, got uint64 (64)`) - gotValue, gotErr := kern.ToGoInt64(source, "test") + gotValue, gotErr := types.ToGoInt64(source, "test") if gotErr.Error() != wantErr.Error() || gotValue != wantValue { t.Errorf("toInt64(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", @@ -173,7 +178,7 @@ func TestAnyInteger(t *testing.T) { failed := 0 for i, input := range inputs { - gotValue, gotOk := kern.AnyInteger(input.source) + gotValue, gotOk := types.AnyInteger(input.source) if gotOk != input.wantOk || gotValue != input.wantValue { t.Errorf("%d: anyInteger(%v) -> gotOk = %t, wantOk = %t; gotValue = %v, wantValue = %v", i+1, input.source, gotOk, input.wantOk, gotValue, input.wantValue) @@ -199,7 +204,7 @@ func TestToStringOk(t *testing.T) { wantValue := "ciao" wantErr := error(nil) - gotValue, gotErr := kern.ToGoString(source, "test") + gotValue, gotErr := str.ToGoString(source, "test") if gotErr != nil { t.Error(gotErr) @@ -210,11 +215,11 @@ func TestToStringOk(t *testing.T) { } func TestToStringErr(t *testing.T) { - source := kern.NewListA() + source := array.NewListA() wantValue := "" - wantErr := errors.New(`test expected string, got list ([])`) + wantErr := errors.New(`test expected string, got array ([])`) - gotValue, gotErr := kern.ToGoString(source, "test") + gotValue, gotErr := str.ToGoString(source, "test") if gotErr != nil && gotErr.Error() != wantErr.Error() { t.Errorf(`ToGoString(%v, "test") gotValue=%q, gotErr=%v -> wantValue=%q, wantErr=%v`, diff --git a/kern/list-type.go b/types/array/list-type.go similarity index 62% rename from kern/list-type.go rename to types/array/list-type.go index d461148..9cc93bb 100644 --- a/kern/list-type.go +++ b/types/array/list-type.go @@ -2,12 +2,13 @@ // All rights reserved. // list-type.go -package kern +package array import ( "fmt" - "reflect" "strings" + + "git.portale-stac.it/go-pkg/expr/kern" ) type ListType []any @@ -50,40 +51,40 @@ func ListFromStrings(stringList []string) (list *ListType) { return } -func (ls *ListType) ToString(opt FmtOpt) (s string) { - indent := GetFormatIndent(opt) - flags := GetFormatFlags(opt) +func (ls *ListType) ToString(opt kern.FmtOpt) (s string) { + indent := kern.GetFormatIndent(opt) + flags := kern.GetFormatFlags(opt) var sb strings.Builder sb.WriteByte('[') if len(*ls) > 0 { - innerOpt := MakeFormatOptions(flags, indent+1) + innerOpt := kern.MakeFormatOptions(flags, indent+1) nest := strings.Repeat(" ", indent+1) - if flags&MultiLine != 0 { + if flags&kern.MultiLine != 0 { sb.WriteByte('\n') sb.WriteString(nest) } for i, item := range []any(*ls) { if i > 0 { - if flags&MultiLine != 0 { + if flags&kern.MultiLine != 0 { sb.WriteString(",\n") sb.WriteString(nest) } else { sb.WriteString(", ") } } - Format(&sb, item, innerOpt) + kern.Format(&sb, item, innerOpt) } - if flags&MultiLine != 0 { + if flags&kern.MultiLine != 0 { sb.WriteByte('\n') sb.WriteString(strings.Repeat(" ", indent)) } } sb.WriteByte(']') s = sb.String() - if flags&Truncate != 0 && len(s) > TruncateSize { - s = TruncateString(s) + if flags&kern.Truncate != 0 && len(s) > kern.TruncateSize { + s = kern.TruncateString(s) } return } @@ -93,7 +94,7 @@ func (ls *ListType) String() string { } func (ls *ListType) TypeName() string { - return "list" + return kern.TypeArray } func (ls *ListType) Contains(t *ListType) (answer bool) { @@ -108,6 +109,13 @@ func (ls *ListType) Contains(t *ListType) (answer bool) { return } +func (ls *ListType) EqualTo(other kern.Equaler) (equal bool) { + if otherList, ok := other.(*ListType); ok { + equal = ls.Equals(*otherList) + } + return +} + func (ls *ListType) Equals(ls2 ListType) (answer bool) { if ls2 != nil && len(*ls) == len(ls2) { answer = true @@ -116,7 +124,7 @@ func (ls *ListType) Equals(ls2 ListType) (answer bool) { // answer = false // break // } - if !Equal(i1, ls2[index]) { + if !kern.Equal(i1, ls2[index]) { answer = false break } @@ -128,20 +136,16 @@ func (ls *ListType) Equals(ls2 ListType) (answer bool) { func (ls1 *ListType) Clone() (ls2 *ListType) { ls := make(ListType, len(*ls1)) for i, item := range *ls1 { - ls[i] = Clone(item) + ls[i] = kern.Clone(item) } ls2 = &ls return } func (ls *ListType) IndexDeepSameCmp(target any) (index int) { - var eq bool - var err error index = -1 for i, item := range *ls { - if eq, err = deepSame(item, target, SameContent); err != nil { - break - } else if eq { + if kern.Equal(item, target) { index = i break } @@ -149,6 +153,21 @@ func (ls *ListType) IndexDeepSameCmp(target any) (index int) { return } +// func (ls *ListType) IndexDeepSameCmp(target any) (index int) { +// var eq bool +// var err error +// index = -1 +// for i, item := range *ls { +// if eq, err = deepSame(item, target, SameContent); err != nil { +// break +// } else if eq { +// index = i +// break +// } +// } +// return +// } + func SameContent(a, b any) (same bool, err error) { la, _ := a.(*ListType) lb, _ := b.(*ListType) @@ -164,30 +183,30 @@ 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) { - 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) - } - } else { - var cmp int - if cmp, err = CmpAnyFract(a, b); err == nil { - eq = cmp == 0 - } - } - } else if deepCmp != nil && IsList(a) && IsList(b) { - eq, err = deepCmp(a, b) - } else { - eq = reflect.DeepEqual(a, b) - } +// func deepSame(a, b any, deepCmp kern.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) +// } +// } else { +// var cmp int +// if cmp, err = fract.CmpAnyFract(a, b); err == nil { +// eq = cmp == 0 +// } +// } +// } else if deepCmp != nil && IsList(a) && IsList(b) { +// eq, err = deepCmp(a, b) +// } else { +// eq = reflect.DeepEqual(a, b) +// } - return -} +// return +// } func (ls *ListType) SetItem(index int64, value any) (err error) { if index >= 0 && index < int64(len(*ls)) { diff --git a/kern/bool.go b/types/boolean/bool.go similarity index 67% rename from kern/bool.go rename to types/boolean/bool.go index 868d982..0c51df0 100644 --- a/kern/bool.go +++ b/types/boolean/bool.go @@ -1,14 +1,21 @@ // Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. -// string.go -package kern +// bool.go +package boolean func IsBool(v any) (ok bool) { _, ok = v.(bool) return ok } +// func (b *bool) EqualTo(other kern.Equaler) (equal bool) { +// if otherBool, ok := other.(*bool); ok { +// equal = b == otherBool +// } +// return +// } + func ToBool(v any) (b bool, ok bool) { ok = true switch x := v.(type) { diff --git a/types/clone-value.go b/types/clone-value.go new file mode 100644 index 0000000..5fb9d7f --- /dev/null +++ b/types/clone-value.go @@ -0,0 +1,36 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// clone-value.go +package types + +// import ( +// "git.portale-stac.it/go-pkg/expr/types/array" +// "git.portale-stac.it/go-pkg/expr/types/dict" +// "git.portale-stac.it/go-pkg/expr/types/list" +// ) + +// func Clone(v any) (c any) { +// if v == nil { +// return +// } +// switch unboxed := v.(type) { +// case int64: +// c = unboxed +// case float64: +// c = unboxed +// case string: +// c = unboxed +// case bool: +// c = unboxed +// case *array.ListType: +// c = unboxed.Clone() +// case *dict.DictType: +// c = unboxed.Clone() +// case *list.LinkedList: +// c = unboxed.Clone() +// default: +// c = v +// } +// return +// } diff --git a/types/compare.go b/types/compare.go new file mode 100644 index 0000000..d50f8f4 --- /dev/null +++ b/types/compare.go @@ -0,0 +1,52 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// compare.go +package types + +import ( + "reflect" + + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/boolean" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/list" + "git.portale-stac.it/go-pkg/expr/types/str" +) + +func Equal(value1, value2 any) (equal bool) { + if value1 == nil && value2 == nil { + equal = true + } else if value1 == nil || value2 == nil { + equal = false + } else if boolean.IsBool(value1) && boolean.IsBool(value2) { + equal = value1.(bool) == value2.(bool) + } else if array.IsList(value1) && array.IsList(value2) { + ls1 := value1.(*array.ListType) + ls2 := value2.(*array.ListType) + equal = ls1.Equals(*ls2) + } else if dict.IsDict(value1) && dict.IsDict(value2) { + d1 := value1.(*dict.DictType) + d2 := value2.(*dict.DictType) + equal = d1.Equals(*d2) + } else if list.IsLinkedList(value1) && list.IsLinkedList(value2) { + ll1 := value1.(*list.LinkedList) + ll2 := value2.(*list.LinkedList) + equal = ll1.Equals(ll2) + } else if IsInteger(value1) && IsInteger(value2) { + equal = value1.(int64) == value2.(int64) + } else if str.IsString(value1) && str.IsString(value2) { + equal = value1.(string) == value2.(string) + } else if float.IsFloat(value1) && float.IsFloat(value2) { + equal = value1.(float64) == value2.(float64) + } else if IsNumOrFract(value1) && IsNumOrFract(value2) { + if eq, err := fract.CmpAnyFract(value1, value2); err == nil { + equal = eq == 0 + } + } else if !reflect.DeepEqual(value1, value2) { + equal = false + } + return +} diff --git a/kern/dict-type.go b/types/dict/dict-type.go similarity index 80% rename from kern/dict-type.go rename to types/dict/dict-type.go index a1d87b8..8b73a9a 100644 --- a/kern/dict-type.go +++ b/types/dict/dict-type.go @@ -2,12 +2,14 @@ // All rights reserved. // dict-type.go -package kern +package dict import ( "fmt" "reflect" "strings" + + "git.portale-stac.it/go-pkg/expr/kern" ) const DictTypeName = "dict" @@ -39,7 +41,7 @@ func NewDict(dictAny map[any]any) (dict *DictType) { return } -func newDict(dictAny map[any]Term) (dict *DictType) { +func newDict(dictAny map[any]kern.Term) (dict *DictType) { // TODO Change with a call to NewDict() var d DictType if dictAny != nil { @@ -54,14 +56,14 @@ func newDict(dictAny map[any]Term) (dict *DictType) { return } -func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) { - indent := GetFormatIndent(opt) - flags := GetFormatFlags(opt) +func (dict *DictType) toMultiLine(sb *strings.Builder, opt kern.FmtOpt) { + indent := kern.GetFormatIndent(opt) + flags := kern.GetFormatFlags(opt) //sb.WriteString(strings.Repeat(" ", indent)) sb.WriteByte('{') if len(*dict) > 0 { - innerOpt := MakeFormatOptions(flags, indent+1) + innerOpt := kern.MakeFormatOptions(flags, indent+1) nest := strings.Repeat(" ", indent+1) sb.WriteByte('\n') @@ -83,9 +85,9 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) { fmt.Fprintf(sb, "%v", name) } sb.WriteString(": ") - if f, ok := value.(Formatter); ok { + if f, ok := value.(kern.Formatter); ok { sb.WriteString(f.ToString(innerOpt)) - } else if _, ok = value.(Functor); ok { + } else if _, ok = value.(kern.Functor); ok { sb.WriteString("func(){}") } else { fmt.Fprintf(sb, "%v", value) @@ -97,10 +99,10 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) { sb.WriteString("}") } -func (dict *DictType) ToString(opt FmtOpt) string { +func (dict *DictType) ToString(opt kern.FmtOpt) string { var sb strings.Builder - flags := GetFormatFlags(opt) - if flags&MultiLine != 0 { + flags := kern.GetFormatFlags(opt) + if flags&kern.MultiLine != 0 { dict.toMultiLine(&sb, opt) } else { sb.WriteByte('{') @@ -119,9 +121,9 @@ func (dict *DictType) ToString(opt FmtOpt) string { fmt.Fprintf(&sb, "%v", key) } sb.WriteString(": ") - if formatter, ok := value.(Formatter); ok { + if formatter, ok := value.(kern.Formatter); ok { sb.WriteString(formatter.ToString(opt)) - } else if t, ok := value.(Term); ok { + } else if t, ok := value.(kern.Term); ok { sb.WriteString(t.String()) } else { fmt.Fprintf(&sb, "%#v", value) @@ -161,7 +163,7 @@ func (dict *DictType) GetItem(key any) (value any, exists bool) { func (dict *DictType) Clone() (c *DictType) { c = newDict(nil) for k, v := range *dict { - (*c)[k] = Clone(v) + (*c)[k] = kern.Clone(v) } return } @@ -179,7 +181,7 @@ func (dict *DictType) Equals(dict2 DictType) (answer bool) { answer = true for key, value1 := range *dict { if value2, exists := dict2.GetItem(key); exists { - if !Equal(value1, value2) { + if !kern.Equal(value1, value2) { answer = false break } @@ -194,6 +196,6 @@ func (dict *DictType) Equals(dict2 DictType) (answer bool) { //////////////// -type DictFormat interface { - ToDict() *DictType -} +// type DictFormat interface { +// ToDict() *DictType +// } diff --git a/kern/float.go b/types/float/float.go similarity index 96% rename from kern/float.go rename to types/float/float.go index 813e93d..e4a9a7c 100644 --- a/kern/float.go +++ b/types/float/float.go @@ -2,7 +2,7 @@ // All rights reserved. // float.go -package kern +package float func IsFloat(v any) (ok bool) { _, ok = v.(float64) diff --git a/kern/fraction-type.go b/types/fract/fraction-type.go similarity index 84% rename from kern/fraction-type.go rename to types/fract/fraction-type.go index e44adcb..7ec96c3 100644 --- a/kern/fraction-type.go +++ b/types/fract/fraction-type.go @@ -2,7 +2,7 @@ // All rights reserved. // fraction-type.go -package kern +package fract //https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html @@ -12,6 +12,8 @@ import ( "math" "strconv" "strings" + + "git.portale-stac.it/go-pkg/expr/kern" ) type FractionType struct { @@ -23,6 +25,18 @@ func NewFraction(num, den int64) *FractionType { return &FractionType{num, den} } +func (fr *FractionType) EqualTo(other kern.Equaler) (equal bool) { + if otherFract, ok := other.(*FractionType); ok && otherFract != nil { + equal = fr.Equals(*otherFract) + } + return +} + +func (fr *FractionType) Equals(other FractionType) bool { + // return fr.num*other.den == other.num*fr.den + return fr.num == other.num && fr.den == other.den +} + func Float64ToFraction(f float64) (fract *FractionType, err error) { var sign string intPart, decPart := math.Modf(f) @@ -72,7 +86,7 @@ func MakeGeneratingFraction(s string) (f *FractionType, err error) { } for _, c := range dec[0:lsd] { if c < '0' || c > '9' { - return nil, ErrExpectedGot("fract", "digit", c) + return nil, kern.ErrExpectedGot("fract", "digit", c) } num = num*10 + int64(c-'0') den = den * 10 @@ -83,7 +97,7 @@ func MakeGeneratingFraction(s string) (f *FractionType, err error) { mul := int64(1) for _, c := range subParts[0] { if c < '0' || c > '9' { - return nil, ErrExpectedGot("fract", "digit", c) + return nil, kern.ErrExpectedGot("fract", "digit", c) } num = num*10 + int64(c-'0') sub = sub*10 + int64(c-'0') @@ -96,7 +110,7 @@ func MakeGeneratingFraction(s string) (f *FractionType, err error) { p := subParts[1][0 : len(subParts[1])-1] for _, c := range p { if c < '0' || c > '9' { - return nil, ErrExpectedGot("fract", "digit", c) + return nil, kern.ErrExpectedGot("fract", "digit", c) } num = num*10 + int64(c-'0') den = den*10 + 9 @@ -114,37 +128,37 @@ exit: return } -func (f *FractionType) N() int64 { - return f.num +func (fr *FractionType) N() int64 { + return fr.num } -func (f *FractionType) D() int64 { - return f.den +func (fr *FractionType) D() int64 { + return fr.den } -func (f *FractionType) ToFloat() float64 { - return float64(f.num) / float64(f.den) +func (fr *FractionType) ToFloat() float64 { + return float64(fr.num) / float64(fr.den) } -func (f *FractionType) String() string { - return f.ToString(0) +func (fr *FractionType) String() string { + return fr.ToString(0) } -func (f *FractionType) ToString(opt FmtOpt) string { +func (fr *FractionType) ToString(opt kern.FmtOpt) string { var sb strings.Builder - if opt&MultiLine == 0 { - sb.WriteString(fmt.Sprintf("%d:%d", f.num, f.den)) + if opt&kern.MultiLine == 0 { + sb.WriteString(fmt.Sprintf("%d:%d", fr.num, fr.den)) } else { var sign, num string - if f.num < 0 && opt&TTY == 0 { - num = strconv.FormatInt(-f.num, 10) + if fr.num < 0 && opt&kern.TTY == 0 { + num = strconv.FormatInt(-fr.num, 10) sign = "-" } else { - num = strconv.FormatInt(f.num, 10) + num = strconv.FormatInt(fr.num, 10) } - den := strconv.FormatInt(f.den, 10) + den := strconv.FormatInt(fr.den, 10) size := max(len(num), len(den)) - if opt&TTY != 0 { + if opt&kern.TTY != 0 { sNum := fmt.Sprintf("\x1b[4m%[1]*s\x1b[0m\n", -size, fmt.Sprintf("%[1]*s", (size+len(num))/2, sign+num)) sb.WriteString(sNum) } else { @@ -170,7 +184,7 @@ func (f *FractionType) ToString(opt FmtOpt) string { return sb.String() } -func (f *FractionType) TypeName() string { +func (fr *FractionType) TypeName() string { return "fraction" } @@ -224,7 +238,7 @@ func anyToFract(v any) (f *FractionType, err error) { } else if dec, ok := v.(float64); ok { f, err = Float64ToFraction(dec) } else { - err = ErrExpectedGot("fract", TypeFraction, v) + err = kern.ErrExpectedGot("fract", kern.TypeFraction, v) } } return diff --git a/kern/linked-list-type.go b/types/list/linked-list-type.go similarity index 69% rename from kern/linked-list-type.go rename to types/list/linked-list-type.go index adc69c6..2bc5c9e 100644 --- a/kern/linked-list-type.go +++ b/types/list/linked-list-type.go @@ -2,14 +2,15 @@ // All rights reserved. // linked-list-type.go -package kern +package list import ( "strings" + + "git.portale-stac.it/go-pkg/expr/kern" ) const LinkedListTypeName = "lisked-list" -const MaxUint64Allowed = uint64(9_223_372_036_854_775_807) func IsLinkedList(v any) (ok bool) { _, ok = v.(*LinkedList) @@ -22,7 +23,7 @@ func NewLinkedListA(listAny ...any) (list *LinkedList) { } list = NewLinkedList() for _, item := range listAny { - list.PushBack(FixAnyNumber(item)) + list.PushBack(kern.FixAnyNumber(item)) } return } @@ -35,17 +36,17 @@ func LinkedListFromStrings(stringList []string) (list *LinkedList) { return } -func (ls *LinkedList) ToString(opt FmtOpt) (s string) { - indent := GetFormatIndent(opt) - flags := GetFormatFlags(opt) +func (ls *LinkedList) ToString(opt kern.FmtOpt) (s string) { + indent := kern.GetFormatIndent(opt) + flags := kern.GetFormatFlags(opt) var sb strings.Builder sb.WriteString("[<") if ls.Len() > 0 { - innerOpt := MakeFormatOptions(flags, indent+1) + innerOpt := kern.MakeFormatOptions(flags, indent+1) nest := strings.Repeat(" ", indent+1) - if flags&MultiLine != 0 { + if flags&kern.MultiLine != 0 { sb.WriteByte('\n') sb.WriteString(nest) } @@ -53,35 +54,26 @@ func (ls *LinkedList) ToString(opt FmtOpt) (s string) { i := 0 for item := ls.FirstNode(); item != nil; item = item.Next() { if i > 0 { - if flags&MultiLine != 0 { + if flags&kern.MultiLine != 0 { sb.WriteString(",\n") sb.WriteString(nest) } else { sb.WriteString(", ") } } - // data := item.Data() - // if s, ok := data.(string); ok { - // sb.WriteByte('"') - // sb.WriteString(s) - // sb.WriteByte('"') - // } else if formatter, ok := data.(Formatter); ok { - // sb.WriteString(formatter.ToString(innerOpt)) - // } else { - // fmt.Fprintf(&sb, "%v", data) - // } - Format(&sb, item.Data(), innerOpt) + + kern.Format(&sb, item.Data(), innerOpt) i++ } - if flags&MultiLine != 0 { + if flags&kern.MultiLine != 0 { sb.WriteByte('\n') sb.WriteString(strings.Repeat(" ", indent)) } } sb.WriteString(">]") s = sb.String() - if flags&Truncate != 0 && len(s) > TruncateSize { - s = TruncateString(s) + if flags&kern.Truncate != 0 && len(s) > kern.TruncateSize { + s = kern.TruncateString(s) } return } @@ -111,7 +103,7 @@ func (ls1 *LinkedList) Equals(ls2 *LinkedList) (answer bool) { answer = true i2 := ls2.FirstNode() for i1 := ls1.FirstNode(); i1 != nil; i1 = i1.Next() { - if !Equal(i1.Data(), i2.Data()) { + if !kern.Equal(i1.Data(), i2.Data()) { answer = false break } @@ -124,7 +116,7 @@ func (ls1 *LinkedList) Equals(ls2 *LinkedList) (answer bool) { func (ls1 *LinkedList) Clone() (ls2 *LinkedList) { ls2 = NewLinkedListA() for i1 := ls1.FirstNode(); i1 != nil; i1 = i1.Next() { - ls2.PushBack(Clone(i1.Data())) + ls2.PushBack(kern.Clone(i1.Data())) } return } diff --git a/kern/linked-list.go b/types/list/linked-list.go similarity index 94% rename from kern/linked-list.go rename to types/list/linked-list.go index 5bfd9d0..6feb7c5 100644 --- a/kern/linked-list.go +++ b/types/list/linked-list.go @@ -1,8 +1,13 @@ -// simple-list project slist.go -package kern +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// linked-list.go +package list import ( "fmt" + + "git.portale-stac.it/go-pkg/expr/kern" ) type ListNode struct { @@ -48,7 +53,7 @@ func (ls *LinkedList) PushFront(data any) *ListNode { func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) { switch seq := data.(type) { - case Iterator: + case kern.Iterator: result = ls.IterPushFront(seq) default: ls.PushFront(data) @@ -57,7 +62,7 @@ func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) { return } -func (ls *LinkedList) IterPushFront(it Iterator) *LinkedList { +func (ls *LinkedList) IterPushFront(it kern.Iterator) *LinkedList { for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() { ls.PushFront(item) } @@ -79,7 +84,7 @@ func (ls *LinkedList) PushBack(data any) (node *ListNode) { func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) { switch seq := data.(type) { - case Iterator: + case kern.Iterator: result = ls.IterPushBack(seq) default: ls.PushBack(data) @@ -88,7 +93,7 @@ func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) { return } -func (ls *LinkedList) IterPushBack(it Iterator) *LinkedList { +func (ls *LinkedList) IterPushBack(it kern.Iterator) *LinkedList { for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() { ls.PushBack(item) } diff --git a/kern/number.go b/types/number.go similarity index 64% rename from kern/number.go rename to types/number.go index 30ba440..fce19c8 100644 --- a/kern/number.go +++ b/types/number.go @@ -2,10 +2,15 @@ // All rights reserved. // number.go -package kern +package types import ( "fmt" + + "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/float" + "git.portale-stac.it/go-pkg/expr/types/fract" + "git.portale-stac.it/go-pkg/expr/types/str" ) func IsInteger(v any) (ok bool) { @@ -14,21 +19,21 @@ func IsInteger(v any) (ok bool) { } func IsNumber(v any) (ok bool) { - return IsFloat(v) || IsInteger(v) + return float.IsFloat(v) || IsInteger(v) } func IsNumOrFract(v any) (ok bool) { - return IsFloat(v) || IsInteger(v) || IsFraction(v) + return float.IsFloat(v) || IsInteger(v) || fract.IsFraction(v) } func IsNumberString(v any) (ok bool) { - return IsString(v) || IsNumber(v) + return str.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 { + if fract, ok := v.(*fract.FractionType); ok { f = fract.ToFloat() } else { i, _ := v.(int64) @@ -65,45 +70,13 @@ func AnyInteger(v any) (i int64, ok bool) { return } -func FixAnyNumber(v any) (fixed any) { - switch unboxed := v.(type) { - case int: - fixed = int64(unboxed) - case int8: - fixed = int64(unboxed) - case int16: - fixed = int64(unboxed) - case int32: - fixed = int64(unboxed) - case uint: - fixed = int64(unboxed) - case uint8: - fixed = int64(unboxed) - case uint16: - fixed = int64(unboxed) - case uint32: - fixed = int64(unboxed) - case uint64: - if unboxed <= MaxUint64Allowed { - fixed = int64(unboxed) - } else { - fixed = float64(unboxed) - } - case float32: - fixed = float64(unboxed) - default: - fixed = v - } - 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) + err = fmt.Errorf("%s expected integer, got %s (%v)", description, kern.TypeName(value), value) } return } @@ -114,7 +87,7 @@ func ToGoInt64(value any, description string) (i int64, err error) { } else if valueInt, ok := value.(int); ok { i = int64(valueInt) } else { - err = fmt.Errorf("%s expected integer, got %s (%v)", description, TypeName(value), value) + err = fmt.Errorf("%s expected integer, got %s (%v)", description, kern.TypeName(value), value) } return } diff --git a/kern/string.go b/types/str/string.go similarity index 82% rename from kern/string.go rename to types/str/string.go index 00f48d8..d5bc554 100644 --- a/kern/string.go +++ b/types/str/string.go @@ -2,10 +2,12 @@ // All rights reserved. // string.go -package kern +package str import ( "fmt" + + "git.portale-stac.it/go-pkg/expr/kern" ) func IsString(v any) (ok bool) { @@ -17,7 +19,7 @@ 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) + err = fmt.Errorf("%s expected string, got %s (%v)", description, kern.TypeName(value), value) } return } diff --git a/types/types.go b/types/types.go new file mode 100644 index 0000000..f4f5d3f --- /dev/null +++ b/types/types.go @@ -0,0 +1,20 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// types.go +package types + +// func TypeName(v any) (name string) { +// if v == nil { +// name = "nil" +// } else if typer, ok := v.(kern.Typer); ok { +// name = typer.TypeName() +// } else if IsInteger(v) { +// name = "integer" +// } else if float.IsFloat(v) { +// name = "float" +// } else { +// name = fmt.Sprintf("%T", v) +// } +// return +// } diff --git a/types/util.go b/types/util.go new file mode 100644 index 0000000..692d01e --- /dev/null +++ b/types/util.go @@ -0,0 +1,41 @@ +// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// dict-type.go +package types + +import ( + "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types/dict" +) + +func ContextToDict(ctx kern.ExprContext) (dt *dict.DictType) { + var keys []string + // Variables + keys = ctx.EnumVars(nil) + vars := dict.MakeDict() + for _, key := range keys { + value, _ := ctx.GetVar(key) + vars.SetItem(key, value) + } + + // Functions + keys = ctx.EnumFuncs(func(name string) bool { return true }) + funcs := dict.MakeDict() + for _, key := range keys { + funcInfo, _ := ctx.GetFuncInfo(key) + funcs.SetItem(key, funcInfo) + } + + dt = dict.MakeDict() + dt.SetItem("vars", vars) + dt.SetItem("funcs", funcs) + return +} + +func ContextToString(ctx kern.ExprContext, opt kern.FmtOpt) string { + if dict, ok := ctx.ToDict().(*dict.DictType); ok { + return dict.ToString(opt) + } + return "" +} diff --git a/util/utils.go b/util/utils.go index 6712123..d6327b6 100644 --- a/util/utils.go +++ b/util/utils.go @@ -7,7 +7,10 @@ package util import ( "reflect" - "git.portale-stac.it/go-pkg/expr/kern" + "git.portale-stac.it/go-pkg/expr/types" + "git.portale-stac.it/go-pkg/expr/types/array" + "git.portale-stac.it/go-pkg/expr/types/dict" + "git.portale-stac.it/go-pkg/expr/types/float" ) func IsFunc(v any) bool { @@ -22,16 +25,16 @@ func FromGenericAny(v any) (exprAny any, ok bool) { if exprAny, ok = v.(string); ok { return } - if exprAny, ok = kern.AnyInteger(v); ok { + if exprAny, ok = types.AnyInteger(v); ok { return } - if exprAny, ok = kern.AnyFloat(v); ok { + if exprAny, ok = float.AnyFloat(v); ok { return } - if exprAny, ok = v.(*kern.DictType); ok { + if exprAny, ok = v.(*dict.DictType); ok { return } - if exprAny, ok = v.(*kern.ListType); ok { + if exprAny, ok = v.(*array.ListType); ok { return } }