diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 7da63078..d7b1378e 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1751,10 +1751,18 @@ (break) # match data structure template - (or isarr (= t :struct) (= t :table)) + (or (= t :struct) (= t :table)) + (eachp [i sub-pattern] pattern + (visit-pattern-1 b2g s i sub-pattern)) + + isarr (do - (when isarr (get-length-sym s)) + (get-length-sym s) (eachp [i sub-pattern] pattern + (when (= sub-pattern '&) + # TODO: check that & is followed by something + (put b2g (pattern (inc i)) @[[slice s i]]) + (break)) (visit-pattern-1 b2g s i sub-pattern))) # match global unification @@ -1774,14 +1782,24 @@ (def isarr (or (= t :array) (and (= t :tuple) (= (tuple/type pattern) :brackets)))) (when isarr (array/push anda (get-length-sym s)) - (array/push anda [<= (length pattern) (get-length-sym s)])) + (def pattern-len + (if-let [ rest-idx (find-index (fn [x] (= x '&)) pattern) ] + rest-idx + (length pattern))) + (array/push anda [<= pattern-len (get-length-sym s)])) (cond # match data structure template - (or isarr (= t :struct) (= t :table)) + (or (= t :struct) (= t :table)) (eachp [i sub-pattern] pattern - (when (not isarr) - (array/push anda [not= nil (get-sym s i)])) + (array/push anda [not= nil (get-sym s i)]) + (visit-pattern-2 anda gun preds s i sub-pattern)) + + isarr + (eachp [i sub-pattern] pattern + # stop recursing to sub-patterns if the rest sigil is found + (when (= sub-pattern '&) + (break)) (visit-pattern-2 anda gun preds s i sub-pattern)) # match local binding diff --git a/test/suite0008.janet b/test/suite0008.janet index a53b16a4..c93ddafc 100644 --- a/test/suite0008.janet +++ b/test/suite0008.janet @@ -106,6 +106,10 @@ (assert (= nil (match {:a :hi} {:a a :b b} a)) "match 3") (assert (= nil (match [1 2] [a b c] a)) "match 4") (assert (= 2 (match [1 2] [a b] b)) "match 5") +(assert (= [2 :a :b] (match [1 2 :a :b] [o & rest] rest)) "match 6") +(assert (= [] (match @[:a] @[x & r] r :fallback)) "match 7") +(assert (= :fallback (match @[1] @[x y & r] r :fallback)) "match 8") +(assert (= [1 2 3 4] (match @[1 2 3 4] @[x y z & r] [x y z ;r] :fallback)) "match 9") # And/or checks