; Iter 17a — first fixture exercising the per-fn arena (alloca for
; non-escaping allocations).
;
; `peek` builds a Box(n) and immediately matches on it, returning
; a literal Int that does not depend on the box's payload. The
; box's value is fully consumed by the local match — it never
; flows to a fn arg, never becomes a ctor field, never returns.
; Iter 17a's escape analysis flags the `(term-ctor Box MkBox n)`
; allocation as non-escaping; codegen lowers it to LLVM `alloca`
; instead of the runtime allocator. The heap is not touched at
; all by this fn.
;
; `count` repeats the same pattern under recursion: each call to
; `count` builds a fresh Box(_), matches it, and returns either 0
; or 1 + (count rest). Without the alloca optimisation each
; recursive frame allocates a Box on the heap; with the
; optimisation, each frame's Box dies with its frame.
;
; Expected stdout (one per line):
;   42  — peek(0) returns the literal 42 from the only arm
;   42  — peek(123) ditto (the input value never reaches stdout)
;    5  — count(5)
;    0  — count(0)

(module escape_local_demo

  (data Box (vars a)
    (ctor MkBox a))

  (fn peek
    (doc "Build a Box(n), discard the payload, return 42. The Box is non-escaping.")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params n)
    (body
      (let b (term-ctor Box MkBox n)
        (match b
          (case (pat-ctor MkBox _) 42)))))

  (fn count
    (doc "Recurse n times; each call builds a temporary Box, discards its payload via _, and returns 0 if n<=0, else 1 + count(n-1).")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params n)
    (body
      (if (app le n 0)
        0
        (let b (term-ctor Box MkBox n)
          (match b
            (case (pat-ctor MkBox _) (app + 1 (app count (app - n 1)))))))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq (seq (app print (app peek 0)) (do io/print_str "\n"))
      (seq (seq (app print (app peek 123)) (do io/print_str "\n"))
      (seq (seq (app print (app count 5)) (do io/print_str "\n"))
           (seq (app print (app count 0)) (do io/print_str "\n"))))))))
