(module sort
  (data IntList
    (doc "Singly-linked Int list, boxed.")
    (ctor Nil)
    (ctor Cons (con Int) (con IntList)))
  (fn insert
    (doc "Insert y into a sorted list xs, preserving order.")
    (type (fn-type (params (own (con Int)) (own (con IntList))) (ret (own (con IntList)))))
    (params y xs)
    (body (match xs
      (case (pat-ctor Nil) (term-ctor IntList Cons y (term-ctor IntList Nil)))
      (case (pat-ctor Cons h t) (if (app le y h) (term-ctor IntList Cons y (term-ctor IntList Cons h t)) (term-ctor IntList Cons h (app insert y t)))))))
  (fn sort
    (doc "Insertion sort: build the result by inserting each head into the sorted tail.")
    (type (fn-type (params (own (con IntList))) (ret (own (con IntList)))))
    (params xs)
    (body (match xs
      (case (pat-ctor Nil) (term-ctor IntList Nil))
      (case (pat-ctor Cons h t) (app insert h (app sort t))))))
  (fn print_list
    (type (fn-type (params (own (con IntList))) (ret (own (con Unit))) (effects IO)))
    (params xs)
    (body (match xs
      (case (pat-ctor Nil) (lit-unit))
      (case (pat-ctor Cons h t) (seq (seq (app print h) (do io/print_str "\n")) (tail-app print_list t))))))
  (fn main
    (doc "Sort and print [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].")
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body (let xs (term-ctor IntList Cons 3 (term-ctor IntList Cons 1 (term-ctor IntList Cons 4 (term-ctor IntList Cons 1 (term-ctor IntList Cons 5 (term-ctor IntList Cons 9 (term-ctor IntList Cons 2 (term-ctor IntList Cons 6 (term-ctor IntList Cons 5 (term-ctor IntList Cons 3 (term-ctor IntList Cons 5 (term-ctor IntList Nil)))))))))))) (app print_list (app sort xs))))))
