refactored data-types to reduce plugin sizes

This commit is contained in:
2026-06-08 07:02:56 +02:00
parent fec7cc546c
commit b6da9bcad4
90 changed files with 1039 additions and 803 deletions
+9 -7
View File
@@ -10,10 +10,12 @@ import (
"slices" "slices"
"git.portale-stac.it/go-pkg/expr/kern" "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 { type ListIterator struct {
a *kern.ListType a *array.ListType
count int64 count int64
index int64 index int64
start int64 start int64
@@ -21,7 +23,7 @@ type ListIterator struct {
step int64 step int64
} }
func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) { func NewListIterator(list *array.ListType, args []any) (it *ListIterator) {
var argc int = 0 var argc int = 0
listLen := int64(len(([]any)(*list))) listLen := int64(len(([]any)(*list)))
if args != nil { 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} it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1}
if argc >= 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 { if i < 0 {
i = listLen + i i = listLen + i
} }
it.start = i it.start = i
} }
if argc >= 2 { 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 { if i < 0 {
i = listLen + i i = listLen + i
} }
it.stop = i it.stop = i
} }
if argc >= 3 { 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 { if i < 0 {
i = -i i = -i
} }
@@ -60,8 +62,8 @@ func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) {
return return
} }
func NewArrayIterator(array []any) (it *ListIterator) { func NewArrayIterator(a []any) (it *ListIterator) {
it = &ListIterator{a: (*kern.ListType)(&array), count: 0, index: -1, start: 0, stop: int64(len(array)) - 1, step: 1} it = &ListIterator{a: (*array.ListType)(&a), count: 0, index: -1, start: 0, stop: int64(len(a)) - 1, step: 1}
return return
} }
+29 -21
View File
@@ -12,6 +12,14 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 ( 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) { 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 return
} }
func isFloatFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
func isBoolFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
func isStringFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
func isFractionFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
func isRationalFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
func isListFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
func isDictionaryFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) { 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 return
} }
@@ -67,7 +75,7 @@ func boolFunc(ctx kern.ExprContext, name string, args map[string]any) (result an
switch v := args[kern.ParamValue].(type) { switch v := args[kern.ParamValue].(type) {
case int64: case int64:
result = (v != 0) result = (v != 0)
case *kern.FractionType: case *fract.FractionType:
result = v.N() != 0 result = v.N() != 0
case float64: case float64:
result = v != 0.0 result = v != 0.0
@@ -75,9 +83,9 @@ func boolFunc(ctx kern.ExprContext, name string, args map[string]any) (result an
result = v result = v
case string: case string:
result = len(v) > 0 result = len(v) > 0
case *kern.ListType: case *array.ListType:
result = len(*v) > 0 result = len(*v) > 0
case *kern.DictType: case *dict.DictType:
result = len(*v) > 0 result = len(*v) > 0
default: default:
err = kern.ErrCantConvert(name, v, "bool") 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 { if i, err = strconv.Atoi(v); err == nil {
result = int64(i) result = int64(i)
} }
case *kern.FractionType: case *fract.FractionType:
result = int64(v.N() / v.D()) result = int64(v.N() / v.D())
default: default:
err = kern.ErrCantConvert(name, v, "int") 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 { if f, err = strconv.ParseFloat(v, 64); err == nil {
result = f result = f
} }
case *kern.FractionType: case *fract.FractionType:
result = v.ToFloat() result = v.ToFloat()
default: default:
err = kern.ErrCantConvert(name, v, "float") err = kern.ErrCantConvert(name, v, "float")
@@ -149,7 +157,7 @@ func stringFunc(ctx kern.ExprContext, name string, args map[string]any) (result
} }
case string: case string:
result = v result = v
case *kern.FractionType: case *fract.FractionType:
result = v.ToString(0) result = v.ToString(0)
case kern.Formatter: case kern.Formatter:
result = v.ToString(0) result = v.ToString(0)
@@ -174,19 +182,19 @@ func fractFunc(ctx kern.ExprContext, name string, args map[string]any) (result a
} }
if err == nil { if err == nil {
result = kern.NewFraction(v, den) result = fract.NewFraction(v, den)
} }
case float64: case float64:
result, err = kern.Float64ToFraction(v) result, err = fract.Float64ToFraction(v)
case bool: case bool:
if v { if v {
result = kern.NewFraction(1, 1) result = fract.NewFraction(1, 1)
} else { } else {
result = kern.NewFraction(0, 1) result = fract.NewFraction(0, 1)
} }
case string: case string:
result, err = kern.MakeGeneratingFraction(v) result, err = fract.MakeGeneratingFraction(v)
case *kern.FractionType: case *fract.FractionType:
result = v result = v
default: default:
err = kern.ErrCantConvert(name, v, "float") 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) { 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) items := args[kern.ParamValue].([]any)
for _, arg := range items { for _, arg := range items {
list.PushBack(arg) list.PushBack(arg)
+5 -3
View File
@@ -9,6 +9,8 @@ import (
"io" "io"
"git.portale-stac.it/go-pkg/expr/kern" "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 ( const (
@@ -32,8 +34,8 @@ func parseRunArgs(localCtx kern.ExprContext, args map[string]any) (it kern.Itera
} }
} }
var vars *kern.DictType var vars *dict.DictType
if vars, ok = args[iterParamVars].(*kern.DictType); !ok && args[iterParamVars] != nil { 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])) err = fmt.Errorf("paramter %q must be a dictionary, passed %v [%s]", iterParamVars, args[iterParamVars], kern.TypeName(args[iterParamVars]))
return return
} }
@@ -73,7 +75,7 @@ func runFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
break break
} else { } else {
var success bool var success bool
if success, ok = kern.ToBool(v); !success || !ok { if success, ok = boolean.ToBool(v); !success || !ok {
break break
} }
} }
+25 -21
View File
@@ -9,10 +9,14 @@ import (
"io" "io"
"git.portale-stac.it/go-pkg/expr/kern" "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) { 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", err = fmt.Errorf("%s(): param nr %d (%d in %d) has wrong type %T, number expected",
funcName, paramPos+1, subPos+1, level, paramValue) 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 sumAsFloat, sumAsFract bool
var floatSum float64 = 0.0 var floatSum float64 = 0.0
var intSum int64 = 0 var intSum int64 = 0
var fractSum *kern.FractionType var fractSum *fract.FractionType
var v any var v any
level++ level++
for v, err = it.Next(); err == nil; v, err = it.Next() { 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) v = NewListIterator(list, nil)
} }
if subIter, ok := v.(kern.Iterator); ok { 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++ count++
if !sumAsFloat { if !sumAsFloat {
if kern.IsFloat(v) { if float.IsFloat(v) {
sumAsFloat = true sumAsFloat = true
if sumAsFract { if sumAsFract {
floatSum = fractSum.ToFloat() floatSum = fractSum.ToFloat()
} else { } else {
floatSum = float64(intSum) floatSum = float64(intSum)
} }
} else if !sumAsFract && kern.IsFraction(v) { } else if !sumAsFract && fract.IsFraction(v) {
fractSum = kern.NewFraction(intSum, 1) fractSum = fract.NewFraction(intSum, 1)
sumAsFract = true sumAsFract = true
} }
} }
if sumAsFloat { if sumAsFloat {
floatSum += kern.NumAsFloat(v) floatSum += types.NumAsFloat(v)
} else if sumAsFract { } else if sumAsFract {
var item *kern.FractionType var item *fract.FractionType
var ok bool var ok bool
if item, ok = v.(*kern.FractionType); !ok { if item, ok = v.(*fract.FractionType); !ok {
iv, _ := v.(int64) iv, _ := v.(int64)
item = kern.NewFraction(iv, 1) item = fract.NewFraction(iv, 1)
} }
fractSum = kern.SumFract(fractSum, item) fractSum = fract.SumFract(fractSum, item)
} else { } else {
iv, _ := v.(int64) iv, _ := v.(int64)
intSum += iv intSum += iv
@@ -98,12 +102,12 @@ func doMul(ctx kern.ExprContext, name string, it kern.Iterator, count, level int
var mulAsFloat, mulAsFract bool var mulAsFloat, mulAsFract bool
var floatProd float64 = 1.0 var floatProd float64 = 1.0
var intProd int64 = 1 var intProd int64 = 1
var fractProd *kern.FractionType var fractProd *fract.FractionType
var v any var v any
level++ level++
for v, err = it.Next(); err == nil; v, err = it.Next() { 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) v = NewListIterator(list, nil)
} }
if subIter, ok := v.(kern.Iterator); ok { 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++ count++
if !mulAsFloat { if !mulAsFloat {
if kern.IsFloat(v) { if float.IsFloat(v) {
mulAsFloat = true mulAsFloat = true
if mulAsFract { if mulAsFract {
floatProd = fractProd.ToFloat() floatProd = fractProd.ToFloat()
} else { } else {
floatProd = float64(intProd) floatProd = float64(intProd)
} }
} else if !mulAsFract && kern.IsFraction(v) { } else if !mulAsFract && fract.IsFraction(v) {
fractProd = kern.NewFraction(intProd, 1) fractProd = fract.NewFraction(intProd, 1)
mulAsFract = true mulAsFract = true
} }
} }
if mulAsFloat { if mulAsFloat {
floatProd *= kern.NumAsFloat(v) floatProd *= types.NumAsFloat(v)
} else if mulAsFract { } else if mulAsFract {
var item *kern.FractionType var item *fract.FractionType
var ok bool var ok bool
if item, ok = v.(*kern.FractionType); !ok { if item, ok = v.(*fract.FractionType); !ok {
iv, _ := v.(int64) iv, _ := v.(int64)
item = kern.NewFraction(iv, 1) item = fract.NewFraction(iv, 1)
} }
fractProd = kern.MulFract(fractProd, item) fractProd = fract.MulFract(fractProd, item)
} else { } else {
iv, _ := v.(int64) iv, _ := v.(int64)
intProd *= iv intProd *= iv
+9 -7
View File
@@ -10,6 +10,8 @@ import (
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern" "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 ( const (
@@ -43,8 +45,8 @@ func joinStrFunc(ctx kern.ExprContext, name string, args map[string]any) (result
if v, exists := args[kern.ParamItem]; exists { if v, exists := args[kern.ParamItem]; exists {
argv := v.([]any) argv := v.([]any)
if len(argv) == 1 { if len(argv) == 1 {
if ls, ok := argv[0].(*kern.ListType); ok { if a, ok := argv[0].(*array.ListType); ok {
result, err = doJoinStr(name, sep, NewListIterator(ls, nil)) result, err = doJoinStr(name, sep, NewListIterator(a, nil))
} else if it, ok := argv[0].(kern.Iterator); ok { } else if it, ok := argv[0].(kern.Iterator); ok {
result, err = doJoinStr(name, sep, it) result, err = doJoinStr(name, sep, it)
} else if s, ok := argv[0].(string); ok { } 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]) 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 return
} }
if count, err = kern.ToGoInt(args[kern.ParamCount], name+"()"); err != nil { if count, err = types.ToGoInt(args[kern.ParamCount], name+"()"); err != nil {
return return
} }
@@ -194,11 +196,11 @@ func splitStrFunc(ctx kern.ExprContext, name string, args map[string]any) (resul
} else { } else {
parts = []string{} parts = []string{}
} }
list := make(kern.ListType, len(parts)) a := make(array.ListType, len(parts))
for i, part := range parts { for i, part := range parts {
list[i] = part a[i] = part
} }
result = &list result = &a
return return
} }
+3
View File
@@ -3,6 +3,9 @@
//go:build graph //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 // graph.go
package main package main
+7 -4
View File
@@ -14,6 +14,9 @@ import (
"git.portale-stac.it/go-pkg/expr" "git.portale-stac.it/go-pkg/expr"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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" "git.portale-stac.it/go-pkg/utils"
// https://pkg.go.dev/github.com/ergochat/readline#section-readme // 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) { func printResult(opt *Options, result any) {
if f, ok := result.(kern.Formatter); ok { if f, ok := result.(kern.Formatter); ok {
fmt.Println(f.ToString(opt.formOpt)) fmt.Println(f.ToString(opt.formOpt))
} else if kern.IsInteger(result) { } else if types.IsInteger(result) {
fmt.Printf(opt.baseVerb, result) fmt.Printf(opt.baseVerb, result)
fmt.Println() fmt.Println()
} else if kern.IsString(result) { } else if str.IsString(result) {
fmt.Printf("\"%s\"\n", result) fmt.Printf("\"%s\"\n", result)
} else { } else {
fmt.Println(result) fmt.Println(result)
@@ -257,7 +260,7 @@ func registerLocalFunctions(ctx kern.ExprContext) {
vars := ctx.EnumVars(func(name string) bool { vars := ctx.EnumVars(func(name string) bool {
return len(name) > 0 && name[0] == '_' return len(name) > 0 && name[0] == '_'
}) })
result = kern.ListFromStrings(vars) result = array.ListFromStrings(vars)
return return
} }
@@ -309,7 +312,7 @@ func registerLocalFunctions(ctx kern.ExprContext) {
name, _, _ := strings.Cut(e, "=") name, _, _ := strings.Cut(e, "=")
vars = append(vars, name) vars = append(vars, name)
} }
result = kern.ListFromStrings(vars) result = array.ListFromStrings(vars)
return return
} }
+9 -6
View File
@@ -11,6 +11,9 @@ import (
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern" "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 type dictIterMode int
@@ -22,7 +25,7 @@ const (
) )
type DictIterator struct { type DictIterator struct {
a *kern.DictType a *dict.DictType
count int64 count int64
index int64 index int64
keys []any 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 sortType = sortTypeNone
var s string var s string
var argAny any var argAny any
@@ -78,7 +81,7 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err
} else { } else {
argAny = "default" 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) { switch strings.ToLower(s) {
case "a", "asc": case "a", "asc":
sortType = sortTypeAsc sortType = sortTypeAsc
@@ -99,7 +102,7 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err
argAny = "default" 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) { switch strings.ToLower(s) {
case "k", "key", "keys": case "k", "key", "keys":
dictIt.iterMode = dictIterModeKeys 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) { 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) it.makeKeys(m, sortTypeNone)
return return
} }
@@ -190,7 +193,7 @@ func (it *DictIterator) Current() (item any, err error) {
case dictIterModeItems: case dictIterModeItems:
a := *(it.a) a := *(it.a)
pair := []any{it.keys[it.index], a[it.keys[it.index]]} pair := []any{it.keys[it.index], a[it.keys[it.index]]}
item = kern.NewList(pair) item = array.NewList(pair)
} }
} else { } else {
err = io.EOF err = io.EOF
+3 -2
View File
@@ -9,6 +9,7 @@ import (
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/types/boolean"
) )
//var globalCtx *SimpleStore //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) { func CtrlEnable(ctx kern.ExprContext, name string) (currentStatus bool) {
name = fixCtrlVar(name) 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) 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) { func CtrlDisable(ctx kern.ExprContext, name string) (currentStatus bool) {
name = fixCtrlVar(name) 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) currentStatus, _ = v.(bool)
} }
+4 -2
View File
@@ -12,6 +12,8 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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" "git.portale-stac.it/go-pkg/expr/util"
) )
@@ -50,9 +52,9 @@ func EvalStringV(source string, args []Arg) (result any, err error) {
} else { } else {
err = fmt.Errorf("invalid function specification: %q", arg.Name) 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) 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) ctx.SetVar(arg.Name, float)
} else if _, ok := arg.Value.(string); ok { } else if _, ok := arg.Value.(string); ok {
ctx.SetVar(arg.Name, arg.Value) ctx.SetVar(arg.Name, arg.Value)
+2 -1
View File
@@ -13,6 +13,7 @@ import (
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern" "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" "git.portale-stac.it/go-pkg/expr/util"
) )
@@ -22,7 +23,7 @@ const (
) )
func checkStringParamExpected(funcName string, paramValue any, paramPos int) (err error) { 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)) err = fmt.Errorf("%s(): param nr %d has wrong type %s, string expected", funcName, paramPos+1, kern.TypeName(paramValue))
} }
return return
+4 -3
View File
@@ -10,6 +10,7 @@ import (
"slices" "slices"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/types"
) )
type IntIterator struct { 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} it = &IntIterator{count: 0, index: -1, start: 0, stop: 0, step: 1}
if argc >= 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 return
} }
if argc >= 2 { if argc >= 2 {
it.start = it.stop 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 return
} }
if argc >= 3 { 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 return
} }
} else if it.start > it.stop { } else if it.start > it.stop {
+6 -3
View File
@@ -9,6 +9,9 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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) { 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) { switch v := value.(type) {
case *kern.ListType: case *array.ListType:
it = NewListIterator(v, nil) it = NewListIterator(v, nil)
case *kern.LinkedList: case *list.LinkedList:
it = NewLinkedListIterator(v, nil) it = NewLinkedListIterator(v, nil)
case *kern.DictType: case *dict.DictType:
it, err = NewDictIterator(v, nil) it, err = NewDictIterator(v, nil)
case []any: case []any:
it = NewArrayIterator(v) it = NewArrayIterator(v)
-30
View File
@@ -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
}
+23
View File
@@ -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
}
+1
View File
@@ -6,6 +6,7 @@ package kern
const ( const (
TypeAny = "any" TypeAny = "any"
TypeArray = "array"
TypeNil = "nil" TypeNil = "nil"
TypeBoolean = "boolean" TypeBoolean = "boolean"
TypeFloat = "float" TypeFloat = "float"
-41
View File
@@ -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
}
+7
View File
@@ -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)
+23
View File
@@ -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
View File
@@ -29,35 +29,6 @@ type ExprContext interface {
RegisterFuncInfo(info ExprFunc) RegisterFuncInfo(info ExprFunc)
RegisterFunc(name string, f Functor, returnType string, param []ExprFuncParam) (funcInfo ExprFunc, err error) 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 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
View File
@@ -21,6 +21,10 @@ const (
Base16 Base16
) )
type Formatter interface {
ToString(options FmtOpt) string
}
const ( const (
TruncateEllipsis = "(...)" TruncateEllipsis = "(...)"
MinTruncateSize = 10 MinTruncateSize = 10
@@ -45,10 +49,6 @@ func GetFormatIndent(opt FmtOpt) int {
return int(opt >> 16) return int(opt >> 16)
} }
type Formatter interface {
ToString(options FmtOpt) string
}
func Format(sb *strings.Builder, item any, opt FmtOpt) { func Format(sb *strings.Builder, item any, opt FmtOpt) {
if s, ok := item.(string); ok { if s, ok := item.(string); ok {
sb.WriteByte('"') sb.WriteByte('"')
@@ -73,22 +73,3 @@ func GetFormatted(v any, opt FmtOpt) (text string) {
} }
return 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
}
+26
View File
@@ -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
}
+37
View File
@@ -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
}
+4 -3
View File
@@ -10,16 +10,17 @@ import (
"slices" "slices"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/types/list"
) )
type LinkedListIterator struct { type LinkedListIterator struct {
a *kern.LinkedList a *list.LinkedList
count int64 count int64
index 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()} it = &LinkedListIterator{a: list, count: 0, index: -1, current: list.FirstNode()}
return return
} }
+7 -4
View File
@@ -7,6 +7,9 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 // -------- dict term
@@ -23,16 +26,16 @@ func newDictTerm(args map[any]*scan.Term) *scan.Term {
// -------- dict func // -------- dict func
func evalDict(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { func evalDict(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
dict, _ := opTerm.Value().(map[any]*scan.Term) dt, _ := opTerm.Value().(map[any]*scan.Term)
items := make(kern.DictType, len(dict)) items := make(dict.DictType, len(dt))
for key, tree := range dict { for key, tree := range dt {
var param any var param any
if param, err = tree.Compute(ctx); err != nil { if param, err = tree.Compute(ctx); err != nil {
break break
} }
var keyValue any var keyValue any
if keyValue, err = (key.(*scan.Term)).Compute(ctx); err == nil { 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 items[keyValue] = param
} else { } else {
err = key.(*scan.Term).Errorf("dict key can be integer or string, got %s", kern.TypeName(keyValue)) err = key.(*scan.Term).Errorf("dict key can be integer or string, got %s", kern.TypeName(keyValue))
+9 -6
View File
@@ -10,6 +10,9 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 // -------- 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) { 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} requiredFields := []string{kern.NextName}
fieldsMask := 0b1 fieldsMask := 0b1
foundFields := 0 foundFields := 0
@@ -123,7 +126,7 @@ func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
v = dc v = dc
} else { } else {
if dictIt, ok := firstChildValue.(*kern.DictType); ok { if dictIt, ok := firstChildValue.(*dict.DictType); ok {
var args []any var args []any
if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil { if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil {
v, err = NewDictIterator(dictIt, args) 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") 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 var args []any
if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil { 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 var args []any
if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil { 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 { } else if intVal, ok := firstChildValue.(int64); ok {
var args []any var args []any
+4 -3
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/list"
) )
// -------- list term // -------- list term
@@ -27,9 +28,9 @@ func newLinkedListTerm(row, col int, args []*scan.Term) *scan.Term {
// -------- list func // -------- list func
func evalLinkedList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { func evalLinkedList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
list, _ := opTerm.Value().([]*scan.Term) listTerm, _ := opTerm.Value().([]*scan.Term)
items := kern.NewLinkedList() items := list.NewLinkedList()
for _, tree := range list { for _, tree := range listTerm {
var param any var param any
if param, err = tree.Compute(ctx); err != nil { if param, err = tree.Compute(ctx); err != nil {
break break
+2 -1
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/array"
) )
// -------- list term // -------- list term
@@ -28,7 +29,7 @@ func newListTerm(row, col int, args []*scan.Term) *scan.Term {
// -------- list func // -------- list func
func evalList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) { func evalList(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
list, _ := opTerm.Value().([]*scan.Term) list, _ := opTerm.Value().([]*scan.Term)
items := make(kern.ListType, len(list)) items := make(array.ListType, len(list))
for i, tree := range list { for i, tree := range list {
var param any var param any
if param, err = tree.Compute(ctx); err != nil { if param, err = tree.Compute(ctx); err != nil {
+11
View File
@@ -7,10 +7,21 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/fract"
) )
// -------- literal term // -------- literal term
func newLiteralTerm(tk *scan.Token) *scan.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{ return &scan.Term{
Tk: *tk, Tk: *tk,
Parent: nil, Parent: nil,
+14 -12
View File
@@ -7,6 +7,8 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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" "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) { func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term, value any) (err error) {
var collectionValue, keyListValue, keyValue any var collectionValue, keyListValue, keyValue any
var keyList *kern.ListType var keyList *array.ListType
var ok bool var ok bool
if collectionValue, err = collectionTerm.Compute(ctx); err != nil { 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 { if keyListValue, err = keyListTerm.Compute(ctx); err != nil {
return 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)) err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, kern.TypeName(keyListValue))
return return
} }
@@ -63,13 +65,13 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca
} }
switch collection := collectionValue.(type) { switch collection := collectionValue.(type) {
case *kern.ListType: case *array.ListType:
if index, ok := keyValue.(int64); ok { if index, ok := keyValue.(int64); ok {
err = collection.SetItem(index, value) err = collection.SetItem(index, value)
} else { } else {
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue)) err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue))
} }
case *kern.DictType: case *dict.DictType:
collection.SetItem(keyValue, value) collection.SetItem(keyValue, value)
default: default:
err = collectionTerm.Errorf("collection expected") 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) { func evalAssignDictItem(ctx kern.ExprContext, dotTerm *scan.Term, valueTerm kern.Term) (v any, err error) {
var ok bool var ok bool
var dictAny, dotKey any var dictAny, dotKey any
var dict *kern.DictType var dt *dict.DictType
if err = dotTerm.CheckOperands(); err != nil { if err = dotTerm.CheckOperands(); err != nil {
return return
@@ -102,8 +104,8 @@ func evalAssignDictItem(ctx kern.ExprContext, dotTerm *scan.Term, valueTerm kern
if dictAny, err = dotLeftTerm.Compute(ctx); err != nil { if dictAny, err = dotLeftTerm.Compute(ctx); err != nil {
return return
} }
if dict, ok = dictAny.(*kern.DictType); !ok { if dt, ok = dictAny.(*dict.DictType); !ok {
err = dotTerm.Tk.ErrorExpectedGot(kern.DictTypeName) err = dotTerm.Tk.ErrorExpectedGot(dict.DictTypeName)
return return
} }
@@ -119,7 +121,7 @@ func evalAssignDictItem(ctx kern.ExprContext, dotTerm *scan.Term, valueTerm kern
return return
} }
dict.SetItem(dotKey, v) dt.SetItem(dotKey, v)
return 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) { func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term) (value any, err error) {
var collectionValue, keyListValue, keyValue any var collectionValue, keyListValue, keyValue any
var keyList *kern.ListType var keyList *array.ListType
var ok bool var ok bool
if collectionValue, err = collectionTerm.Compute(ctx); err != nil { 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 { if keyListValue, err = keyListTerm.Compute(ctx); err != nil {
return 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)) err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, kern.TypeName(keyListValue))
return return
} }
@@ -197,13 +199,13 @@ func getCollectionItemValue(ctx kern.ExprContext, collectionTerm, keyListTerm *s
} }
switch collection := collectionValue.(type) { switch collection := collectionValue.(type) {
case *kern.ListType: case *array.ListType:
if index, ok := keyValue.(int64); ok { if index, ok := keyValue.(int64); ok {
value = (*collection)[index] value = (*collection)[index]
} else { } else {
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue)) err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, kern.TypeName(keyValue))
} }
case *kern.DictType: case *dict.DictType:
value = (*collection)[keyValue] value = (*collection)[keyValue]
default: default:
err = collectionTerm.Errorf("collection expected") err = collectionTerm.Errorf("collection expected")
+2 -1
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types"
) )
//-------- Bitwise NOT term //-------- Bitwise NOT term
@@ -28,7 +29,7 @@ func evalBitwiseNot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error)
return return
} }
if kern.IsInteger(value) { if types.IsInteger(value) {
i, _ := value.(int64) i, _ := value.(int64)
v = ^i v = ^i
} else { } else {
+10 -9
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/boolean"
) )
//-------- NOT term //-------- NOT term
@@ -30,7 +31,7 @@ func evalNot(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if b, ok := kern.ToBool(rightValue); ok { if b, ok := boolean.ToBool(rightValue); ok {
v = !b v = !b
} else { } else {
err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue) err = opTerm.ErrIncompatiblePrefixPostfixType(rightValue)
@@ -68,8 +69,8 @@ func evalAndWithoutShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err e
return return
} }
leftBool, lok = kern.ToBool(leftValue) leftBool, lok = boolean.ToBool(leftValue)
rightBool, rok = kern.ToBool(rightValue) rightBool, rok = boolean.ToBool(rightValue)
if lok && rok { if lok && rok {
v = leftBool && rightBool v = leftBool && rightBool
@@ -90,14 +91,14 @@ func evalAndWithShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err erro
return 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)) // err = fmt.Errorf("got %s as left operand type of 'AND' operator, it must be bool", expr.TypeName(leftValue))
// return // return
err = self.ErrIncompatibleType(leftValue, "left") err = self.ErrIncompatibleType(leftValue, "left")
} else if !leftBool { } else if !leftBool {
v = false v = false
} else if rightValue, err = self.Children[1].Compute(ctx); err == nil { } 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 v = rightBool
} else { } else {
err = self.ErrIncompatibleTypes(leftValue, rightValue) err = self.ErrIncompatibleTypes(leftValue, rightValue)
@@ -136,8 +137,8 @@ func evalOrWithoutShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err er
return return
} }
leftBool, lok = kern.ToBool(leftValue) leftBool, lok = boolean.ToBool(leftValue)
rightBool, rok = kern.ToBool(rightValue) rightBool, rok = boolean.ToBool(rightValue)
if lok && rok { if lok && rok {
v = leftBool || rightBool v = leftBool || rightBool
@@ -158,13 +159,13 @@ func evalOrWithShortcut(ctx kern.ExprContext, self *scan.Term) (v any, err error
return 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)) err = fmt.Errorf("got %s as left operand type of 'OR' operator, it must be bool", kern.TypeName(leftValue))
return return
} else if leftBool { } else if leftBool {
v = true v = true
} else if rightValue, err = self.Children[1].Compute(ctx); err == nil { } 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 v = rightBool
} else { } else {
err = self.ErrIncompatibleTypes(leftValue, rightValue) err = self.ErrIncompatibleTypes(leftValue, rightValue)
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/str"
) )
//-------- builtin term //-------- builtin term
@@ -31,7 +32,7 @@ func evalBuiltin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
} }
count := 0 count := 0
if kern.IsString(childValue) { if str.IsString(childValue) {
module, _ := childValue.(string) module, _ := childValue.(string)
count, err = ImportInContextByGlobPattern(ctx, module) count, err = ImportInContextByGlobPattern(ctx, module)
} else { } else {
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/list"
) )
//-------- context term //-------- context term
@@ -48,7 +49,7 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error
} }
if err == nil { if err == nil {
var item any var item any
values := kern.NewLinkedListA() values := list.NewLinkedListA()
for item, err = it.Next(); err == nil; item, err = it.Next() { for item, err = it.Next(); err == nil; item, err = it.Next() {
values.PushBack(item) values.PushBack(item)
} }
+3 -17
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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" "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 { } else {
err = indexTerm.Tk.ErrorExpectedGot("identifier") err = indexTerm.Tk.ErrorExpectedGot("identifier")
} }
case *kern.DictType: case *dict.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)
// }
// }
v, err = dotGetDictItemValue(ctx, unboxedValue, opTerm.Children[1]) v, err = dotGetDictItemValue(ctx, unboxedValue, opTerm.Children[1])
default: default:
if rightValue, err = opTerm.Children[1].Compute(ctx); err == nil { 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 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 ok bool
var rightValue any var rightValue any
s := rightTerm.Symbol() s := rightTerm.Symbol()
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types"
) )
//-------- fact term //-------- fact term
@@ -30,7 +31,7 @@ func evalFact(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if kern.IsInteger(leftValue) { if types.IsInteger(leftValue) {
if i, _ := leftValue.(int64); i >= 0 { if i, _ := leftValue.(int64); i >= 0 {
f := int64(1) f := int64(1)
for k := int64(1); k <= i; k++ { for k := int64(1); k <= i; k++ {
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/boolean"
) )
//-------- map term //-------- map term
@@ -117,7 +118,7 @@ func (it *filterIterator) Next() (item any, err error) {
ctx.DeleteVar("_") ctx.DeleteVar("_")
if err == nil { if err == nil {
if success, valid := kern.ToBool(result); valid { if success, valid := boolean.ToBool(result); valid {
if success { if success {
item = attempt item = attempt
break break
+4 -3
View File
@@ -11,6 +11,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/fract"
) )
// -------- fraction term // -------- fraction term
@@ -51,7 +52,7 @@ func evalFraction(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
num = -num num = -num
} }
if num != 0 { if num != 0 {
if g := kern.Gcd(num, den); g != 1 { if g := fract.Gcd(num, den); g != 1 {
num = num / g num = num / g
den = den / g den = den / g
} }
@@ -59,11 +60,11 @@ func evalFraction(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
v = num v = num
} else { } else {
// v = &expr.FractionType{num, den} // v = &expr.FractionType{num, den}
v = kern.NewFraction(num, den) v = fract.NewFraction(num, den)
} }
} else { } else {
// v = &FractionType{0, den} // v = &FractionType{0, den}
v = kern.NewFraction(0, den) v = fract.NewFraction(0, den)
} }
return return
} }
+9 -6
View File
@@ -11,6 +11,9 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- group by term
@@ -52,13 +55,13 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
keyByIndex = true keyByIndex = true
} else if rightValue, err = opTerm.Children[1].Compute(ctx); err != nil { } else if rightValue, err = opTerm.Children[1].Compute(ctx); err != nil {
return return
} else if kern.IsString(rightValue) { } else if str.IsString(rightValue) {
sKey = rightValue.(string) sKey = rightValue.(string)
} else { } else {
return nil, fmt.Errorf("right operand of GROUPBY must be a string or identifier '__'; got %s", kern.TypeName(rightValue)) 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() { for item, err = it.Next(); err == nil; item, err = it.Next() {
ctx.SetVar("_", item) ctx.SetVar("_", item)
ctx.SetVar("__", it.Index()) ctx.SetVar("__", it.Index())
@@ -66,7 +69,7 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
var sItemKey string var sItemKey string
if d, ok := item.(*kern.DictType); ok { if d, ok := item.(*dict.DictType); ok {
if keyByIndex || len(sKey) == 0 { if keyByIndex || len(sKey) == 0 {
sItemKey = strconv.Itoa(int(it.Index())) sItemKey = strconv.Itoa(int(it.Index()))
} else if d.HasKey(sKey) { } 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())) sItemKey = strconv.Itoa(int(it.Index()))
} }
var ls *kern.ListType var ls *array.ListType
if lsAny, exists := values.GetItem(sItemKey); exists && lsAny != nil { if lsAny, exists := values.GetItem(sItemKey); exists && lsAny != nil {
ls = lsAny.(*kern.ListType) ls = lsAny.(*array.ListType)
} }
if ls == nil { if ls == nil {
ls = kern.NewListA() ls = array.NewListA()
} }
ls.AppendItem(item) ls.AppendItem(item)
values.SetItem(sItemKey, ls) values.SetItem(sItemKey, ls)
+7 -5
View File
@@ -7,6 +7,8 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- in term
@@ -33,11 +35,11 @@ func evalIn(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if kern.IsList(rightValue) { if array.IsList(rightValue) {
list, _ := rightValue.(*kern.ListType) a, _ := rightValue.(*array.ListType)
v = list.IndexDeepSameCmp(leftValue) >= 0 v = a.IndexDeepSameCmp(leftValue) >= 0
} else if kern.IsDict(rightValue) { } else if dict.IsDict(rightValue) {
dict, _ := rightValue.(*kern.DictType) dict, _ := rightValue.(*dict.DictType)
v = dict.HasKey(leftValue) v = dict.HasKey(leftValue)
} else { } else {
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
+6 -4
View File
@@ -7,6 +7,8 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- include term
@@ -29,9 +31,9 @@ func evalInclude(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
} }
count := 0 count := 0
if kern.IsList(childValue) { if array.IsList(childValue) {
list, _ := childValue.(*kern.ListType) a, _ := childValue.(*array.ListType)
for i, filePathSpec := range *list { for i, filePathSpec := range *a {
if filePath, ok := filePathSpec.(string); ok { if filePath, ok := filePathSpec.(string); ok {
if v, err = EvalFile(ctx, filePath); err == nil { if v, err = EvalFile(ctx, filePath); err == nil {
count++ count++
@@ -44,7 +46,7 @@ func evalInclude(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
break break
} }
} }
} else if kern.IsString(childValue) { } else if str.IsString(childValue) {
filePath, _ := childValue.(string) filePath, _ := childValue.(string)
if v, err = EvalFile(ctx, filePath); err == nil { if v, err = EvalFile(ctx, filePath); err == nil {
count++ count++
+20 -16
View File
@@ -7,6 +7,10 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 // -------- 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] index = (*indexList)[0]
return 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 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 { if v < 0 && v >= -maxValue {
v = maxValue + v v = maxValue + v
} }
@@ -41,7 +45,7 @@ func verifyIndex(indexTerm *scan.Term, indexList *kern.ListType, maxValue int) (
return 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) v, _ := ((*indexList)[0]).(*intPair)
startIndex = v.a startIndex = v.a
endIndex = v.b 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) { func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
var leftValue, rightValue any var leftValue, rightValue any
var indexList *kern.ListType var indexList *array.ListType
var ok bool var ok bool
if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil { 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] indexTerm := opTerm.Children[1]
if indexList, ok = rightValue.(*kern.ListType); !ok { if indexList, ok = rightValue.(*array.ListType); !ok {
err = opTerm.Errorf("invalid index expression") err = opTerm.Errorf("invalid index expression")
return return
} else if len(*indexList) != 1 { } else if len(*indexList) != 1 {
@@ -82,14 +86,14 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if kern.IsInteger((*indexList)[0]) { if types.IsInteger((*indexList)[0]) {
switch unboxedValue := leftValue.(type) { switch unboxedValue := leftValue.(type) {
case *kern.ListType: case *array.ListType:
var index int var index int
if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil { if index, err = verifyIndex(indexTerm, indexList, len(*unboxedValue)); err == nil {
v = (*unboxedValue)[index] v = (*unboxedValue)[index]
} }
case *kern.LinkedList: case *list.LinkedList:
var index int var index int
if index, err = verifyIndex(indexTerm, indexList, unboxedValue.Len()); err == nil { if index, err = verifyIndex(indexTerm, indexList, unboxedValue.Len()); err == nil {
v, err = unboxedValue.At(index) 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 { if index, err = verifyIndex(indexTerm, indexList, len(unboxedValue)); err == nil {
v = string(unboxedValue[index]) v = string(unboxedValue[index])
} }
case *kern.DictType: case *dict.DictType:
v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue) v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue)
default: default:
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
} }
} else if isIntPair((*indexList)[0]) { } else if isIntPair((*indexList)[0]) {
switch unboxedValue := leftValue.(type) { switch unboxedValue := leftValue.(type) {
case *kern.ListType: case *array.ListType:
var start, end int var start, end int
if start, end, err = verifyRange(indexTerm, indexList, len(*unboxedValue)); err == nil { 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 v = &sublist
} }
case *kern.LinkedList: case *list.LinkedList:
var start, end int var start, end int
if start, end, err = verifyRange(indexTerm, indexList, unboxedValue.Len()); err == nil { if start, end, err = verifyRange(indexTerm, indexList, unboxedValue.Len()); err == nil {
v = unboxedValue.Sub(start, end) v = unboxedValue.Sub(start, end)
@@ -125,8 +129,8 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
default: default:
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
} }
} else if kern.IsDict(leftValue) { } else if dict.IsDict(leftValue) {
d := leftValue.(*kern.DictType) d := leftValue.(*dict.DictType)
v, err = getDictItem(d, indexTerm, indexList, rightValue) v, err = getDictItem(d, indexTerm, indexList, rightValue)
} else { } else {
rightChild := opTerm.Children[1] rightChild := opTerm.Children[1]
@@ -135,7 +139,7 @@ func evalIndex(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return 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 ok bool
var indexValue any var indexValue any
+24 -22
View File
@@ -7,6 +7,8 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- 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) { 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 var it kern.Iterator
if it, ok = leftValue.(kern.Iterator); !ok { if it, ok = leftValue.(kern.Iterator); !ok {
it = NewFormalIterator(leftValue) it = NewFormalIterator(leftValue)
} }
ls := kern.NewLinkedList() ls := list.NewLinkedList()
ls.SeqPushBack(it) ls.SeqPushBack(it)
newList := kern.ListType(nil) newArray := array.ListType(nil)
if newSize := len(*list) + int(ls.Len()); newSize > cap(*list) { if newSize := len(*a) + int(ls.Len()); newSize > cap(*a) {
newList = make([]any, 0, newSize) newArray = make([]any, 0, newSize)
for node := ls.FirstNode(); node != nil; node = node.Next() { for node := ls.FirstNode(); node != nil; node = node.Next() {
newList = append(newList, node.Data()) newArray = append(newArray, node.Data())
} }
} }
for _, item := range *list { for _, item := range *a {
newList = append(newList, item) newArray = append(newArray, item)
} }
result = &newList result = &newArray
} else if list, ok := rightValue.(*kern.LinkedList); ok { } else if ll, ok := rightValue.(*list.LinkedList); ok {
var it kern.Iterator var it kern.Iterator
if it, ok = leftValue.(kern.Iterator); !ok { if it, ok = leftValue.(kern.Iterator); !ok {
it = NewFormalIterator(leftValue) it = NewFormalIterator(leftValue)
} }
result = list.SeqPushBack(it) result = ll.SeqPushBack(it)
} else { } else {
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) 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) { 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 var it kern.Iterator
if it, ok = rightValue.(kern.Iterator); !ok { if it, ok = rightValue.(kern.Iterator); !ok {
it = NewFormalIterator(rightValue) it = NewFormalIterator(rightValue)
} }
ls := kern.NewLinkedList() ls := list.NewLinkedList()
ls.SeqPushBack(it) ls.SeqPushBack(it)
newList := *list newArray := *a
if newSize := len(*list) + int(ls.Len()); newSize > cap(*list) { if newSize := len(*a) + int(ls.Len()); newSize > cap(*a) {
newList = make([]any, 0, newSize) newArray = make([]any, 0, newSize)
for _, item := range *list { for _, item := range *a {
newList = append(newList, item) newArray = append(newArray, item)
} }
} }
for node := ls.FirstNode(); node != nil; node = node.Next() { for node := ls.FirstNode(); node != nil; node = node.Next() {
newList = append(newList, node.Data()) newArray = append(newArray, node.Data())
} }
result = &newList result = &newArray
} else if list, ok := leftValue.(*kern.LinkedList); ok { } else if ll, ok := leftValue.(*list.LinkedList); ok {
var it kern.Iterator var it kern.Iterator
if it, ok = rightValue.(kern.Iterator); !ok { if it, ok = rightValue.(kern.Iterator); !ok {
it = NewFormalIterator(rightValue) it = NewFormalIterator(rightValue)
} }
result = list.SeqPushBack(it) result = ll.SeqPushBack(it)
} else { } else {
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
} }
+10 -12
View File
@@ -7,6 +7,10 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- length term
@@ -28,25 +32,19 @@ func evalLength(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if kern.IsList(childValue) { if array.IsList(childValue) {
ls, _ := childValue.(*kern.ListType) ls, _ := childValue.(*array.ListType)
v = int64(len(*ls)) v = int64(len(*ls))
} else if kern.IsString(childValue) { } else if str.IsString(childValue) {
s, _ := childValue.(string) s, _ := childValue.(string)
v = int64(len(s)) v = int64(len(s))
} else if kern.IsDict(childValue) { } else if dict.IsDict(childValue) {
m, _ := childValue.(*kern.DictType) m, _ := childValue.(*dict.DictType)
v = int64(len(*m)) v = int64(len(*m))
} else if lls, ok := childValue.(*kern.LinkedList); ok { } else if lls, ok := childValue.(*list.LinkedList); ok {
v = int64(lls.Len()) v = int64(lls.Len())
} else if it, ok := childValue.(kern.Iterator); ok { } else if it, ok := childValue.(kern.Iterator); ok {
v = int64(it.Count()) 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 { } else {
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue) err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
} }
-21
View File
@@ -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:]) v, err = NewIterIter(it, ctx, opTerm.Children[1:])
return return
} }
+3 -2
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types"
) )
// -------- post increment term // -------- post increment term
@@ -49,7 +50,7 @@ func evalPostInc(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
ctx.UnsafeSetVar(namePrefix+"_value", v1) 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 v = childValue
i, _ := childValue.(int64) i, _ := childValue.(int64)
ctx.SetVar(opTerm.Children[0].Source(), i+1) 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 { /* if it, ok := childValue.(Iterator); ok {
v, err = it.Next() 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 v = childValue
i, _ := childValue.(int64) i, _ := childValue.(int64)
ctx.SetVar(opTerm.Children[0].Source(), i-1) ctx.SetVar(opTerm.Children[0].Source(), i-1)
+3 -2
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types"
) )
// -------- pre increment term // -------- pre increment term
@@ -27,7 +28,7 @@ func evalPreInc(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return 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 i := childValue.(int64) + 1
ctx.SetVar(opTerm.Children[0].Source(), i) ctx.SetVar(opTerm.Children[0].Source(), i)
v = i v = i
@@ -56,7 +57,7 @@ func evalPreDec(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return 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 i := childValue.(int64) - 1
ctx.SetVar(opTerm.Children[0].Source(), i) ctx.SetVar(opTerm.Children[0].Source(), i)
v = i v = i
+25 -20
View File
@@ -9,6 +9,11 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- 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) { 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) s, _ := leftValue.(string)
n, _ := rightValue.(int64) n, _ := rightValue.(int64)
v = strings.Repeat(s, int(n)) v = strings.Repeat(s, int(n))
} else if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { } else if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) {
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
v = kern.NumAsFloat(leftValue) * kern.NumAsFloat(rightValue) v = types.NumAsFloat(leftValue) * types.NumAsFloat(rightValue)
} else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) { } else if fract.IsFraction(leftValue) || fract.IsFraction(rightValue) {
v, err = kern.MulAnyFract(leftValue, rightValue) v, err = fract.MulAnyFract(leftValue, rightValue)
} else { } else {
leftInt, _ := leftValue.(int64) leftInt, _ := leftValue.(int64)
rightInt, _ := rightValue.(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) { func divValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error) {
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) {
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
d := kern.NumAsFloat(rightValue) d := types.NumAsFloat(rightValue)
if d == 0.0 { if d == 0.0 {
err = opTerm.ErrDivisionByZero() err = opTerm.ErrDivisionByZero()
} else { } else {
v = kern.NumAsFloat(leftValue) / d v = types.NumAsFloat(leftValue) / d
} }
} else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) { } else if fract.IsFraction(leftValue) || fract.IsFraction(rightValue) {
v, err = kern.DivAnyFract(leftValue, rightValue) v, err = fract.DivAnyFract(leftValue, rightValue)
} else { } else {
leftInt, _ := leftValue.(int64) leftInt, _ := leftValue.(int64)
if rightInt, _ := rightValue.(int64); rightInt == 0 { 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 v = leftInt / rightInt
} }
} }
} else if kern.IsString(leftValue) && kern.IsString(rightValue) { } else if str.IsString(leftValue) && str.IsString(rightValue) {
source := leftValue.(string) source := leftValue.(string)
sep := rightValue.(string) sep := rightValue.(string)
v = kern.ListFromStrings(strings.Split(source, sep)) v = array.ListFromStrings(strings.Split(source, sep))
} else if kern.IsString(leftValue) && kern.IsInteger(rightValue) { } else if str.IsString(leftValue) && types.IsInteger(rightValue) {
source := leftValue.(string) source := leftValue.(string)
partSize := int(rightValue.(int64)) partSize := int(rightValue.(int64))
if partSize == 0 { if partSize == 0 {
@@ -108,7 +113,7 @@ func divValues(opTerm *scan.Term, leftValue, rightValue any) (v any, err error)
if remainder > 0 { if remainder > 0 {
parts = append(parts, source[len(source)-remainder:]) parts = append(parts, source[len(source)-remainder:])
} }
v = kern.NewList(parts) v = array.NewList(parts)
} }
} else { } else {
err = opTerm.ErrIncompatibleTypes(leftValue, rightValue) err = opTerm.ErrIncompatibleTypes(leftValue, rightValue)
@@ -145,12 +150,12 @@ func evalDivideAsFloat(ctx kern.ExprContext, floatDivTerm *scan.Term) (v any, er
return return
} }
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) {
d := kern.NumAsFloat(rightValue) d := types.NumAsFloat(rightValue)
if d == 0.0 { if d == 0.0 {
err = floatDivTerm.ErrDivisionByZero() err = floatDivTerm.ErrDivisionByZero()
} else { } else {
v = kern.NumAsFloat(leftValue) / d v = types.NumAsFloat(leftValue) / d
} }
} else { } else {
err = floatDivTerm.ErrIncompatibleTypes(leftValue, rightValue) 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) { 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) rightInt, _ := rightValue.(int64)
if rightInt == 0 { if rightInt == 0 {
err = opTerm.ErrDivisionByZero() err = opTerm.ErrDivisionByZero()
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types"
) )
// -------- range term // -------- 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 { } else if leftValue, rightValue, err = opTerm.EvalInfix(ctx); err != nil {
return return
} }
if !(kern.IsInteger(leftValue) && kern.IsInteger(rightValue)) { if !(types.IsInteger(leftValue) && types.IsInteger(rightValue)) {
// err = opTerm.errIncompatibleTypes(leftValue, rightValue) // err = opTerm.errIncompatibleTypes(leftValue, rightValue)
err = errRangeInvalidSpecification(opTerm) err = errRangeInvalidSpecification(opTerm)
return return
+23 -18
View File
@@ -9,6 +9,11 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- equal term
@@ -26,22 +31,22 @@ func newEqualTerm(tk *scan.Token) (inst *scan.Term) {
// type deepFuncTemplate func(a, b any) (eq bool, err error) // type deepFuncTemplate func(a, b any) (eq bool, err error)
func equals(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) { func equals(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) {
if kern.IsNumOrFract(a) && kern.IsNumOrFract(b) { if types.IsNumOrFract(a) && types.IsNumOrFract(b) {
if kern.IsNumber(a) && kern.IsNumber(b) { if types.IsNumber(a) && types.IsNumber(b) {
if kern.IsInteger(a) && kern.IsInteger(b) { if types.IsInteger(a) && types.IsInteger(b) {
li, _ := a.(int64) li, _ := a.(int64)
ri, _ := b.(int64) ri, _ := b.(int64)
eq = li == ri eq = li == ri
} else { } else {
eq = kern.NumAsFloat(a) == kern.NumAsFloat(b) eq = types.NumAsFloat(a) == types.NumAsFloat(b)
} }
} else { } else {
var cmp int var cmp int
if cmp, err = kern.CmpAnyFract(a, b); err == nil { if cmp, err = fract.CmpAnyFract(a, b); err == nil {
eq = cmp == 0 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) eq, err = deepCmp(a, b)
} else { } else {
eq = reflect.DeepEqual(a, b) 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) { func evalNotEqual(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
if v, err = evalEqual(ctx, opTerm); err == nil { if v, err = evalEqual(ctx, opTerm); err == nil {
b, _ := kern.ToBool(v) b, _ := boolean.ToBool(v)
v = !b v = !b
} }
return 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) { func lessThan(self *scan.Term, a, b any) (isLess bool, err error) {
if kern.IsNumOrFract(a) && kern.IsNumOrFract(b) { if types.IsNumOrFract(a) && types.IsNumOrFract(b) {
if kern.IsNumber(a) && kern.IsNumber(b) { if types.IsNumber(a) && types.IsNumber(b) {
if kern.IsInteger(a) && kern.IsInteger(b) { if types.IsInteger(a) && types.IsInteger(b) {
li, _ := a.(int64) li, _ := a.(int64)
ri, _ := b.(int64) ri, _ := b.(int64)
isLess = li < ri isLess = li < ri
} else { } else {
isLess = kern.NumAsFloat(a) < kern.NumAsFloat(b) isLess = types.NumAsFloat(a) < types.NumAsFloat(b)
} }
} else { } else {
var cmp int var cmp int
if cmp, err = kern.CmpAnyFract(a, b); err == nil { if cmp, err = fract.CmpAnyFract(a, b); err == nil {
isLess = cmp < 0 isLess = cmp < 0
} }
} }
} else if kern.IsString(a) && kern.IsString(b) { } else if str.IsString(a) && str.IsString(b) {
ls, _ := a.(string) ls, _ := a.(string)
rs, _ := b.(string) rs, _ := b.(string)
isLess = ls < rs isLess = ls < rs
// Inclusion test // Inclusion test
} else if kern.IsList(a) && kern.IsList(b) { } else if array.IsList(a) && array.IsList(b) {
aList, _ := a.(*kern.ListType) aList, _ := a.(*array.ListType)
bList, _ := b.(*kern.ListType) bList, _ := b.(*array.ListType)
isLess = len(*aList) < len(*bList) && bList.Contains(aList) isLess = len(*aList) < len(*bList) && bList.Contains(aList)
} else { } else {
err = self.ErrIncompatibleTypes(a, b) 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) { func lessThanOrEqual(self *scan.Term, a, b any) (isLessEq bool, err error) {
if isLessEq, err = lessThan(self, a, b); err == nil { if isLessEq, err = lessThan(self, a, b); err == nil {
if !isLessEq { if !isLessEq {
if kern.IsList(a) && kern.IsList(b) { if array.IsList(a) && array.IsList(b) {
isLessEq, err = kern.SameContent(a, b) isLessEq, err = array.SameContent(a, b)
} else { } else {
isLessEq, err = equals(a, b, nil) isLessEq, err = equals(a, b, nil)
} }
+3 -2
View File
@@ -7,6 +7,7 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types"
) )
//-------- bit right shift term //-------- 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) { 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) leftInt := leftValue.(int64)
rightInt := rightValue.(int64) rightInt := rightValue.(int64)
v = leftInt >> rightInt 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) { 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) leftInt := leftValue.(int64)
rightInt := rightValue.(int64) rightInt := rightValue.(int64)
v = leftInt << rightInt v = leftInt << rightInt
+4 -2
View File
@@ -7,6 +7,8 @@ package expr
import ( import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- plus sign term
@@ -38,14 +40,14 @@ func evalSign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if kern.IsFloat(rightValue) { if float.IsFloat(rightValue) {
if opTerm.Tk.Sym == scan.SymChangeSign { if opTerm.Tk.Sym == scan.SymChangeSign {
f, _ := rightValue.(float64) f, _ := rightValue.(float64)
v = -f v = -f
} else { } else {
v = rightValue v = rightValue
} }
} else if kern.IsInteger(rightValue) { } else if types.IsInteger(rightValue) {
if opTerm.Tk.Sym == scan.SymChangeSign { if opTerm.Tk.Sym == scan.SymChangeSign {
i, _ := rightValue.(int64) i, _ := rightValue.(int64)
v = -i v = -i
+33 -27
View File
@@ -10,6 +10,12 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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 //-------- 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) { 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) v = fmt.Sprintf("%v%v", leftValue, rightValue)
} else if kern.IsNumber(leftValue) && kern.IsNumber(rightValue) { } else if types.IsNumber(leftValue) && types.IsNumber(rightValue) {
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
v = kern.NumAsFloat(leftValue) + kern.NumAsFloat(rightValue) v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue)
} else { } else {
leftInt, _ := leftValue.(int64) leftInt, _ := leftValue.(int64)
rightInt, _ := rightValue.(int64) rightInt, _ := rightValue.(int64)
v = leftInt + rightInt v = leftInt + rightInt
} }
} else if kern.IsList(leftValue) && kern.IsList(rightValue) { } else if array.IsList(leftValue) && array.IsList(rightValue) {
var leftList, rightList *kern.ListType var leftList, rightList *array.ListType
leftList, _ = leftValue.(*kern.ListType) leftList, _ = leftValue.(*array.ListType)
rightList, _ = rightValue.(*kern.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, *leftList...)
sumList = append(sumList, *rightList...) sumList = append(sumList, *rightList...)
v = &sumList v = &sumList
} else if (kern.IsFraction(leftValue) && kern.IsNumber(rightValue)) || (kern.IsFraction(rightValue) && kern.IsNumber(leftValue)) { } else if (fract.IsFraction(leftValue) && types.IsNumber(rightValue)) || (fract.IsFraction(rightValue) && types.IsNumber(leftValue)) {
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
v = kern.NumAsFloat(leftValue) + kern.NumAsFloat(rightValue) v = types.NumAsFloat(leftValue) + types.NumAsFloat(rightValue)
} else { } else {
v, err = kern.SumAnyFract(leftValue, rightValue) v, err = fract.SumAnyFract(leftValue, rightValue)
} }
} else if kern.IsDict(leftValue) && kern.IsDict(rightValue) { } else if dict.IsDict(leftValue) && dict.IsDict(rightValue) {
leftDict, _ := leftValue.(*kern.DictType) leftDict, _ := leftValue.(*dict.DictType)
rightDict, _ := rightValue.(*kern.DictType) rightDict, _ := rightValue.(*dict.DictType)
c := leftDict.Clone() c := leftDict.Clone()
c.Merge(rightDict) c.Merge(rightDict)
v = c v = c
} else if kern.IsFraction(leftValue) && kern.IsFraction(rightValue) { } else if fract.IsFraction(leftValue) && fract.IsFraction(rightValue) {
v, err = kern.SumAnyFract(leftValue, rightValue) v, err = fract.SumAnyFract(leftValue, rightValue)
} else { } else {
err = plusTerm.ErrIncompatibleTypes(leftValue, rightValue) 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) { func diffValues(minusTerm *scan.Term, leftValue, rightValue any) (v any, err error) {
if kern.IsNumOrFract(leftValue) && kern.IsNumOrFract(rightValue) { if types.IsNumOrFract(leftValue) && types.IsNumOrFract(rightValue) {
if kern.IsFloat(leftValue) || kern.IsFloat(rightValue) { if float.IsFloat(leftValue) || float.IsFloat(rightValue) {
v = kern.NumAsFloat(leftValue) - kern.NumAsFloat(rightValue) v = types.NumAsFloat(leftValue) - types.NumAsFloat(rightValue)
} else if kern.IsFraction(leftValue) || kern.IsFraction(rightValue) { } else if fract.IsFraction(leftValue) || fract.IsFraction(rightValue) {
v, err = kern.SubAnyFract(leftValue, rightValue) v, err = fract.SubAnyFract(leftValue, rightValue)
} else { } else {
leftInt, _ := leftValue.(int64) leftInt, _ := leftValue.(int64)
rightInt, _ := rightValue.(int64) rightInt, _ := rightValue.(int64)
v = leftInt - rightInt v = leftInt - rightInt
} }
} else if kern.IsList(leftValue) && kern.IsList(rightValue) { } else if array.IsList(leftValue) && array.IsList(rightValue) {
leftList, _ := leftValue.(*kern.ListType) leftList, _ := leftValue.(*array.ListType)
rightList, _ := rightValue.(*kern.ListType) rightList, _ := rightValue.(*array.ListType)
diffList := make(kern.ListType, 0, len(*leftList)-len(*rightList)) diffList := make(array.ListType, 0, len(*leftList)-len(*rightList))
for _, item := range *leftList { for _, item := range *leftList {
if slices.Index(*rightList, item) < 0 { if slices.Index(*rightList, item) < 0 {
diffList = append(diffList, item) diffList = append(diffList, item)
+3 -2
View File
@@ -9,6 +9,7 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "git.portale-stac.it/go-pkg/expr/scan"
"git.portale-stac.it/go-pkg/expr/types/array"
) )
//-------- unset term //-------- unset term
@@ -50,8 +51,8 @@ func evalUnset(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
} }
count := 0 count := 0
if kern.IsList(childValue) { if array.IsList(childValue) {
list, _ := childValue.(*kern.ListType) list, _ := childValue.(*array.ListType)
for _, item := range *list { for _, item := range *list {
if deleted, err = deleteContextItem(ctx, opTerm, item); err != nil { if deleted, err = deleteContextItem(ctx, opTerm, item); err != nil {
break break
+2 -2
View File
@@ -12,7 +12,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/util" "git.portale-stac.it/go-pkg/expr/util"
) )
@@ -518,7 +517,8 @@ func (scanner *Scanner) parseNumber(firstCh byte) (tk *Token) {
if sym == SymFloat { if sym == SymFloat {
value, err = strconv.ParseFloat(txt, 64) value, err = strconv.ParseFloat(txt, 64)
} else if sym == SymFraction { } else if sym == SymFraction {
value, err = kern.MakeGeneratingFraction(txt) // value, err = kern.MakeGeneratingFraction(txt)
value = txt
} else { } else {
value, err = strconv.ParseInt(txt, numBase, 64) value, err = strconv.ParseInt(txt, numBase, 64)
} }
-3
View File
@@ -9,8 +9,6 @@ import (
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern"
) )
func TestScanner(t *testing.T) { func TestScanner(t *testing.T) {
@@ -62,7 +60,6 @@ func TestScanner(t *testing.T) {
/* 38 */ {`\`, SymError, errors.New("incomplete escape sequence"), nil}, /* 38 */ {`\`, SymError, errors.New("incomplete escape sequence"), nil},
/* 39 */ {`"string"`, SymString, "string", nil}, /* 39 */ {`"string"`, SymString, "string", nil},
/* 40 */ {`identifier`, SymIdentifier, "identifier", nil}, /* 40 */ {`identifier`, SymIdentifier, "identifier", nil},
/* 41 */ {`1.2(3)`, SymFraction, kern.NewFraction(37, 30), nil},
} }
for i, input := range inputs { for i, input := range inputs {
-9
View File
@@ -199,15 +199,6 @@ func (t *Term) Compute(ctx kern.ExprContext) (v any, err error) {
return 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 { func (t *Term) ErrIncompatibleTypes(leftValue, rightValue any) error {
leftType := kern.TypeName(leftValue) leftType := kern.TypeName(leftValue)
leftText := kern.GetFormatted(leftValue, kern.Truncate) leftText := kern.GetFormatted(leftValue, kern.Truncate)
+4 -3
View File
@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/types"
"git.portale-stac.it/go-pkg/expr/util" "git.portale-stac.it/go-pkg/expr/util"
// "strings" // "strings"
) )
@@ -76,12 +77,12 @@ func (ctx *SimpleStore) Clone() kern.ExprContext {
// } // }
// } // }
func (ctx *SimpleStore) ToDict() (dict *kern.DictType) { func (ctx *SimpleStore) ToDict() any {
return kern.ContextToDict(ctx) return types.ContextToDict(ctx)
} }
func (ctx *SimpleStore) ToString(opt kern.FmtOpt) string { 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 { // func (ctx *SimpleStore) ToString(opt kern.FmtOpt) string {
+10 -10
View File
@@ -21,15 +21,15 @@ func TestBool(t *testing.T) {
/* 5 */ {`not "true"`, false, nil}, /* 5 */ {`not "true"`, false, nil},
/* 6 */ {`not "false"`, false, nil}, /* 6 */ {`not "false"`, false, nil},
/* 7 */ {`not ""`, true, 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}, /* 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"`)}, /* 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 '[]' [list] on its left side`)}, /* 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}, /* 12 */ {`true or false`, true, nil},
/* 13 */ {`true or []`, 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}, /* 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", ".") // t.Setenv("EXPR_PATH", ".")
@@ -48,13 +48,13 @@ func TestBoolNoShortcut(t *testing.T) {
/* 5 */ {`not "true"`, false, nil}, /* 5 */ {`not "true"`, false, nil},
/* 6 */ {`not "false"`, false, nil}, /* 6 */ {`not "false"`, false, nil},
/* 7 */ {`not ""`, true, 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}, /* 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"`}, /* 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 '[]' [list] and right operand 'false' [bool] 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}, /* 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"`}, /* 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 '[]' [list] and right operand 'false' [bool] 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", ".") // t.Setenv("EXPR_PATH", ".")
+19 -17
View File
@@ -7,7 +7,8 @@ package expr
import ( import (
"testing" "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) { func TestFuncBase(t *testing.T) {
@@ -35,10 +36,10 @@ func TestFuncBase(t *testing.T) {
/* 19 */ {`isFract(1:3)`, true, nil}, /* 19 */ {`isFract(1:3)`, true, nil},
/* 20 */ {`isFract(3:1)`, false, nil}, /* 20 */ {`isFract(3:1)`, false, nil},
/* 21 */ {`isRational(3:1)`, true, nil}, /* 21 */ {`isRational(3:1)`, true, nil},
/* 22 */ {`fract("2.2(3)")`, kern.NewFraction(67, 30), nil}, /* 22 */ {`fract("2.2(3)")`, fract.NewFraction(67, 30), nil},
/* 23 */ {`fract("1.21(3)")`, kern.NewFraction(91, 75), nil}, /* 23 */ {`fract("1.21(3)")`, fract.NewFraction(91, 75), nil},
/* 24 */ {`fract(1.21(3))`, kern.NewFraction(91, 75), nil}, /* 24 */ {`fract(1.21(3))`, fract.NewFraction(91, 75), nil},
/* 25 */ {`fract(1.21)`, kern.NewFraction(121, 100), nil}, /* 25 */ {`fract(1.21)`, fract.NewFraction(121, 100), nil},
/* 26 */ {`dec(2)`, float64(2), nil}, /* 26 */ {`dec(2)`, float64(2), nil},
/* 27 */ {`dec(2.0)`, float64(2), nil}, /* 27 */ {`dec(2.0)`, float64(2), nil},
/* 28 */ {`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`}, /* 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`}, /* 32 */ {`dec(1,2,3)`, nil, `dec(): too many params -- expected 1, got 3`},
/* 33 */ {`isBool(false)`, true, nil}, /* 33 */ {`isBool(false)`, true, nil},
/* 34 */ {`fract(1:2)`, kern.NewFraction(1, 2), nil}, /* 34 */ {`fract(1:2)`, fract.NewFraction(1, 2), nil},
/* 35 */ {`fract(12,2)`, kern.NewFraction(6, 1), nil}, /* 35 */ {`fract(12,2)`, fract.NewFraction(6, 1), nil},
/* 36 */ {`bool(2)`, true, nil}, /* 36 */ {`bool(2)`, true, nil},
/* 37 */ {`bool(1:2)`, true, nil}, /* 37 */ {`bool(1:2)`, true, nil},
/* 38 */ {`bool(1.0)`, true, nil}, /* 38 */ {`bool(1.0)`, true, nil},
@@ -60,7 +61,7 @@ func TestFuncBase(t *testing.T) {
/* 44 */ {`bool({1:"one"})`, true, nil}, /* 44 */ {`bool({1:"one"})`, true, nil},
/* 45 */ {`dec(false)`, float64(0), nil}, /* 45 */ {`dec(false)`, float64(0), nil},
/* 46 */ {`dec(1:2)`, float64(0.5), 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}, /* 48 */ {`eval("a=3"); a`, int64(3), nil},
/* 49 */ {`int(5:2)`, int64(2), nil}, /* 49 */ {`int(5:2)`, int64(2), nil},
@@ -95,20 +96,21 @@ func TestFuncBaseFraction(t *testing.T) {
section := "Builtin-Base-Fraction" section := "Builtin-Base-Fraction"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`fract(-0.5)`, kern.NewFraction(-1, 2), nil}, /* 1 */ {`fract(-0.5)`, fract.NewFraction(-1, 2), nil},
/* 2 */ {`fract("")`, (*kern.FractionType)(nil), `bad syntax`}, /* 2 */ {`fract("")`, (*fract.FractionType)(nil), `bad syntax`},
/* 3 */ {`fract("-1")`, kern.NewFraction(-1, 1), nil}, /* 3 */ {`fract("-1")`, fract.NewFraction(-1, 1), nil},
/* 4 */ {`fract("+1")`, kern.NewFraction(1, 1), nil}, /* 4 */ {`fract("+1")`, fract.NewFraction(1, 1), nil},
/* 5 */ {`fract("1a")`, (*kern.FractionType)(nil), `strconv.ParseInt: parsing "1a": invalid syntax`}, /* 5 */ {`fract("1a")`, (*fract.FractionType)(nil), `strconv.ParseInt: parsing "1a": invalid syntax`},
/* 6 */ {`fract(1,0)`, nil, `fract(): division by zero`}, /* 6 */ {`fract(1,0)`, nil, `fract(): division by zero`},
/* 7 */ {`fract(5, "1")`, nil, `fract(): expected integer, got string ("1")`}, /* 7 */ {`fract(5, "1")`, nil, `fract(): expected integer, got string ("1")`},
/* 8 */ {`fract(true)`, kern.NewFraction(1, 1), nil}, /* 8 */ {`fract(true)`, fract.NewFraction(1, 1), nil},
/* 9 */ {`fract(false)`, kern.NewFraction(0, 1), nil}, /* 9 */ {`fract(false)`, fract.NewFraction(0, 1), nil},
/* 10 */ {`1.2(3)`, fract.NewFraction(37, 30), nil},
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 8) // runTestSuiteSpec(t, section, inputs, 5)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }
@@ -118,7 +120,7 @@ func TestFuncBaseOthers(t *testing.T) {
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`set("a", 3); a`, int64(3), nil}, /* 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)`}, /* 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}, // /* 4 */ {`seq(1,2,4)`, kern.NewLinkedListA(int64(1), int64(2), int64(3)), nil},
} }
+2 -2
View File
@@ -7,7 +7,7 @@ package expr
import ( import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/array"
) )
func TestFuncString(t *testing.T) { func TestFuncString(t *testing.T) {
@@ -30,7 +30,7 @@ func TestFuncString(t *testing.T) {
/* 14 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "789")`, true, nil}, /* 14 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "789")`, true, nil},
/* 15 */ {`builtin "string"; strEndsWith("0123456789", "xyz", "0125")`, false, 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`}, /* 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)`}, /* 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`}, /* 19 */ {`builtin "string"; strJoin()`, nil, `strJoin(): too few params -- expected 1 or more, got 0`},
/* 20 */ {`builtin "string"; strUpper("StOp")`, "STOP", nil}, /* 20 */ {`builtin "string"; strUpper("StOp")`, "STOP", nil},
+6 -4
View File
@@ -98,11 +98,13 @@ func doTest(t *testing.T, ctx kern.ExprContext, section string, input *inputType
gotResult, gotErr = ast.Eval(ctx) gotResult, gotErr = ast.Eval(ctx)
} }
eq := kern.Equal(gotResult, input.wantResult) if gotErr == nil && wantErr != nil {
eq := kern.Equal(gotResult, input.wantResult)
if !eq /*gotResult != input.wantResult*/ { 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)) 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 good = false
}
} }
if gotErr != wantErr { if gotErr != wantErr {
+3 -3
View File
@@ -7,7 +7,7 @@ package expr
import ( import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/list"
) )
func TestCtrlSet(t *testing.T) { func TestCtrlSet(t *testing.T) {
@@ -82,8 +82,8 @@ func TestList(t *testing.T) {
section := "Context" section := "Context"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`$$(5)`, kern.NewLinkedListA(5), nil}, /* 1 */ {`$$(5)`, list.NewLinkedListA(5), nil},
/* 2 */ {`$$($(2))`, kern.NewLinkedListA(0, 1), nil}, /* 2 */ {`$$($(2))`, list.NewLinkedListA(0, 1), nil},
/* 3 */ {`string(($$global).funcs.bool)`, `bool(value):boolean{}`, nil}, /* 3 */ {`string(($$global).funcs.bool)`, `bool(value):boolean{}`, nil},
} }
+20 -17
View File
@@ -11,40 +11,42 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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) { func TestDictParser(t *testing.T) {
section := "Dict" section := "Dict"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`{}`, kern.NewDict(nil), nil}, /* 1 */ {`{}`, dict.NewDict(nil), nil},
/* 2 */ {`{123}`, nil, errors.New("[1:6] expected `:`, got `}`")}, /* 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}, /* 4 */ {`{1:"one",2:"two",3:"three"}[3]`, "three", nil},
/* 5 */ {`#{1:"one",2:"two",3:"three"}`, int64(3), 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}, /* 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}, /* 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`, kern.NewDict(map[any]any{"z": int64(9), "a": int64(1), "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`)}, /* 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}, /* 11 */ {`D={"a":1, "b":2}; D["a"]`, int64(1), nil},
/* 12 */ {`m={ /* 12 */ {`m={
"a":1, "a":1,
//"b":2, //"b":2,
"c":3 "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}, /* 13 */ {`D={"a":1, "b":2}; D."a"`, int64(1), nil},
/* 14 */ {`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}, /* 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`}, /* 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`}, /* 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}, /* 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`}, /* 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 "{}"`}, /* 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 `;`"}, /* 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) // runTestSuiteSpec(t, section, inputs, 23, 24)
@@ -56,9 +58,9 @@ func TestAccessSubFields(t *testing.T) {
ctx := NewSimpleStore() ctx := NewSimpleStore()
ctx.UnsafeSetVar( ctx.UnsafeSetVar(
"D", "D",
kern.NewDict(map[any]any{ dict.NewDict(map[any]any{
"a": kern.NewDict(map[any]any{"uno": int64(10)}), "a": dict.NewDict(map[any]any{"uno": int64(10)}),
"b": kern.NewListA(1, 2, 3), "b": list.NewLinkedListA(1, 2, 3),
}), }),
) // D={"a": {"uno":1}} ) // D={"a": {"uno":1}}
@@ -66,10 +68,11 @@ func TestAccessSubFields(t *testing.T) {
/* 1 */ {`D.a.uno`, int64(10), nil}, /* 1 */ {`D.a.uno`, int64(10), nil},
/* 2 */ {`D.a.uno = 111; D.a."uno"`, int64(111), nil}, /* 2 */ {`D.a.uno = 111; D.a."uno"`, int64(111), nil},
/* 3 */ {`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) runCtxTestSuiteSpec(t, ctx, section, inputs, 4)
runCtxTestSuite(t, ctx, section, inputs) // runCtxTestSuite(t, ctx, section, inputs)
} }
func TestDictToStringMultiLine(t *testing.T) { func TestDictToStringMultiLine(t *testing.T) {
@@ -81,7 +84,7 @@ func TestDictToStringMultiLine(t *testing.T) {
args := map[any]any{ args := map[any]any{
"first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)), "first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)),
} }
dict := kern.NewDict(args) dict := dict.NewDict(args)
got := dict.ToString(kern.MultiLine) got := dict.ToString(kern.MultiLine)
// fmt.Printf("got=%q\n", got) // fmt.Printf("got=%q\n", got)
@@ -103,7 +106,7 @@ func TestDictToString(t *testing.T) {
args := map[any]any{ args := map[any]any{
"first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)), "first": newLiteralTerm(scan.NewValueToken(0, 0, scan.SymInteger, "1", 1)),
} }
dict := kern.NewDict(args) dict := dict.NewDict(args)
got := dict.ToString(0) got := dict.ToString(0)
// fmt.Printf("got=%q\n", got) // fmt.Printf("got=%q\n", got)
+2 -2
View File
@@ -7,7 +7,7 @@ package expr
import ( import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/dict"
) )
func TestExpr(t *testing.T) { 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 ")"`}, /* 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}, /* 16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil},
/* 17 */ {`true ? {"a"} :: {"b"}`, "a", 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 */ {` /* 19 */ {`
ds={ ds={
"init":func(@end){@current=0 but true}, "init":func(@end){@current=0 but true},
+15 -14
View File
@@ -8,29 +8,30 @@ import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/types/fract"
) )
func TestFractionsParser(t *testing.T) { func TestFractionsParser(t *testing.T) {
section := "Fraction" section := "Fraction"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`1:2`, kern.NewFraction(1, 2), nil}, /* 1 */ {`1:2`, fract.NewFraction(1, 2), nil},
/* 2 */ {`1:2 + 1`, kern.NewFraction(3, 2), nil}, /* 2 */ {`1:2 + 1`, fract.NewFraction(3, 2), nil},
/* 3 */ {`1:2 - 1`, kern.NewFraction(-1, 2), nil}, /* 3 */ {`1:2 - 1`, fract.NewFraction(-1, 2), nil},
/* 4 */ {`1:2 * 1`, kern.NewFraction(1, 2), nil}, /* 4 */ {`1:2 * 1`, fract.NewFraction(1, 2), nil},
/* 5 */ {`1:2 * 2:3`, kern.NewFraction(2, 6), nil}, /* 5 */ {`1:2 * 2:3`, fract.NewFraction(2, 6), nil},
/* 6 */ {`1:2 / 2:3`, kern.NewFraction(3, 4), nil}, /* 6 */ {`1:2 / 2:3`, fract.NewFraction(3, 4), nil},
/* 7 */ {`1:"5"`, nil, `denominator must be integer, got string (5)`}, /* 7 */ {`1:"5"`, nil, `denominator must be integer, got string (5)`},
/* 8 */ {`"1":5`, nil, `numerator must be integer, got string (1)`}, /* 8 */ {`"1":5`, nil, `numerator must be integer, got string (1)`},
/* 9 */ {`1:+5`, kern.NewFraction(1, 5), nil}, /* 9 */ {`1:+5`, fract.NewFraction(1, 5), nil},
/* 10 */ {`1:(-2)`, kern.NewFraction(-1, 2), nil}, /* 10 */ {`1:(-2)`, fract.NewFraction(-1, 2), nil},
/* 11 */ {`builtin "math.arith"; add(1:2, 2:3)`, kern.NewFraction(7, 6), 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}, /* 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}, /* 14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil},
/* 15 */ {`1:0`, nil, `[1:3] division by zero`}, /* 15 */ {`1:0`, nil, `[1:3] division by zero`},
/* 16 */ {`1+1:2+0.5`, float64(2), nil}, /* 16 */ {`1+1:2+0.5`, float64(2), nil},
/* 17 */ {`1:(2-2)`, nil, `[1:3] division by zero`}, /* 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}, /* 19 */ {`1:2 == 0.5`, true, nil},
} }
// runTestSuiteSpec(t, section, inputs, 26) // runTestSuiteSpec(t, section, inputs, 26)
@@ -38,7 +39,7 @@ func TestFractionsParser(t *testing.T) {
} }
func TestFractionToStringSimple(t *testing.T) { func TestFractionToStringSimple(t *testing.T) {
source := kern.NewFraction(1, 2) source := fract.NewFraction(1, 2)
want := "1:2" want := "1:2"
got := source.ToString(0) got := source.ToString(0)
if got != want { if got != want {
@@ -47,7 +48,7 @@ func TestFractionToStringSimple(t *testing.T) {
} }
func TestFractionToStringMultiline(t *testing.T) { func TestFractionToStringMultiline(t *testing.T) {
source := kern.NewFraction(1, 2) source := fract.NewFraction(1, 2)
want := "1\n-\n2" want := "1\n-\n2"
got := source.ToString(kern.MultiLine) got := source.ToString(kern.MultiLine)
if got != want { if got != want {
@@ -56,7 +57,7 @@ func TestFractionToStringMultiline(t *testing.T) {
} }
func TestToStringMultilineTty(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" want := "\x1b[4m-1\x1b[0m\n 2"
got := source.ToString(kern.MultiLine | kern.TTY) got := source.ToString(kern.MultiLine | kern.TTY)
if got != want { if got != want {
+2 -2
View File
@@ -7,7 +7,7 @@ package expr
import ( import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/array"
) )
func TestCollections(t *testing.T) { 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`}, /* 5 */ {`"abcdef"[1:2:3]`, nil, `[1:14] invalid range specification`},
/* 6 */ {`"abcdef"[((1>0)?{1}:{0}):3]`, "bc", nil}, /* 6 */ {`"abcdef"[((1>0)?{1}:{0}):3]`, "bc", nil},
/* 7 */ {`"abcdef"[[0,1][0]:1]`, "a", 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", ".") t.Setenv("EXPR_PATH", ".")
+3 -3
View File
@@ -7,14 +7,14 @@ package expr
import ( import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/list"
) )
func TestIterIterator(t *testing.T) { func TestIterIterator(t *testing.T) {
section := "Iter-Iter" section := "Iter-Iter"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`it=$(4); $$($(it) filter ${_}==100)`, kern.NewLinkedListA(), nil}, /* 1 */ {`it=$(4); $$($(it) filter ${_}==100)`, list.NewLinkedListA(), nil},
/* 2 */ {`it=$(4); $$($(it, $_) filter ${_}==100)`, kern.NewLinkedListA(), nil}, /* 2 */ {`it=$(4); $$($(it, $_) filter ${_}==100)`, list.NewLinkedListA(), nil},
/* 3 */ {`it=$(4); $(it, 10+$_, last-1) digest ${_}`, int64(12), 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}, /* 4 */ {`f=func(n){last-n}; it=$(4); $(it, 10+$_, f(-1)) digest ${_}`, int64(14), nil},
} }
+19 -19
View File
@@ -8,12 +8,12 @@ import (
"io" "io"
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/array"
) )
func TestNewListIterator(t *testing.T) { func TestNewListIterator(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, 3, 1}) it := NewListIterator(a, []any{1, 3, 1})
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} else if item != "b" { } else if item != "b" {
@@ -24,8 +24,8 @@ func TestNewListIterator(t *testing.T) {
} }
func TestNewListIterator2(t *testing.T) { func TestNewListIterator2(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{3, 1, -1}) it := NewListIterator(a, []any{3, 1, -1})
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} else if item != "d" { } else if item != "d" {
@@ -36,8 +36,8 @@ func TestNewListIterator2(t *testing.T) {
} }
func TestNewListIterator3(t *testing.T) { func TestNewListIterator3(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, -1, 1}) it := NewListIterator(a, []any{1, -1, 1})
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} else if item != "b" { } else if item != "b" {
@@ -93,8 +93,8 @@ func TestNewIterList5(t *testing.T) {
func TestNewIterList6(t *testing.T) { func TestNewIterList6(t *testing.T) {
ctx := NewSimpleStore() ctx := NewSimpleStore()
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it1, _ := NewIterator(ctx, list, nil) it1, _ := NewIterator(ctx, a, nil)
it, _ := NewIterator(ctx, it1, nil) it, _ := NewIterator(ctx, it1, nil)
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
@@ -115,8 +115,8 @@ func TestNewString(t *testing.T) {
func TestHasOperation(t *testing.T) { func TestHasOperation(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, 3, 1}) it := NewListIterator(a, []any{1, 3, 1})
hasOp := it.HasOperation("reset") hasOp := it.HasOperation("reset")
if !hasOp { if !hasOp {
t.Errorf("HasOperation(reset) must be true, got false") t.Errorf("HasOperation(reset) must be true, got false")
@@ -125,8 +125,8 @@ func TestHasOperation(t *testing.T) {
func TestCallOperationReset(t *testing.T) { func TestCallOperationReset(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, 3, 1}) it := NewListIterator(a, []any{1, 3, 1})
if v, err := it.CallOperation("reset", nil); err != nil { if v, err := it.CallOperation("reset", nil); err != nil {
t.Errorf("Error on CallOperation(reset): %v", err) t.Errorf("Error on CallOperation(reset): %v", err)
} else { } else {
@@ -136,8 +136,8 @@ func TestCallOperationReset(t *testing.T) {
func TestCallOperationIndex(t *testing.T) { func TestCallOperationIndex(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, 3, 1}) it := NewListIterator(a, []any{1, 3, 1})
if v, err := it.CallOperation("index", nil); err != nil { if v, err := it.CallOperation("index", nil); err != nil {
t.Errorf("Error on CallOperation(index): %v", err) t.Errorf("Error on CallOperation(index): %v", err)
} else { } else {
@@ -147,8 +147,8 @@ func TestCallOperationIndex(t *testing.T) {
func TestCallOperationCount(t *testing.T) { func TestCallOperationCount(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, 3, 1}) it := NewListIterator(a, []any{1, 3, 1})
if v, err := it.CallOperation("count", nil); err != nil { if v, err := it.CallOperation("count", nil); err != nil {
t.Errorf("Error on CallOperation(count): %v", err) t.Errorf("Error on CallOperation(count): %v", err)
} else { } else {
@@ -158,8 +158,8 @@ func TestCallOperationCount(t *testing.T) {
func TestCallOperationUnknown(t *testing.T) { func TestCallOperationUnknown(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") a := array.NewListA("a", "b", "c", "d")
it := NewListIterator(list, []any{1, 3, 1}) it := NewListIterator(a, []any{1, 3, 1})
if v, err := it.CallOperation("unknown", nil); err == nil { if v, err := it.CallOperation("unknown", nil); err == nil {
t.Errorf("Expected error on CallOperation(unknown), got %v", v) t.Errorf("Expected error on CallOperation(unknown), got %v", v)
} }
+15 -12
View File
@@ -9,6 +9,9 @@ import (
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan" "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) { 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}, /* 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}, /* 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}, /* 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`}, /* 23 */ {`$$($(1,4,0))`, nil, `step cannot be zero`},
/* 24 */ {`$$($(1,4,-1))`, nil, `step cannot be negative when start < stop`}, /* 24 */ {`$$($(1,4,-1))`, nil, `step cannot be negative when start < stop`},
/* 25 */ {`$$($(4,1,1))`, nil, `step cannot be positive 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) { func TestCallOpDictIter(t *testing.T) {
section := "DictIterator-CallOp" 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 { if it, err := NewDictIterator(inner, nil); err != nil {
t.Errorf(`%s -- NewIterIter() failed: %v`, section, err) t.Errorf(`%s -- NewIterIter() failed: %v`, section, err)
} else { } else {
@@ -87,7 +90,7 @@ func TestCallOpDictIter(t *testing.T) {
func TestCallOpLinkedListIter(t *testing.T) { func TestCallOpLinkedListIter(t *testing.T) {
section := "LinkedListIterator-CallOp" section := "LinkedListIterator-CallOp"
inner := kern.NewLinkedListA(1, 2, 3) inner := list.NewLinkedListA(1, 2, 3)
it := NewLinkedListIterator(inner, nil) it := NewLinkedListIterator(inner, nil)
testIteratorCallOp(t, section, it) 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) { func TestFilterIterator(t *testing.T) {
section := "Iterator-Filter" section := "Iterator-Filter"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`$$([1,2,3] filter $_%2==0)`, kern.NewLinkedListA(2), nil}, /* 1 */ {`$$([1,2,3] filter $_%2==0)`, list.NewLinkedListA(2), nil},
/* 2 */ {`it = [1,2,3] filter $_%2!=1; $$(it)`, kern.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}, /* 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}, /* 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) { func TestCatIterator(t *testing.T) {
section := "Iterator-Cat" section := "Iterator-Cat"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`$$([1] cat [])`, kern.NewLinkedListA(1), nil}, /* 1 */ {`$$([1] cat [])`, list.NewLinkedListA(1), nil},
/* 2 */ {`$$([1] cat [2])`, kern.NewLinkedListA(1, 2), nil}, /* 2 */ {`$$([1] cat [2])`, list.NewLinkedListA(1, 2), nil},
/* 3 */ {`$$([1] cat nil)`, kern.NewLinkedListA(1), nil}, /* 3 */ {`$$([1] cat nil)`, list.NewLinkedListA(1), nil},
/* 4 */ {`$$(nil cat [2])`, kern.NewLinkedListA(2), nil}, /* 4 */ {`$$(nil cat [2])`, list.NewLinkedListA(2), nil},
/* 5 */ {`$$(nil cat nil)`, kern.NewLinkedListA(), 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 "-"`}, /* 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) { func TestMapIterator(t *testing.T) {
section := "Iterator-Map" section := "Iterator-Map"
inputs := []inputType{ 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}, /* 2 */ {`#$$($(10) map ${_})`, int64(10), nil},
/* 3 */ {`#$$($(10,0) 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`}, /* 5 */ {`$$(["1", "2", "3"] map int())`, nil, `int(): too few params -- expected 1, got 0`},
} }
+28 -27
View File
@@ -7,56 +7,57 @@ package expr
import ( import (
"testing" "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) { func TestListParser(t *testing.T) {
section := "List" section := "List"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`[]`, kern.NewListA(), nil}, /* 1 */ {`[]`, array.NewListA(), nil},
/* 2 */ {`[1,2,3]`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, /* 2 */ {`[1,2,3]`, array.NewListA(int64(1), int64(2), int64(3)), nil},
/* 3 */ {`[1,2,"hello"]`, kern.NewListA(int64(1), int64(2), "hello"), nil}, /* 3 */ {`[1,2,"hello"]`, array.NewListA(int64(1), int64(2), "hello"), nil},
/* 4 */ {`[1+2, not true, "hello"]`, kern.NewListA(int64(3), false, "hello"), nil}, /* 4 */ {`[1+2, not true, "hello"]`, array.NewListA(int64(3), false, "hello"), nil},
/* 5 */ {`[1,2]+[3]`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, /* 5 */ {`[1,2]+[3]`, array.NewListA(int64(1), int64(2), int64(3)), nil},
/* 6 */ {`[1,4,3,2]-[3]`, kern.NewListA(int64(1), int64(4), int64(2)), 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}, /* 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}, /* 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}, /* 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`}, /* 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}, /* 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}, /* 12 */ {`[1,2,3] <+ 2+2`, array.NewListA(int64(1), int64(2), int64(3), int64(4)), nil},
/* 13 */ {`2-1 +> [2,3]`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, /* 13 */ {`2-1 +> [2,3]`, array.NewListA(int64(1), int64(2), int64(3)), nil},
/* 14 */ {`[1,2,3][1]`, int64(2), nil}, /* 14 */ {`[1,2,3][1]`, int64(2), nil},
/* 15 */ {`ls=[1,2,3] but ls[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}, /* 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`}, /* 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}, /* 18 */ {`["a", "b", "c"]`, array.NewListA("a", "b", "c"), nil},
/* 19 */ {`["a", "b", "c"]`, kern.NewList([]any{"a", "b", "c"}), nil}, /* 19 */ {`["a", "b", "c"]`, array.NewList([]any{"a", "b", "c"}), nil},
/* 20 */ {`#["a", "b", "c"]`, int64(3), nil}, /* 20 */ {`#["a", "b", "c"]`, int64(3), nil},
/* 21 */ {`"b" in ["a", "b", "c"]`, true, nil}, /* 21 */ {`"b" in ["a", "b", "c"]`, true, nil},
/* 22 */ {`a=[1,2]; (a)<+3`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, /* 22 */ {`a=[1,2]; (a)<+3`, array.NewListA(int64(1), int64(2), int64(3)), nil},
/* 23 */ {`a=[1,2]; (a)<+3; a`, kern.NewListA(int64(1), int64(2)), nil}, /* 23 */ {`a=[1,2]; (a)<+3; a`, array.NewListA(int64(1), int64(2)), nil},
/* 24 */ {`["a","b","c","d"][1]`, "b", nil}, /* 24 */ {`["a","b","c","d"][1]`, "b", nil},
/* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`}, /* 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`}, /* 27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`},
/* 28 */ {`2 << 3;`, int64(16), nil}, /* 28 */ {`2 << 3;`, int64(16), nil},
/* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`}, /* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`},
/* 30 */ {`2 >> 3;`, int64(0), nil}, /* 30 */ {`2 >> 3;`, int64(0), nil},
/* 31 */ {`a=[1,2]; a<+3`, kern.NewListA(int64(1), int64(2), int64(3)), nil}, /* 31 */ {`a=[1,2]; a<+3`, array.NewListA(int64(1), int64(2), int64(3)), nil},
/* 32 */ {`a=[1,2]; 5+>a`, kern.NewListA(int64(5), int64(1), int64(2)), nil}, /* 32 */ {`a=[1,2]; 5+>a`, array.NewListA(int64(5), int64(1), int64(2)), nil},
/* 33 */ {`L=[1,2]; L[0]=9; L`, kern.NewListA(int64(9), 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)`}, /* 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`}, /* 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}, /* 37 */ {`[0,1,2,3,4][2:3]`, array.NewListA(int64(2)), nil},
/* 38 */ {`[0,1,2,3,4][3:-1]`, kern.NewListA(int64(3)), nil}, /* 38 */ {`[0,1,2,3,4][3:-1]`, array.NewListA(int64(3)), nil},
/* 30 */ {`[0,1,2,3,4][-3:-1]`, kern.NewListA(int64(2), 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:]`, kern.NewListA(int64(0), int64(1), int64(2), int64(3), int64(4)), 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])`, kern.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`, kern.NewListA(), nil}, /* 42 */ {`L=[]; [1] >> L; L`, array.NewListA(), nil},
/* 43 */ {`L=[]; L << [1]; L`, kern.NewListA(), nil}, /* 43 */ {`L=[]; L << [1]; L`, array.NewListA(), nil},
// /* 44 */ {`[0,1,2,3,4][2:3]`, kern.NewListA(int64(20)), 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" section := "Linked-List"
inputs := []inputType{ 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}, /* 2 */ {`it=$([<1,2,3>]); it++`, int64(1), nil},
/* 3 */ {`it=$([<1,2,3>]); #($$(it))`, int64(3), nil}, /* 3 */ {`it=$([<1,2,3>]); #($$(it))`, int64(3), nil},
/* 4 */ {`[<1,2,3>][0]`, int64(1), 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", ".") // t.Setenv("EXPR_PATH", ".")
+39 -37
View File
@@ -7,7 +7,9 @@ package expr
import ( import (
"testing" "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) { func TestOperator(t *testing.T) {
@@ -52,26 +54,26 @@ func TestOperator(t *testing.T) {
func TestOperatorInsert(t *testing.T) { func TestOperatorInsert(t *testing.T) {
section := "Operator-Insert" section := "Operator-Insert"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`["a", "b"] << nil`, kern.NewListA("a", "b"), nil}, /* 1 */ {`["a", "b"] << nil`, array.NewListA("a", "b"), nil},
/* 2 */ {`["a", "b"] << []`, kern.NewListA("a", "b", kern.NewListA()), nil}, /* 2 */ {`["a", "b"] << []`, array.NewListA("a", "b", array.NewListA()), nil},
/* 3 */ {`["a", "b"] << $([])`, kern.NewListA("a", "b"), nil}, /* 3 */ {`["a", "b"] << $([])`, array.NewListA("a", "b"), nil},
/* 4 */ {`["a", "b"] << 3`, kern.NewListA("a", "b", int64(3)), 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"]' [list] are not compatible with operator "<<"`}, /* 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"]`, kern.NewListA("a", "b"), nil}, /* 6 */ {`nil >> ["a", "b"]`, array.NewListA("a", "b"), nil},
/* 7 */ {`[] >> ["a", "b"]`, kern.NewListA(kern.NewListA(), "a", "b"), nil}, /* 7 */ {`[] >> ["a", "b"]`, array.NewListA(array.NewListA(), "a", "b"), nil},
/* 8 */ {`$([]) >> ["a", "b"]`, kern.NewListA("a", "b"), nil}, /* 8 */ {`$([]) >> ["a", "b"]`, array.NewListA("a", "b"), nil},
/* 9 */ {`["a", "b"] << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), 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])`, kern.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`, kern.NewListA("a", "b"), 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"`}, /* 12 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`},
/* 13 */ {`[<>] << 1`, kern.NewLinkedListA(1), nil}, /* 13 */ {`[<>] << 1`, list.NewLinkedListA(1), nil},
/* 14 */ {`[<>] << [1,2]`, kern.NewLinkedListA(kern.NewListA(int64(1), int64(2))), nil}, /* 14 */ {`[<>] << [1,2]`, list.NewLinkedListA(array.NewListA(int64(1), int64(2))), nil},
/* 15 */ {`[<>] << [<1,2>]`, kern.NewLinkedListA(kern.NewLinkedListA(1, 2)), nil}, /* 15 */ {`[<>] << [<1,2>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
/* 16 */ {`1 >> [<>]`, kern.NewLinkedListA(1), nil}, /* 16 */ {`1 >> [<>]`, list.NewLinkedListA(1), nil},
/* 17 */ {`[1,2] >> [<>]`, kern.NewLinkedListA(kern.NewListA(int64(1), int64(2))), nil}, /* 17 */ {`[1,2] >> [<>]`, list.NewLinkedListA(array.NewListA(int64(1), int64(2))), nil},
/* 18 */ {`[<1,2>] >> [<>]`, kern.NewLinkedListA(kern.NewLinkedListA(1, 2)), nil}, /* 18 */ {`[<1,2>] >> [<>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
/* 19 */ {`$([1,2]) >> [<>]`, kern.NewLinkedListA(1, 2), nil}, /* 19 */ {`$([1,2]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
/* 20 */ {`$([<1,2>]) >> [<>]`, kern.NewLinkedListA(1, 2), nil}, /* 20 */ {`$([<1,2>]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
} }
// runTestSuiteSpec(t, section, inputs, 9) // runTestSuiteSpec(t, section, inputs, 9)
@@ -81,10 +83,10 @@ func TestOperatorInsert(t *testing.T) {
func TestOperatorDeepAssign(t *testing.T) { func TestOperatorDeepAssign(t *testing.T) {
section := "Operator-DeepAssign" section := "Operator-DeepAssign"
inputs := []inputType{ 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}, /* 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`, kern.NewDict(map[any]any{"uno": int64(1), "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`, kern.NewListA("x", "b"), 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`, kern.NewListA("a", "b"), nil}, /* 4 */ {`LL=["a", "b"]; L:=LL; L[0]="x"; LL`, array.NewListA("a", "b"), nil},
} }
// runTestSuiteSpec(t, section, inputs, 4) // runTestSuiteSpec(t, section, inputs, 4)
@@ -105,25 +107,25 @@ func TestOperatorGroupBy(t *testing.T) {
section := "Operator-GroupBy" section := "Operator-GroupBy"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`L=[{"num": 1, "alpha": "one"}, {"num": 2, "alpha": "two"}, {"num": 3, "alpha": "three"}]; L groupby "num"`, /* 1 */ {`L=[{"num": 1, "alpha": "one"}, {"num": 2, "alpha": "two"}, {"num": 3, "alpha": "three"}]; L groupby "num"`,
kern.NewDict(map[any]any{ dict.NewDict(map[any]any{
"1": kern.NewListA(kern.NewDict(map[any]any{"num": int64(1), "alpha": "one"})), "1": array.NewListA(dict.NewDict(map[any]any{"num": int64(1), "alpha": "one"})),
"2": kern.NewListA(kern.NewDict(map[any]any{"num": int64(2), "alpha": "two"})), "2": array.NewListA(dict.NewDict(map[any]any{"num": int64(2), "alpha": "two"})),
"3": kern.NewListA(kern.NewDict(map[any]any{"num": int64(3), "alpha": "three"})), "3": array.NewListA(dict.NewDict(map[any]any{"num": int64(3), "alpha": "three"})),
}), }),
nil}, nil},
/* 2 */ {`cars = [{"model": "compas", "vendor": "jeep"}, {"model": "limited", "vendor": "jeep"}, {"model": "600", "vendor":"fiat"}]; cars groupby "vendor"`, /* 2 */ {`cars = [{"model": "compas", "vendor": "jeep"}, {"model": "limited", "vendor": "jeep"}, {"model": "600", "vendor":"fiat"}]; cars groupby "vendor"`,
kern.NewDict(map[any]any{ dict.NewDict(map[any]any{
"jeep": kern.NewListA( "jeep": array.NewListA(
kern.NewDict(map[any]any{"model": "compas", "vendor": "jeep"}), dict.NewDict(map[any]any{"model": "compas", "vendor": "jeep"}),
kern.NewDict(map[any]any{"model": "limited", "vendor": "jeep"})), dict.NewDict(map[any]any{"model": "limited", "vendor": "jeep"})),
"fiat": kern.NewListA(kern.NewDict(map[any]any{"model": "600", "vendor": "fiat"})), "fiat": array.NewListA(dict.NewDict(map[any]any{"model": "600", "vendor": "fiat"})),
}), }),
nil}, nil},
/* 3 */ {`[3,4,5] groupby $__`, /* 3 */ {`[3,4,5] groupby $__`,
kern.NewDict(map[any]any{ dict.NewDict(map[any]any{
"0": kern.NewListA(int64(3)), "0": array.NewListA(int64(3)),
"1": kern.NewListA(int64(4)), "1": array.NewListA(int64(4)),
"2": kern.NewListA(int64(5)), "2": array.NewListA(int64(5)),
}), }),
nil}, nil},
} }
+4 -3
View File
@@ -7,7 +7,8 @@ package expr
import ( import (
"testing" "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) { func TestGeneralParser(t *testing.T) {
@@ -132,9 +133,9 @@ func TestGeneralParser(t *testing.T) {
/* 116 */ {`null`, nil, `undefined variable or function "null"`}, /* 116 */ {`null`, nil, `undefined variable or function "null"`},
/* 117 */ {`{"key"}`, nil, "[1:8] expected `:`, got `}`"}, /* 117 */ {`{"key"}`, nil, "[1:8] expected `:`, got `}`"},
/* 118 */ {`{"key":}`, nil, "[1:9] expected `dictionary-value`, 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}, /* 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}, /* 122 */ {`x="abc"; x ?! #x`, int64(3), nil},
/* 123 */ {`x ?! #x`, nil, `[1:7] prefix/postfix operator "#" does not support operand '<nil>' [nil]`}, /* 123 */ {`x ?! #x`, nil, `[1:7] prefix/postfix operator "#" does not support operand '<nil>' [nil]`},
/* 124 */ {`x ?! (x+1)`, nil, nil}, /* 124 */ {`x ?! (x+1)`, nil, nil},
+1 -1
View File
@@ -30,7 +30,7 @@ func TestPluginExists(t *testing.T) {
func TestMakePluginName(t *testing.T) { func TestMakePluginName(t *testing.T) {
name := "json" name := "json"
want := "expr-" + name + "-plugin" + SHAREDLIBRARY_EXTENSION want := "expr-" + name + /*"-plugin" +*/ SHAREDLIBRARY_EXTENSION
if got := makePluginName(name); got != want { if got := makePluginName(name); got != want {
t.Errorf("makePluginName(%q) failed: Got: %q, Want: %q", name, got, want) t.Errorf("makePluginName(%q) failed: Got: %q, Want: %q", name, got, want)
+3 -3
View File
@@ -7,7 +7,7 @@ package expr
import ( import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/types/array"
) )
func TestStringsParser(t *testing.T) { func TestStringsParser(t *testing.T) {
@@ -19,9 +19,9 @@ func TestStringsParser(t *testing.T) {
/* 4 */ {`"uno" * (2+1)`, `unounouno`, nil}, /* 4 */ {`"uno" * (2+1)`, `unounouno`, nil},
/* 5 */ {`"abc"[1]`, `b`, nil}, /* 5 */ {`"abc"[1]`, `b`, nil},
/* 6 */ {`#"abc"`, int64(3), 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}, /* 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"}, /* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"},
} }
+23 -18
View File
@@ -10,6 +10,11 @@ import (
"testing" "testing"
"git.portale-stac.it/go-pkg/expr/kern" "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" "git.portale-stac.it/go-pkg/expr/util"
) )
@@ -19,7 +24,7 @@ func TestIsString(t *testing.T) {
failed := 0 failed := 0
count++ count++
if !kern.IsBool(true) { if !boolean.IsBool(true) {
t.Errorf("%d: IsBool(true) -> result = false, want true", count) t.Errorf("%d: IsBool(true) -> result = false, want true", count)
failed++ failed++
} else { } else {
@@ -27,7 +32,7 @@ func TestIsString(t *testing.T) {
} }
count++ count++
if !kern.IsString("abc") { if !str.IsString("abc") {
t.Errorf("%d: IsString(\"abc\") -> result = false, want true", count) t.Errorf("%d: IsString(\"abc\") -> result = false, want true", count)
failed++ failed++
} else { } else {
@@ -35,7 +40,7 @@ func TestIsString(t *testing.T) {
} }
count++ count++
if !kern.IsInteger(int64(123)) { if !types.IsInteger(int64(123)) {
t.Errorf("%d: IsInteger(123) -> result = false, want true", count) t.Errorf("%d: IsInteger(123) -> result = false, want true", count)
failed++ failed++
} else { } else {
@@ -43,7 +48,7 @@ func TestIsString(t *testing.T) {
} }
count++ count++
if !kern.IsFloat(1.23) { if !float.IsFloat(1.23) {
t.Errorf("%d: IsFloat(1.23) -> result = false, want true", count) t.Errorf("%d: IsFloat(1.23) -> result = false, want true", count)
failed++ failed++
} else { } else {
@@ -51,7 +56,7 @@ func TestIsString(t *testing.T) {
} }
count++ count++
if !kern.IsFloat(kern.NumAsFloat(123)) { if !float.IsFloat(types.NumAsFloat(123)) {
t.Errorf("%d: IsFloat(numAsFloat(123)) -> result = false, want true", count) t.Errorf("%d: IsFloat(numAsFloat(123)) -> result = false, want true", count)
failed++ failed++
} else { } else {
@@ -60,14 +65,14 @@ func TestIsString(t *testing.T) {
count++ count++
if kern.IsIterator("fake") { 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++ failed++
} else { } else {
succeeded++ succeeded++
} }
count++ count++
b, ok := kern.ToBool(true) b, ok := boolean.ToBool(true)
if !(ok && b) { if !(ok && b) {
t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok) t.Errorf("%d: toBool(true) b=%v, ok=%v -> result = false, want true", count, b, ok)
failed++ failed++
@@ -76,7 +81,7 @@ func TestIsString(t *testing.T) {
} }
count++ count++
b, ok = kern.ToBool("abc") b, ok = boolean.ToBool("abc")
if !(ok && b) { if !(ok && b) {
t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok) t.Errorf("%d: toBool(\"abc\") b=%v, ok=%v -> result = false, want true", count, b, ok)
failed++ failed++
@@ -85,7 +90,7 @@ func TestIsString(t *testing.T) {
} }
count++ count++
b, ok = kern.ToBool([]int{}) b, ok = boolean.ToBool([]int{})
if ok { if ok {
t.Errorf("%d: toBool([]) b=%v, ok=%v -> result = true, want false", count, b, ok) t.Errorf("%d: toBool([]) b=%v, ok=%v -> result = true, want false", count, b, ok)
failed++ failed++
@@ -101,7 +106,7 @@ func TestToIntOk(t *testing.T) {
wantValue := int(64) wantValue := int(64)
wantErr := error(nil) wantErr := error(nil)
gotValue, gotErr := kern.ToGoInt(source, "test") gotValue, gotErr := types.ToGoInt(source, "test")
if gotErr != nil || gotValue != wantValue { if gotErr != nil || gotValue != wantValue {
t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v",
@@ -114,7 +119,7 @@ func TestToIntErr(t *testing.T) {
wantValue := 0 wantValue := 0
wantErr := errors.New(`test expected integer, got uint64 (64)`) 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 { if gotErr.Error() != wantErr.Error() || gotValue != wantValue {
t.Errorf("toInt(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", 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) wantValue := int64(64)
wantErr := error(nil) wantErr := error(nil)
gotValue, gotErr := kern.ToGoInt64(source, "test") gotValue, gotErr := types.ToGoInt64(source, "test")
if gotErr != nil || gotValue != wantValue { if gotErr != nil || gotValue != wantValue {
t.Errorf("toInt64(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", 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) wantValue := int64(0)
wantErr := errors.New(`test expected integer, got uint64 (64)`) 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 { if gotErr.Error() != wantErr.Error() || gotValue != wantValue {
t.Errorf("toInt64(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v", t.Errorf("toInt64(%v, \"test\") gotValue=%v, gotErr=%v -> wantValue=%v, wantErr=%v",
@@ -173,7 +178,7 @@ func TestAnyInteger(t *testing.T) {
failed := 0 failed := 0
for i, input := range inputs { for i, input := range inputs {
gotValue, gotOk := kern.AnyInteger(input.source) gotValue, gotOk := types.AnyInteger(input.source)
if gotOk != input.wantOk || gotValue != input.wantValue { if gotOk != input.wantOk || gotValue != input.wantValue {
t.Errorf("%d: anyInteger(%v) -> gotOk = %t, wantOk = %t; gotValue = %v, wantValue = %v", t.Errorf("%d: anyInteger(%v) -> gotOk = %t, wantOk = %t; gotValue = %v, wantValue = %v",
i+1, input.source, gotOk, input.wantOk, gotValue, input.wantValue) i+1, input.source, gotOk, input.wantOk, gotValue, input.wantValue)
@@ -199,7 +204,7 @@ func TestToStringOk(t *testing.T) {
wantValue := "ciao" wantValue := "ciao"
wantErr := error(nil) wantErr := error(nil)
gotValue, gotErr := kern.ToGoString(source, "test") gotValue, gotErr := str.ToGoString(source, "test")
if gotErr != nil { if gotErr != nil {
t.Error(gotErr) t.Error(gotErr)
@@ -210,11 +215,11 @@ func TestToStringOk(t *testing.T) {
} }
func TestToStringErr(t *testing.T) { func TestToStringErr(t *testing.T) {
source := kern.NewListA() source := array.NewListA()
wantValue := "" 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() { if gotErr != nil && gotErr.Error() != wantErr.Error() {
t.Errorf(`ToGoString(%v, "test") gotValue=%q, gotErr=%v -> wantValue=%q, wantErr=%v`, t.Errorf(`ToGoString(%v, "test") gotValue=%q, gotErr=%v -> wantValue=%q, wantErr=%v`,
+62 -43
View File
@@ -2,12 +2,13 @@
// All rights reserved. // All rights reserved.
// list-type.go // list-type.go
package kern package array
import ( import (
"fmt" "fmt"
"reflect"
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern"
) )
type ListType []any type ListType []any
@@ -50,40 +51,40 @@ func ListFromStrings(stringList []string) (list *ListType) {
return return
} }
func (ls *ListType) ToString(opt FmtOpt) (s string) { func (ls *ListType) ToString(opt kern.FmtOpt) (s string) {
indent := GetFormatIndent(opt) indent := kern.GetFormatIndent(opt)
flags := GetFormatFlags(opt) flags := kern.GetFormatFlags(opt)
var sb strings.Builder var sb strings.Builder
sb.WriteByte('[') sb.WriteByte('[')
if len(*ls) > 0 { if len(*ls) > 0 {
innerOpt := MakeFormatOptions(flags, indent+1) innerOpt := kern.MakeFormatOptions(flags, indent+1)
nest := strings.Repeat(" ", indent+1) nest := strings.Repeat(" ", indent+1)
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
sb.WriteByte('\n') sb.WriteByte('\n')
sb.WriteString(nest) sb.WriteString(nest)
} }
for i, item := range []any(*ls) { for i, item := range []any(*ls) {
if i > 0 { if i > 0 {
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
sb.WriteString(",\n") sb.WriteString(",\n")
sb.WriteString(nest) sb.WriteString(nest)
} else { } else {
sb.WriteString(", ") sb.WriteString(", ")
} }
} }
Format(&sb, item, innerOpt) kern.Format(&sb, item, innerOpt)
} }
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
sb.WriteByte('\n') sb.WriteByte('\n')
sb.WriteString(strings.Repeat(" ", indent)) sb.WriteString(strings.Repeat(" ", indent))
} }
} }
sb.WriteByte(']') sb.WriteByte(']')
s = sb.String() s = sb.String()
if flags&Truncate != 0 && len(s) > TruncateSize { if flags&kern.Truncate != 0 && len(s) > kern.TruncateSize {
s = TruncateString(s) s = kern.TruncateString(s)
} }
return return
} }
@@ -93,7 +94,7 @@ func (ls *ListType) String() string {
} }
func (ls *ListType) TypeName() string { func (ls *ListType) TypeName() string {
return "list" return kern.TypeArray
} }
func (ls *ListType) Contains(t *ListType) (answer bool) { func (ls *ListType) Contains(t *ListType) (answer bool) {
@@ -108,6 +109,13 @@ func (ls *ListType) Contains(t *ListType) (answer bool) {
return 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) { func (ls *ListType) Equals(ls2 ListType) (answer bool) {
if ls2 != nil && len(*ls) == len(ls2) { if ls2 != nil && len(*ls) == len(ls2) {
answer = true answer = true
@@ -116,7 +124,7 @@ func (ls *ListType) Equals(ls2 ListType) (answer bool) {
// answer = false // answer = false
// break // break
// } // }
if !Equal(i1, ls2[index]) { if !kern.Equal(i1, ls2[index]) {
answer = false answer = false
break break
} }
@@ -128,20 +136,16 @@ func (ls *ListType) Equals(ls2 ListType) (answer bool) {
func (ls1 *ListType) Clone() (ls2 *ListType) { func (ls1 *ListType) Clone() (ls2 *ListType) {
ls := make(ListType, len(*ls1)) ls := make(ListType, len(*ls1))
for i, item := range *ls1 { for i, item := range *ls1 {
ls[i] = Clone(item) ls[i] = kern.Clone(item)
} }
ls2 = &ls ls2 = &ls
return return
} }
func (ls *ListType) IndexDeepSameCmp(target any) (index int) { func (ls *ListType) IndexDeepSameCmp(target any) (index int) {
var eq bool
var err error
index = -1 index = -1
for i, item := range *ls { for i, item := range *ls {
if eq, err = deepSame(item, target, SameContent); err != nil { if kern.Equal(item, target) {
break
} else if eq {
index = i index = i
break break
} }
@@ -149,6 +153,21 @@ func (ls *ListType) IndexDeepSameCmp(target any) (index int) {
return 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) { func SameContent(a, b any) (same bool, err error) {
la, _ := a.(*ListType) la, _ := a.(*ListType)
lb, _ := b.(*ListType) lb, _ := b.(*ListType)
@@ -164,30 +183,30 @@ func SameContent(a, b any) (same bool, err error) {
return return
} }
func deepSame(a, b any, deepCmp DeepFuncTemplate) (eq bool, err error) { // func deepSame(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) {
if IsNumOrFract(a) && IsNumOrFract(b) { // if IsNumOrFract(a) && IsNumOrFract(b) {
if IsNumber(a) && IsNumber(b) { // if IsNumber(a) && IsNumber(b) {
if IsInteger(a) && IsInteger(b) { // if IsInteger(a) && IsInteger(b) {
li, _ := a.(int64) // li, _ := a.(int64)
ri, _ := b.(int64) // ri, _ := b.(int64)
eq = li == ri // eq = li == ri
} else { // } else {
eq = NumAsFloat(a) == NumAsFloat(b) // eq = NumAsFloat(a) == NumAsFloat(b)
} // }
} else { // } else {
var cmp int // var cmp int
if cmp, err = CmpAnyFract(a, b); err == nil { // if cmp, err = fract.CmpAnyFract(a, b); err == nil {
eq = cmp == 0 // eq = cmp == 0
} // }
} // }
} else if deepCmp != nil && IsList(a) && IsList(b) { // } else if deepCmp != nil && IsList(a) && IsList(b) {
eq, err = deepCmp(a, b) // eq, err = deepCmp(a, b)
} else { // } else {
eq = reflect.DeepEqual(a, b) // eq = reflect.DeepEqual(a, b)
} // }
return // return
} // }
func (ls *ListType) SetItem(index int64, value any) (err error) { func (ls *ListType) SetItem(index int64, value any) (err error) {
if index >= 0 && index < int64(len(*ls)) { if index >= 0 && index < int64(len(*ls)) {
+9 -2
View File
@@ -1,14 +1,21 @@
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). // Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved. // All rights reserved.
// string.go // bool.go
package kern package boolean
func IsBool(v any) (ok bool) { func IsBool(v any) (ok bool) {
_, ok = v.(bool) _, ok = v.(bool)
return ok 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) { func ToBool(v any) (b bool, ok bool) {
ok = true ok = true
switch x := v.(type) { switch x := v.(type) {
+36
View File
@@ -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
// }
+52
View File
@@ -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
}
+20 -18
View File
@@ -2,12 +2,14 @@
// All rights reserved. // All rights reserved.
// dict-type.go // dict-type.go
package kern package dict
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern"
) )
const DictTypeName = "dict" const DictTypeName = "dict"
@@ -39,7 +41,7 @@ func NewDict(dictAny map[any]any) (dict *DictType) {
return 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() // TODO Change with a call to NewDict()
var d DictType var d DictType
if dictAny != nil { if dictAny != nil {
@@ -54,14 +56,14 @@ func newDict(dictAny map[any]Term) (dict *DictType) {
return return
} }
func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) { func (dict *DictType) toMultiLine(sb *strings.Builder, opt kern.FmtOpt) {
indent := GetFormatIndent(opt) indent := kern.GetFormatIndent(opt)
flags := GetFormatFlags(opt) flags := kern.GetFormatFlags(opt)
//sb.WriteString(strings.Repeat(" ", indent)) //sb.WriteString(strings.Repeat(" ", indent))
sb.WriteByte('{') sb.WriteByte('{')
if len(*dict) > 0 { if len(*dict) > 0 {
innerOpt := MakeFormatOptions(flags, indent+1) innerOpt := kern.MakeFormatOptions(flags, indent+1)
nest := strings.Repeat(" ", indent+1) nest := strings.Repeat(" ", indent+1)
sb.WriteByte('\n') sb.WriteByte('\n')
@@ -83,9 +85,9 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) {
fmt.Fprintf(sb, "%v", name) fmt.Fprintf(sb, "%v", name)
} }
sb.WriteString(": ") sb.WriteString(": ")
if f, ok := value.(Formatter); ok { if f, ok := value.(kern.Formatter); ok {
sb.WriteString(f.ToString(innerOpt)) sb.WriteString(f.ToString(innerOpt))
} else if _, ok = value.(Functor); ok { } else if _, ok = value.(kern.Functor); ok {
sb.WriteString("func(){}") sb.WriteString("func(){}")
} else { } else {
fmt.Fprintf(sb, "%v", value) fmt.Fprintf(sb, "%v", value)
@@ -97,10 +99,10 @@ func (dict *DictType) toMultiLine(sb *strings.Builder, opt FmtOpt) {
sb.WriteString("}") sb.WriteString("}")
} }
func (dict *DictType) ToString(opt FmtOpt) string { func (dict *DictType) ToString(opt kern.FmtOpt) string {
var sb strings.Builder var sb strings.Builder
flags := GetFormatFlags(opt) flags := kern.GetFormatFlags(opt)
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
dict.toMultiLine(&sb, opt) dict.toMultiLine(&sb, opt)
} else { } else {
sb.WriteByte('{') sb.WriteByte('{')
@@ -119,9 +121,9 @@ func (dict *DictType) ToString(opt FmtOpt) string {
fmt.Fprintf(&sb, "%v", key) fmt.Fprintf(&sb, "%v", key)
} }
sb.WriteString(": ") sb.WriteString(": ")
if formatter, ok := value.(Formatter); ok { if formatter, ok := value.(kern.Formatter); ok {
sb.WriteString(formatter.ToString(opt)) sb.WriteString(formatter.ToString(opt))
} else if t, ok := value.(Term); ok { } else if t, ok := value.(kern.Term); ok {
sb.WriteString(t.String()) sb.WriteString(t.String())
} else { } else {
fmt.Fprintf(&sb, "%#v", value) 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) { func (dict *DictType) Clone() (c *DictType) {
c = newDict(nil) c = newDict(nil)
for k, v := range *dict { for k, v := range *dict {
(*c)[k] = Clone(v) (*c)[k] = kern.Clone(v)
} }
return return
} }
@@ -179,7 +181,7 @@ func (dict *DictType) Equals(dict2 DictType) (answer bool) {
answer = true answer = true
for key, value1 := range *dict { for key, value1 := range *dict {
if value2, exists := dict2.GetItem(key); exists { if value2, exists := dict2.GetItem(key); exists {
if !Equal(value1, value2) { if !kern.Equal(value1, value2) {
answer = false answer = false
break break
} }
@@ -194,6 +196,6 @@ func (dict *DictType) Equals(dict2 DictType) (answer bool) {
//////////////// ////////////////
type DictFormat interface { // type DictFormat interface {
ToDict() *DictType // ToDict() *DictType
} // }
+1 -1
View File
@@ -2,7 +2,7 @@
// All rights reserved. // All rights reserved.
// float.go // float.go
package kern package float
func IsFloat(v any) (ok bool) { func IsFloat(v any) (ok bool) {
_, ok = v.(float64) _, ok = v.(float64)
@@ -2,7 +2,7 @@
// All rights reserved. // All rights reserved.
// fraction-type.go // 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 //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" "math"
"strconv" "strconv"
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern"
) )
type FractionType struct { type FractionType struct {
@@ -23,6 +25,18 @@ func NewFraction(num, den int64) *FractionType {
return &FractionType{num, den} 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) { func Float64ToFraction(f float64) (fract *FractionType, err error) {
var sign string var sign string
intPart, decPart := math.Modf(f) intPart, decPart := math.Modf(f)
@@ -72,7 +86,7 @@ func MakeGeneratingFraction(s string) (f *FractionType, err error) {
} }
for _, c := range dec[0:lsd] { for _, c := range dec[0:lsd] {
if c < '0' || c > '9' { if c < '0' || c > '9' {
return nil, ErrExpectedGot("fract", "digit", c) return nil, kern.ErrExpectedGot("fract", "digit", c)
} }
num = num*10 + int64(c-'0') num = num*10 + int64(c-'0')
den = den * 10 den = den * 10
@@ -83,7 +97,7 @@ func MakeGeneratingFraction(s string) (f *FractionType, err error) {
mul := int64(1) mul := int64(1)
for _, c := range subParts[0] { for _, c := range subParts[0] {
if c < '0' || c > '9' { if c < '0' || c > '9' {
return nil, ErrExpectedGot("fract", "digit", c) return nil, kern.ErrExpectedGot("fract", "digit", c)
} }
num = num*10 + int64(c-'0') num = num*10 + int64(c-'0')
sub = sub*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] p := subParts[1][0 : len(subParts[1])-1]
for _, c := range p { for _, c := range p {
if c < '0' || c > '9' { if c < '0' || c > '9' {
return nil, ErrExpectedGot("fract", "digit", c) return nil, kern.ErrExpectedGot("fract", "digit", c)
} }
num = num*10 + int64(c-'0') num = num*10 + int64(c-'0')
den = den*10 + 9 den = den*10 + 9
@@ -114,37 +128,37 @@ exit:
return return
} }
func (f *FractionType) N() int64 { func (fr *FractionType) N() int64 {
return f.num return fr.num
} }
func (f *FractionType) D() int64 { func (fr *FractionType) D() int64 {
return f.den return fr.den
} }
func (f *FractionType) ToFloat() float64 { func (fr *FractionType) ToFloat() float64 {
return float64(f.num) / float64(f.den) return float64(fr.num) / float64(fr.den)
} }
func (f *FractionType) String() string { func (fr *FractionType) String() string {
return f.ToString(0) return fr.ToString(0)
} }
func (f *FractionType) ToString(opt FmtOpt) string { func (fr *FractionType) ToString(opt kern.FmtOpt) string {
var sb strings.Builder var sb strings.Builder
if opt&MultiLine == 0 { if opt&kern.MultiLine == 0 {
sb.WriteString(fmt.Sprintf("%d:%d", f.num, f.den)) sb.WriteString(fmt.Sprintf("%d:%d", fr.num, fr.den))
} else { } else {
var sign, num string var sign, num string
if f.num < 0 && opt&TTY == 0 { if fr.num < 0 && opt&kern.TTY == 0 {
num = strconv.FormatInt(-f.num, 10) num = strconv.FormatInt(-fr.num, 10)
sign = "-" sign = "-"
} else { } 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)) 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)) sNum := fmt.Sprintf("\x1b[4m%[1]*s\x1b[0m\n", -size, fmt.Sprintf("%[1]*s", (size+len(num))/2, sign+num))
sb.WriteString(sNum) sb.WriteString(sNum)
} else { } else {
@@ -170,7 +184,7 @@ func (f *FractionType) ToString(opt FmtOpt) string {
return sb.String() return sb.String()
} }
func (f *FractionType) TypeName() string { func (fr *FractionType) TypeName() string {
return "fraction" return "fraction"
} }
@@ -224,7 +238,7 @@ func anyToFract(v any) (f *FractionType, err error) {
} else if dec, ok := v.(float64); ok { } else if dec, ok := v.(float64); ok {
f, err = Float64ToFraction(dec) f, err = Float64ToFraction(dec)
} else { } else {
err = ErrExpectedGot("fract", TypeFraction, v) err = kern.ErrExpectedGot("fract", kern.TypeFraction, v)
} }
} }
return return
@@ -2,14 +2,15 @@
// All rights reserved. // All rights reserved.
// linked-list-type.go // linked-list-type.go
package kern package list
import ( import (
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern"
) )
const LinkedListTypeName = "lisked-list" const LinkedListTypeName = "lisked-list"
const MaxUint64Allowed = uint64(9_223_372_036_854_775_807)
func IsLinkedList(v any) (ok bool) { func IsLinkedList(v any) (ok bool) {
_, ok = v.(*LinkedList) _, ok = v.(*LinkedList)
@@ -22,7 +23,7 @@ func NewLinkedListA(listAny ...any) (list *LinkedList) {
} }
list = NewLinkedList() list = NewLinkedList()
for _, item := range listAny { for _, item := range listAny {
list.PushBack(FixAnyNumber(item)) list.PushBack(kern.FixAnyNumber(item))
} }
return return
} }
@@ -35,17 +36,17 @@ func LinkedListFromStrings(stringList []string) (list *LinkedList) {
return return
} }
func (ls *LinkedList) ToString(opt FmtOpt) (s string) { func (ls *LinkedList) ToString(opt kern.FmtOpt) (s string) {
indent := GetFormatIndent(opt) indent := kern.GetFormatIndent(opt)
flags := GetFormatFlags(opt) flags := kern.GetFormatFlags(opt)
var sb strings.Builder var sb strings.Builder
sb.WriteString("[<") sb.WriteString("[<")
if ls.Len() > 0 { if ls.Len() > 0 {
innerOpt := MakeFormatOptions(flags, indent+1) innerOpt := kern.MakeFormatOptions(flags, indent+1)
nest := strings.Repeat(" ", indent+1) nest := strings.Repeat(" ", indent+1)
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
sb.WriteByte('\n') sb.WriteByte('\n')
sb.WriteString(nest) sb.WriteString(nest)
} }
@@ -53,35 +54,26 @@ func (ls *LinkedList) ToString(opt FmtOpt) (s string) {
i := 0 i := 0
for item := ls.FirstNode(); item != nil; item = item.Next() { for item := ls.FirstNode(); item != nil; item = item.Next() {
if i > 0 { if i > 0 {
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
sb.WriteString(",\n") sb.WriteString(",\n")
sb.WriteString(nest) sb.WriteString(nest)
} else { } else {
sb.WriteString(", ") sb.WriteString(", ")
} }
} }
// data := item.Data()
// if s, ok := data.(string); ok { kern.Format(&sb, item.Data(), innerOpt)
// 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)
i++ i++
} }
if flags&MultiLine != 0 { if flags&kern.MultiLine != 0 {
sb.WriteByte('\n') sb.WriteByte('\n')
sb.WriteString(strings.Repeat(" ", indent)) sb.WriteString(strings.Repeat(" ", indent))
} }
} }
sb.WriteString(">]") sb.WriteString(">]")
s = sb.String() s = sb.String()
if flags&Truncate != 0 && len(s) > TruncateSize { if flags&kern.Truncate != 0 && len(s) > kern.TruncateSize {
s = TruncateString(s) s = kern.TruncateString(s)
} }
return return
} }
@@ -111,7 +103,7 @@ func (ls1 *LinkedList) Equals(ls2 *LinkedList) (answer bool) {
answer = true answer = true
i2 := ls2.FirstNode() i2 := ls2.FirstNode()
for i1 := ls1.FirstNode(); i1 != nil; i1 = i1.Next() { for i1 := ls1.FirstNode(); i1 != nil; i1 = i1.Next() {
if !Equal(i1.Data(), i2.Data()) { if !kern.Equal(i1.Data(), i2.Data()) {
answer = false answer = false
break break
} }
@@ -124,7 +116,7 @@ func (ls1 *LinkedList) Equals(ls2 *LinkedList) (answer bool) {
func (ls1 *LinkedList) Clone() (ls2 *LinkedList) { func (ls1 *LinkedList) Clone() (ls2 *LinkedList) {
ls2 = NewLinkedListA() ls2 = NewLinkedListA()
for i1 := ls1.FirstNode(); i1 != nil; i1 = i1.Next() { for i1 := ls1.FirstNode(); i1 != nil; i1 = i1.Next() {
ls2.PushBack(Clone(i1.Data())) ls2.PushBack(kern.Clone(i1.Data()))
} }
return return
} }
@@ -1,8 +1,13 @@
// simple-list project slist.go // Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
package kern // All rights reserved.
// linked-list.go
package list
import ( import (
"fmt" "fmt"
"git.portale-stac.it/go-pkg/expr/kern"
) )
type ListNode struct { type ListNode struct {
@@ -48,7 +53,7 @@ func (ls *LinkedList) PushFront(data any) *ListNode {
func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) { func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) {
switch seq := data.(type) { switch seq := data.(type) {
case Iterator: case kern.Iterator:
result = ls.IterPushFront(seq) result = ls.IterPushFront(seq)
default: default:
ls.PushFront(data) ls.PushFront(data)
@@ -57,7 +62,7 @@ func (ls *LinkedList) SeqPushFront(data any) (result *LinkedList) {
return 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() { for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() {
ls.PushFront(item) ls.PushFront(item)
} }
@@ -79,7 +84,7 @@ func (ls *LinkedList) PushBack(data any) (node *ListNode) {
func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) { func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) {
switch seq := data.(type) { switch seq := data.(type) {
case Iterator: case kern.Iterator:
result = ls.IterPushBack(seq) result = ls.IterPushBack(seq)
default: default:
ls.PushBack(data) ls.PushBack(data)
@@ -88,7 +93,7 @@ func (ls *LinkedList) SeqPushBack(data any) (result *LinkedList) {
return 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() { for item, err1 := it.Next(); err1 == nil; item, err1 = it.Next() {
ls.PushBack(item) ls.PushBack(item)
} }
+12 -39
View File
@@ -2,10 +2,15 @@
// All rights reserved. // All rights reserved.
// number.go // number.go
package kern package types
import ( import (
"fmt" "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) { func IsInteger(v any) (ok bool) {
@@ -14,21 +19,21 @@ func IsInteger(v any) (ok bool) {
} }
func IsNumber(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) { 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) { func IsNumberString(v any) (ok bool) {
return IsString(v) || IsNumber(v) return str.IsString(v) || IsNumber(v)
} }
func NumAsFloat(v any) (f float64) { func NumAsFloat(v any) (f float64) {
var ok bool var ok bool
if f, ok = v.(float64); !ok { if f, ok = v.(float64); !ok {
if fract, ok := v.(*FractionType); ok { if fract, ok := v.(*fract.FractionType); ok {
f = fract.ToFloat() f = fract.ToFloat()
} else { } else {
i, _ := v.(int64) i, _ := v.(int64)
@@ -65,45 +70,13 @@ func AnyInteger(v any) (i int64, ok bool) {
return 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) { func ToGoInt(value any, description string) (i int, err error) {
if valueInt64, ok := value.(int64); ok { if valueInt64, ok := value.(int64); ok {
i = int(valueInt64) i = int(valueInt64)
} else if valueInt, ok := value.(int); ok { } else if valueInt, ok := value.(int); ok {
i = valueInt i = valueInt
} else { } 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 return
} }
@@ -114,7 +87,7 @@ func ToGoInt64(value any, description string) (i int64, err error) {
} else if valueInt, ok := value.(int); ok { } else if valueInt, ok := value.(int); ok {
i = int64(valueInt) i = int64(valueInt)
} else { } 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 return
} }
+4 -2
View File
@@ -2,10 +2,12 @@
// All rights reserved. // All rights reserved.
// string.go // string.go
package kern package str
import ( import (
"fmt" "fmt"
"git.portale-stac.it/go-pkg/expr/kern"
) )
func IsString(v any) (ok bool) { 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 { if s, ok := value.(string); ok {
return s, nil return s, nil
} else { } 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 return
} }
+20
View File
@@ -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
// }
+41
View File
@@ -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
View File
@@ -7,7 +7,10 @@ package util
import ( import (
"reflect" "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 { func IsFunc(v any) bool {
@@ -22,16 +25,16 @@ func FromGenericAny(v any) (exprAny any, ok bool) {
if exprAny, ok = v.(string); ok { if exprAny, ok = v.(string); ok {
return return
} }
if exprAny, ok = kern.AnyInteger(v); ok { if exprAny, ok = types.AnyInteger(v); ok {
return return
} }
if exprAny, ok = kern.AnyFloat(v); ok { if exprAny, ok = float.AnyFloat(v); ok {
return return
} }
if exprAny, ok = v.(*kern.DictType); ok { if exprAny, ok = v.(*dict.DictType); ok {
return return
} }
if exprAny, ok = v.(*kern.ListType); ok { if exprAny, ok = v.(*array.ListType); ok {
return return
} }
} }