Boolean operators now use the crossFunction util func

This commit is contained in:
Mike Farah 2020-12-21 11:42:35 +11:00
parent a23272727d
commit 9876b0ce8f
2 changed files with 27 additions and 55 deletions

View File

@ -45,6 +45,13 @@ var alternativeOperatorScenarios = []expressionScenario{
"D0, P[b], (!!str)::cat\n", "D0, P[b], (!!str)::cat\n",
}, },
}, },
{
skipDoc: true,
expression: `false // true`,
expected: []string{
"D0, P[], (!!bool)::true\n",
},
},
} }
func TestAlternativeOperatorScenarios(t *testing.T) { func TestAlternativeOperatorScenarios(t *testing.T) {

View File

@ -25,74 +25,39 @@ func isTruthy(c *CandidateNode) (bool, error) {
type boolOp func(bool, bool) bool type boolOp func(bool, bool) bool
func performBoolOp(results *list.List, lhs *list.List, rhs *list.List, op boolOp) error { func performBoolOp(op boolOp) func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
for lhsChild := lhs.Front(); lhsChild != nil; lhsChild = lhsChild.Next() { return func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
lhsCandidate := lhsChild.Value.(*CandidateNode) lhs.Node = UnwrapDoc(lhs.Node)
lhsTrue, errDecoding := isTruthy(lhsCandidate) rhs.Node = UnwrapDoc(rhs.Node)
lhsTrue, errDecoding := isTruthy(lhs)
if errDecoding != nil { if errDecoding != nil {
return errDecoding return nil, errDecoding
} }
for rhsChild := rhs.Front(); rhsChild != nil; rhsChild = rhsChild.Next() { rhsTrue, errDecoding := isTruthy(rhs)
rhsCandidate := rhsChild.Value.(*CandidateNode) if errDecoding != nil {
rhsTrue, errDecoding := isTruthy(rhsCandidate) return nil, errDecoding
if errDecoding != nil {
return errDecoding
}
boolResult := createBooleanCandidate(lhsCandidate, op(lhsTrue, rhsTrue))
results.PushBack(boolResult)
} }
return createBooleanCandidate(lhs, op(lhsTrue, rhsTrue)), nil
} }
return nil
}
func booleanOp(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode, op boolOp) (*list.List, error) {
var results = list.New()
if matchingNodes.Len() == 0 {
lhs, err := d.GetMatchingNodes(list.New(), pathNode.Lhs)
if err != nil {
return nil, err
}
rhs, err := d.GetMatchingNodes(list.New(), pathNode.Rhs)
if err != nil {
return nil, err
}
return results, performBoolOp(results, lhs, rhs, op)
}
for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
lhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Lhs)
if err != nil {
return nil, err
}
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Rhs)
if err != nil {
return nil, err
}
err = performBoolOp(results, lhs, rhs, op)
if err != nil {
return nil, err
}
}
return results, nil
} }
func OrOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) { func OrOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
log.Debugf("-- orOp") log.Debugf("-- orOp")
return booleanOp(d, matchingNodes, pathNode, func(b1 bool, b2 bool) bool { return crossFunction(d, matchingNodes, pathNode, performBoolOp(
return b1 || b2 func(b1 bool, b2 bool) bool {
}) return b1 || b2
}))
} }
func AndOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) { func AndOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
log.Debugf("-- AndOp") log.Debugf("-- AndOp")
return booleanOp(d, matchingNodes, pathNode, func(b1 bool, b2 bool) bool { return crossFunction(d, matchingNodes, pathNode, performBoolOp(
return b1 && b2 func(b1 bool, b2 bool) bool {
}) return b1 && b2
}))
} }
func NotOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) { func NotOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {