refactor(joinir): Phase 287 P2 - Modularize contract_checks (facade pattern)
- contract_checks.rs (846行) を facade 化 - 6モジュールへ分割(1 module = 1 contract): - terminator_targets.rs (208行) - Branch/Jump検証 - exit_bindings.rs (35行) - exit_bindings ↔ exit_phis - carrier_inputs.rs (145行) - carrier_inputs完全性 - boundary_creation.rs (160行) - B1/C2不変条件 - entry_params.rs (317行) - Entry param一貫性 - mod.rs (30行) - Facade - Total: 846 → 895行(+49行モジュール境界オーバーヘッド) - 意味論不変: エラータグ/ヒント文すべて保存 - Fail-Fast遵守: silent fallback追加なし - 検証: Build 0 errors / Pattern6 RC=9 / quick 154/154 PASS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
# Self Current Task — Now (main)
|
||||
|
||||
## Current Focus: Post Phase 188.3 (Refactoring Window)
|
||||
## Current Focus: Phase 287 P2(Contract Checks facade)
|
||||
|
||||
**2025-12-27: Phase 188.3 完了** ✅
|
||||
- Pattern6(NestedLoopMinimal): `apps/tests/phase1883_nested_minimal.hako` が RC=9
|
||||
@ -8,7 +8,19 @@
|
||||
- `./tools/smokes/v2/run.sh --profile quick` 154/154 PASS 維持
|
||||
- 入口: `docs/development/current/main/phases/phase-188.3/README.md`
|
||||
- 次の指示書(refactor挟み込み): `docs/development/current/main/phases/phase-188.3/P2-REFACTORING-INSTRUCTIONS.md`
|
||||
- 次の指示書(でかいファイル分割): `docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md`
|
||||
|
||||
**2025-12-27: Phase 287 P0 完了** ✅
|
||||
- `merge/mod.rs` を modularize(1,555 → 1,053 lines)
|
||||
- SSOT: `boundary.loop_header_func_name` 優先、`boundary.continuation_func_ids` で除外、`MAIN` 明示除外
|
||||
- 検証: Pattern6 RC=9 / quick 154 PASS / 恒常ログ増加なし
|
||||
- 入口: `docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md`
|
||||
|
||||
**2025-12-27: Phase 287 P1 完了** ✅
|
||||
- `ast_feature_extractor.rs` を facade 化(1,148 → 135 lines)
|
||||
- `pattern_recognizers/`(8 modules)へ分割(1 module = 1 質問)
|
||||
- 検証: Build 0 errors / Pattern6 RC=9 / quick 154 PASS / 恒常ログ増加なし
|
||||
- 入口: `docs/development/current/main/phases/phase-287/P1-AST_FEATURE_EXTRACTOR-INSTRUCTIONS.md`
|
||||
- 次の指示書(P2): `docs/development/current/main/phases/phase-287/P2-CONTRACT_CHECKS-MODULARIZATION-INSTRUCTIONS.md`
|
||||
|
||||
**2025-12-27: Phase 188.2 完了** ✅
|
||||
- StepTreeの `max_loop_depth` を SSOT に採用(Option A)
|
||||
@ -101,7 +113,8 @@
|
||||
- quick smoke 154/154 PASS 維持、Pattern1/4 PoC 両方 PASS
|
||||
|
||||
**次のステップ**:
|
||||
1. **Phase 287(optional)**: Hygiene(破壊的変更なし、既定挙動不変)
|
||||
1. **Phase 287(P2)**: `contract_checks.rs` の facade 化(意味論不変)
|
||||
- 指示書: `docs/development/current/main/phases/phase-287/P2-CONTRACT_CHECKS-MODULARIZATION-INSTRUCTIONS.md`
|
||||
2. (post self-host / docs-first)**Phase 29y**: MIR lifecycle vocab freeze(RC/weak/ABI)
|
||||
- 相談パケット: `docs/development/current/main/investigations/phase-29y-mir-lifecycle-vocab-consult.md`
|
||||
3. (future design, separate phase)Plan 生成の正規化(相談パケット)
|
||||
|
||||
@ -13,10 +13,11 @@ Related:
|
||||
- SSOT: `docs/reference/language/repl.md`
|
||||
- 次: Phase 288.2+(任意): REPL UX improvements(history / multiline / load 等)
|
||||
|
||||
- **Phase 287(✅ complete): ビルド/テスト軽量化(quick gate の責務分離)**
|
||||
- 目的: `tools/smokes/v2/run.sh --profile quick` を 45秒以内(目安)へ戻し、開発サイクルを軽くする
|
||||
- **Phase 287(active): Big Files Refactoring follow-ups(意味論不変)**
|
||||
- 状況: P0/P1 ✅ 完了(merge modularize / ast_feature_extractor facade)
|
||||
- 次(P2): `contract_checks.rs` を facade 化して契約単位で分割
|
||||
- 入口: `docs/development/current/main/phases/phase-287/README.md`
|
||||
- 手順: `docs/development/current/main/phases/phase-287/P1-INSTRUCTIONS.md`
|
||||
- 指示書: `docs/development/current/main/phases/phase-287/P2-CONTRACT_CHECKS-MODULARIZATION-INSTRUCTIONS.md`
|
||||
|
||||
- **Phase 284(✅ COMPLETE): Return as ExitKind SSOT(patternに散らさない)**
|
||||
- 目的: `return` を “pattern最適化の個別実装” にせず、`ExitKind` と `compose::*` / `emit_frag()` に収束させる
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Phase 287 P0: Big Files Refactoring 指示書(意味論不変 / 推定の削減)
|
||||
|
||||
**Date**: 2025-12-27
|
||||
**Status**: Complete ✅
|
||||
**Scope**: Rust 側の“でかいファイル”を分割して、推定(heuristics)依存を減らす
|
||||
**Non-goals**: 新機能、既定挙動変更、silent fallback 追加、env var 追加
|
||||
|
||||
@ -44,6 +45,11 @@ find src -name '*.rs' -print0 | xargs -0 wc -l | sort -nr | head -50
|
||||
実行用の詳細プラン:
|
||||
- `docs/development/current/main/phases/phase-287/P0-MERGE_MOD_MODULARIZATION_PLAN.md`
|
||||
|
||||
結果(実装済み):
|
||||
- `merge/mod.rs`: 1,555 → 1,053 lines
|
||||
- 新規モジュール: `entry_selector.rs`, `header_phi_prebuild.rs`, `value_remapper.rs`, `boundary_logging.rs`
|
||||
- heuristic 排除: continuation 判定は `boundary.continuation_func_ids` を SSOT に採用(文字列一致を撤去)
|
||||
|
||||
#### 目標構造(案)
|
||||
|
||||
```
|
||||
@ -52,11 +58,13 @@ src/mir/builder/control_flow/joinir/merge/
|
||||
├── entry_selector.rs # loop header / entry block 選定(SSOT)
|
||||
├── header_phi_prebuild.rs # LoopHeaderPhiBuilder 呼び出し(SSOT)
|
||||
├── boundary_logging.rs # verbose/debug のみ(trace統一)
|
||||
└── verification/ # “契約検証” をまとめる
|
||||
├── mod.rs
|
||||
└── ... (既存 contract_checks.rs を移す/薄くする)
|
||||
└── debug_assertions.rs # merge 内の fail-fast / 契約検証(debug で固定)
|
||||
```
|
||||
|
||||
注:
|
||||
- Phase 287 P0 では `verification/` の新設ではなく、既存の “契約検証” を `debug_assertions.rs` に統合した(意味論不変)。
|
||||
- 次(P2)で `contract_checks.rs` を facade 化し、契約単位のモジュール分割を行う(`contract_checks/` を新設予定)。
|
||||
|
||||
#### SSOT(ここで削る推定)
|
||||
|
||||
- loop header の推定を boundary に寄せる:
|
||||
@ -95,6 +103,10 @@ src/mir/builder/control_flow/joinir/merge/
|
||||
現状: 複数の “検出器” が同居。純粋関数なので物理分割が安全。
|
||||
方針: `pattern_recognizers/` を作って“1 recognizer = 1 質問”にする。
|
||||
|
||||
結果(実装済み):
|
||||
- `ast_feature_extractor.rs`: 1,148 → 135 lines(facade)
|
||||
- `pattern_recognizers/`: 8 modules(1 module = 1 質問)
|
||||
|
||||
#### 目標構造(案)
|
||||
|
||||
```
|
||||
|
||||
@ -1,12 +1,19 @@
|
||||
# Phase 287 P0: `merge/mod.rs` Modularization Plan(意味論不変)
|
||||
|
||||
**Date**: 2025-12-27
|
||||
**Status**: Planning Complete(Ready for Implementation)
|
||||
**Status**: Historical(Implemented) ✅
|
||||
**Parent**: Phase 287 (Big Files Refactoring)
|
||||
**Goal**: `src/mir/builder/control_flow/joinir/merge/mod.rs` を“配線だけ”に寄せる(意味論不変)
|
||||
|
||||
---
|
||||
|
||||
## Note
|
||||
|
||||
この文書は実装前のプラン。Phase 287 P0 は既に完了しているので、現状の入口は以下:
|
||||
|
||||
- 入口(完了ログ): `docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md`
|
||||
- 次(P2): `docs/development/current/main/phases/phase-287/P2-CONTRACT_CHECKS-MODULARIZATION-INSTRUCTIONS.md`
|
||||
|
||||
## 前提(直近の SSOT)
|
||||
|
||||
- Pattern6 の merge/latch 事故は SSOT 化済み
|
||||
@ -120,4 +127,3 @@ cargo build --release
|
||||
## リスクメモ
|
||||
|
||||
- `merge/mod.rs` と `merge/instruction_rewriter.rs` は両方で “entry 選定” を持ちがちなので、SSOT を二重にしない(可能なら selector を共用、ただし大きく動かさない)。
|
||||
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
# Phase 287 P1: `ast_feature_extractor.rs` 分割指示書(意味論不変)
|
||||
|
||||
**Date**: 2025-12-27
|
||||
**Status**: Complete ✅
|
||||
**Scope**: `src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs`(1,148行)を“recognizer単位”に分割
|
||||
**Non-goals**: ルーティング条件の変更、検出仕様の変更、silent fallback 追加、`merge/instruction_rewriter.rs` の大改造
|
||||
|
||||
実装:
|
||||
- commit: `de1cd1fea`
|
||||
- Phase hub: `docs/development/current/main/phases/phase-287/README.md`
|
||||
|
||||
---
|
||||
|
||||
## 目的(SSOT)
|
||||
|
||||
- “推定(heuristics)で決めているところ”を増やさず、既存検出の **契約を保ったまま** 構造(フォルダ/モジュール)で責務分離する。
|
||||
- `ast_feature_extractor.rs` を **facade**(re-export + glue)へ寄せて、個別検出は “1ファイル=1質問” にする。
|
||||
|
||||
---
|
||||
|
||||
## 背景(現状)
|
||||
|
||||
- `ast_feature_extractor.rs` は純粋関数中心だが、複数の検出器が同居して巨大化している。
|
||||
- `escape_pattern_recognizer.rs` のように、既に分割できることは確認済み。
|
||||
|
||||
---
|
||||
|
||||
## 目標の構造(案)
|
||||
|
||||
```
|
||||
src/mir/builder/control_flow/joinir/patterns/
|
||||
├── ast_feature_extractor.rs # facade(公開関数の入口)
|
||||
└── pattern_recognizers/ # NEW
|
||||
├── mod.rs
|
||||
├── continue_break.rs # continue/break/return の単純探索
|
||||
├── infinite_loop.rs # condition==true の判定
|
||||
├── if_else_phi.rs # if-else phi 検出
|
||||
├── carrier_count.rs # carrier count(代入ベース)
|
||||
├── parse_number.rs # parse_number 系の検出
|
||||
├── parse_string.rs # parse_string 系の検出
|
||||
└── skip_whitespace.rs # skip_ws 系の検出
|
||||
```
|
||||
|
||||
注:
|
||||
- 既存の `escape_pattern_recognizer.rs` はそのままでも良い(P1で無理に統合しない)。
|
||||
- “recognizer名” は **検出の質問** を表す(例: `detect_infinite_loop`、`detect_continue_pattern` など)。
|
||||
|
||||
---
|
||||
|
||||
## 実績(実装済み)
|
||||
|
||||
- `ast_feature_extractor.rs` は facade 化され、既存 import の互換を維持したまま `pattern_recognizers/` へ分割済み。
|
||||
- 恒常ログ増加なし、build/quick/Pattern6 の回帰なし(意味論不変)。
|
||||
|
||||
---
|
||||
|
||||
## 進め方(安全な順序)
|
||||
|
||||
### Step 1: facade化の準備(最小差分)
|
||||
|
||||
- `pattern_recognizers/` を追加し、`mod.rs` を置く(空でもよい)。
|
||||
- `ast_feature_extractor.rs` から、新フォルダの関数を `pub(crate)` で re-export できる形にする。
|
||||
|
||||
### Step 2: “依存が少ない” 検出器から移す
|
||||
|
||||
優先(低依存):
|
||||
- `detect_continue_in_body` / `detect_break_in_body` / `detect_return_in_body`
|
||||
- `detect_infinite_loop`
|
||||
|
||||
ルール:
|
||||
- 公開関数シグネチャは維持(呼び出し側の差分最小)。
|
||||
- `pub(crate)` API の入口は **ast_feature_extractor.rs に残す**(外部参照の破壊を避ける)。
|
||||
|
||||
### Step 3: 中依存(helper多め)を移す
|
||||
|
||||
- if-else phi 系
|
||||
- carrier count 系
|
||||
|
||||
### Step 4: 個別パターン recognizer を移す(必要なら)
|
||||
|
||||
- parse_number / parse_string / skip_whitespace など
|
||||
- 既に抽出済みの recognizer と重複する場合は、P1では **統合しない**(P2以降で整理)。
|
||||
|
||||
---
|
||||
|
||||
## テスト(仕様固定)
|
||||
|
||||
P1 は意味論不変が主目的なので “薄く” で良い:
|
||||
|
||||
- 既存の unit tests があるなら移設に合わせて位置だけ更新
|
||||
- 新規追加するなら、各 recognizer に 1本まで(代表ケースのみ)
|
||||
|
||||
---
|
||||
|
||||
## 検証手順(受け入れ基準)
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako # RC=9
|
||||
./tools/smokes/v2/run.sh --profile quick
|
||||
```
|
||||
|
||||
受け入れ:
|
||||
- ビルド 0 errors
|
||||
- quick 154/154 PASS
|
||||
- Pattern6 RC=9 維持
|
||||
- 恒常ログ増加なし
|
||||
@ -0,0 +1,110 @@
|
||||
# Phase 287 P2: `merge/contract_checks.rs` 分割指示書(意味論不変)
|
||||
|
||||
**Date**: 2025-12-27
|
||||
**Status**: Ready(next)
|
||||
**Scope**: `src/mir/builder/control_flow/joinir/merge/contract_checks.rs`(~846行)を facade 化し、契約検証を “1 module = 1 契約” に分割
|
||||
**Non-goals**: エラータグ変更、検証条件の追加/緩和、`merge/instruction_rewriter.rs` の分割、silent fallback 追加
|
||||
|
||||
---
|
||||
|
||||
## 目的(SSOT)
|
||||
|
||||
- merge の “Fail-Fast 契約” を **構造で見える化**する。
|
||||
- `contract_checks.rs` を facade(re-export + glue)に寄せ、検証ロジックを責務分離する。
|
||||
- 既存の呼び出し点を壊さない(public 関数名/シグネチャを基本維持)。
|
||||
|
||||
---
|
||||
|
||||
## 現状
|
||||
|
||||
`src/mir/builder/control_flow/joinir/merge/contract_checks.rs` は複数契約を同居させており、読む側が “どの契約がどこにあるか” を追いにくい。
|
||||
|
||||
代表的な契約(例):
|
||||
- terminator target existence
|
||||
- exit_bindings ↔ exit_phis
|
||||
- carrier_inputs completeness
|
||||
- boundary contract at creation(B1/C2)
|
||||
- entry params consistency
|
||||
|
||||
---
|
||||
|
||||
## 目標の構造(案)
|
||||
|
||||
```
|
||||
src/mir/builder/control_flow/joinir/merge/
|
||||
├── contract_checks.rs # facade(旧名維持 / re-export)
|
||||
└── contract_checks/ # NEW
|
||||
├── mod.rs
|
||||
├── terminator_targets.rs # verify_all_terminator_targets_exist
|
||||
├── exit_bindings.rs # verify_exit_bindings_have_exit_phis
|
||||
├── carrier_inputs.rs # verify_carrier_inputs_complete
|
||||
├── boundary_creation.rs # verify_boundary_contract_at_creation(B1/C2)
|
||||
└── entry_params.rs # verify_boundary_entry_params
|
||||
```
|
||||
|
||||
ルール:
|
||||
- `contract_checks.rs` は **呼び出し側互換のための facade** に徹する。
|
||||
- 新規の “総合入口” を作るなら `contract_checks::run_all_pipeline_checks()` のみ(既存があるなら整理だけ)。
|
||||
|
||||
---
|
||||
|
||||
## 手順(安全な順序)
|
||||
|
||||
### Step 1: `contract_checks/` を追加し facade を作る
|
||||
|
||||
- `contract_checks/mod.rs` に各 module を `pub(super)` で生やす
|
||||
- `src/mir/builder/control_flow/joinir/merge/contract_checks.rs` から `pub(super) use ...` で既存 API を re-export
|
||||
|
||||
### Step 2: 低依存の契約から移す
|
||||
|
||||
優先:
|
||||
- `verify_all_terminator_targets_exist()`(依存が少ない)
|
||||
- `verify_exit_bindings_have_exit_phis()`
|
||||
|
||||
### Step 3: `verify_carrier_inputs_complete()` を移す
|
||||
|
||||
- ここは “エラータグ/ヒント文” が契約なので、文言変更は避ける。
|
||||
|
||||
### Step 4: boundary creation(B1/C2)を移す
|
||||
|
||||
- `verify_boundary_contract_at_creation()` は “入口で fail-fast する” という意味で重要なので、移設後も呼び出し位置を変えない。
|
||||
|
||||
### Step 5: entry params を移す
|
||||
|
||||
- `verify_boundary_entry_params()` は “param 順序” の SSOT なので、テストがあるなら位置だけ追従させる。
|
||||
|
||||
---
|
||||
|
||||
## テスト(仕様固定)
|
||||
|
||||
P2 は意味論不変が主目的なので、原則 “既存テストを壊さない” を優先する。
|
||||
|
||||
- 既存の `#[cfg(test)]` が `contract_checks.rs` にある場合:
|
||||
- 最小差分で `contract_checks/` の該当 module へ移動
|
||||
- もしくは facade 側に残して import だけ更新(どちらでも可)
|
||||
|
||||
新規テストは原則不要(既存で十分)。
|
||||
|
||||
---
|
||||
|
||||
## 検証手順(受け入れ基準)
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako # RC=9
|
||||
./tools/smokes/v2/run.sh --profile quick
|
||||
```
|
||||
|
||||
受け入れ:
|
||||
- Build: 0 errors
|
||||
- quick: 154/154 PASS
|
||||
- Pattern6: RC=9 維持
|
||||
- 恒常ログ増加なし
|
||||
|
||||
---
|
||||
|
||||
## Out of Scope(重要)
|
||||
|
||||
- `src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs` の物理分割
|
||||
- エラータグの変更、契約の意味変更、条件追加による挙動変化
|
||||
- “便利な fallback” の追加(Fail-Fast 原則に反するため)
|
||||
@ -1,14 +1,45 @@
|
||||
# Phase 287: Normalizer Hygiene(正規化器整理)
|
||||
# Phase 287: Developer Hygiene(big files / smoke / normalizer)
|
||||
|
||||
**Status**: Planning
|
||||
**Date**: 2025-12-26
|
||||
**Status**: In progress (P0/P1 complete, P2 next)
|
||||
**Date**: 2025-12-27
|
||||
**Previous**: Phase 286 (Plan Line完全運用化)
|
||||
|
||||
## 概要
|
||||
## 概要(SSOT)
|
||||
|
||||
Phase 286 でPlan lineへの移行が完了したため、legacy Pattern5 削除とnormalizer.rs の整理を実施。
|
||||
Phase 287 は「開発導線の整備(意味論不変)」を優先して、巨大ファイルの責務分離(big files refactoring)と、既存の hygiene(smoke/normalizer)を扱う。
|
||||
|
||||
## Phase 286 完了作業(本セッション)
|
||||
## 2025-12-27 Update: Big Files Refactoring(P0)✅
|
||||
|
||||
`merge/mod.rs` を modularize(意味論不変)し、SSOT(boundary-first / continuation SSOT)を強化した。
|
||||
|
||||
- 入口: `docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md`
|
||||
|
||||
## 2025-12-27 Update: AST Feature Extractor modularization(P1)✅
|
||||
|
||||
`ast_feature_extractor.rs` を facade にして、`pattern_recognizers/` 配下へ recognizer 単位で分割した(意味論不変)。
|
||||
|
||||
- 入口: `docs/development/current/main/phases/phase-287/P1-AST_FEATURE_EXTRACTOR-INSTRUCTIONS.md`
|
||||
- 次(P2): `docs/development/current/main/phases/phase-287/P2-CONTRACT_CHECKS-MODULARIZATION-INSTRUCTIONS.md`
|
||||
|
||||
---
|
||||
|
||||
## Next (P2)
|
||||
|
||||
- `contract_checks.rs` を facade 化して、契約検証を “1 module = 1 契約” に分割する(意味論不変)。
|
||||
- 指示書: `docs/development/current/main/phases/phase-287/P2-CONTRACT_CHECKS-MODULARIZATION-INSTRUCTIONS.md`
|
||||
|
||||
---
|
||||
|
||||
## Legacy / Historical (2025-12-26 plan)
|
||||
|
||||
以下は「Phase 287 を hygiene として計画していた時期のログ」。今後の候補として残すが、P0/P1(big files)とは別系統。
|
||||
|
||||
### Legacy docs(smoke quick)
|
||||
|
||||
- P1(legacy): quick 軽量化(~45s 目標): `docs/development/current/main/phases/phase-287/P1-INSTRUCTIONS.md`
|
||||
- P2(legacy, optional): quick をさらに 45s へ寄せる: `docs/development/current/main/phases/phase-287/P2-INSTRUCTIONS.md`
|
||||
|
||||
## Phase 286 完了作業(historical)
|
||||
|
||||
### ✅ Legacy Pattern5 削除(488行)
|
||||
|
||||
@ -78,9 +109,9 @@ Pattern4 → Pattern8 → Pattern9 → Pattern3 → Pattern1 → Pattern2
|
||||
|
||||
**注**: Pattern5/6/7 は Plan line 経由で処理(`PLAN_EXTRACTORS` テーブル)
|
||||
|
||||
## Phase 287 計画(後回し)
|
||||
## Legacy backlog (post-2025-12-27)
|
||||
|
||||
### P0: normalizer.rs 分割計画
|
||||
### (legacy) normalizer.rs 分割計画
|
||||
|
||||
**現状**: `src/mir/builder/control_flow/plan/normalizer.rs` が大きすぎる(推定 1,500+ 行)
|
||||
|
||||
@ -103,7 +134,7 @@ Pattern4 → Pattern8 → Pattern9 → Pattern3 → Pattern1 → Pattern2
|
||||
- テスト分離(Pattern5 正規化のみをユニットテスト)
|
||||
- 責任分離(SRP原則)
|
||||
|
||||
### P1: LOOP_PATTERNS テーブル完全削除
|
||||
### (legacy) LOOP_PATTERNS テーブル完全削除
|
||||
|
||||
**背景**: 全Pattern が Plan line 経由になれば、`LOOP_PATTERNS` テーブルは不要
|
||||
|
||||
|
||||
Reference in New Issue
Block a user