using selfhost.shared.mir.json_emit as JsonEmitBox
// Shared MIR helpers (P1/P2)
using selfhost.shared.mir.schema as MirSchema
using selfhost.shared.mir.builder as BlockBuilder
using lang.compiler.pipeline_v2.localvar_ssa_box as LocalSSABox
using selfhost.shared.common.box_helpers as BoxHelpers

flow EmitMirFlow {
  _int(n) { return "" + n }

  emit_return_int(v) {
    local mod_full = BlockBuilder.const_ret(v)
    return JsonEmitBox.to_json(mod_full)
  }

  _map_binop(opk) {
    if opk == "+" { return "Add" }
    if opk == "-" { return "Sub" }
    if opk == "*" { return "Mul" }
    if opk == "/" { return "Div" }
    if opk == "%" { return "Mod" }
    return opk
  }

  emit_binop(lhs, rhs, opk) {
    local kind = EmitMirFlow._map_binop(opk)
    local mod_full = BlockBuilder.binop(lhs, rhs, kind)
    return JsonEmitBox.to_json(mod_full)
  }

  emit_compare_cfg(lhs, rhs, cmp) {
    return EmitMirFlow.emit_compare_cfg2(lhs, rhs, cmp, 0)
  }

  // emit_compare_cfg2: materialize=1 なら cond を copy して branch する
  emit_compare_cfg2(lhs, rhs, cmp, materialize) {
    local mod_full = BlockBuilder.compare_branch(lhs, rhs, cmp)
    if materialize != 0 {
      // functions[0].blocks[0].instructions に cond=3 材化(copy 5<-3) を挿入
      local fns = BoxHelpers.map_get(mod_full, "functions")
      local fns_len = BoxHelpers.array_len(fns)
      if fns_len > 0 {
        local blocks = BoxHelpers.map_get(BoxHelpers.array_get(fns, 0), "blocks")
        local blocks_len = BoxHelpers.array_len(blocks)
        if blocks_len > 0 {
          local insts = BoxHelpers.map_get(BoxHelpers.array_get(blocks, 0), "instructions")
          if insts != null { LocalSSABox.ensure_after_last_def_copy(insts, 3, 5) }
        }
      }
    }
    return JsonEmitBox.to_json(mod_full)
  }

  // emit_loop_counter: while (i < limit) { i = i + 1 } ; return i
  // Minimal loop CFG without PHI by updating the same dst id for 'i'.
  // Blocks:
  //   0: const i=0 -> r1; const limit -> r2; const one=1 -> r4; jump 1
  //   1: compare lt r1 r2 -> r3; branch r3 then:2 else:3
  //   2: binop add r1 r4 -> r1; jump 1
  //   3: ret r1
  emit_loop_counter(limit) {
    local mod_full = BlockBuilder.loop_counter(limit)
    return JsonEmitBox.to_json(mod_full)
  }

  // P4: emit extern call for op_eq via shared BlockBuilder (immediate values)
  // Shape: const 1=lhs; const 2=rhs; mir_call Extern(op_eq)(1,2)->r3; ret r3
  emit_op_eq(lhs, rhs) {
    local vals = new ArrayBox()
    vals.push(lhs)
    vals.push(rhs)
    local mod_full = BlockBuilder.extern_call_ival_ret("nyrt.ops.op_eq", vals, "nyrt.ops.op_eq")
    return JsonEmitBox.to_json(mod_full)
  }

  // P4: generic extern/global/method/constructor emitters (immediate values)
  emit_extern_call(name, arg_vals) {
    local mod_full = BlockBuilder.extern_call_ival_ret(name, arg_vals, name)
    LocalSSABox.ensure_materialize_last_ret(mod_full)
    return JsonEmitBox.to_json(mod_full)
  }
  emit_global_call(name, arg_vals) {
    local mod_full = BlockBuilder.global_call_ival_ret(name, arg_vals, name)
    LocalSSABox.ensure_materialize_last_ret(mod_full)
    return JsonEmitBox.to_json(mod_full)
  }
  emit_method_call(method, recv_val, arg_vals) {
    local mod_full = BlockBuilder.method_call_ival_ret(method, recv_val, arg_vals, method)
    LocalSSABox.ensure_materialize_last_ret(mod_full)
    return JsonEmitBox.to_json(mod_full)
  }
  emit_constructor(box_type, arg_vals) {
    local mod_full = BlockBuilder.constructor_call_ival_ret(box_type, arg_vals, box_type)
    LocalSSABox.ensure_materialize_last_ret(mod_full)
    return JsonEmitBox.to_json(mod_full)
  }

  // P5: ctor(ArrayBox)→size()→ret via shared builder
  emit_array_ctor_then_size() {
    local mod_full = BlockBuilder.ctor_then_size_ret()
    return JsonEmitBox.to_json(mod_full)
  }


  // Internal: LocalSSA materialize last ret value with a copy
  _ssa_materialize_last_result(mod_full) {
    // Delegate to LocalSSABox for structural materialization policy.
    LocalSSABox.ensure_materialize_last_ret(mod_full)
  }

}
