// tree_ops.cm — Tree data structure operations kernel
// Pointer chasing, recursion, allocation patterns.

// Binary tree: create, walk, transform, check
function make_tree(depth) {
  if (depth <= 0) return {val: 1, left: null, right: null}
  return {
    val: depth,
    left: make_tree(depth - 1),
    right: make_tree(depth - 1)
  }
}

function tree_check(node) {
  if (!node) return 0
  if (!node.left) return node.val
  return node.val + tree_check(node.left) - tree_check(node.right)
}

function tree_sum(node) {
  if (!node) return 0
  return node.val + tree_sum(node.left) + tree_sum(node.right)
}

function tree_depth(node) {
  if (!node) return 0
  var l = tree_depth(node.left)
  var r = tree_depth(node.right)
  return 1 + (l > r ? l : r)
}

function tree_count(node) {
  if (!node) return 0
  return 1 + tree_count(node.left) + tree_count(node.right)
}

// Transform tree: map values
function tree_map(node, fn) {
  if (!node) return null
  return {
    val: fn(node.val),
    left: tree_map(node.left, fn),
    right: tree_map(node.right, fn)
  }
}

// Flatten tree to array (in-order)
function tree_flatten(node, result) {
  if (!node) return null
  tree_flatten(node.left, result)
  push(result, node.val)
  tree_flatten(node.right, result)
  return null
}

// Build sorted tree from array (balanced)
function build_balanced(arr, lo, hi) {
  if (lo > hi) return null
  var mid = floor((lo + hi) / 2)
  return {
    val: arr[mid],
    left: build_balanced(arr, lo, mid - 1),
    right: build_balanced(arr, mid + 1, hi)
  }
}

// Find a value in BST
function bst_find(node, val) {
  if (!node) return false
  if (val == node.val) return true
  if (val < node.val) return bst_find(node.left, val)
  return bst_find(node.right, val)
}

return {
  // Binary tree create + check (allocation heavy)
  tree_create_check: function(n) {
    var i = 0
    var t = null
    var x = 0
    for (i = 0; i < n; i++) {
      t = make_tree(10)
      x += tree_check(t)
    }
    return x
  },

  // Deep tree traversals
  tree_traversal: function(n) {
    var t = make_tree(12)
    var x = 0
    var i = 0
    for (i = 0; i < n; i++) {
      x += tree_sum(t) + tree_depth(t) + tree_count(t)
    }
    return x
  },

  // Tree map (create new tree from old)
  tree_transform: function(n) {
    var t = make_tree(10)
    var i = 0
    var mapped = null
    for (i = 0; i < n; i++) {
      mapped = tree_map(t, function(v) { return v * 2 + 1 })
    }
    return mapped
  },

  // Flatten + rebuild (array <-> tree conversion)
  tree_flatten_rebuild: function(n) {
    var t = make_tree(10)
    var i = 0
    var flat = null
    var rebuilt = null
    for (i = 0; i < n; i++) {
      flat = []
      tree_flatten(t, flat)
      rebuilt = build_balanced(flat, 0, length(flat) - 1)
    }
    return rebuilt
  },

  // BST search (pointer chasing)
  bst_search: function(n) {
    // Build a balanced BST of 1024 elements
    var data = []
    var i = 0
    for (i = 0; i < 1024; i++) push(data, i)
    var bst = build_balanced(data, 0, 1023)
    var found = 0
    for (i = 0; i < n; i++) {
      if (bst_find(bst, i % 1024)) found++
    }
    return found
  }
}
