deep list inclusion and item membership implemented
This commit is contained in:
parent
4b25a07699
commit
d84e690ef3
63
list-type.go
63
list-type.go
@ -85,7 +85,7 @@ func (ls *ListType) contains(t *ListType) (answer bool) {
|
|||||||
if len(*ls) >= len(*t) {
|
if len(*ls) >= len(*t) {
|
||||||
answer = true
|
answer = true
|
||||||
for _, item := range *t {
|
for _, item := range *t {
|
||||||
if answer = ls.indexDeepCmp(item) >= 0; !answer {
|
if answer = ls.indexDeepSameCmp(item) >= 0; !answer {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,10 +93,57 @@ func (ls *ListType) contains(t *ListType) (answer bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// func equal(a,b *ListType) (eq bool) {
|
func (list *ListType) indexDeepSameCmp(target any) (index int) {
|
||||||
// if len(*a) == len(*b) {
|
var eq bool
|
||||||
// eq = true
|
var err error
|
||||||
// for i, v := range
|
index = -1
|
||||||
// }
|
for i, item := range *list {
|
||||||
// return
|
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
|
||||||
|
}
|
||||||
|
@ -30,7 +30,7 @@ func evalIn(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
|
|
||||||
if IsList(rightValue) {
|
if IsList(rightValue) {
|
||||||
list, _ := rightValue.(*ListType)
|
list, _ := rightValue.(*ListType)
|
||||||
v = list.indexDeepCmp(leftValue) >= 0
|
v = list.indexDeepSameCmp(leftValue) >= 0
|
||||||
} else if IsDict(rightValue) {
|
} else if IsDict(rightValue) {
|
||||||
dict, _ := rightValue.(*DictType)
|
dict, _ := rightValue.(*DictType)
|
||||||
v = dict.hasKey(leftValue)
|
v = dict.hasKey(leftValue)
|
||||||
|
@ -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 isNumOrFract(a) && isNumOrFract(b) {
|
||||||
if IsNumber(a) && IsNumber(b) {
|
if IsNumber(a) && IsNumber(b) {
|
||||||
if IsInteger(a) && IsInteger(b) {
|
if IsInteger(a) && IsInteger(b) {
|
||||||
@ -34,6 +36,8 @@ func equals(a, b any) (eq bool, err error) {
|
|||||||
eq = cmp == 0
|
eq = cmp == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if deepCmp != nil && IsList(a) && IsList(b) {
|
||||||
|
eq, err = deepCmp(a, b)
|
||||||
} else {
|
} else {
|
||||||
eq = reflect.DeepEqual(a, b)
|
eq = reflect.DeepEqual(a, b)
|
||||||
}
|
}
|
||||||
@ -48,7 +52,7 @@ func evalEqual(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err = equals(leftValue, rightValue)
|
v, err = equals(leftValue, rightValue, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,15 +112,7 @@ func lessThan(self *term, a, b any) (isLess bool, err error) {
|
|||||||
} else if IsList(a) && IsList(b) {
|
} else if IsList(a) && IsList(b) {
|
||||||
aList, _ := a.(*ListType)
|
aList, _ := a.(*ListType)
|
||||||
bList, _ := b.(*ListType)
|
bList, _ := b.(*ListType)
|
||||||
isLess = len(*aList) < len(*bList)
|
isLess = len(*aList) < len(*bList) && bList.contains(aList)
|
||||||
if isLess {
|
|
||||||
for _, item := range *aList {
|
|
||||||
if bList.indexDeepCmp(item) < 0 {
|
|
||||||
isLess = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleTypes(a, b)
|
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) {
|
func lessThanOrEqual(self *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 IsList(a) && IsList(b) {
|
if IsList(a) && IsList(b) {
|
||||||
isLessEq, err = sameContent(a, b)
|
isLessEq, err = sameContent(a, b)
|
||||||
} else {
|
} else {
|
||||||
isLessEq, err = equals(a, b)
|
isLessEq, err = equals(a, b, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,13 @@ func TestRelational(t *testing.T) {
|
|||||||
/* 27 */ {`[1,2,3] > [9]`, false, nil},
|
/* 27 */ {`[1,2,3] > [9]`, false, nil},
|
||||||
/* 28 */ {`[1,2,3] >= [6]`, false, nil},
|
/* 28 */ {`[1,2,3] >= [6]`, false, nil},
|
||||||
/* 29 */ {`[1,2,3] >= [2,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", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
// parserTestSpec(t, section, inputs, 27)
|
// parserTestSpec(t, section, inputs, 31)
|
||||||
parserTest(t, section, inputs)
|
parserTest(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user