; Iter 18g.1 RED-test fixture: minimal tail-recursive list-sum
; under explicit-mode + (drop-iterative). Demonstrates the leak
; surfaced by the 18f.2 latency bench: the LCons outer cell, whose
; only ptr field `t` is moved into the tail-app of `sum_acc`, has
; no drop site and leaks once per element.
;
; Built and run with `AILANG_RC_STATS=1` under `--alloc=rc`. The
; stderr summary should show `allocs == frees + small_const`,
; where `small_const` covers the Tree-shaped drop-frames (zero
; here — the program returns Int, no live ADTs at exit).
;
; Pre-fix: `live = N` (one outer LCons cell per consumed element).
; Post-fix: `live = 0`.

(module rc_tail_sum_explicit_leak

  (data IntList
    (ctor LNil)
    (ctor LCons (con Int) (con IntList))
    (drop-iterative))

  (fn cons_n_acc
    (type
      (fn-type
        (params (own (con Int)) (own (con IntList)))
        (ret (own (con IntList)))))
    (params n acc)
    (body
      (if (app eq n 0)
        acc
        (tail-app cons_n_acc
          (app - n 1)
          (term-ctor IntList LCons (app - n 1) acc)))))

  (fn cons_n
    (type
      (fn-type
        (params (own (con Int)))
        (ret (own (con IntList)))))
    (params n)
    (body
      (app cons_n_acc n (term-ctor IntList LNil))))

  (fn sum_acc
    (type
      (fn-type
        (params (own (con IntList)) (own (con Int)))
        (ret (own (con Int)))))
    (params xs acc)
    (body
      (match xs
        (case (pat-ctor LNil) acc)
        (case (pat-ctor LCons h t)
          (tail-app sum_acc t (app + acc h))))))

  (fn sum_list
    (type
      (fn-type
        (params (own (con IntList)))
        (ret (own (con Int)))))
    (params xs)
    (body
      (app sum_acc xs 0)))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (app print (app sum_list (app cons_n 100))))))
