A lot of changes. Main ones are:
- fraction type renamed as FractionType and moved from operator-fraction.go to fraction-type.go - ListType moved from operator-list.go to list-type.go - all test file were renamed adding the "t_" prefix - defined a test template in file t_temple_test.go - new test file t_relational_test.go where relational tests are collected - lists can now compared as set using operators <, <=, >, and >= (IMPORTANT: here = menas same content, not same list)
This commit is contained in:
+121
-92
@@ -4,13 +4,13 @@
|
||||
// operator-rel.go
|
||||
package expr
|
||||
|
||||
import "reflect"
|
||||
|
||||
//-------- equal term
|
||||
|
||||
func newEqualTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
// class: classOperator,
|
||||
// kind: kindBool,
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priRelational,
|
||||
@@ -18,6 +18,29 @@ func newEqualTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func equals(a, b any) (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 {
|
||||
eq = reflect.DeepEqual(a, b)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func evalEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
@@ -25,21 +48,7 @@ func evalEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if IsNumber(leftValue) && IsNumber(rightValue) {
|
||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||
li, _ := leftValue.(int64)
|
||||
ri, _ := rightValue.(int64)
|
||||
v = li == ri
|
||||
} else {
|
||||
v = numAsFloat(leftValue) == numAsFloat(rightValue)
|
||||
}
|
||||
} else if IsString(leftValue) && IsString(rightValue) {
|
||||
ls, _ := leftValue.(string)
|
||||
rs, _ := rightValue.(string)
|
||||
v = ls == rs
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
v, err = equals(leftValue, rightValue)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -47,9 +56,7 @@ func evalEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
|
||||
func newNotEqualTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
// class: classOperator,
|
||||
// kind: kindBool,
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priRelational,
|
||||
@@ -65,38 +72,11 @@ func evalNotEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// func evalNotEqual(ctx exprContext, self *term) (v any, err error) {
|
||||
// var leftValue, rightValue any
|
||||
|
||||
// if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// if isNumber(leftValue) && isNumber(rightValue) {
|
||||
// if isInteger(leftValue) && isInteger(rightValue) {
|
||||
// li, _ := leftValue.(int64)
|
||||
// ri, _ := rightValue.(int64)
|
||||
// v = li != ri
|
||||
// } else {
|
||||
// v = numAsFloat(leftValue) != numAsFloat(rightValue)
|
||||
// }
|
||||
// } else if isString(leftValue) && isString(rightValue) {
|
||||
// ls, _ := leftValue.(string)
|
||||
// rs, _ := rightValue.(string)
|
||||
// v = ls != rs
|
||||
// } else {
|
||||
// err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
//-------- less term
|
||||
|
||||
func newLessTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
// class: classOperator,
|
||||
// kind: kindBool,
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priRelational,
|
||||
@@ -104,28 +84,52 @@ func newLessTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
}
|
||||
|
||||
func lessThan(self *term, a, b any) (isLess bool, err error) {
|
||||
if isNumOrFract(a) && isNumOrFract(b) {
|
||||
if IsNumber(a) && IsNumber(b) {
|
||||
if IsInteger(a) && IsInteger(b) {
|
||||
li, _ := a.(int64)
|
||||
ri, _ := b.(int64)
|
||||
isLess = li < ri
|
||||
} else {
|
||||
isLess = numAsFloat(a) < numAsFloat(b)
|
||||
}
|
||||
} else {
|
||||
var cmp int
|
||||
if cmp, err = cmpAnyFract(a, b); err == nil {
|
||||
isLess = cmp < 0
|
||||
}
|
||||
}
|
||||
} else if IsString(a) && IsString(b) {
|
||||
ls, _ := a.(string)
|
||||
rs, _ := b.(string)
|
||||
isLess = ls < rs
|
||||
// Inclusion test
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(a, b)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalLess(ctx ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if IsNumber(leftValue) && IsNumber(rightValue) {
|
||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||
li, _ := leftValue.(int64)
|
||||
ri, _ := rightValue.(int64)
|
||||
v = li < ri
|
||||
} else {
|
||||
v = numAsFloat(leftValue) < numAsFloat(rightValue)
|
||||
}
|
||||
} else if IsString(leftValue) && IsString(rightValue) {
|
||||
ls, _ := leftValue.(string)
|
||||
rs, _ := rightValue.(string)
|
||||
v = ls < rs
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
v, err = lessThan(self, leftValue, rightValue)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -141,6 +145,33 @@ 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalLessEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
@@ -148,21 +179,8 @@ func evalLessEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if IsNumber(leftValue) && IsNumber(rightValue) {
|
||||
if IsInteger(leftValue) && IsInteger(rightValue) {
|
||||
li, _ := leftValue.(int64)
|
||||
ri, _ := rightValue.(int64)
|
||||
v = li <= ri
|
||||
} else {
|
||||
v = numAsFloat(leftValue) <= numAsFloat(rightValue)
|
||||
}
|
||||
} else if IsString(leftValue) && IsString(rightValue) {
|
||||
ls, _ := leftValue.(string)
|
||||
rs, _ := rightValue.(string)
|
||||
v = ls <= rs
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
v, err = lessThanOrEqual(self, leftValue, rightValue)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -170,9 +188,7 @@ func evalLessEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
|
||||
func newGreaterTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
// class: classOperator,
|
||||
// kind: kindBool,
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priRelational,
|
||||
@@ -181,10 +197,18 @@ func newGreaterTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func evalGreater(ctx ExprContext, self *term) (v any, err error) {
|
||||
if v, err = evalLessEqual(ctx, self); err == nil {
|
||||
b, _ := toBool(v)
|
||||
v = !b
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
v, err = lessThan(self, rightValue, leftValue)
|
||||
|
||||
// if v, err = evalLessEqual(ctx, self); err == nil {
|
||||
// b, _ := toBool(v)
|
||||
// v = !b
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,9 +216,7 @@ func evalGreater(ctx ExprContext, self *term) (v any, err error) {
|
||||
|
||||
func newGreaterEqualTerm(tk *Token) (inst *term) {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
// class: classOperator,
|
||||
// kind: kindBool,
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priRelational,
|
||||
@@ -203,10 +225,17 @@ func newGreaterEqualTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func evalGreaterEqual(ctx ExprContext, self *term) (v any, err error) {
|
||||
if v, err = evalLess(ctx, self); err == nil {
|
||||
b, _ := toBool(v)
|
||||
v = !b
|
||||
var leftValue, rightValue any
|
||||
|
||||
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
v, err = lessThanOrEqual(self, rightValue, leftValue)
|
||||
// if v, err = evalLess(ctx, self); err == nil {
|
||||
// b, _ := toBool(v)
|
||||
// v = !b
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user