388 lines
12 KiB
Markdown
388 lines
12 KiB
Markdown
|
|
# Phase 194: JsonParser P1/P2/P5 実戦投入
|
|||
|
|
|
|||
|
|
**Status**: Ready for Implementation
|
|||
|
|
**Date**: 2025-12-09
|
|||
|
|
**Prerequisite**: Phase 193 complete (MethodCall in init with ConditionEnv constraints)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 目的
|
|||
|
|
|
|||
|
|
Phase 170-193 で構築した JoinIR インフラを **実コード(JsonParser)で検証**する。
|
|||
|
|
|
|||
|
|
**スコープ**: 「今の設計で素直に通せるところだけ」に絞る(無理に新 Pattern を作らない)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 194-1: 対象ループの選定(実戦版)
|
|||
|
|
|
|||
|
|
### 目標
|
|||
|
|
`tools/hako_shared/json_parser.hako` から、**JoinIR で通す対象**と**保留するループ**を明確に分ける。
|
|||
|
|
|
|||
|
|
### 対象ループ候補
|
|||
|
|
|
|||
|
|
#### ✅ JoinIR で通せるループ(digits 依存なし)
|
|||
|
|
|
|||
|
|
**Pattern 1/2 系**:
|
|||
|
|
```nyash
|
|||
|
|
// _skip_whitespace (既に PoC 済み)
|
|||
|
|
loop(i < len and (s[i] == ' ' or s[i] == '\n' or ...)) {
|
|||
|
|
i = i + 1
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
- **Pattern**: P1 or P2 (条件のみ、単純インクリメント)
|
|||
|
|
- **Carrier**: i (IntegerBox)
|
|||
|
|
- **Update**: i = i + 1
|
|||
|
|
|
|||
|
|
**Pattern 5 系(Trim)**:
|
|||
|
|
```nyash
|
|||
|
|
// _trim leading/trailing (TrimLoopLowerer)
|
|||
|
|
loop(start < len and s[start] == ' ') {
|
|||
|
|
start = start + 1
|
|||
|
|
}
|
|||
|
|
loop(end > 0 and s[end - 1] == ' ') {
|
|||
|
|
end = end - 1
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
- **Pattern**: P5 (Trim specialized)
|
|||
|
|
- **Carrier**: start, end (IntegerBox)
|
|||
|
|
- **Update**: start+1 or end-1
|
|||
|
|
|
|||
|
|
**Pattern 2 系(簡略版 parse_string)**:
|
|||
|
|
```nyash
|
|||
|
|
// _parse_string の簡略形(escape なし・buffer 1 キャリア版)
|
|||
|
|
local buffer = ""
|
|||
|
|
local i = start
|
|||
|
|
loop(i < len and s[i] != '"') {
|
|||
|
|
buffer = buffer + s[i]
|
|||
|
|
i = i + 1
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
- **Pattern**: P2 (break 条件あり)
|
|||
|
|
- **Carrier**: buffer (StringBox), i (IntegerBox)
|
|||
|
|
- **Update**: buffer concat, i+1
|
|||
|
|
- **制約**: escape 処理なし(`\` を含まない想定)
|
|||
|
|
|
|||
|
|
#### ⚠️ 保留ループ(Phase 200+)
|
|||
|
|
|
|||
|
|
**digits テーブル依存**:
|
|||
|
|
```nyash
|
|||
|
|
// _parse_number
|
|||
|
|
local digit = digits.indexOf(s[i]) // ← ConditionEnv 制約で保留
|
|||
|
|
result = result * 10 + digit
|
|||
|
|
```
|
|||
|
|
- **理由**: `digits` は外部ローカル変数 → ConditionEnv に含まれない
|
|||
|
|
- **対応**: Phase 200+ で ConditionEnv 拡張または .hako リライト
|
|||
|
|
|
|||
|
|
**複雑キャリア + flatten**:
|
|||
|
|
```nyash
|
|||
|
|
// _unescape_string
|
|||
|
|
local escaped = false
|
|||
|
|
local result = ""
|
|||
|
|
loop(...) {
|
|||
|
|
if(escaped) { ... }
|
|||
|
|
else if(ch == '\\') { escaped = true }
|
|||
|
|
else { result = result + ch }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
- **理由**: escaped フラグ + 条件分岐が複雑
|
|||
|
|
- **対応**: Phase 195+ (Pattern 3 拡張)
|
|||
|
|
|
|||
|
|
**MethodCall 複数**:
|
|||
|
|
```nyash
|
|||
|
|
// _parse_array, _parse_object
|
|||
|
|
local value = _parse_value(...) // ← MethodCall が複数・ネスト
|
|||
|
|
array.push(value)
|
|||
|
|
```
|
|||
|
|
- **理由**: MethodCall が複雑、ネストあり
|
|||
|
|
- **対応**: Phase 195+ (MethodCall 拡張)
|
|||
|
|
|
|||
|
|
### 成果物
|
|||
|
|
- **対象ループリスト**(3-5 個程度)
|
|||
|
|
- **保留ループリスト**(理由付き)
|
|||
|
|
- ドキュメント: `phase194-loop-inventory.md` (簡易版)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 194-2: routing 側の適用拡張
|
|||
|
|
|
|||
|
|
### 対象ファイル
|
|||
|
|
- `src/mir/builder/control_flow/joinir/routing.rs`
|
|||
|
|
|
|||
|
|
### 実装内容
|
|||
|
|
|
|||
|
|
#### 1. Whitelist 更新(関数名ベース)
|
|||
|
|
|
|||
|
|
現在の routing は whitelist で JoinIR 適用を制御している。以下を追加:
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
// src/mir/builder/control_flow/joinir/routing.rs
|
|||
|
|
|
|||
|
|
const JOINIR_ENABLED_FUNCTIONS: &[&str] = &[
|
|||
|
|
// 既存(PoC 済み)
|
|||
|
|
"_skip_whitespace",
|
|||
|
|
"_trim",
|
|||
|
|
|
|||
|
|
// Phase 194 追加
|
|||
|
|
"_trim_leading",
|
|||
|
|
"_trim_trailing",
|
|||
|
|
"_parse_string_simple", // escape なし版
|
|||
|
|
|
|||
|
|
// 保留(明示的にコメント)
|
|||
|
|
// "_parse_number", // Phase 200+: digits.indexOf 依存
|
|||
|
|
// "_unescape_string", // Phase 195+: 複雑キャリア
|
|||
|
|
// "_parse_array", // Phase 195+: MethodCall 複数
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
pub fn should_use_joinir(function_name: &str) -> bool {
|
|||
|
|
JOINIR_ENABLED_FUNCTIONS.contains(&function_name)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. PatternPipelineContext の調整(必要に応じて)
|
|||
|
|
|
|||
|
|
既存の Pattern 1/2/5 で処理できる範囲なので、新規 Pattern は追加しない。
|
|||
|
|
|
|||
|
|
ただし、routing ロジックで以下を確認:
|
|||
|
|
- P1/P2 の選択ロジックが正しく動作しているか
|
|||
|
|
- P5 (Trim) の検出が JsonParser のループで発火するか
|
|||
|
|
|
|||
|
|
### 設計原則
|
|||
|
|
|
|||
|
|
- **新 Pattern なし**: 既存 P1/P2/P5 で処理
|
|||
|
|
- **Fail-Fast**: 対応できないループは明示的にスキップ(fallback to legacy)
|
|||
|
|
- **whitelist 方式**: 段階的に対象を広げる(一気に全部オンにしない)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 194-3: 実戦 E2E 実行
|
|||
|
|
|
|||
|
|
### 目標
|
|||
|
|
JsonParser 全体を `NYASH_JOINIR_CORE=1` で実行し、JoinIR ルートが動作することを確認。
|
|||
|
|
|
|||
|
|
### テストケース選定
|
|||
|
|
|
|||
|
|
#### 1. 代表ケース(min/basic)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Minimal JSON
|
|||
|
|
echo '{"key": "value"}' > /tmp/test_min.json
|
|||
|
|
NYASH_JOINIR_CORE=1 ./target/release/hakorune tools/hako_shared/json_parser.hako /tmp/test_min.json
|
|||
|
|
|
|||
|
|
# 期待結果: RC が想定通り(parse 成功)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. Trace で JoinIR ルート確認
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# JoinIR trace 有効化
|
|||
|
|
NYASH_JOINIR_CORE=1 NYASH_JOINIR_DEBUG=1 ./target/release/hakorune tools/hako_shared/json_parser.hako /tmp/test_min.json 2>&1 | grep "\[trace:joinir\]"
|
|||
|
|
|
|||
|
|
# 確認項目:
|
|||
|
|
# - [trace:joinir] _skip_whitespace: Pattern 1/2 適用
|
|||
|
|
# - [trace:joinir] _trim_leading: Pattern 5 適用
|
|||
|
|
# - [joinir/freeze] が出ていないこと(freeze = fallback to legacy)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3. 退行確認(既存テスト)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Phase 190-193 の E2E テストが引き続き動作
|
|||
|
|
./target/release/hakorune apps/tests/phase190_atoi_impl.hako
|
|||
|
|
# Expected: 12
|
|||
|
|
|
|||
|
|
./target/release/hakorune apps/tests/phase191_body_local_atoi.hako
|
|||
|
|
# Expected: 123
|
|||
|
|
|
|||
|
|
./target/release/hakorune apps/tests/phase193_init_method_call.hako
|
|||
|
|
# Expected: コンパイル成功
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 落ちた場合の対応
|
|||
|
|
|
|||
|
|
**Fail-Fast 戦略**:
|
|||
|
|
- エラーが出たループは **inventory に追加するだけ**
|
|||
|
|
- 無理に直さない(Phase 195+ の課題として記録)
|
|||
|
|
- whitelist から外して legacy 経路にフォールバック
|
|||
|
|
|
|||
|
|
### 成果物
|
|||
|
|
- 実行ログ(成功 or 失敗箇所の記録)
|
|||
|
|
- JoinIR ルートを踏んだループのリスト
|
|||
|
|
- inventory: 「Phase 19x で対応するループ」リスト
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 194-4: hako_check / selfhost との軽い接続(オプション)
|
|||
|
|
|
|||
|
|
### 目標(余力があれば)
|
|||
|
|
|
|||
|
|
hako_check や selfhost Stage-3 で、Phase 194 で JoinIR 化したループが実際に踏まれているかをチェック。
|
|||
|
|
|
|||
|
|
### 実施内容
|
|||
|
|
|
|||
|
|
#### 1. hako_check の JsonParser 関連ルール
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# JsonParser の品質チェック
|
|||
|
|
./tools/hako_check.sh tools/hako_shared/json_parser.hako --dead-code
|
|||
|
|
|
|||
|
|
# 確認:
|
|||
|
|
# - 今回 JoinIR 化したループ(_skip_whitespace, _trim 等)が使われているか
|
|||
|
|
# - デッドコードとして検出されていないか
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. selfhost Stage-3 代表パス
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# セルフホストコンパイラで JsonParser 使用
|
|||
|
|
NYASH_USE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
|||
|
|
./target/release/hakorune apps/selfhost-runtime/example_with_json.hako
|
|||
|
|
|
|||
|
|
# 確認:
|
|||
|
|
# - JsonParser のループが JoinIR 経路で動作
|
|||
|
|
# - セルフホストコンパイラ全体が正常動作
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 判断基準
|
|||
|
|
|
|||
|
|
**厳しければ Phase 195+ に回す**:
|
|||
|
|
- selfhost 全体の動作確認は時間がかかる
|
|||
|
|
- Phase 194 のゴールは「JsonParser の一部ループが動く」こと
|
|||
|
|
- 完全検証は次フェーズでも OK
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 194-5: ドキュメント更新
|
|||
|
|
|
|||
|
|
### 1. JsonParser ループサマリ作成
|
|||
|
|
|
|||
|
|
**ファイル**: `docs/development/current/main/phase194-loop-inventory.md` (新規)
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
# Phase 194: JsonParser ループ Inventory
|
|||
|
|
|
|||
|
|
## JoinIR で動作中のループ(Phase 194)
|
|||
|
|
|
|||
|
|
| ループ名 | Pattern | Carrier | Update | 状態 |
|
|||
|
|
|---------|---------|---------|--------|------|
|
|||
|
|
| _skip_whitespace | P1/P2 | i | i+1 | ✅ 動作 |
|
|||
|
|
| _trim_leading | P5 | start | start+1 | ✅ 動作 |
|
|||
|
|
| _trim_trailing | P5 | end | end-1 | ✅ 動作 |
|
|||
|
|
| _parse_string_simple | P2 | buffer, i | concat, i+1 | ✅ 動作 |
|
|||
|
|
|
|||
|
|
## 保留ループ(Phase 200+)
|
|||
|
|
|
|||
|
|
| ループ名 | 保留理由 | 対応予定 |
|
|||
|
|
|---------|---------|---------|
|
|||
|
|
| _parse_number | digits.indexOf 依存(ConditionEnv 制約) | Phase 200+ |
|
|||
|
|
| _unescape_string | 複雑キャリア + flatten | Phase 195+ |
|
|||
|
|
| _parse_array | MethodCall 複数・ネスト | Phase 195+ |
|
|||
|
|
| _parse_object | MethodCall 複数・ネスト | Phase 195+ |
|
|||
|
|
|
|||
|
|
## 統計
|
|||
|
|
|
|||
|
|
- **JoinIR 対応**: 4/8 ループ(50%)
|
|||
|
|
- **Pattern 分布**: P1/P2: 2, P5: 2
|
|||
|
|
- **保留**: 4 ループ(明確な理由付き)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. CURRENT_TASK.md 更新
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
## Phase 194: JsonParser P1/P2/P5 実戦投入(完了: 2025-12-XX)
|
|||
|
|
|
|||
|
|
**目標**: Phase 170-193 のインフラを実コードで検証
|
|||
|
|
|
|||
|
|
**実装内容**:
|
|||
|
|
- ✅ 対象ループ選定(4 ループを JoinIR 化、4 ループを保留)
|
|||
|
|
- ✅ routing whitelist 更新(_skip_whitespace, _trim_*, _parse_string_simple)
|
|||
|
|
- ✅ E2E 実行: JsonParser が JoinIR ルートで動作確認
|
|||
|
|
- ✅ Trace で JoinIR ルート確認([joinir/freeze] なし)
|
|||
|
|
|
|||
|
|
**成果**:
|
|||
|
|
- JsonParser の 4/8 ループが JoinIR 経路で動作(P1/P2/P5)
|
|||
|
|
- digits.indexOf 等は Phase 200+ に明示的に保留
|
|||
|
|
- 既存テスト(phase190-193)退行なし
|
|||
|
|
|
|||
|
|
**技術的発見**:
|
|||
|
|
- P1/P2/P5 の実戦適用で箱の品質確認完了
|
|||
|
|
- ConditionEnv 制約が明確化(digits テーブル依存ループは保留)
|
|||
|
|
- Fail-Fast 戦略により、無理のない段階的拡張を実現
|
|||
|
|
|
|||
|
|
**次のステップ**: Phase 195(Pattern 3 拡張)or Phase 200+(ConditionEnv 拡張)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. joinir-architecture-overview.md 更新
|
|||
|
|
|
|||
|
|
Section 7.2 "残タスク" に追記:
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
- [x] **Phase 194**: JsonParser P1/P2/P5 実戦投入
|
|||
|
|
- 4/8 ループが JoinIR 経路で動作確認
|
|||
|
|
- digits.indexOf 等は Phase 200+ に保留
|
|||
|
|
- 実戦検証により箱の品質確認完了
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 成功基準
|
|||
|
|
|
|||
|
|
- [x] 対象ループリスト作成(4 ループ選定、4 ループ保留)
|
|||
|
|
- [x] routing whitelist 更新完了
|
|||
|
|
- [x] JsonParser E2E テストが JoinIR ルートで動作
|
|||
|
|
- [x] Trace で JoinIR ルート確認(freeze なし)
|
|||
|
|
- [x] 既存テスト(phase190-193)退行なし
|
|||
|
|
- [x] ドキュメント更新(inventory + CURRENT_TASK.md)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 設計原則(Phase 194)
|
|||
|
|
|
|||
|
|
1. **「今できること」に集中**:
|
|||
|
|
- P1/P2/P5 で通せるループのみ対象
|
|||
|
|
- 新 Pattern を作らない(既存インフラ再利用)
|
|||
|
|
|
|||
|
|
2. **Fail-Fast 戦略**:
|
|||
|
|
- digits テーブル依存は明示的に保留
|
|||
|
|
- 落ちたら inventory に追加(無理に直さない)
|
|||
|
|
|
|||
|
|
3. **段階的拡張**:
|
|||
|
|
- whitelist で対象を絞る(一気に全部オンにしない)
|
|||
|
|
- 実戦検証 → 課題発見 → 次 Phase で対応
|
|||
|
|
|
|||
|
|
4. **箱理論の実践**:
|
|||
|
|
- 既存の箱(ConditionEnv/UpdateEnv/NumberAccumulation)の品質検証
|
|||
|
|
- 無理のない範囲での実戦投入
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 関連ファイル
|
|||
|
|
|
|||
|
|
### 実装対象
|
|||
|
|
- `src/mir/builder/control_flow/joinir/routing.rs` (whitelist 更新)
|
|||
|
|
|
|||
|
|
### テスト対象
|
|||
|
|
- `tools/hako_shared/json_parser.hako` (JsonParser 本体)
|
|||
|
|
- `/tmp/test_min.json` (テストデータ)
|
|||
|
|
|
|||
|
|
### ドキュメント
|
|||
|
|
- `docs/development/current/main/phase194-loop-inventory.md` (新規作成)
|
|||
|
|
- `docs/development/current/main/joinir-architecture-overview.md` (更新)
|
|||
|
|
- `CURRENT_TASK.md` (Phase 194 完了マーク)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 次の Phase への接続
|
|||
|
|
|
|||
|
|
### Phase 195 候補: Pattern 3 拡張(if-in-loop)
|
|||
|
|
- _unescape_string の escaped フラグ対応
|
|||
|
|
- 条件分岐を跨ぐ body-local 変数
|
|||
|
|
|
|||
|
|
### Phase 200+ 候補: ConditionEnv 拡張
|
|||
|
|
- 外部ローカル変数(digits テーブル)対応
|
|||
|
|
- _parse_number の digits.indexOf サポート
|
|||
|
|
|
|||
|
|
### 判断基準
|
|||
|
|
- Phase 194 の実戦投入で「どこが詰まったか」を見て優先順位決定
|
|||
|
|
- 無理に全部対応しない(Fail-Fast で課題を明確化)
|