;; Full-pattern parser tests: as-patterns, lazy ~, negative literals,
;; infix constructor patterns (`:`, any consym), lambda pattern args,
;; and let pattern-bindings.

;; ── as-patterns ──
(hk-test
  "as pattern, wraps constructor"
  (hk-parse "case x of n@(Just y) -> n")
  (list
    :case
    (list :var "x")
    (list
      (list
        :alt
        (list
          :p-as
          "n"
          (list :p-con "Just" (list (list :p-var "y"))))
        (list :var "n")))))

(hk-test
  "as pattern, wraps wildcard"
  (hk-parse "case x of all@_ -> all")
  (list
    :case
    (list :var "x")
    (list
      (list
        :alt
        (list :p-as "all" (list :p-wild))
        (list :var "all")))))

(hk-test
  "as in lambda"
  (hk-parse "\\xs@(a : rest) -> xs")
  (list
    :lambda
    (list
      (list
        :p-as
        "xs"
        (list
          :p-con
          ":"
          (list (list :p-var "a") (list :p-var "rest")))))
    (list :var "xs")))

;; ── lazy patterns ──
(hk-test
  "lazy var"
  (hk-parse "case x of ~y -> y")
  (list
    :case
    (list :var "x")
    (list
      (list :alt (list :p-lazy (list :p-var "y")) (list :var "y")))))

(hk-test
  "lazy constructor"
  (hk-parse "\\(~(Just x)) -> x")
  (list
    :lambda
    (list
      (list
        :p-lazy
        (list :p-con "Just" (list (list :p-var "x")))))
    (list :var "x")))

;; ── negative literal patterns ──
(hk-test
  "negative int pattern"
  (hk-parse "case n of\n  -1 -> 0\n  _ -> n")
  (list
    :case
    (list :var "n")
    (list
      (list :alt (list :p-int -1) (list :int 0))
      (list :alt (list :p-wild) (list :var "n")))))

(hk-test
  "negative float pattern"
  (hk-parse "case x of -0.5 -> 1")
  (list
    :case
    (list :var "x")
    (list (list :alt (list :p-float -0.5) (list :int 1)))))

;; ── infix constructor patterns (`:` and any consym) ──
(hk-test
  "cons pattern"
  (hk-parse "case xs of x : rest -> x")
  (list
    :case
    (list :var "xs")
    (list
      (list
        :alt
        (list
          :p-con
          ":"
          (list (list :p-var "x") (list :p-var "rest")))
        (list :var "x")))))

(hk-test
  "cons is right-associative in pats"
  (hk-parse "case xs of a : b : rest -> rest")
  (list
    :case
    (list :var "xs")
    (list
      (list
        :alt
        (list
          :p-con
          ":"
          (list
            (list :p-var "a")
            (list
              :p-con
              ":"
              (list (list :p-var "b") (list :p-var "rest")))))
        (list :var "rest")))))

(hk-test
  "consym pattern"
  (hk-parse "case p of a :+: b -> a")
  (list
    :case
    (list :var "p")
    (list
      (list
        :alt
        (list
          :p-con
          ":+:"
          (list (list :p-var "a") (list :p-var "b")))
        (list :var "a")))))

;; ── lambda with pattern args ──
(hk-test
  "lambda with constructor pattern"
  (hk-parse "\\(Just x) -> x")
  (list
    :lambda
    (list (list :p-con "Just" (list (list :p-var "x"))))
    (list :var "x")))

(hk-test
  "lambda with tuple pattern"
  (hk-parse "\\(a, b) -> a + b")
  (list
    :lambda
    (list
      (list
        :p-tuple
        (list (list :p-var "a") (list :p-var "b"))))
    (list :op "+" (list :var "a") (list :var "b"))))

(hk-test
  "lambda with wildcard"
  (hk-parse "\\_ -> 42")
  (list :lambda (list (list :p-wild)) (list :int 42)))

(hk-test
  "lambda with mixed apats"
  (hk-parse "\\x _ (Just y) -> y")
  (list
    :lambda
    (list
      (list :p-var "x")
      (list :p-wild)
      (list :p-con "Just" (list (list :p-var "y"))))
    (list :var "y")))

;; ── let pattern-bindings ──
(hk-test
  "let tuple pattern-binding"
  (hk-parse "let (x, y) = pair in x + y")
  (list
    :let
    (list
      (list
        :bind
        (list
          :p-tuple
          (list (list :p-var "x") (list :p-var "y")))
        (list :var "pair")))
    (list :op "+" (list :var "x") (list :var "y"))))

(hk-test
  "let constructor pattern-binding"
  (hk-parse "let Just x = m in x")
  (list
    :let
    (list
      (list
        :bind
        (list :p-con "Just" (list (list :p-var "x")))
        (list :var "m")))
    (list :var "x")))

(hk-test
  "let cons pattern-binding"
  (hk-parse "let (x : rest) = xs in x")
  (list
    :let
    (list
      (list
        :bind
        (list
          :p-con
          ":"
          (list (list :p-var "x") (list :p-var "rest")))
        (list :var "xs")))
    (list :var "x")))

;; ── do with constructor-pattern binds ──
(hk-test
  "do bind to tuple pattern"
  (hk-parse "do\n  (a, b) <- pairs\n  return a")
  (list
    :do
    (list
      (list
        :do-bind
        (list
          :p-tuple
          (list (list :p-var "a") (list :p-var "b")))
        (list :var "pairs"))
      (list
        :do-expr
        (list :app (list :var "return") (list :var "a"))))))

{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
