;; stdlib.sx — tests for standard-library functions added in Phase 5:
;; Eq/Ord, Show, Num, Functor, Monad, Applicative, plus common Prelude.

(define
  hk-t
  (fn
    (lbl src expected)
    (hk-test lbl (hk-deep-force (hk-run src)) expected)))

(define
  hk-ts
  (fn
    (lbl src expected)
    (hk-test
      lbl
      (hk-deep-force (hk-run (str "main = show (" src ")")))
      expected)))

;; ── Ord ──────────────────────────────────────────────────────
(hk-test
  "compare lt"
  (hk-deep-force (hk-run "main = compare 1 2"))
  (list "LT"))
(hk-test
  "compare eq"
  (hk-deep-force (hk-run "main = compare 3 3"))
  (list "EQ"))
(hk-test
  "compare gt"
  (hk-deep-force (hk-run "main = compare 9 5"))
  (list "GT"))
(hk-test "min" (hk-deep-force (hk-run "main = min 3 5")) 3)
(hk-test "max" (hk-deep-force (hk-run "main = max 3 5")) 5)

;; ── Show ─────────────────────────────────────────────────────
(hk-ts "show int" "42" "42")
(hk-ts "show neg" "negate 7" "-7")
(hk-ts "show bool T" "True" "True")
(hk-ts "show bool F" "False" "False")
(hk-ts "show list" "[1,2,3]" "[1, 2, 3]")
(hk-ts "show Just" "Just 5" "(Just 5)")
(hk-ts "show Nothing" "Nothing" "Nothing")
(hk-ts "show LT" "LT" "LT")
(hk-ts "show tuple" "(1, True)" "(1, True)")

;; ── Num extras ───────────────────────────────────────────────
(hk-test "signum pos" (hk-deep-force (hk-run "main = signum 5")) 1)
(hk-test
  "signum neg"
  (hk-deep-force (hk-run "main = signum (negate 3)"))
  (- 0 1))
(hk-test "signum zero" (hk-deep-force (hk-run "main = signum 0")) 0)
(hk-test "fromIntegral" (hk-deep-force (hk-run "main = fromIntegral 7")) 7)

;; ── foldr / foldl ────────────────────────────────────────────
(hk-test "foldr sum" (hk-deep-force (hk-run "main = foldr (+) 0 [1,2,3]")) 6)
(hk-test "foldl sum" (hk-deep-force (hk-run "main = foldl (+) 0 [1,2,3]")) 6)
(hk-test "foldl1" (hk-deep-force (hk-run "main = foldl1 (+) [1,2,3,4]")) 10)
(hk-test
  "foldr cons"
  (hk-deep-force (hk-run "main = show (foldr (:) [] [1,2,3])"))
  "[1, 2, 3]")

;; ── List ops ─────────────────────────────────────────────────
(hk-test
  "reverse"
  (hk-deep-force (hk-run "main = show (reverse [1,2,3])"))
  "[3, 2, 1]")
(hk-test "null []" (hk-deep-force (hk-run "main = null []")) (list "True"))
(hk-test
  "null xs"
  (hk-deep-force (hk-run "main = null [1]"))
  (list "False"))
(hk-test
  "elem yes"
  (hk-deep-force (hk-run "main = elem 2 [1,2,3]"))
  (list "True"))
(hk-test
  "elem no"
  (hk-deep-force (hk-run "main = elem 9 [1,2,3]"))
  (list "False"))
(hk-test
  "zip"
  (hk-deep-force (hk-run "main = show (zip [1,2] [3,4])"))
  "[(1, 3), (2, 4)]")
(hk-test "sum" (hk-deep-force (hk-run "main = sum [1,2,3,4,5]")) 15)
(hk-test "product" (hk-deep-force (hk-run "main = product [1,2,3,4]")) 24)
(hk-test "maximum" (hk-deep-force (hk-run "main = maximum [3,1,9,2]")) 9)
(hk-test "minimum" (hk-deep-force (hk-run "main = minimum [3,1,9,2]")) 1)
(hk-test
  "any yes"
  (hk-deep-force (hk-run "main = any (\\x -> x > 3) [1,2,5]"))
  (list "True"))
(hk-test
  "any no"
  (hk-deep-force (hk-run "main = any (\\x -> x > 9) [1,2,5]"))
  (list "False"))
(hk-test
  "all yes"
  (hk-deep-force (hk-run "main = all (\\x -> x > 0) [1,2,5]"))
  (list "True"))
(hk-test
  "all no"
  (hk-deep-force (hk-run "main = all (\\x -> x > 3) [1,2,5]"))
  (list "False"))

;; ── Higher-order ─────────────────────────────────────────────
(hk-test "flip" (hk-deep-force (hk-run "main = flip (-) 3 10")) 7)
(hk-test "const" (hk-deep-force (hk-run "main = const 42 True")) 42)

;; ── Functor ──────────────────────────────────────────────────
(hk-test
  "fmap list"
  (hk-deep-force (hk-run "main = show (fmap (+1) [1,2,3])"))
  "[2, 3, 4]")

;; ── Monad / Applicative ──────────────────────────────────────
(hk-test "return" (hk-deep-force (hk-run "main = return 7")) (list "IO" 7))
(hk-test "pure" (hk-deep-force (hk-run "main = pure 7")) (list "IO" 7))
(hk-test
  "when T"
  (hk-deep-force (hk-run "main = when True (return 1)"))
  (list "IO" 1))
(hk-test
  "when F"
  (hk-deep-force (hk-run "main = when False (return 1)"))
  (list "IO" (list "()")))
(hk-test
  "unless F"
  (hk-deep-force (hk-run "main = unless False (return 2)"))
  (list "IO" 2))

;; ── lookup / maybe / either ─────────────────────────────────
(hk-test
  "lookup hit"
  (hk-deep-force (hk-run "main = show (lookup 2 [(1,10),(2,20)])"))
  "(Just 20)")
(hk-test
  "lookup miss"
  (hk-deep-force (hk-run "main = show (lookup 9 [(1,10)])"))
  "Nothing")
(hk-test
  "maybe def"
  (hk-deep-force (hk-run "main = maybe 0 (+1) Nothing"))
  0)
(hk-test
  "maybe just"
  (hk-deep-force (hk-run "main = maybe 0 (+1) (Just 5)"))
  6)

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