// lower_return_method_array_map_box.hako — Return(Method recv Var, method in {size,length,len,get,set,push})
// Emits a minimal mir_call(Method) structure (not executed in VM/Core path here).

using "selfhost.shared.json.utils.json_frag" as JsonFragBox
using selfhost.vm.helpers.method_alias_policy as MethodAliasPolicy
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox

static box LowerReturnMethodArrayMapBox {
  try_lower(program_json) {
    local s = "" + program_json
    local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0); if k_ret < 0 { return null }
    local k_m = JsonFragBox.index_of_from(s, "\"type\":\"Method\"", k_ret); if k_m < 0 { return null }
    // receiver must be Var(name)
    local k_recv = JsonFragBox.index_of_from(s, "\"recv\":{\"type\":\"Var\"", k_m); if k_recv < 0 { return null }

    // Extract receiver variable name
    local recv_name = null
    {
      local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_recv)
      if kn >= 0 {
        recv_name = JsonFragBox.read_string_after(s, kn + 8)
      }
    }

    local method = null
    { local km = JsonFragBox.index_of_from(s, "\"method\":\"", k_m); if km < 0 { return null } method = JsonFragBox.read_string_after(s, km + 9) }
    // Standardize: generate 'size' (len/length are accepted aliases at receiver)
    method = MethodAliasPolicy.normalize_size(method)
    // Allow basic methods
    if !(method == "size" || method == "length" || method == "len" || method == "get" || method == "set" || method == "push") { return null }

    // Dev trace: show what we matched (always print for now)
    print("[builder/arraymap] matched return method pattern")
    print("[builder/arraymap]   method=" + method)
    print("[builder/arraymap]   recv_name=" + recv_name)

    // Parse up to two Int args with actual values
    // Prepare instruction JSON text (avoid Box allocations in VM)
    local insts = ""
    // FIXME: Receiver placeholder: const 0 -> r1（Var 解決は未実装なので 0 を受信者に置く）
    // TODO: Use recv_name to find actual parameter slot instead of hardcoded 0
    insts = insts + "{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}"
    local k_args = JsonFragBox.index_of_from(s, "\"args\":", k_m)
    local next_id = 2
    local args_text = ""
    local first_arg = 1
    if k_args >= 0 {
      // first arg: Int or Var(Int)
      local k_i1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_args)
      local k_v1 = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_args)
      if k_i1 >= 0 && (k_v1 < 0 || k_i1 < k_v1) {
        // read numeric after value:
        local k_val1 = JsonFragBox.index_of_from(s, "\"value\":", k_i1)
        if k_val1 >= 0 {
          local v1 = JsonFragBox.read_int_after(s, k_val1 + 8)
          if v1 != null {
            insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + v1 + "}}"
            if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
            args_text = args_text + ("" + next_id)
            next_id = next_id + 1
          }
        }
        // second arg after first
        local k_i2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_i1 + 1)
        local k_v2a = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_i1 + 1)
        if k_i2 >= 0 {
          local k_v2 = JsonFragBox.index_of_from(s, "\"value\":", k_i2)
          if k_v2 >= 0 {
            local v2 = JsonFragBox.read_int_after(s, k_v2 + 8)
            if v2 != null {
              insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + v2 + "}}"
              if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
              args_text = args_text + ("" + next_id)
              next_id = next_id + 1
            }
          }
        } else if k_v2a >= 0 {
          // second arg is Var: resolve Local Int value
          local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_v2a)
          if kn >= 0 {
            local name2 = JsonFragBox.read_string_after(s, kn)
            local v = PatternUtilBox.find_local_int_before(s, name2, k_m)
            if v != null {
              insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + v + "}}"
              if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
              args_text = args_text + ("" + next_id)
              next_id = next_id + 1
            }
          }
        }
      } else if k_v1 >= 0 && (k_i1 < 0 || k_v1 < k_i1) {
        // first arg is Var: resolve Local value (Int/Bool/Float/String)
        local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_v1)
        if kn >= 0 {
          local namev = JsonFragBox.read_string_after(s, kn)
          // Prefer exact-name Local lookups via PatternUtilBox
          // Int / Bool / Float / String (in this order)
          {
            local vi = PatternUtilBox.find_local_int_before(s, namev, k_m)
            if vi != null {
              insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + vi + "}}"
              if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
              args_text = args_text + ("" + next_id)
              next_id = next_id + 1
            }
          }
          {
            local vb = PatternUtilBox.find_local_bool_before(s, namev, k_m)
            if vb != null {
              insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + vb + "}}"
              if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
              args_text = args_text + ("" + next_id)
              next_id = next_id + 1
            }
          }
          {
            local vf = PatternUtilBox.find_local_float_before(s, namev, k_m)
            if vf != null {
              insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"f64\\\",\\\"value\\\":" + vf + "}}"
              if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
              args_text = args_text + ("" + next_id)
              next_id = next_id + 1
            }
          }
          {
            local vs = PatternUtilBox.find_local_string_before(s, namev, k_m)
            if vs != null {
              insts = insts + ",{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + next_id + ",\\\"value\\\":{\\\"type\\\":\\\"string\\\",\\\"value\\\":\\\"" + vs + "\\\"}}"
              if first_arg == 0 { args_text = args_text + "," } else { first_arg = 0 }
              args_text = args_text + ("" + next_id)
              next_id = next_id + 1
            }
          }
        }
      }
    }
    // mir_call(method=method, receiver=r1, args=[...]) -> dst 4; ret 4
    local mir = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
               insts + "," +
               "{\"op\":\"mir_call\",\"dst\":4,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"method\":\"" + method + "\",\"receiver\":1},\"args\":[" + args_text + "],\"effects\":[]}}," +
               "{\"op\":\"ret\",\"value\":4}]}]}]}"
    return mir
  }
}
