// Binary Trees benchmark - recursive data structures
type Tree =
    | Leaf
    | Node(Tree, Tree)

fn make(depth: Int): Tree = {
    if depth == 0 then Leaf
    else Node(make(depth - 1), make(depth - 1))
}

fn check(tree: Tree): Int = {
    match tree {
        Leaf => 1,
        Node(left, right) => 1 + check(left) + check(right)
    }
}

fn main(): Unit = {
    let maxDepth = 12

    let stretchTree = make(maxDepth + 1)
    let stretchCheck = check(stretchTree)
    Console.print("stretch tree check: " + toString(stretchCheck))

    let longLivedTree = make(maxDepth)

    let sum4 = sumChecks(256, 4, 0)
    Console.print("256 trees of depth 4 check: " + toString(sum4))

    let sum6 = sumChecks(64, 6, 0)
    Console.print("64 trees of depth 6 check: " + toString(sum6))

    let sum8 = sumChecks(16, 8, 0)
    Console.print("16 trees of depth 8 check: " + toString(sum8))

    Console.print("long lived tree check: " + toString(check(longLivedTree)))
}

fn sumChecks(n: Int, depth: Int, acc: Int): Int = {
    if n == 0 then acc
    else sumChecks(n - 1, depth, acc + check(make(depth)))
}
