'and' and 'or' operators are now evaluated using logic shortcut (this behaviour can be changed setting system var '_bool_shortcut' to false
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
// operator-bool.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
|
||||
//-------- NOT term
|
||||
|
||||
func newNotTerm(tk *Token) (inst *term) {
|
||||
@@ -48,6 +50,15 @@ func newAndTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func evalAnd(ctx exprContext, self *term) (v any, err error) {
|
||||
if isEnabled(ctx, preset_bool_shortcut) {
|
||||
v, err = evalAndWithShortcut(ctx, self)
|
||||
} else {
|
||||
v, err = evalAndWithoutShortcut(ctx, self)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalAndWithoutShortcut(ctx exprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var leftBool, rightBool bool
|
||||
var lok, rok bool
|
||||
@@ -67,6 +78,32 @@ func evalAnd(ctx exprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalAndWithShortcut(ctx exprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if err = self.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = self.children[0].compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftBool, lok := toBool(leftValue); !lok {
|
||||
err = fmt.Errorf("got %T as left operand type of 'and' operator, it must be bool", leftBool)
|
||||
return
|
||||
} else if !leftBool {
|
||||
v = false
|
||||
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
|
||||
if rightBool, rok := toBool(rightValue); rok {
|
||||
v = rightBool
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//-------- OR term
|
||||
|
||||
func newOrTerm(tk *Token) (inst *term) {
|
||||
@@ -82,6 +119,15 @@ func newOrTerm(tk *Token) (inst *term) {
|
||||
}
|
||||
|
||||
func evalOr(ctx exprContext, self *term) (v any, err error) {
|
||||
if isEnabled(ctx, preset_bool_shortcut) {
|
||||
v, err = evalOrWithShortcut(ctx, self)
|
||||
} else {
|
||||
v, err = evalOrWithoutShortcut(ctx, self)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalOrWithoutShortcut(ctx exprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var leftBool, rightBool bool
|
||||
var lok, rok bool
|
||||
@@ -101,6 +147,32 @@ func evalOr(ctx exprContext, self *term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func evalOrWithShortcut(ctx exprContext, self *term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
|
||||
if err = self.checkOperands(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftValue, err = self.children[0].compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if leftBool, lok := toBool(leftValue); !lok {
|
||||
err = fmt.Errorf("got %T as left operand type of 'or' operator, it must be bool", leftBool)
|
||||
return
|
||||
} else if leftBool {
|
||||
v = true
|
||||
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
|
||||
if rightBool, rok := toBool(rightValue); rok {
|
||||
v = rightBool
|
||||
} else {
|
||||
err = self.errIncompatibleTypes(leftValue, rightValue)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// init
|
||||
func init() {
|
||||
registerTermConstructor(SymNot, newNotTerm)
|
||||
|
||||
Reference in New Issue
Block a user