@@ -11,6 +11,8 @@ type slotData struct {
1111 size int
1212}
1313
14+ var emptySlotData slotData
15+
1416type FastMatcher struct {
1517 def MatchDef
1618 slots []slotData
@@ -27,7 +29,9 @@ func NewFastMatcher(def *MatchDef) *FastMatcher {
2729}
2830
2931func (m * FastMatcher ) Reset () {
30- m .slots = m .slots [:0 ]
32+ for i := 0 ; i < m .def .NumSlots ; i ++ {
33+ m .slots [i ] = emptySlotData
34+ }
3135 m .buckets .Reset ()
3236}
3337
@@ -98,6 +102,12 @@ func (m *FastMatcher) literalFromSlot(slot SlotID) FastVal {
98102 if isLiteralToken (token ) {
99103 var parser fastLitParser
100104 value = parser .Parse (token , tokenData )
105+ } else if slotInfo .size > 0 {
106+ if token == tknObjectStart {
107+ value = NewObjectFastVal (m .tokens .data [slotInfo .start : slotInfo .start + slotInfo .size ])
108+ } else if token == tknArrayStart {
109+ value = NewArrayFastVal (m .tokens .data [slotInfo .start : slotInfo .start + slotInfo .size ])
110+ }
101111 }
102112
103113 m .tokens .Seek (savePos )
@@ -222,20 +232,38 @@ func (m *FastMatcher) matchOp(op *OpNode, litVal *FastVal) error {
222232 return nil
223233 }
224234
235+ var slotNotFound bool
225236 lhsVal := NewMissingFastVal ()
226237 if op .Lhs != nil {
227238 lhsVal = m .resolveParam (op .Lhs , litVal )
239+ if _ , ok := op .Lhs .(SlotRef ); ok && lhsVal .IsMissing () {
240+ slotNotFound = true
241+ }
228242 } else if litVal != nil {
229243 lhsVal = * litVal
230244 }
231245
232246 rhsVal := NewMissingFastVal ()
233247 if op .Rhs != nil {
234248 rhsVal = m .resolveParam (op .Rhs , litVal )
249+ if _ , ok := op .Rhs .(SlotRef ); ok && rhsVal .IsMissing () {
250+ slotNotFound = true
251+ }
235252 } else if litVal != nil {
236253 rhsVal = * litVal
237254 }
238255
256+ if slotNotFound {
257+ // If references are for slots and at least one wasn't found
258+ // then the matchOp should not execute
259+ m .buckets .MarkNode (bucketIdx , false )
260+
261+ if m .buckets .IsResolved (0 ) {
262+ return nil
263+ }
264+ return nil
265+ }
266+
239267 var opRes bool
240268 switch op .Op {
241269 case OpTypeEquals :
@@ -548,7 +576,7 @@ func (m *FastMatcher) matchExec(token tokenType, tokenData []byte, tokenDataLen
548576 }
549577 }
550578 } else if token == tknObjectStart {
551- objStartPos := m .tokens .Position ()
579+ objStartPos := m .tokens .Position () - 1 /* to include the objStart itself*/
552580 if len (node .Elems ) == 0 {
553581 // If we have no element handlers, we can just skip the whole thing...
554582 m .skipValue (token )
@@ -569,6 +597,7 @@ func (m *FastMatcher) matchExec(token tokenType, tokenData []byte, tokenDataLen
569597 objEndPos := m .tokens .Position ()
570598
571599 objFastVal := NewObjectFastVal (m .tokens .data [objStartPos :objEndPos ])
600+
572601 for _ , op := range node .Ops {
573602 err := m .matchOp (& op , & objFastVal )
574603 if err != nil {
@@ -580,7 +609,7 @@ func (m *FastMatcher) matchExec(token tokenType, tokenData []byte, tokenDataLen
580609 }
581610 }
582611 } else if token == tknArrayStart {
583- arrayStartPos := m .tokens .Position ()
612+ arrayStartPos := m .tokens .Position () - 1 // Should be -1 to include the [
584613 if len (node .Loops ) == 0 {
585614 err , shouldReturn := m .matchObjectOrArray (token , tokenData , node )
586615 if shouldReturn {
@@ -699,6 +728,7 @@ func (m *FastMatcher) matchObjectOrArray(token tokenType, tokenData []byte, node
699728 if err != nil {
700729 return err , true
701730 }
731+
702732 // Keep this here to catch any empty array or empty objs
703733 if token == endToken {
704734 return nil , true
0 commit comments