;; quicksort.hs — naive functional quicksort.

(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-prog-val
  (fn
    (src name)
    (hk-deep-force (get (hk-eval-program (hk-core src)) name))))

(define
  hk-qs-source
  "qsort [] = []
qsort (x:xs) = qsort smaller ++ [x] ++ qsort larger
  where
    smaller = filter (< x) xs
    larger  = filter (>= x) xs
result = qsort [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
")

(hk-test
  "quicksort.hs — sort a list of ints"
  (hk-as-list (hk-prog-val hk-qs-source "result"))
  (list 1 1 2 3 3 4 5 5 5 6 9))

(hk-test
  "quicksort.hs — empty list"
  (hk-as-list
    (hk-prog-val
      (str hk-qs-source "e = qsort []\n")
      "e"))
  (list))

(hk-test
  "quicksort.hs — singleton"
  (hk-as-list
    (hk-prog-val
      (str hk-qs-source "s = qsort [42]\n")
      "s"))
  (list 42))

(hk-test
  "quicksort.hs — already sorted"
  (hk-as-list
    (hk-prog-val
      (str hk-qs-source "asc = qsort [1, 2, 3, 4, 5]\n")
      "asc"))
  (list 1 2 3 4 5))

(hk-test
  "quicksort.hs — reverse sorted"
  (hk-as-list
    (hk-prog-val
      (str hk-qs-source "desc = qsort [5, 4, 3, 2, 1]\n")
      "desc"))
  (list 1 2 3 4 5))

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