refactored data-types to reduce plugin sizes
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
+29
-21
@@ -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)
|
||||
|
||||
+5
-3
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+25
-21
@@ -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
|
||||
|
||||
+9
-7
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+7
-4
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -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
|
||||
|
||||
+3
-2
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -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)
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+4
-3
@@ -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 {
|
||||
|
||||
+6
-3
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package kern
|
||||
|
||||
const (
|
||||
TypeAny = "any"
|
||||
TypeArray = "array"
|
||||
TypeNil = "nil"
|
||||
TypeBoolean = "boolean"
|
||||
TypeFloat = "float"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
}
|
||||
+1
-30
@@ -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)
|
||||
}
|
||||
|
||||
+4
-23
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+7
-4
@@ -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))
|
||||
|
||||
+9
-6
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-1
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
+14
-12
@@ -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")
|
||||
|
||||
+2
-1
@@ -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 {
|
||||
|
||||
+10
-9
@@ -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)
|
||||
|
||||
+2
-1
@@ -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 {
|
||||
|
||||
+2
-1
@@ -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)
|
||||
}
|
||||
|
||||
+3
-17
@@ -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()
|
||||
|
||||
+2
-1
@@ -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++ {
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+9
-6
@@ -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)
|
||||
|
||||
+7
-5
@@ -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)
|
||||
|
||||
+6
-4
@@ -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++
|
||||
|
||||
+20
-16
@@ -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
|
||||
|
||||
|
||||
+24
-22
@@ -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)
|
||||
}
|
||||
|
||||
+10
-12
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+25
-20
@@ -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()
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+23
-18
@@ -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)
|
||||
}
|
||||
|
||||
+3
-2
@@ -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
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
+33
-27
@@ -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)
|
||||
|
||||
+3
-2
@@ -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
|
||||
|
||||
+2
-2
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
+4
-3
@@ -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 {
|
||||
|
||||
+10
-10
@@ -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", ".")
|
||||
|
||||
+19
-17
@@ -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},
|
||||
}
|
||||
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -98,12 +98,14 @@ func doTest(t *testing.T, ctx kern.ExprContext, section string, input *inputType
|
||||
gotResult, gotErr = ast.Eval(ctx)
|
||||
}
|
||||
|
||||
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 gotErr != wantErr {
|
||||
if wantErr == nil || gotErr == nil || (gotErr.Error() != wantErr.Error()) {
|
||||
|
||||
+3
-3
@@ -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},
|
||||
}
|
||||
|
||||
|
||||
+20
-17
@@ -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)
|
||||
|
||||
|
||||
+2
-2
@@ -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},
|
||||
|
||||
+15
-14
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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", ".")
|
||||
|
||||
+3
-3
@@ -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},
|
||||
}
|
||||
|
||||
+19
-19
@@ -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)
|
||||
}
|
||||
|
||||
+15
-12
@@ -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`},
|
||||
}
|
||||
|
||||
|
||||
+28
-27
@@ -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", ".")
|
||||
|
||||
+39
-37
@@ -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},
|
||||
}
|
||||
|
||||
+4
-3
@@ -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>' [nil]`},
|
||||
/* 124 */ {`x ?! (x+1)`, nil, nil},
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+3
-3
@@ -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"},
|
||||
}
|
||||
|
||||
|
||||
+23
-18
@@ -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`,
|
||||
|
||||
@@ -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)) {
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
// }
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
// }
|
||||
@@ -2,7 +2,7 @@
|
||||
// All rights reserved.
|
||||
|
||||
// float.go
|
||||
package kern
|
||||
package float
|
||||
|
||||
func IsFloat(v any) (ok bool) {
|
||||
_, ok = v.(float64)
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
// }
|
||||
@@ -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 ""
|
||||
}
|
||||
+8
-5
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user