forgot to add the array module. Separated tests on array and list from operators
This commit is contained in:
+17
-56
@@ -11,62 +11,6 @@ import (
|
||||
"git.portale-stac.it/go-pkg/expr/types/list"
|
||||
)
|
||||
|
||||
func TestArray(t *testing.T) {
|
||||
section := "Array"
|
||||
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`[]`, array.NewArrayA(), nil},
|
||||
/* 2 */ {`[1,2,3]`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 3 */ {`[1,2,"hello"]`, array.NewArrayA(int64(1), int64(2), "hello"), nil},
|
||||
/* 4 */ {`[1+2, not true, "hello"]`, array.NewArrayA(int64(3), false, "hello"), nil},
|
||||
/* 5 */ {`[1,2]+[3]`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 6 */ {`[1,4,3,2]-[3]`, array.NewArrayA(int64(1), int64(4), int64(2)), nil},
|
||||
/* 7 */ {`builtin "math.arith"; add([1,4,3,2])`, int64(10), nil},
|
||||
/* 8 */ {`builtin "math.arith"; add([1,[2,2],3,2])`, int64(10), nil},
|
||||
/* 9 */ {`builtin "math.arith"; mul([1,4,3.0,2])`, float64(24.0), nil},
|
||||
/* 10 */ {`builtin "math.arith"; add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`},
|
||||
/* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil},
|
||||
/* 12 */ {`[1,2,3] <+ 2+2`, array.NewArrayA(int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 13 */ {`2-1 +> [2,3]`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 14 */ {`[1,2,3][1]`, int64(2), nil},
|
||||
/* 15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil},
|
||||
/* 16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil},
|
||||
/* 17 */ {`list=["one","two","three"]; list[10]`, nil, `[1:34] index 10 out of bounds`},
|
||||
/* 18 */ {`["a", "b", "c"]`, array.NewArrayA("a", "b", "c"), nil},
|
||||
/* 19 */ {`["a", "b", "c"]`, array.NewArray([]any{"a", "b", "c"}), nil},
|
||||
/* 20 */ {`#["a", "b", "c"]`, int64(3), nil},
|
||||
/* 21 */ {`"b" in ["a", "b", "c"]`, true, nil},
|
||||
/* 22 */ {`a=[1,2]; (a)<+3`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 23 */ {`a=[1,2]; (a)<+3; a`, array.NewArrayA(int64(1), int64(2)), nil},
|
||||
/* 24 */ {`["a","b","c","d"][1]`, "b", nil},
|
||||
/* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`},
|
||||
/* 26 */ {`[0,1,2,3,4][:]`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`},
|
||||
/* 28 */ {`2 << 3;`, int64(16), nil},
|
||||
/* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`},
|
||||
/* 30 */ {`2 >> 3;`, int64(0), nil},
|
||||
/* 31 */ {`a=[1,2]; a<+3`, array.NewArrayA(int64(1), int64(2), int64(3)), nil},
|
||||
/* 32 */ {`a=[1,2]; 5+>a`, array.NewArrayA(int64(5), int64(1), int64(2)), nil},
|
||||
/* 33 */ {`L=[1,2]; L[0]=9; L`, array.NewArrayA(int64(9), int64(2)), nil},
|
||||
/* 34 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
|
||||
/* 35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [array]`},
|
||||
/* 36 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
|
||||
/* 37 */ {`[0,1,2,3,4][2:3]`, array.NewArrayA(int64(2)), nil},
|
||||
/* 38 */ {`[0,1,2,3,4][3:-1]`, array.NewArrayA(int64(3)), nil},
|
||||
/* 30 */ {`[0,1,2,3,4][-3:-1]`, array.NewArrayA(int64(2), int64(3)), nil},
|
||||
/* 40 */ {`[0,1,2,3,4][0:]`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 41 */ {`[0] << $([1,2,3,4])`, array.NewArrayA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
||||
/* 42 */ {`L=[]; [1] >> L; L`, array.NewArrayA(), nil},
|
||||
/* 43 */ {`L=[]; L << [1]; L`, array.NewArrayA(), nil},
|
||||
// /* 44 */ {`[0,1,2,3,4][2:3]`, kern.NewListA(int64(20)), nil},
|
||||
}
|
||||
|
||||
// t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 44)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func TestLinkedListParser(t *testing.T) {
|
||||
section := "Linked-List"
|
||||
|
||||
@@ -89,3 +33,20 @@ func TestLinkedListParser(t *testing.T) {
|
||||
// runTestSuiteSpec(t, section, inputs, 4)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func TestLinkedInsert(t *testing.T) {
|
||||
section := "LinkedList-Insert"
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`[<>] << 1`, list.NewLinkedListA(1), nil},
|
||||
/* 2 */ {`[<>] << [1,2]`, list.NewLinkedListA(array.NewArrayA(int64(1), int64(2))), nil},
|
||||
/* 3 */ {`[<>] << [<1,2>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
|
||||
/* 4 */ {`1 >> [<>]`, list.NewLinkedListA(1), nil},
|
||||
/* 5 */ {`[1,2] >> [<>]`, list.NewLinkedListA(array.NewArrayA(int64(1), int64(2))), nil},
|
||||
/* 6 */ {`[<1,2>] >> [<>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
|
||||
/* 7 */ {`$([1,2]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
|
||||
/* 8 */ {`$([<1,2>]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
|
||||
}
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 9)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ 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 TestOperator(t *testing.T) {
|
||||
@@ -51,48 +50,6 @@ func TestOperator(t *testing.T) {
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func TestOperatorInsert(t *testing.T) {
|
||||
section := "Operator-Insert"
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`["a", "b"] << nil`, array.NewArrayA("a", "b"), nil},
|
||||
/* 2 */ {`["a", "b"] << []`, array.NewArrayA("a", "b", array.NewArrayA()), nil},
|
||||
/* 3 */ {`["a", "b"] << $([])`, array.NewArrayA("a", "b"), nil},
|
||||
/* 4 */ {`["a", "b"] << 3`, array.NewArrayA("a", "b", int64(3)), nil},
|
||||
/* 5 */ {`3 << ["a", "b"]`, nil, `[1:5] left operand '3' [integer] and right operand '["a", "b"]' [array] are not compatible with operator "<<"`},
|
||||
/* 6 */ {`nil >> ["a", "b"]`, array.NewArrayA("a", "b"), nil},
|
||||
/* 7 */ {`[] >> ["a", "b"]`, array.NewArrayA(array.NewArrayA(), "a", "b"), nil},
|
||||
/* 8 */ {`$([]) >> ["a", "b"]`, array.NewArrayA("a", "b"), nil},
|
||||
/* 9 */ {`["a", "b"] << $([1,2,3])`, array.NewArrayA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||
/* 10 */ {`L=["a", "b"]; L << $([1,2,3])`, array.NewArrayA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||
/* 11 */ {`L=["a", "b"]; L << $([1,2,3]); L`, array.NewArrayA("a", "b"), nil},
|
||||
/* 12 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`},
|
||||
/* 13 */ {`[<>] << 1`, list.NewLinkedListA(1), nil},
|
||||
/* 14 */ {`[<>] << [1,2]`, list.NewLinkedListA(array.NewArrayA(int64(1), int64(2))), nil},
|
||||
/* 15 */ {`[<>] << [<1,2>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
|
||||
/* 16 */ {`1 >> [<>]`, list.NewLinkedListA(1), nil},
|
||||
/* 17 */ {`[1,2] >> [<>]`, list.NewLinkedListA(array.NewArrayA(int64(1), int64(2))), nil},
|
||||
/* 18 */ {`[<1,2>] >> [<>]`, list.NewLinkedListA(list.NewLinkedListA(1, 2)), nil},
|
||||
/* 19 */ {`$([1,2]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
|
||||
/* 20 */ {`$([<1,2>]) >> [<>]`, list.NewLinkedListA(1, 2), nil},
|
||||
}
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 9)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func TestOperatorDeepAssign(t *testing.T) {
|
||||
section := "Operator-DeepAssign"
|
||||
inputs := []inputType{
|
||||
/* 1 */ {`DD={"uno": 1, "due": 2}; D=DD; D["uno"]=11; DD`, dict.NewDict(map[any]any{"uno": int64(11), "due": int64(2)}), nil},
|
||||
/* 2 */ {`DD={"uno": 1, "due": 2}; D:=DD; D["uno"]=11; DD`, dict.NewDict(map[any]any{"uno": int64(1), "due": int64(2)}), nil},
|
||||
/* 3 */ {`LL=["a", "b"]; L=LL; L[0]="x"; LL`, array.NewArrayA("x", "b"), nil},
|
||||
/* 4 */ {`LL=["a", "b"]; L:=LL; L[0]="x"; LL`, array.NewArrayA("a", "b"), nil},
|
||||
}
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 4)
|
||||
RunTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
func TestOperatorDigest(t *testing.T) {
|
||||
section := "Operator-Digest"
|
||||
inputs := []inputType{
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||
// All rights reserved.
|
||||
|
||||
// array-type.go
|
||||
package array
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type ArrayType []any
|
||||
|
||||
func IsArray(v any) (ok bool) {
|
||||
_, ok = v.(*ArrayType)
|
||||
return ok
|
||||
}
|
||||
|
||||
func NewArrayA(listAny ...any) (list *ArrayType) {
|
||||
if listAny == nil {
|
||||
listAny = []any{}
|
||||
}
|
||||
return NewArray(listAny)
|
||||
}
|
||||
|
||||
func NewArray(arrayAny []any) (aRef *ArrayType) {
|
||||
if arrayAny != nil {
|
||||
a := make(ArrayType, len(arrayAny))
|
||||
copy(a, arrayAny)
|
||||
aRef = &a
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func MakeArray(length, capacity int) (list *ArrayType) {
|
||||
if capacity < length {
|
||||
capacity = length
|
||||
}
|
||||
ls := make(ArrayType, length, capacity)
|
||||
list = &ls
|
||||
return
|
||||
}
|
||||
|
||||
func ArrayFromStrings(stringSlice []string) (aRef *ArrayType) {
|
||||
aRef = MakeArray(len(stringSlice), 0)
|
||||
for i, s := range stringSlice {
|
||||
(*aRef)[i] = s
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) ToString(opt kern.FmtOpt) (s string) {
|
||||
indent := kern.GetFormatIndent(opt)
|
||||
flags := kern.GetFormatFlags(opt)
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteByte('[')
|
||||
if len(*aRef) > 0 {
|
||||
innerOpt := kern.MakeFormatOptions(flags, indent+1)
|
||||
nest := strings.Repeat(" ", indent+1)
|
||||
|
||||
if flags&kern.MultiLine != 0 {
|
||||
sb.WriteByte('\n')
|
||||
sb.WriteString(nest)
|
||||
}
|
||||
for i, item := range []any(*aRef) {
|
||||
if i > 0 {
|
||||
if flags&kern.MultiLine != 0 {
|
||||
sb.WriteString(",\n")
|
||||
sb.WriteString(nest)
|
||||
} else {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
}
|
||||
kern.Format(&sb, item, innerOpt)
|
||||
}
|
||||
if flags&kern.MultiLine != 0 {
|
||||
sb.WriteByte('\n')
|
||||
sb.WriteString(strings.Repeat(" ", indent))
|
||||
}
|
||||
}
|
||||
sb.WriteByte(']')
|
||||
s = sb.String()
|
||||
if flags&kern.Truncate != 0 && len(s) > kern.TruncateSize {
|
||||
s = kern.TruncateString(s)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) String() string {
|
||||
return aRef.ToString(0)
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) TypeName() string {
|
||||
return kern.TypeArray
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) Contains(t *ArrayType) (answer bool) {
|
||||
if len(*aRef) >= len(*t) {
|
||||
answer = true
|
||||
for _, item := range *t {
|
||||
if answer = aRef.IndexDeepSameCmp(item) >= 0; !answer {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) EqualTo(other kern.Equaler) (equal bool) {
|
||||
if otherList, ok := other.(*ArrayType); ok {
|
||||
equal = aRef.Equals(*otherList)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) Equals(ls2 ArrayType) (answer bool) {
|
||||
if ls2 != nil && len(*aRef) == len(ls2) {
|
||||
answer = true
|
||||
for index, i1 := range *aRef {
|
||||
// if !reflect.DeepEqual(i1, ls2[index]) {
|
||||
// answer = false
|
||||
// break
|
||||
// }
|
||||
if !kern.Equal(i1, ls2[index]) {
|
||||
answer = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) Clone() kern.Cloner {
|
||||
ls := make(ArrayType, len(*aRef))
|
||||
for i, item := range *aRef {
|
||||
ls[i] = kern.Clone(item)
|
||||
}
|
||||
return &ls
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) IndexDeepSameCmp(target any) (index int64) {
|
||||
index = -1
|
||||
for i, item := range *aRef {
|
||||
if kern.Equal(item, target) {
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
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) {
|
||||
aRef, aValid := a.(*ArrayType)
|
||||
bRef, bValid := b.(*ArrayType)
|
||||
if !aValid || !bValid {
|
||||
err = fmt.Errorf("invalid type for comparison")
|
||||
return
|
||||
}
|
||||
if len(*aRef) == len(*bRef) {
|
||||
same = true
|
||||
for _, item := range *aRef {
|
||||
if pos := bRef.IndexDeepSameCmp(item); pos < 0 {
|
||||
same = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// func deepSame(a, b any, deepCmp kern.DeepFuncTemplate) (eq bool, err error) {
|
||||
// if IsNumOrFract(a) && IsNumOrFract(b) {
|
||||
// if IsNumber(a) && IsNumber(b) {
|
||||
// if IsInteger(a) && IsInteger(b) {
|
||||
// li, _ := a.(int64)
|
||||
// ri, _ := b.(int64)
|
||||
// eq = li == ri
|
||||
// } else {
|
||||
// eq = NumAsFloat(a) == NumAsFloat(b)
|
||||
// }
|
||||
// } else {
|
||||
// var cmp int
|
||||
// if cmp, err = fract.CmpAnyFract(a, b); err == nil {
|
||||
// eq = cmp == 0
|
||||
// }
|
||||
// }
|
||||
// } else if deepCmp != nil && IsList(a) && IsList(b) {
|
||||
// eq, err = deepCmp(a, b)
|
||||
// } else {
|
||||
// eq = reflect.DeepEqual(a, b)
|
||||
// }
|
||||
|
||||
// return
|
||||
// }
|
||||
|
||||
func (aRef *ArrayType) SetItem(index int64, value any) (err error) {
|
||||
if index >= 0 && index < int64(len(*aRef)) {
|
||||
(*aRef)[index] = value
|
||||
} else {
|
||||
err = fmt.Errorf("index %d out of bounds (0, %d)", index, len(*aRef)-1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (aRef *ArrayType) AppendItem(value any) {
|
||||
*aRef = append(*aRef, value)
|
||||
}
|
||||
Reference in New Issue
Block a user