@@ -54,10 +54,25 @@ func emptyOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
5454
5555type crossFunctionCalculation func (d * dataTreeNavigator , context Context , lhs * CandidateNode , rhs * CandidateNode ) (* CandidateNode , error )
5656
57- func resultsForRHS (d * dataTreeNavigator , context Context , lhsCandidate * CandidateNode , rhs Context , calculation crossFunctionCalculation , results * list.List , calcWhenEmpty bool ) error {
57+ func resultsForRHS (d * dataTreeNavigator , context Context , lhsCandidate * CandidateNode , prefs crossFunctionPreferences , rhsExp * ExpressionNode , results * list.List ) error {
5858
59- if calcWhenEmpty && rhs .MatchingNodes .Len () == 0 {
60- resultCandidate , err := calculation (d , context , lhsCandidate , nil )
59+ if prefs .LhsResultValue != nil {
60+ result , err := prefs .LhsResultValue (lhsCandidate )
61+ if err != nil {
62+ return err
63+ } else if result != nil {
64+ results .PushBack (result )
65+ return nil
66+ }
67+ }
68+
69+ rhs , err := d .GetMatchingNodes (context , rhsExp )
70+ if err != nil {
71+ return err
72+ }
73+
74+ if prefs .CalcWhenEmpty && rhs .MatchingNodes .Len () == 0 {
75+ resultCandidate , err := prefs .Calculation (d , context , lhsCandidate , nil )
6176 if err != nil {
6277 return err
6378 }
@@ -70,7 +85,7 @@ func resultsForRHS(d *dataTreeNavigator, context Context, lhsCandidate *Candidat
7085 for rightEl := rhs .MatchingNodes .Front (); rightEl != nil ; rightEl = rightEl .Next () {
7186 log .Debugf ("Applying calc" )
7287 rhsCandidate := rightEl .Value .(* CandidateNode )
73- resultCandidate , err := calculation (d , context , lhsCandidate , rhsCandidate )
88+ resultCandidate , err := prefs . Calculation (d , context , lhsCandidate , rhsCandidate )
7489 if err != nil {
7590 return err
7691 }
@@ -81,22 +96,24 @@ func resultsForRHS(d *dataTreeNavigator, context Context, lhsCandidate *Candidat
8196 return nil
8297}
8398
84- func doCrossFunc (d * dataTreeNavigator , context Context , expressionNode * ExpressionNode , calculation crossFunctionCalculation , calcWhenEmpty bool ) (Context , error ) {
99+ type crossFunctionPreferences struct {
100+ CalcWhenEmpty bool
101+ // if this returns a result node,
102+ // we wont bother calculating the RHS
103+ LhsResultValue func (* CandidateNode ) (* CandidateNode , error )
104+ Calculation crossFunctionCalculation
105+ }
106+
107+ func doCrossFunc (d * dataTreeNavigator , context Context , expressionNode * ExpressionNode , prefs crossFunctionPreferences ) (Context , error ) {
85108 var results = list .New ()
86109 lhs , err := d .GetMatchingNodes (context , expressionNode .LHS )
87110 if err != nil {
88111 return Context {}, err
89112 }
90113 log .Debugf ("crossFunction LHS len: %v" , lhs .MatchingNodes .Len ())
91114
92- rhs , err := d .GetMatchingNodes (context , expressionNode .RHS )
93-
94- if err != nil {
95- return Context {}, err
96- }
97-
98- if calcWhenEmpty && lhs .MatchingNodes .Len () == 0 {
99- err := resultsForRHS (d , context , nil , rhs , calculation , results , calcWhenEmpty )
115+ if prefs .CalcWhenEmpty && lhs .MatchingNodes .Len () == 0 {
116+ err := resultsForRHS (d , context , nil , prefs , expressionNode .RHS , results )
100117 if err != nil {
101118 return Context {}, err
102119 }
@@ -105,7 +122,7 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
105122 for el := lhs .MatchingNodes .Front (); el != nil ; el = el .Next () {
106123 lhsCandidate := el .Value .(* CandidateNode )
107124
108- err : = resultsForRHS (d , context , lhsCandidate , rhs , calculation , results , calcWhenEmpty )
125+ err = resultsForRHS (d , context , lhsCandidate , prefs , expressionNode . RHS , results )
109126 if err != nil {
110127 return Context {}, err
111128 }
@@ -115,6 +132,11 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
115132}
116133
117134func crossFunction (d * dataTreeNavigator , context Context , expressionNode * ExpressionNode , calculation crossFunctionCalculation , calcWhenEmpty bool ) (Context , error ) {
135+ prefs := crossFunctionPreferences {CalcWhenEmpty : calcWhenEmpty , Calculation : calculation }
136+ return crossFunctionWithPrefs (d , context , expressionNode , prefs )
137+ }
138+
139+ func crossFunctionWithPrefs (d * dataTreeNavigator , context Context , expressionNode * ExpressionNode , prefs crossFunctionPreferences ) (Context , error ) {
118140 var results = list .New ()
119141
120142 var evaluateAllTogether = true
@@ -124,15 +146,16 @@ func crossFunction(d *dataTreeNavigator, context Context, expressionNode *Expres
124146 break
125147 }
126148 }
149+
127150 if evaluateAllTogether {
128151 log .Debug ("crossFunction evaluateAllTogether!" )
129- return doCrossFunc (d , context , expressionNode , calculation , calcWhenEmpty )
152+ return doCrossFunc (d , context , expressionNode , prefs )
130153 }
131154
132155 log .Debug ("crossFunction evaluate apart!" )
133156
134157 for matchEl := context .MatchingNodes .Front (); matchEl != nil ; matchEl = matchEl .Next () {
135- innerResults , err := doCrossFunc (d , context .SingleChildContext (matchEl .Value .(* CandidateNode )), expressionNode , calculation , calcWhenEmpty )
158+ innerResults , err := doCrossFunc (d , context .SingleChildContext (matchEl .Value .(* CandidateNode )), expressionNode , prefs )
136159 if err != nil {
137160 return Context {}, err
138161 }
0 commit comments