diff --git a/docs/development/roadmap/phases/phase-10.1/python_implementation_roadmap.txt b/docs/development/roadmap/phases/phase-10.1/python_implementation_roadmap.txt new file mode 100644 index 00000000..d18c09ab --- /dev/null +++ b/docs/development/roadmap/phases/phase-10.1/python_implementation_roadmap.txt @@ -0,0 +1,184 @@ +# PythonParserBox 実装ロードマップ +Based on ChatGPT5's Python Language Feature Surface Map + +## 🎯 実装優先順位の考え方 + +### 1. 最小限の価値を早く提供 +- まずPythonコードが「動く」状態を作る +- 完璧な言語機能カバレッジより、実用的なサブセットを優先 + +### 2. Nyashの強みを活かせる部分から +- ループ最適化(for/while → MIR/JIT高速化) +- 関数呼び出し(def → BoxCall高速化) +- 数値計算(BinOp → ネイティブ性能) + +### 3. 段階的な拡張を可能にする設計 +- 未実装機能はCPython execへフォールバック +- 実装済み機能から徐々にMIR変換を拡大 + +## 📋 Phase 1: Core Subset(1-2週間) +**目標**: 基本的なPythonコードをNyashで実行可能にする + +### 文(Statement) +- [x] def - 関数定義 → Nyash関数/Box +- [x] if/elif/else - 条件分岐 → CondBr +- [x] for - ループ → Loop + Iterator +- [x] while - ループ → Loop +- [x] return - 戻り値 → Return +- [ ] import(最小限) - 標準モジュールは後回し + +### 式(Expression) +- [x] 関数呼び出し - Call → BoxCall +- [x] 演算子(算術) - +,-,*,/,% → BinOp +- [x] 比較演算子 - ==,!=,<,>,<=,>= → Compare +- [x] 変数参照/代入 - Name → Load/Store +- [x] リテラル - 数値/文字列/bool → Const + +### データ型(最小限) +- [x] int → IntegerBox +- [x] float → FloatBox +- [x] str → StringBox +- [x] bool → BoolBox +- [x] list(基本) → ArrayBox + +## 📋 Phase 2: Data Model(2-3週間) +**目標**: Pythonの特殊メソッドをNyashのBoxメソッドにマッピング + +### 特殊メソッド +- [ ] __init__ → constructor/birth +- [ ] __len__ → length() +- [ ] __getitem__ → get() +- [ ] __setitem__ → set() +- [ ] __iter__ → iterator() +- [ ] __str__ → toString() + +### コレクション拡張 +- [ ] dict → MapBox +- [ ] tuple → ImmutableArrayBox(新規) +- [ ] set → SetBox(新規) + +### 演算子オーバーロード +- [ ] __add__, __sub__ 等 → operator+, operator- +- [ ] __eq__, __lt__ 等 → equals(), compareTo() + +## 📋 Phase 3: Advanced Features(1ヶ月) +**目標**: Pythonの生産性の高い機能を実装 + +### 制御フロー拡張 +- [ ] try/except → エラーハンドリング +- [ ] with文 → リソース管理 +- [ ] break/continue → ループ制御 + +### 高度な機能 +- [ ] ジェネレータ(yield) → GeneratorBox +- [ ] デコレータ → 関数ラッパー +- [ ] 内包表記 → 最適化されたループ +- [ ] ラムダ式 → 匿名関数 + +### クラスシステム +- [ ] class文 → box定義 +- [ ] 継承 → from構文 +- [ ] super() → from Parent.method() + +## 📋 Phase 4: Modern Python(将来) +**目標**: 最新のPython機能をサポート + +### 非同期 +- [ ] async/await → 非同期Box(将来のNyash非同期と統合) +- [ ] async for/with → 非同期イテレータ + +### パターンマッチ(3.10+) +- [ ] match/case → Nyashのパターンマッチ(将来実装時) + +### 型ヒント +- [ ] 型アノテーション → MIRの型情報として活用 +- [ ] typing モジュール → 静的型チェック情報 + +## 🚀 実装戦略 + +### Step 1: AST変換の基礎(Phase 1開始) +```python +# Python側でAST→JSON +import ast +import json + +def parse_to_json(code): + tree = ast.parse(code) + return json.dumps(ast_to_dict(tree)) + +# 最小限のノードから実装 +def ast_to_dict(node): + if isinstance(node, ast.FunctionDef): + return { + "type": "FunctionDef", + "name": node.name, + "args": [arg.arg for arg in node.args.args], + "body": [ast_to_dict(stmt) for stmt in node.body] + } + # ... 他のノードタイプを順次追加 +``` + +### Step 2: Nyash AST生成(Rust側) +```rust +// JSON → Nyash AST +fn convert_python_ast(json: &str) -> Result { + let py_ast: PythonAst = serde_json::from_str(json)?; + match py_ast { + PythonAst::FunctionDef { name, args, body } => { + // Python def → Nyash function + ast::BoxDef { + name, + methods: vec![ast::Method { + name: name.clone(), + params: args, + body: convert_statements(body), + }], + .. + } + } + // ... 他のケース + } +} +``` + +### Step 3: 段階的な実行 +1. 最初はCPython exec()でそのまま実行 +2. 変換可能な部分からMIR生成 +3. MIR化された部分はVM/JITで高速実行 +4. 未対応部分は自動的にCPythonフォールバック + +## 📊 期待される成果 + +### Phase 1完了時点 +- 簡単な数値計算スクリプトが2-5倍高速化 +- 基本的なループが最適化される +- Nyashの既存Box(FileBox等)がPythonから使える + +### Phase 2完了時点 +- Pythonのリスト/辞書操作が高速化 +- NyashとPythonのデータ構造が相互運用可能 +- 特殊メソッドによる自然な統合 + +### Phase 3完了時点 +- Pythonの生産的な機能がNyashで高速実行 +- 既存Pythonコードの大部分が動作 +- デコレータやジェネレータも最適化 + +## 🎯 最初の一歩(今すぐ開始) + +1. pyo3でPythonParserBoxの骨組み作成 +2. 最小限のparse_to_json実装(def + return) +3. 単純な関数のAST変換テスト +4. "Hello from Python in Nyash"を表示 + +```python +# 最初のテストケース +def hello(): + return "Hello from Python in Nyash" + +# これがNyashで動けば成功! +``` + +--- +作成日: 2025-08-27 +ChatGPT5のサーフェスマップを基に優先順位付けしたロードマップ \ No newline at end of file diff --git a/src/jit/lower/builder.rs b/src/jit/lower/builder.rs index 9c5a2384..e4b1c010 100644 --- a/src/jit/lower/builder.rs +++ b/src/jit/lower/builder.rs @@ -25,6 +25,17 @@ pub trait IRBuilder { fn emit_return(&mut self); /// Phase 10_d scaffolding: host-call emission (symbolic) fn emit_host_call(&mut self, _symbol: &str, _argc: usize, _has_ret: bool) { } + // ==== Phase 10.7 (control-flow wiring, default no-op) ==== + /// Optional: prepare N basic blocks and return their handles (0..N-1) + fn prepare_blocks(&mut self, _count: usize) { } + /// Optional: switch current insertion point to a given block index + fn switch_to_block(&mut self, _index: usize) { } + /// Optional: seal a block after all predecessors are known + fn seal_block(&mut self, _index: usize) { } + /// Optional: conditional branch, treating the top-of-stack as condition (i64!=0 or b1) + fn br_if_top_is_true(&mut self, _then_index: usize, _else_index: usize) { } + /// Optional: unconditional jump to target block index + fn jump_to(&mut self, _target_index: usize) { } } pub struct NoopBuilder { diff --git a/src/jit/lower/core.rs b/src/jit/lower/core.rs index 9edfb175..39a41d34 100644 --- a/src/jit/lower/core.rs +++ b/src/jit/lower/core.rs @@ -24,16 +24,43 @@ impl LowerCore { for (i, v) in func.params.iter().copied().enumerate() { self.param_index.insert(v, i); } + // Prepare block mapping (Phase 10.7 stub): deterministic ordering by sorted keys + let mut bb_ids: Vec<_> = func.blocks.keys().copied().collect(); + bb_ids.sort_by_key(|b| b.0); + builder.prepare_blocks(bb_ids.len()); builder.prepare_signature_i64(func.params.len(), true); builder.begin_function(&func.signature.name); - for (_bb_id, bb) in func.blocks.iter() { + // Iterate blocks in the sorted order to keep indices stable + for (idx, bb_id) in bb_ids.iter().enumerate() { + let bb = func.blocks.get(bb_id).unwrap(); + builder.switch_to_block(idx); for instr in bb.instructions.iter() { self.cover_if_supported(instr); self.try_emit(builder, instr); } if let Some(term) = &bb.terminator { self.cover_if_supported(term); - self.try_emit(builder, term); + // Branch/Jump need block mapping: pass indices + match term { + crate::mir::MirInstruction::Branch { condition, then_bb, else_bb } => { + // Try to place condition on stack (param/const path); builder will adapt + self.push_value_if_known_or_param(builder, condition); + // Map BasicBlockId -> index + let then_index = bb_ids.iter().position(|x| x == then_bb).unwrap_or(0); + let else_index = bb_ids.iter().position(|x| x == else_bb).unwrap_or(0); + builder.br_if_top_is_true(then_index, else_index); + builder.seal_block(then_index); + builder.seal_block(else_index); + } + crate::mir::MirInstruction::Jump { target } => { + let target_index = bb_ids.iter().position(|x| x == target).unwrap_or(0); + builder.jump_to(target_index); + builder.seal_block(target_index); + } + _ => { + self.try_emit(builder, term); + } + } } } builder.end_function();