; Bench fixture (Bench iter): balanced-tree build + sum.
;
; Allocates a balanced binary tree of `Node value left right` cells,
; then walks it summing the value field. Distinct from
; `bench_list_sum` in two ways:
;   1. Each tree node has an additional pointer field versus a list
;      cell — 32-byte alloc instead of 24-byte. The branching shape
;      means the recursion structure is genuinely tree-shaped: the
;      build cannot be made tail-recursive without explicit
;      continuation passing, so this fixture is constrained to depths
;      where the recursion stack fits.
;   2. The traversal pattern hits two children per node, exercising
;      the GC's mark-phase pointer-chasing heuristics differently from
;      a plain linked-list walk.
;
; Depth picked: 20  -> 2^20 - 1 = 1_048_575 nodes -> 32 MB heap usage.
; Recursion depth in `build_tree` and `sum_tree` matches `depth`,
; which fits comfortably in the default 8 MB system stack.
;
; Hardcoded multi-call form: build/sum the same tree thrice for
; signal averaging. The depths are different per call so the GC has
; to deal with three independent live-set sizes.
;
; Expected stdout (one int per line):
;   depth 16: 2^16 - 1 = 65535 nodes, sum = 65535
;   depth 18: 2^18 - 1 = 262143 nodes, sum = 262143
;   depth 20: 2^20 - 1 = 1048575 nodes, sum = 1048575
;
; (Each node stores literal `1`; sum is therefore node count.)

(module bench_tree_walk

  (data Tree
    (ctor Leaf)
    (ctor Node (con Int) (con Tree) (con Tree)))

  (fn build_tree
    (doc "Balanced binary tree of given depth, every value = 1.")
    (type
      (fn-type
        (params (own (con Int)))
        (ret (own (con Tree)))))
    (params depth)
    (body
      (if (app eq depth 0)
        (term-ctor Tree Leaf)
        (term-ctor Tree Node
          1
          (app build_tree (app - depth 1))
          (app build_tree (app - depth 1))))))

  (fn sum_tree
    (doc "Sum every Node value via match recursion. Constructor-blocked: not tail-recursive, but recursion depth = tree depth so fits.")
    (type
      (fn-type
        (params (own (con Tree)))
        (ret (own (con Int)))))
    (params t)
    (body
      (match t
        (case (pat-ctor Leaf) 0)
        (case (pat-ctor Node v l r)
          (app + v (app + (app sum_tree l) (app sum_tree r)))))))

  (fn run_one
    (doc "Build a tree of given depth, sum it, print the sum.")
    (type (fn-type (params (own (con Int))) (ret (own (con Unit))) (effects IO)))
    (params depth)
    (body
      (app print (app sum_tree (app build_tree depth)))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq (app run_one 16)
      (seq (app run_one 18)
           (app run_one 20))))))
