// ControlFlowBuilder — If/Match 正規化ビルダー（コンパイル時メタ）
// 生成物は AST JSON v0 のノード文字列、またはステートメント配列（文字列配列）。

static box ControlFlowBuilder {
  // If 文: then/else は配列（文ノード文字列）
  if_stmt(cond_json, then_stmts, else_stmts) {
    using "apps/lib/json_builder.hako" as JB
    return JB.if_(cond_json, then_stmts, else_stmts)
  }

  // If 式: res_name へ代入して合流（[Local(res), If(..)] の配列を返す）
  if_expr(cond_json, then_expr_json, else_expr_json, res_name) {
    using "apps/lib/json_builder.hako" as JB
    local res_var = JB.variable(res_name)
    local decl = JB.local_decl([res_name], [null])
    local then_s = [ JB.assignment(res_var, then_expr_json) ]
    local else_s = [ JB.assignment(res_var, else_expr_json) ]
    local ifn = JB.if_(cond_json, then_s, else_s)
    return [ decl, ifn ]
  }

  // Match 式（簡易版）: scrutinee を一度だけ評価し、res_name に収束。
  // arms: array of { cond_json, guard_json|null, body_expr_json }。
  // default アームは cond_json == "__NY_PATTERN_DEFAULT" で指定。
  match_expr(scrut_json, arms, res_name) {
    return this.match_expr_with_names(scrut_json, arms, res_name, "__ny_scrut")
  }

  match_expr_with_names(scrut_json, arms, res_name, scrut_name) {
    using "apps/lib/json_builder.hako" as JB
    using "apps/lib/pattern_builder.hako" as PT

    // scrutinee を一度だけ評価
    local decl_scrut = JB.local_decl([scrut_name], [scrut_json])
    local scrut_var = JB.variable(scrut_name)

    // res の宣言
    local res_decl = JB.local_decl([res_name], [null])
    local res_var = JB.variable(res_name)

    // デフォルト（任意）を抽出
    local normals = []
    local default_arm = null
    local i = 0
    loop(i < arms.length()) {
      local a = arms.get(i)
      if a.cond_json == PT.default() {
        default_arm = a
      } else {
        normals.push(a)
      }
      i = i + 1
    }

    // 連鎖 If を構築
    function cond_fuse(c, g) {
      if g == null { return c }
      return PT.and_([c, g])
    }

    // 末尾から畳み込んで If 連鎖を組み立てる
    local chain = null
    i = normals.length() - 1
    loop(i >= 0) {
      local a = normals.get(i)
      local cond_all = cond_fuse(a.cond_json, a.guard_json)
      local then_s = [ JB.assignment(res_var, a.body_expr_json) ]
      local else_s = null
      if chain != null { else_s = [ chain ] }
      local ifn = JB.if_(cond_all, then_s, else_s)
      chain = ifn
      i = i - 1
    }

    // デフォルト（無ければ null を代入して収束させる）
    if default_arm != null {
      if chain == null {
        // 単一デフォルト
        chain = JB.assignment(res_var, default_arm.body_expr_json)
        // Assignment は文なので If で包む必要なし
        chain = JB.if_(JB.literal_bool(true), [chain], null)
      } else {
        local def_s = [ JB.assignment(res_var, default_arm.body_expr_json) ]
        chain = JB.if_(JB.literal_bool(true), [chain], def_s) // 常に true の If で else をぶら下げる
      }
    } else {
      // デフォルトなし: 未マッチ経路を res=null へ収束
      local set_null = JB.assignment(res_var, JB.literal_null())
      if chain == null {
        chain = JB.if_(JB.literal_bool(true), [set_null], null)
      } else {
        chain = JB.if_(JB.literal_bool(true), [chain], [set_null])
      }
    }

    return [ decl_scrut, res_decl, chain ]
  }
}
