'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:
2024-03-31 05:09:24 +02:00
parent 94ad968d5e
commit aa705e68bf
2 changed files with 87 additions and 11 deletions
+72
View File
@@ -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)