Fixing booleans

This commit is contained in:
Mike Farah 2022-03-20 11:46:29 +11:00
parent e08b6803f5
commit b552127667
3 changed files with 74 additions and 44 deletions

View File

@ -1 +1,2 @@
cat: purrs a: mike
b: [t, f]

View File

@ -29,8 +29,15 @@ func isTruthy(c *CandidateNode) (bool, error) {
type boolOp func(bool, bool) bool type boolOp func(bool, bool) bool
func performBoolOp(op boolOp) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { func getBoolean(candidate *CandidateNode) (bool, error) {
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { if candidate != nil {
candidate.Node = unwrapDoc(candidate.Node)
return isTruthy(candidate)
}
return false, nil
}
func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode {
owner := lhs owner := lhs
if lhs == nil && rhs == nil { if lhs == nil && rhs == nil {
@ -38,31 +45,45 @@ func performBoolOp(op boolOp) func(d *dataTreeNavigator, context Context, lhs *C
} else if lhs == nil { } else if lhs == nil {
owner = rhs owner = rhs
} }
return owner
}
var errDecoding error func andOp(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
lhsTrue := false owner := getOwner(lhs, rhs)
if lhs != nil { var err error
lhs.Node = unwrapDoc(lhs.Node) lhsBool := true
lhsTrue, errDecoding = isTruthy(lhs) if lhsBool, err = getBoolean(lhs); err != nil {
return nil, err
}
if lhsBool == false {
return createBooleanCandidate(owner, false), nil
}
if errDecoding != nil { rhsBool := true
return nil, errDecoding if rhsBool, err = getBoolean(rhs); err != nil {
return nil, err
} }
}
log.Debugf("-- lhsTrue", lhsTrue)
rhsTrue := false return createBooleanCandidate(owner, rhsBool), nil
if rhs != nil {
rhs.Node = unwrapDoc(rhs.Node)
rhsTrue, errDecoding = isTruthy(rhs)
if errDecoding != nil {
return nil, errDecoding
} }
}
log.Debugf("-- rhsTrue", rhsTrue)
return createBooleanCandidate(owner, op(lhsTrue, rhsTrue)), nil func orOp(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
owner := getOwner(lhs, rhs)
var err error
lhsBool := true
if lhsBool, err = getBoolean(lhs); err != nil {
return nil, err
} }
if lhsBool == true {
return createBooleanCandidate(owner, true), nil
}
rhsBool := true
if rhsBool, err = getBoolean(rhs); err != nil {
return nil, err
}
return createBooleanCandidate(owner, rhsBool), nil
} }
func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *yaml.Node) (bool, error) { func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *yaml.Node) (bool, error) {
@ -134,19 +155,11 @@ func anyOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
func orOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { func orOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("-- orOp") log.Debugf("-- orOp")
return crossFunction(d, context.ReadOnlyClone(), expressionNode, performBoolOp( return crossFunction(d, context.ReadOnlyClone(), expressionNode, orOp, true)
func(b1 bool, b2 bool) bool {
log.Debugf("-- peformingOrOp with %v and %v", b1, b2)
return b1 || b2
}), true)
} }
func andOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { func andOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("-- AndOp")
return crossFunction(d, context.ReadOnlyClone(), expressionNode, performBoolOp(
func(b1 bool, b2 bool) bool {
return b1 && b2
}), true)
} }
func notOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { func notOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {

View File

@ -44,6 +44,22 @@ var booleanOperatorScenarios = []expressionScenario{
"D0, P[], (doc)::b: hi\n", "D0, P[], (doc)::b: hi\n",
}, },
}, },
{
skipDoc: true,
description: "And should not run 2nd arg if first is false",
expression: `select(false and test(3))`,
expected: []string{
"D0, P[], (doc)::b: hi\n",
},
},
{
skipDoc: true,
description: "Or should not run 2nd arg if first is true",
expression: `select(true or test(3))`,
expected: []string{
"D0, P[], (doc)::b: hi\n",
},
},
{ {
description: "`and` example", description: "`and` example",
expression: `true and false`, expression: `true and false`,