diff --git a/docs/説明書/MIR/mir-unified-reference.md b/docs/説明書/MIR/mir-unified-reference.md new file mode 100644 index 00000000..a0264e54 --- /dev/null +++ b/docs/説明書/MIR/mir-unified-reference.md @@ -0,0 +1,235 @@ +# 🤖 Nyash MIR (Mid-level Intermediate Representation) - 統合リファレンス + +*26命令削減実装中・ChatGPT5仕様準拠 - 2025年8月17日版* + +## 🚨 **重要: MIR命令削減プロジェクト進行中** + +**現状**: 35命令実装(175%膨張)→ **目標**: 26命令(ChatGPT5仕様) +**Gemini評価**: 削減戦略「極めて健全」「断行推奨」 + +## 🎯 **MIR概要** + +Nyash MIRは、Everything is Box哲学を基盤とした中間表現です。現在35命令が実装され、インタープリター・VM・WASM・AOTの全バックエンドで統一された実行を実現します。 + +### **🌟 主要特徴** +- **Everything is Box**: 全データがBoxオブジェクトとして統一表現 +- **Effect System**: pure/mut/io/control効果による最適化基盤 +- **所有権管理**: 強参照森(ownership forest)+ weak参照システム +- **非同期対応**: Future/Bus操作の言語レベル統合 +- **FFI/ABI統合**: ExternCall命令による外部API統一呼び出し + +## 🏗️ **命令分類 - 35命令全体系** + +### **Tier-0: コア演算 (8命令)** +基本的な計算・制御フロー命令 + +| 命令 | 形式 | 効果 | 説明 | +|------|------|------|------| +| `Const` | `%dst = const value` | pure | 定数値生成 | +| `BinOp` | `%dst = %lhs op %rhs` | pure | 二項演算(+,-,*,/等) | +| `UnaryOp` | `%dst = op %operand` | pure | 単項演算(not, neg等) | +| `Compare` | `%dst = %lhs cmp %rhs` | pure | 比較演算(==, !=, <等) | +| `Branch` | `br %cond -> %then, %else` | control | 条件分岐 | +| `Jump` | `jmp %target` | control | 無条件ジャンプ | +| `Return` | `ret %value?` | control | 関数戻り | +| `Phi` | `%dst = phi [%val1:%bb1, %val2:%bb2]` | pure | SSA φ関数 | + +### **Tier-1: メモリ・関数操作 (8命令)** +メモリアクセス・関数呼び出し・型操作 + +| 命令 | 形式 | 効果 | 説明 | +|------|------|------|------| +| `Load` | `%dst = load %ptr` | pure | メモリ読み取り | +| `Store` | `store %value -> %ptr` | mut | メモリ書き込み | +| `Call` | `%dst = call %func(%args...)` | context | 関数呼び出し | +| `BoxCall` | `%dst = %box.method(%args...)` | context | Boxメソッド呼び出し | +| `NewBox` | `%dst = new_box "Type"(%args...)` | mut | Box生成 | +| `TypeCheck` | `%dst = type_check %box "Type"` | pure | 型チェック | +| `Cast` | `%dst = cast %value as Type` | pure | 型変換 | +| `Copy` | `%dst = copy %src` | pure | 値コピー | + +### **Tier-2: 配列・デバッグ・制御 (7命令)** +配列操作・デバッグ・例外処理 + +| 命令 | 形式 | 効果 | 説明 | +|------|------|------|------| +| `ArrayGet` | `%dst = %array[%index]` | pure | 配列要素取得 | +| `ArraySet` | `%array[%index] = %value` | mut | 配列要素設定 | +| `Debug` | `debug %value "message"` | io | デバッグ出力 | +| `Print` | `print %value` | io | コンソール出力 | +| `Nop` | `nop` | pure | 無操作 | +| `Throw` | `throw %exception` | control | 例外発生 | +| `Catch` | `catch %type -> %handler` | control | 例外捕捉 | + +### **Tier-3: 参照・非同期・外部API (12命令)** +所有権管理・非同期処理・外部連携 + +| 命令 | 形式 | 効果 | 説明 | +|------|------|------|------| +| `Safepoint` | `safepoint` | io | セーフポイント | +| `RefNew` | `%dst = ref_new %box` | pure | 参照生成 | +| `RefGet` | `%dst = ref_get %ref.field` | pure | 参照経由読み取り | +| `RefSet` | `ref_set %ref.field = %value` | mut | 参照経由書き込み | +| `WeakNew` | `%dst = weak_new %box` | pure | weak参照生成 | +| `WeakLoad` | `%dst = weak_load %weak_ref` | pure | weak参照読み取り | +| `BarrierRead` | `barrier_read %ptr` | io | メモリバリア読み | +| `BarrierWrite` | `barrier_write %ptr` | io | メモリバリア書き | +| `FutureNew` | `%dst = future_new %value` | mut | Future生成 | +| `FutureSet` | `future_set %future = %value` | mut | Future値設定 | +| `Await` | `%dst = await %future` | io | Future待機 | +| `ExternCall` | `%dst = extern_call iface.method(%args...)` | context | 外部API呼び出し | + +## 🎭 **Effect System - 4種類の効果** + +### **効果分類と最適化ルール** + +```rust +pub enum Effect { + Pure, // 再順序化可能、共通部分式除去可能 + Mut, // 同一リソースで順序保持必要 + Io, // 全順序保持必要(副作用あり) + Control, // 制御フロー変更 +} +``` + +### **効果別命令分類** + +#### **Pure命令 (15命令)** +``` +Const, BinOp, UnaryOp, Compare, Phi, Load, TypeCheck, Cast, Copy, +ArrayGet, Nop, RefNew, RefGet, WeakNew, WeakLoad +``` + +#### **Mut命令 (7命令)** +``` +Store, NewBox, ArraySet, RefSet, FutureNew, FutureSet +``` + +#### **Io命令 (6命令)** +``` +Debug, Print, Safepoint, BarrierRead, BarrierWrite, Await +``` + +#### **Control命令 (4命令)** +``` +Branch, Jump, Return, Throw, Catch +``` + +#### **Context依存命令 (3命令)** +``` +Call, BoxCall, ExternCall +``` +*効果は呼び出し先に依存* + +## 🔧 **重要なMIR実装詳細** + +### **ExternCall命令 - FFI/ABI統合** + +```rust +ExternCall { + dst: Option, + iface_name: String, // "env.console", "nyash.math"等 + method_name: String, // "log", "sqrt"等 + args: Vec, + effects: EffectMask, // BID仕様から決定 +} +``` + +**用途**: ブラウザーAPI・ネイティブライブラリ・プラグインの統一呼び出し + +### **所有権管理システム** + +#### **強参照森(Ownership Forest)** +- 各Boxは最大1つの強参照を持つ(in-degree ≤ 1) +- 強参照による循環は禁止(DAG構造保証) +- `NewBox`, `RefSet`で所有権移転 + +#### **weak参照システム** +- 所有権を持たない軽量参照 +- `WeakNew`で生成、`WeakLoad`で安全アクセス +- 参照先削除時は自動的にnull化 + +### **非同期処理 - Future操作** + +```mir +%future = FutureNew %initial_value // Future生成 +FutureSet %future = %result // 結果設定 +%value = Await %future // 結果取得(ブロッキング) +``` + +## 🚀 **バックエンド別対応状況** + +### **実装済みバックエンド** + +| バックエンド | 対応命令数 | 主要用途 | 特徴 | +|-------------|-----------|----------|------| +| **Interpreter** | 35/35 | デバッグ・開発 | 全命令完全対応 | +| **VM** | 35/35 | 高速実行 | レジスタベース | +| **WASM** | 30/35 | Web配布 | ExternCall→import対応 | +| **AOT準備** | 計画中 | ネイティブ | LLVM IR生成予定 | + +### **バックエンド固有の最適化** + +#### **VM バックエンド** +- レジスタベース実行 +- 局所最適化(ローカルBus elision) +- 直接スレッド化 + +#### **WASM バックエンド** +- メモリ線形化(文字列は (ptr,len)) +- ExternCall → import宣言自動生成 +- ホスト側JavaScript連携 + +## 📊 **MIR最適化パス** + +### **Pure命令最適化** +- **共通部分式除去 (CSE)**: 同一pure計算の除去 +- **不変コード移動 (LICM)**: ループ外移動 +- **定数畳み込み**: コンパイル時計算 + +### **Effect-aware最適化** +- **Mut順序保持**: 同一リソースアクセス順序維持 +- **Io順序保持**: 全Io命令の順序保証 +- **Bus elision**: ローカル通信の直接アクセス化 + +## 🧪 **テスト・検証** + +### **MIR検証項目** +- [ ] **所有権森検証**: strong in-degree ≤ 1 +- [ ] **強循環禁止**: 強参照のDAG構造保証 +- [ ] **weak参照安全性**: 失効時null化 +- [ ] **効果注釈正確性**: 各命令の効果分類 +- [ ] **型安全性**: Box型システム整合性 + +### **バックエンド互換性テスト** +```bash +# 全バックエンドMIR一致テスト +./target/release/nyash --dump-mir program.nyash > interpreter.mir +./target/release/nyash --backend vm --dump-mir program.nyash > vm.mir +./target/release/nyash --backend wasm --dump-mir program.nyash > wasm.mir +diff interpreter.mir vm.mir && diff vm.mir wasm.mir +``` + +## 🔮 **将来計画** + +### **Phase 10: AOT/JIT対応** +- LLVM IR生成バックエンド +- ExternCall → ネイティブ関数呼び出し +- 高度な最適化パス統合 + +### **Phase 11: MIR v2設計** +- 命令数最適化(35 → 25命令目標) +- BID統合(Box Interface Definition) +- リソース所有権拡張(own, borrow) + +## 📚 **関連ドキュメント** + +- **FFI/ABI仕様**: `docs/説明書/reference/box-design/ffi-abi-specification.md` +- **実装詳細**: `src/mir/instruction.rs` +- **Phase計画**: `docs/予定/native-plan/copilot_issues.txt` + +--- + +**最終更新**: 2025年8月17日 +**実装ベース**: 35命令完全対応 +**次期計画**: BID統合プラグインシステム(Phase 9.75f-BID) \ No newline at end of file diff --git a/src/backend/vm.rs b/src/backend/vm.rs index 6e655d9c..4a2ebece 100644 --- a/src/backend/vm.rs +++ b/src/backend/vm.rs @@ -1049,6 +1049,13 @@ impl Default for VM { mod tests { use super::*; use crate::mir::{MirModule, MirFunction, FunctionSignature, MirType, EffectMask, BasicBlock}; + use crate::NyashParser; + use crate::runtime::NyashRuntime; + use crate::core::model::BoxDeclaration as CoreBoxDecl; + use crate::interpreter::SharedState; + use crate::box_factory::user_defined::UserDefinedBoxFactory; + use std::sync::Arc; + use std::collections::HashMap; #[test] fn test_basic_vm_execution() { @@ -1089,4 +1096,79 @@ mod tests { let value = vm.get_value(ValueId(3)).unwrap(); assert_eq!(value.as_integer().unwrap(), 42); } + + fn collect_box_declarations(ast: &crate::ast::ASTNode, runtime: &NyashRuntime) { + fn walk(node: &crate::ast::ASTNode, runtime: &NyashRuntime) { + match node { + crate::ast::ASTNode::Program { statements, .. } => { + for st in statements { walk(st, runtime); } + } + crate::ast::ASTNode::BoxDeclaration { name, fields, methods, constructors, init_fields, weak_fields, is_interface, extends, implements, type_parameters, .. } => { + let decl = CoreBoxDecl { + name: name.clone(), + fields: fields.clone(), + methods: methods.clone(), + constructors: constructors.clone(), + init_fields: init_fields.clone(), + weak_fields: weak_fields.clone(), + is_interface: *is_interface, + extends: extends.clone(), + implements: implements.clone(), + type_parameters: type_parameters.clone(), + }; + if let Ok(mut map) = runtime.box_declarations.write() { + map.insert(name.clone(), decl); + } + } + _ => {} + } + } + walk(ast, runtime); + } + + #[test] + fn test_vm_user_box_birth_and_method() { + let code = r#" +box Person { + init { name } + birth(n) { + me.name = n + } + greet() { + return "Hello, " + me.name + } +} + +return new Person("Alice").greet() +"#; + + // Parse to AST + let ast = NyashParser::parse_from_string(code).expect("parse failed"); + + // Prepare runtime with user-defined declarations and factory + let runtime = { + let rt = NyashRuntime::new(); + collect_box_declarations(&ast, &rt); + let mut shared = SharedState::new(); + shared.box_declarations = rt.box_declarations.clone(); + let udf = Arc::new(UserDefinedBoxFactory::new(shared)); + if let Ok(mut reg) = rt.box_registry.lock() { reg.register(udf); } + rt + }; + + // Compile to MIR + let mut compiler = crate::mir::MirCompiler::new(); + let compile_result = compiler.compile(ast).expect("mir compile failed"); + + // Debug: Print MIR + println!("=== MIR Output ==="); + let mut printer = crate::mir::MirPrinter::verbose(); + println!("{}", printer.print_module(&compile_result.module)); + println!("=================="); + + // Execute with VM + let mut vm = VM::with_runtime(runtime); + let result = vm.execute_module(&compile_result.module).expect("vm exec failed"); + assert_eq!(result.to_string_box().value, "Hello, Alice"); + } } diff --git a/src/mir/builder.rs b/src/mir/builder.rs index 1d7884aa..3dac41cd 100644 --- a/src/mir/builder.rs +++ b/src/mir/builder.rs @@ -80,6 +80,9 @@ impl MirBuilder { let saved_function = self.current_function.take(); let saved_block = self.current_block.take(); let saved_var_map = std::mem::take(&mut self.variable_map); + let saved_value_gen = self.value_gen.clone(); + // Reset value id generator so that params start from %0, %1, ... + self.value_gen.reset(); // Switch context to new function self.current_function = Some(function); @@ -88,11 +91,11 @@ impl MirBuilder { // Create parameter value ids and bind variable names if let Some(ref mut f) = self.current_function { - // 'me' parameter + // 'me' parameter will be %0 let me_id = self.value_gen.next(); f.params.push(me_id); self.variable_map.insert("me".to_string(), me_id); - // user parameters + // user parameters continue as %1..N for p in ¶ms { let pid = self.value_gen.next(); f.params.push(pid); @@ -125,6 +128,7 @@ impl MirBuilder { self.current_function = saved_function; self.current_block = saved_block; self.variable_map = saved_var_map; + self.value_gen = saved_value_gen; Ok(()) } @@ -905,17 +909,17 @@ impl MirBuilder { /// Build me expression: me fn build_me_expression(&mut self) -> Result { - // For now, return a reference to the current instance - // In a full implementation, this would resolve to the actual instance reference + // If lowering a method/birth function, "me" should be a parameter + if let Some(id) = self.variable_map.get("me").cloned() { + return Ok(id); + } + + // Fallback: use a symbolic constant (legacy behavior) let me_value = self.value_gen.next(); - - // For simplicity, emit a constant representing "me" - // In practice, this should resolve to the current instance context self.emit_instruction(MirInstruction::Const { dst: me_value, value: ConstValue::String("__me__".to_string()), })?; - Ok(me_value) }