; Iter 15b — second consumer demo.
; Imports both std_maybe and std_list. Exercises every combinator at
; least once. xs is a top-level fn `() -> List<Int>` (consts cannot
; reference user fns; the brief flagged this). prep.1 migration
; (kernel-extension-mechanics): type-scoped form for List.<fn> and
; Maybe.<fn>; bare List / Maybe via the explicit imports.

(module std_list_demo

  (import std_maybe)
  (import std_list)

  (fn inc
    (doc "Add 1 to an Int. Used as the (a -> b) arg to map.")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params x)
    (body (app + x 1)))

  (fn add
    (doc "Binary +. Used as the fold accumulator op.")
    (type (fn-type (params (own (con Int)) (own (con Int))) (ret (own (con Int)))))
    (params a b)
    (body (app + a b)))

  (fn is_even
    (doc "Predicate: x mod 2 == 0.")
    (type (fn-type (params (own (con Int))) (ret (own (con Bool)))))
    (params x)
    (body (app eq (app % x 2) 0)))

  (fn double
    (doc "Multiply by 2. Used as the map arg.")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params x)
    (body (app * x 2)))

  (const xs
    (doc "The canonical list [1,2,3,4,5] for the demo. Pure ctor expression, so a const works.")
    (type (con List (con Int)))
    (body
      (term-ctor List Cons 1
        (term-ctor List Cons 2
          (term-ctor List Cons 3
            (term-ctor List Cons 4
              (term-ctor List Cons 5
                (term-ctor List Nil))))))))

  (fn main
    (doc "Drive each std_list combinator once. Expected outputs (per line): 5, false, true, 1, 4, 10, 5, 2, 2, 15, 15.")
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq (seq (app print  (app List.length xs)) (do io/print_str "\n"))
      (seq (seq (app print (app List.is_empty xs)) (do io/print_str "\n"))
      (seq (seq (app print (app List.is_empty (term-ctor List Nil))) (do io/print_str "\n"))
      (seq (seq (app print  (app Maybe.from_maybe -1 (app List.head xs))) (do io/print_str "\n"))
      (seq (seq (app print  (app List.length (app Maybe.from_maybe xs (app List.tail xs)))) (do io/print_str "\n"))
      (seq (seq (app print  (app List.length (app List.append xs xs))) (do io/print_str "\n"))
      (seq (seq (app print  (app Maybe.from_maybe -1 (app List.head (app List.reverse xs)))) (do io/print_str "\n"))
      (seq (seq (app print  (app Maybe.from_maybe -1 (app List.head (app List.map double xs)))) (do io/print_str "\n"))
      (seq (seq (app print  (app List.length (app List.filter is_even xs))) (do io/print_str "\n"))
      (seq (seq (app print  (app List.fold_left add 0 xs)) (do io/print_str "\n"))
           (seq (app print  (app List.fold_right add 0 xs)) (do io/print_str "\n")))))))))))))))
