diff --git a/list-type.go b/list-type.go index 439ed7a..f97990e 100644 --- a/list-type.go +++ b/list-type.go @@ -85,7 +85,7 @@ func (ls *ListType) contains(t *ListType) (answer bool) { if len(*ls) >= len(*t) { answer = true for _, item := range *t { - if answer = ls.indexDeepCmp(item) >= 0; !answer { + if answer = ls.indexDeepSameCmp(item) >= 0; !answer { break } } @@ -93,10 +93,57 @@ func (ls *ListType) contains(t *ListType) (answer bool) { return } -// func equal(a,b *ListType) (eq bool) { -// if len(*a) == len(*b) { -// eq = true -// for i, v := range -// } -// return -// } +func (list *ListType) indexDeepSameCmp(target any) (index int) { + var eq bool + var err error + index = -1 + for i, item := range *list { + if eq, err = deepSame(item, target, sameContent); err != nil { + break + } else if eq { + index = i + break + } + } + return +} + +func sameContent(a, b any) (same bool, err error) { + la, _ := a.(*ListType) + lb, _ := b.(*ListType) + if len(*la) == len(*lb) { + same = true + for _, item := range *la { + if pos := lb.indexDeepSameCmp(item); pos < 0 { + same = false + break + } + } + } + return +} + +func deepSame(a, b any, deepCmp deepFuncTemplate) (eq bool, err error) { + if isNumOrFract(a) && isNumOrFract(b) { + if IsNumber(a) && IsNumber(b) { + if IsInteger(a) && IsInteger(b) { + li, _ := a.(int64) + ri, _ := b.(int64) + eq = li == ri + } else { + eq = numAsFloat(a) == numAsFloat(b) + } + } else { + var cmp int + if cmp, err = cmpAnyFract(a, b); err == nil { + eq = cmp == 0 + } + } + } else if deepCmp != nil && IsList(a) && IsList(b) { + eq, err = deepCmp(a, b) + } else { + eq = reflect.DeepEqual(a, b) + } + + return +} diff --git a/operator-in.go b/operator-in.go index bd3fa53..440daa3 100644 --- a/operator-in.go +++ b/operator-in.go @@ -30,7 +30,7 @@ func evalIn(ctx ExprContext, self *term) (v any, err error) { if IsList(rightValue) { list, _ := rightValue.(*ListType) - v = list.indexDeepCmp(leftValue) >= 0 + v = list.indexDeepSameCmp(leftValue) >= 0 } else if IsDict(rightValue) { dict, _ := rightValue.(*DictType) v = dict.hasKey(leftValue) diff --git a/operator-rel.go b/operator-rel.go index 260ead9..a8ff2e2 100644 --- a/operator-rel.go +++ b/operator-rel.go @@ -18,7 +18,9 @@ func newEqualTerm(tk *Token) (inst *term) { } } -func equals(a, b any) (eq bool, err error) { +type deepFuncTemplate func(a, b any) (eq bool, err error) + +func equals(a, b any, deepCmp deepFuncTemplate) (eq bool, err error) { if isNumOrFract(a) && isNumOrFract(b) { if IsNumber(a) && IsNumber(b) { if IsInteger(a) && IsInteger(b) { @@ -34,6 +36,8 @@ func equals(a, b any) (eq bool, err error) { eq = cmp == 0 } } + } else if deepCmp != nil && IsList(a) && IsList(b) { + eq, err = deepCmp(a, b) } else { eq = reflect.DeepEqual(a, b) } @@ -48,7 +52,7 @@ func evalEqual(ctx ExprContext, self *term) (v any, err error) { return } - v, err = equals(leftValue, rightValue) + v, err = equals(leftValue, rightValue, nil) return } @@ -108,15 +112,7 @@ func lessThan(self *term, a, b any) (isLess bool, err error) { } else if IsList(a) && IsList(b) { aList, _ := a.(*ListType) bList, _ := b.(*ListType) - isLess = len(*aList) < len(*bList) - if isLess { - for _, item := range *aList { - if bList.indexDeepCmp(item) < 0 { - isLess = false - break - } - } - } + isLess = len(*aList) < len(*bList) && bList.contains(aList) } else { err = self.errIncompatibleTypes(a, b) } @@ -145,27 +141,13 @@ func newLessEqualTerm(tk *Token) (inst *term) { } } -func sameContent(a, b any) (same bool, err error) { - la, _ := a.(*ListType) - lb, _ := b.(*ListType) - if len(*la) == len(*lb) { - same = true - for i, item := range *la { - if same, err = equals(item, (*lb)[i]); err != nil || !same { - break - } - } - } - return -} - func lessThanOrEqual(self *term, a, b any) (isLessEq bool, err error) { if isLessEq, err = lessThan(self, a, b); err == nil { if !isLessEq { if IsList(a) && IsList(b) { isLessEq, err = sameContent(a, b) } else { - isLessEq, err = equals(a, b) + isLessEq, err = equals(a, b, nil) } } } diff --git a/t_relational_test.go b/t_relational_test.go index 39c18b8..43631ed 100644 --- a/t_relational_test.go +++ b/t_relational_test.go @@ -40,10 +40,13 @@ func TestRelational(t *testing.T) { /* 27 */ {`[1,2,3] > [9]`, false, nil}, /* 28 */ {`[1,2,3] >= [6]`, false, nil}, /* 29 */ {`[1,2,3] >= [2,6]`, false, nil}, + /* 30 */ {`[1,[2,3],4] > [[3,2]]`, true, nil}, + /* 31 */ {`[1,[2,[3,4]],5] > [[[4,3],2]]`, true, nil}, + /* 32 */ {`[[4,3],2] IN [1,[2,[3,4]],5]`, true, nil}, } // t.Setenv("EXPR_PATH", ".") - // parserTestSpec(t, section, inputs, 27) + // parserTestSpec(t, section, inputs, 31) parserTest(t, section, inputs) }