docs: def build_tree(X, y, criterion, max_depth, current_depth=1):
      """Builds the decision tree.
      """
  
      # check for max_depth accomplished
      if max_depth >= 0 and current_depth >= max_depth:
          return Leaf(y)
  
      # check for 0 gain
      gain, question = find_best_question(X, y, criterion)
      if gain == 0:
          return Leaf(y)
  
      # split
      true_X, false_X, true_y, false_y = split(X, y, question)
  
      # Build the `true` branch of the tree recursively
      true_branch = build_tree(
          true_X, true_y,
          criterion,
          max_depth,
          current_depth=current_depth+1
      )
      
      # Build the `false` branch of the tree recursively
      false_branch = build_tree(
          false_X, false_y,
          criterion,
          max_depth,
          current_depth=current_depth+1
      )
  
      # returning the root of the tree/subtree
      return Node(
          question=question,
          true_branch=true_branch,
          false_branch=false_branch
      )