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"
|
"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) {
|
func TestLinkedListParser(t *testing.T) {
|
||||||
section := "Linked-List"
|
section := "Linked-List"
|
||||||
|
|
||||||
@@ -89,3 +33,20 @@ func TestLinkedListParser(t *testing.T) {
|
|||||||
// runTestSuiteSpec(t, section, inputs, 4)
|
// runTestSuiteSpec(t, section, inputs, 4)
|
||||||
RunTestSuite(t, section, inputs)
|
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/array"
|
||||||
"git.portale-stac.it/go-pkg/expr/types/dict"
|
"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) {
|
||||||
@@ -51,48 +50,6 @@ func TestOperator(t *testing.T) {
|
|||||||
RunTestSuite(t, section, inputs)
|
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) {
|
func TestOperatorDigest(t *testing.T) {
|
||||||
section := "Operator-Digest"
|
section := "Operator-Digest"
|
||||||
inputs := []inputType{
|
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