(module loop_recur_2_collatz
  (fn main
    (doc "Collatz step counts. collatz_len(27)=111, collatz_len(97)=118, collatz_len(1)=0. Expected stdout (per line): 111, 118, 0.")
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq (app print (app collatz_len 27))
      (seq (app print (app collatz_len 97))
           (app print (app collatz_len 1))))))
  (fn collatz_len
    (doc "Number of Collatz steps to reach 1. Two binders: n (current value) and steps (accumulator). Parity dispatch is a `match` on n%2; the recur lives in the tail of each match arm, not at body toplevel.")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params start)
    (body
      (loop (n (con Int) start) (steps (con Int) 0)
        (if (app eq n 1)
            steps
            (match (app % n 2)
              (case (pat-lit 0) (recur (app / n 2) (app + steps 1)))
              (case _ (recur (app + (app * 3 n) 1) (app + steps 1)))))))))
