; Iter 16b.7 — nested LetRec mutual capture (params, not name).
;
; `nested_sum(n)` returns the sum 1 + 2 + ... + n by combining two
; recursive helpers. The OUTER let-rec `outer(i)` iterates i over
; 1..=n; for each i it calls the INNER let-rec `inner(j)` to count
; how many integers are in 1..=i (= i). The total is then
; 1 + 2 + ... + n = n*(n+1)/2.
;
; The shape exercises:
; - outer captures `n` from `nested_sum`'s fn-params (16b.2 case).
; - inner captures `i` from outer LetRec's PARAMS (16b.7 case
;   under iter — outer LetRec's params are KnownType in body
;   scope, so the inner lift sees a resolvable capture type).
; - inner does NOT capture outer's NAME (still rejected in 16b.7).
;
; Expected stdout (one per line):
;   nested_sum(1) = 1
;   nested_sum(3) = 6
;   nested_sum(5) = 15

(module nested_let_rec

  (fn nested_sum
    (doc "Sum 1 + 2 + ... + n by nested LetRec helpers; inner captures outer's param i.")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params n)
    (body
      (let-rec outer
        (params i)
        (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
        (body
          (if (app gt i n)
            0
            (app +
              (let-rec inner
                (params j)
                (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
                (body
                  (if (app gt j i)
                    0
                    (app + 1 (app inner (app + j 1)))))
                (in (app inner 1)))
              (app outer (app + i 1)))))
        (in (app outer 1)))))

  (fn main
    (doc "Drive nested_sum at 1, 3, 5. Expected (per line): 1, 6, 15.")
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq (seq (app print (app nested_sum 1)) (do io/print_str "\n"))
      (seq (seq (app print (app nested_sum 3)) (do io/print_str "\n"))
           (seq (app print (app nested_sum 5)) (do io/print_str "\n")))))))
