///|
/// A static data value cannot read, call or throw during initialization.
/// Moving its allocation to its only read therefore preserves object identity.
fn Program::is_static_data_value(self : Program, id : Int32) -> Bool {
  guard id >= 0 else { return false }
  let node = self.nodes[self.unwrapped_expression(id)]
  match node.kind {
    NumberLiteral
    | ZeroLiteral
    | StringLiteral
    | BooleanLiteral
    | NullLiteral => true
    Unary if self.operators[node.a] is Minus =>
      self.nodes[self.unwrapped_expression(node.b)].kind is NumberLiteral
    ArrayLiteral => {
      for index in 0.. {
      for index in 0.. false
  }
}

///|
/// Only direct top-level statements execute in this frame exactly once.
/// Register candidates after their initializer, so earlier reads keep their TDZ.
fn ValueBindings::inline_data_values(
  self : ValueBindings,
  rename_top_level : Bool,
) -> Unit {
  let program = self.program
  guard rename_top_level && !program.has_dynamic_scope else { return }
  let available = Array::make(program.symbols.length(), -1)
  let root = program.nodes[program.root]
  for index in 0.. {
        for binding_index in 0..= 0 && !self.has_writes[symbol] else { continue }
        let entry = program.symbols[symbol]
        guard entry.scope == 0 &&
          entry.flags == 0 &&
          entry.link < 0 &&
          entry.use_count == 2 &&
          !program.preserved_names.contains(entry.name) &&
          program.is_static_data_value(binding.b) else {
          continue
        }
        available[symbol] = statement_id
      }
      ExpressionStatement =>
        self.inline_data_expression(statement.a, available, true)
      _ => ()
    }
  }
}

///|
/// Walk expression slots only. Function/class bodies, binding patterns, write
/// targets, delete operands and shorthand keys retain their original bindings.
fn ValueBindings::inline_data_expression(
  self : ValueBindings,
  id : Int32,
  available : Array[Int32],
  needs_primary : Bool,
) -> Unit {
  guard id >= 0 else { return }
  let program = self.program
  let node = program.nodes[id]
  match node.kind {
    Identifier => {
      let reference = program.references[node.a]
      let symbol = reference.symbol
      guard symbol >= 0 && reference.scope == 0 else { return }
      let declaration_id = available[symbol]
      guard declaration_id >= 0 else { return }
      let declaration = program.nodes[declaration_id]
      let binding = program.nodes[program.edges[declaration.b]]
      program.nodes[id] = if needs_primary {
        Node::new(Parenthesized, binding.b, 0, 0, 0)
      } else {
        program.nodes[binding.b]
      }
      let entry = program.symbols[symbol]
      program.symbols[symbol] = { ..entry, flags: entry.flags | SYMBOL_ELIDED, }
      program.nodes[declaration_id] = Node::new(Elided, 0, 0, 0, 0)
      available[symbol] = -1
    }
    Parenthesized => self.inline_data_expression(node.a, available, false)
    EvaluatedValue | Member | Spread =>
      self.inline_data_expression(node.a, available, true)
    Index => {
      self.inline_data_expression(node.a, available, true)
      self.inline_data_expression(node.b, available, false)
    }
    Unary if !(program.operators[node.a] is Delete) =>
      self.inline_data_expression(node.b, available, true)
    Binary | Logical => {
      self.inline_data_expression(node.b, available, true)
      self.inline_data_expression(node.c, available, true)
    }
    Assignment => self.inline_data_expression(node.c, available, false)
    Conditional => {
      self.inline_data_expression(node.a, available, true)
      self.inline_data_expression(node.b, available, false)
      self.inline_data_expression(node.c, available, false)
    }
    Call | New => {
      self.inline_data_expression(node.a, available, true)
      if node.b >= 0 {
        self.inline_data_list(node.b, node.c, available, false)
      }
    }
    ArrayLiteral => self.inline_data_list(node.a, node.b, available, false)
    Sequence => self.inline_data_list(node.a, node.b, available, true)
    ObjectLiteral =>
      for index in 0.. ()
  }
}

///|
fn ValueBindings::inline_data_list(
  self : ValueBindings,
  offset : Int32,
  count : Int32,
  available : Array[Int32],
  needs_primary : Bool,
) -> Unit {
  for index in 0..