;; seq / deepseq tests. seq is strict in its first arg (forces to
;; WHNF) and returns the second arg unchanged. deepseq additionally
;; forces the first arg to normal form.

(define
  hk-prog-val
  (fn
    (src name)
    (hk-deep-force (get (hk-eval-program (hk-core src)) name))))

(define hk-as-list
  (fn (xs)
    (cond
      ((and (list? xs) (= (first xs) "[]")) (list))
      ((and (list? xs) (= (first xs) ":"))
        (cons (nth xs 1) (hk-as-list (nth xs 2))))
      (:else xs))))

(define
  hk-eval-list
  (fn (src) (hk-as-list (hk-eval-expr-source src))))

;; ── seq returns its second arg ──
(hk-test
  "seq with primitive first arg"
  (hk-eval-expr-source "seq 1 99")
  99)

(hk-test
  "seq forces first arg via let"
  (hk-eval-expr-source "let x = 1 + 2 in seq x x")
  3)

(hk-test
  "seq second arg is whatever shape"
  (hk-eval-expr-source "seq 0 \"hello\"")
  "hello")

;; ── seq enables previously-lazy bottom to be forced ──
;; Without seq the let-binding `x = error …` is never forced;
;; with seq it must be forced because seq is strict in its first
;; argument. We don't run that error case here (it would terminate
;; the test), but we do verify the negative — that without seq,
;; the bottom bound is never demanded.
(hk-test
  "lazy let — bottom never forced when unused"
  (hk-eval-expr-source "let x = error \"never\" in 42")
  42)

;; ── deepseq forces nested structure ──
(hk-test
  "deepseq with finite list"
  (hk-eval-expr-source "deepseq [1, 2, 3] 7")
  7)

(hk-test
  "deepseq with constructor value"
  (hk-eval-expr-source "deepseq (Just 5) 11")
  11)

(hk-test
  "deepseq with tuple"
  (hk-eval-expr-source "deepseq (1, 2) 13")
  13)

;; ── seq + arithmetic ──
(hk-test
  "seq used inside arithmetic doesn't poison the result"
  (hk-eval-expr-source "(seq 1 5) + (seq 2 7)")
  12)

;; ── seq in user code ──
(hk-test
  "seq via fun-clause"
  (hk-prog-val
    "f x = seq x (x + 1)\nresult = f 10"
    "result")
  11)

(hk-test
  "seq sequences list construction"
  (hk-eval-list "[seq 1 10, seq 2 20]")
  (list 10 20))

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