diff --git a/CLAUDE.md b/CLAUDE.md
index f05589be..08106f80 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -323,6 +323,13 @@ echo 'print("Hello Nyash!")' > local_tests/test_hello.nyash
./target/debug/nyash app_dice_rpg.nyash
```
+### ⚠️ **ビルド時間に関する重要な注意**
+**wasmtime依存関係により、フルビルドは2-3分かかります。**
+- タイムアウトエラーを避けるため、ビルドコマンドには十分な時間を設定してください
+- 例: `cargo build --release -j32` (3分以上待つ)
+- プラグインのみのビルドは数秒で完了します
+- Phase 9.75fで動的ライブラリ分離により改善作業中
+
### 🐛 デバッグ
#### パーサー無限ループ対策(NEW! 2025-08-09)
diff --git a/Cargo.toml b/Cargo.toml
index 45be164c..cfb42e7c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,11 @@ crate-type = ["cdylib", "rlib"]
name = "nyash"
path = "src/main.rs"
+# WASM runner executable
+[[bin]]
+name = "nyash-wasm-run"
+path = "src/bin/nyash-wasm-run.rs"
+
# Examples for development - only available as examples, not bins
[[example]]
name = "gui_simple_notepad"
@@ -180,5 +185,6 @@ debug = true
members = [
".", # メインのnyash-rustプロジェクト
"plugins/nyash-file", # FileBoxプラグイン
+ "plugins/nyash-math", # Math/Time系プラグイン
]
resolver = "2"
diff --git a/docs/説明書/reference/mir-instruction-set.md b/docs/archive/mir-docs-old/mir-instruction-set.md
similarity index 100%
rename from docs/説明書/reference/mir-instruction-set.md
rename to docs/archive/mir-docs-old/mir-instruction-set.md
diff --git a/docs/説明書/reference/mir-reference.md b/docs/archive/mir-docs-old/mir-reference.md
similarity index 100%
rename from docs/説明書/reference/mir-reference.md
rename to docs/archive/mir-docs-old/mir-reference.md
diff --git a/docs/予定/native-plan/issues/mir_reduction_detailed_analysis.md b/docs/予定/native-plan/issues/mir_reduction_detailed_analysis.md
new file mode 100644
index 00000000..910e2ed3
--- /dev/null
+++ b/docs/予定/native-plan/issues/mir_reduction_detailed_analysis.md
@@ -0,0 +1,361 @@
+# MIR 35→26命令削減: 詳細分析・移行戦略
+
+*実装ベース完全マッピング - 2025年8月17日版*
+
+## 🔍 **現在実装35命令 vs ChatGPT5仕様26命令の完全マッピング**
+
+### **維持する命令 (既存実装 → 26命令仕様)**
+
+| 現在実装 | 26命令仕様 | 効果 | 変更 |
+|----------|------------|------|------|
+| `Const` | `Const` | pure | ✅ 維持 |
+| `BinOp` | `BinOp` | pure | ✅ 維持 |
+| `Compare` | `Compare` | pure | ✅ 維持 |
+| `Branch` | `Branch` | control | ✅ 維持 |
+| `Jump` | `Jump` | control | ✅ 維持 |
+| `Phi` | `Phi` | pure | ✅ 維持 |
+| `Call` | `Call` | context | ✅ 維持 |
+| `Return` | `Return` | control | ✅ 維持 |
+| `NewBox` | `NewBox` | mut | ✅ 維持 |
+| `BoxCall` | `BoxCall` | context | ✅ 維持 |
+| `ExternCall` | `ExternCall` | context | ✅ 維持 |
+| `Safepoint` | `Safepoint` | io | ✅ 維持 |
+| `RefGet` | `RefGet` | pure | ✅ 維持 |
+| `RefSet` | `RefSet` | mut | ✅ 維持 |
+| `WeakNew` | `WeakNew` | pure | ✅ 維持 |
+| `WeakLoad` | `WeakLoad` | pure | ✅ 維持 |
+
+**小計**: 16命令維持
+
+### **削除する命令 (17命令)**
+
+#### **グループ1: BinOp統合 (1命令)**
+
+| 削除命令 | 置換方法 | 実装例 |
+|----------|----------|--------|
+| `UnaryOp` | `BinOp`統合 | `not %a` → `%a xor true`
`neg %a` → `0 sub %a` |
+
+#### **グループ2: BoxField操作統合 (4命令)**
+
+| 削除命令 | 置換方法 | 実装例 |
+|----------|----------|--------|
+| `Load` | `BoxFieldLoad` | `load %ptr` → `%ptr.value` |
+| `Store` | `BoxFieldStore` | `store %val -> %ptr` → `%ptr.value = %val` |
+| `ArrayGet` | `BoxFieldLoad` | `%arr[%idx]` → `%arr.elements[%idx]` |
+| `ArraySet` | `BoxFieldStore` | `%arr[%idx] = %val` → `%arr.elements[%idx] = %val` |
+
+#### **グループ3: intrinsic化 (6命令)**
+
+| 削除命令 | intrinsic名 | 実装例 |
+|----------|-------------|--------|
+| `Print` | `@print` | `print %val` → `call @print, %val` |
+| `Debug` | `@debug` | `debug %val "msg"` → `call @debug, %val, "msg"` |
+| `TypeCheck` | `@type_check` | `type_check %val "Type"` → `call @type_check, %val, "Type"` |
+| `Cast` | `@cast` | `cast %val Type` → `call @cast, %val, Type` |
+| `Throw` | `@throw` | `throw %exc` → `call @throw, %exc` |
+| `Catch` | `@catch` | `catch Type -> %bb` → `call @catch, Type, %bb` |
+
+#### **グループ4: 完全削除 (3命令)**
+
+| 削除命令 | 削除理由 | 代替方法 |
+|----------|----------|----------|
+| `Copy` | 最適化パス専用 | 最適化段階でのみ使用 |
+| `Nop` | 不要 | 削除(プレースホルダー不要) |
+| `RefNew` | 冗長 | `RefGet`で代用可能 |
+
+#### **グループ5: 統合・置換 (3命令)**
+
+| 削除命令 | 統合先 | 実装例 |
+|----------|--------|--------|
+| `BarrierRead` | `AtomicFence` | `barrier_read %ptr` → `atomic_fence acquire` |
+| `BarrierWrite` | `AtomicFence` | `barrier_write %ptr` → `atomic_fence release` |
+| `FutureNew` | `NewBox + BoxCall` | `future_new %val` → `%f = new_box "Future"(%val)` |
+| `FutureSet` | `BoxCall` | `future_set %f = %val` → `%f.set(%val)` |
+| `Await` | `BoxCall` | `await %f` → `%f.await()` |
+
+### **追加する命令 (10命令)**
+
+| 新命令 | 効果 | 目的 | 実装必要度 |
+|--------|------|------|------------|
+| `BoxFieldLoad` | pure | Everything is Box核心 | 🔥 Critical |
+| `BoxFieldStore` | mut | Everything is Box核心 | 🔥 Critical |
+| `WeakCheck` | pure | weak参照完全対応 | ⚡ High |
+| `Send` | io | Bus操作一次市民化 | ⚡ High |
+| `Recv` | io | Bus操作一次市民化 | ⚡ High |
+| `TailCall` | control | JIT最適化基盤 | 📝 Medium |
+| `Adopt` | mut | 所有権移管明示 | 📝 Medium |
+| `Release` | mut | 所有権移管明示 | 📝 Medium |
+| `MemCopy` | mut | 最適化基盤 | 📝 Medium |
+| `AtomicFence` | io | 並行制御統一 | 📝 Medium |
+
+## 🛠️ **具体的実装戦略**
+
+### **Phase 1: 新命令実装**
+
+#### **BoxFieldLoad/BoxFieldStore実装**
+```rust
+// src/mir/instruction.rs
+pub enum MirInstruction {
+ // 新規追加
+ BoxFieldLoad {
+ dst: ValueId,
+ box_val: ValueId,
+ field: String,
+ },
+ BoxFieldStore {
+ box_val: ValueId,
+ field: String,
+ value: ValueId,
+ },
+ // ...
+}
+```
+
+#### **WeakCheck実装**
+```rust
+WeakCheck {
+ dst: ValueId,
+ weak_ref: ValueId,
+}
+```
+
+#### **Send/Recv実装**
+```rust
+Send {
+ data: ValueId,
+ target: ValueId,
+},
+Recv {
+ dst: ValueId,
+ source: ValueId,
+},
+```
+
+### **Phase 2: intrinsic関数システム実装**
+
+#### **intrinsic レジストリ**
+```rust
+// src/interpreter/intrinsics.rs
+pub struct IntrinsicRegistry {
+ functions: HashMap,
+}
+
+impl IntrinsicRegistry {
+ pub fn new() -> Self {
+ let mut registry = Self { functions: HashMap::new() };
+ registry.register("@print", intrinsic_print);
+ registry.register("@debug", intrinsic_debug);
+ registry.register("@type_check", intrinsic_type_check);
+ registry.register("@cast", intrinsic_cast);
+ registry.register("@array_get", intrinsic_array_get);
+ registry.register("@array_set", intrinsic_array_set);
+ registry
+ }
+}
+```
+
+#### **intrinsic関数実装例**
+```rust
+fn intrinsic_print(args: &[Value]) -> Result {
+ println!("{}", args[0]);
+ Ok(Value::Void)
+}
+
+fn intrinsic_array_get(args: &[Value]) -> Result {
+ let array = args[0].as_array_box()?;
+ let index = args[1].as_integer()?;
+ array.get_element(index as usize)
+}
+
+fn intrinsic_array_set(args: &[Value]) -> Result {
+ let array = args[0].as_array_box_mut()?;
+ let index = args[1].as_integer()?;
+ let value = args[2].clone();
+ array.set_element(index as usize, value)
+}
+```
+
+### **Phase 3: AST→MIR生成更新**
+
+#### **Load/Store → BoxFieldLoad/BoxFieldStore変換**
+```rust
+// src/mir/builder.rs
+impl MirBuilder {
+ fn visit_field_access(&mut self, node: &FieldAccessNode) -> Result {
+ let box_val = self.visit_expression(&node.object)?;
+ let dst = self.new_temp_var();
+
+ // 旧: Load命令生成
+ // self.emit(MirInstruction::Load { dst, ptr: box_val });
+
+ // 新: BoxFieldLoad命令生成
+ self.emit(MirInstruction::BoxFieldLoad {
+ dst,
+ box_val,
+ field: node.field.clone(),
+ });
+
+ Ok(dst)
+ }
+
+ fn visit_field_assignment(&mut self, node: &FieldAssignmentNode) -> Result<(), BuildError> {
+ let box_val = self.visit_expression(&node.object)?;
+ let value = self.visit_expression(&node.value)?;
+
+ // 旧: Store命令生成
+ // self.emit(MirInstruction::Store { value, ptr: box_val });
+
+ // 新: BoxFieldStore命令生成
+ self.emit(MirInstruction::BoxFieldStore {
+ box_val,
+ field: node.field.clone(),
+ value,
+ });
+
+ Ok(())
+ }
+}
+```
+
+#### **配列操作 → BoxField + intrinsic変換**
+```rust
+fn visit_array_access(&mut self, node: &ArrayAccessNode) -> Result {
+ let array = self.visit_expression(&node.array)?;
+ let index = self.visit_expression(&node.index)?;
+ let dst = self.new_temp_var();
+
+ // intrinsic化
+ self.emit(MirInstruction::Call {
+ dst: Some(dst),
+ func: self.get_intrinsic_id("@array_get"),
+ args: vec![array, index],
+ effects: EffectMask::PURE,
+ });
+
+ Ok(dst)
+}
+```
+
+### **Phase 4: バックエンド対応**
+
+#### **Interpreter実装**
+```rust
+// src/backend/interpreter.rs
+impl Interpreter {
+ fn execute_box_field_load(&mut self, dst: ValueId, box_val: ValueId, field: &str) -> Result<(), RuntimeError> {
+ let box_obj = self.get_value(box_val)?;
+ let field_value = box_obj.get_field(field)?;
+ self.set_value(dst, field_value);
+ Ok(())
+ }
+
+ fn execute_box_field_store(&mut self, box_val: ValueId, field: &str, value: ValueId) -> Result<(), RuntimeError> {
+ let mut box_obj = self.get_value_mut(box_val)?;
+ let field_value = self.get_value(value)?;
+ box_obj.set_field(field, field_value)?;
+ Ok(())
+ }
+}
+```
+
+#### **VM実装**
+```rust
+// src/backend/vm.rs
+impl VM {
+ fn exec_box_field_load(&mut self, dst: RegId, box_val: RegId, field_id: FieldId) -> VMResult<()> {
+ let box_ptr = self.registers[box_val as usize];
+ let field_value = unsafe {
+ self.load_field(box_ptr, field_id)
+ };
+ self.registers[dst as usize] = field_value;
+ Ok(())
+ }
+}
+```
+
+#### **WASM実装**
+```rust
+// src/backend/wasm/codegen.rs
+impl WasmCodegen {
+ fn generate_box_field_load(&mut self, dst: ValueId, box_val: ValueId, field: &str) -> Result<(), CodegenError> {
+ let box_addr = self.get_value_address(box_val)?;
+ let field_offset = self.get_field_offset(field)?;
+
+ // WASM: i32.load offset=field_offset
+ self.emit_wasm(&format!("i32.load offset={}", field_offset));
+ self.set_value_register(dst);
+ Ok(())
+ }
+}
+```
+
+## 📊 **移行スケジュール詳細**
+
+### **Week 1: 基盤実装 (8/18-8/24)**
+- [ ] 新命令構造体定義
+- [ ] intrinsicレジストリ実装
+- [ ] パーサー拡張(新旧両対応)
+
+### **Week 2: フロントエンド移行 (8/25-8/31)**
+- [ ] AST→MIR変換更新
+- [ ] 配列操作intrinsic化
+- [ ] Load/Store→BoxField変換
+
+### **Week 3: 最適化パス移行 (9/1-9/7)**
+- [ ] Effect分類実装
+- [ ] 所有権森検証
+- [ ] BoxFieldLoad/Store最適化
+
+### **Week 4: バックエンド移行 (9/8-9/14)**
+- [ ] Interpreter新命令実装
+- [ ] VM新命令実装
+- [ ] WASM新命令実装
+
+### **Week 5: クリーンアップ (9/15-9/21)**
+- [ ] 旧命令完全削除
+- [ ] テスト更新
+- [ ] ドキュメント整備
+
+## 🧪 **テスト・検証計画**
+
+### **段階的テスト**
+```bash
+# Week 1終了時
+./scripts/test_mir_parsing_26.sh
+
+# Week 2終了時
+./scripts/test_frontend_migration.sh
+
+# Week 3終了時
+./scripts/test_optimization_passes.sh
+
+# Week 4終了時
+./scripts/test_all_backends.sh
+
+# Week 5終了時
+./scripts/test_golden_mir_final.sh
+```
+
+### **性能回帰テスト**
+```bash
+# 削減前後性能比較
+./scripts/benchmark_mir_reduction.sh
+```
+
+## 🎯 **リスク対策**
+
+### **高リスク箇所**
+1. **配列操作intrinsic化**: パフォーマンス影響大
+2. **BoxField統合**: Box型システムとの整合性
+3. **Effect分類変更**: 最適化ロジック全面見直し
+
+### **対策**
+- **プロトタイプ実装**: 高リスク箇所の事前検証
+- **性能測定**: 各段階での性能チェック
+- **ロールバック**: 問題発生時の迅速復旧
+
+---
+
+**分析完了**: 2025年8月17日
+**実装開始**: 2025年8月18日
+**完了予定**: 2025年9月21日
\ No newline at end of file
diff --git a/docs/予定/native-plan/issues/phase_8_5_mir_35_to_26_reduction.md b/docs/予定/native-plan/issues/phase_8_5_mir_35_to_26_reduction.md
new file mode 100644
index 00000000..7b9de007
--- /dev/null
+++ b/docs/予定/native-plan/issues/phase_8_5_mir_35_to_26_reduction.md
@@ -0,0 +1,253 @@
+# Phase 8.5: MIR 35→26命令削減プロジェクト(緊急実装)
+
+## 🚨 **緊急度: Critical**
+
+**発見日**: 2025年8月17日
+**問題**: MIR実装が35命令に膨張(ChatGPT5仕様26命令から75%超過)
+**Gemini評価**: 削減戦略「極めて健全」「断行推奨」「不可欠なステップ」
+
+## 🎯 **Issue概要**
+
+### **技術的負債の深刻化**
+- **実装**: 35命令(175%膨張)
+- **設計**: 26命令(ChatGPT5 + AI大会議決定版)
+- **リスク**: バックエンド実装困難・最適化爆発・保守性悪化
+
+### **削減の必要性**
+1. **バックエンド負荷**: 各バックエンドで35命令対応が重すぎ
+2. **最適化複雑化**: 命令数に比例して最適化ルール爆発
+3. **テスト困難**: 組み合わせ爆発でテストケース管理不能
+4. **長期保守**: 新機能追加時の影響範囲予測困難
+
+## 📋 **削減対象命令分析**
+
+### **削除対象: 17命令**
+
+#### **1. BinOp統合 (1命令)**
+- `UnaryOp` → `BinOp`統合(not %a → %a xor true)
+
+#### **2. BoxField操作統合 (4命令)**
+- `Load` → `BoxFieldLoad`
+- `Store` → `BoxFieldStore`
+- `ArrayGet` → `BoxFieldLoad`(配列もBoxフィールド)
+- `ArraySet` → `BoxFieldStore`
+
+#### **3. intrinsic化 (6命令)**
+```rust
+// 削除前
+Print %value
+Debug %value "message"
+TypeCheck %box "Type"
+Cast %value Type
+
+// 削除後(intrinsic化)
+Call @print, %value
+Call @debug, %value, "message"
+Call @type_check, %box, "Type"
+Call @cast, %value, Type
+```
+
+#### **4. 完全削除 (4命令)**
+- `Copy` → 最適化パス専用(MIRから除外)
+- `Nop` → 不要命令削除
+- `Throw/Catch` → Call経由例外処理
+
+#### **5. 統合・置換 (2命令)**
+- `RefNew` → 削除(RefGetで代用)
+- `BarrierRead/BarrierWrite` → `AtomicFence`統合
+- `FutureNew/FutureSet/Await` → `NewBox + BoxCall`実装
+
+### **新規追加: 10命令**
+
+#### **Box操作明示化**
+- `BoxFieldLoad/BoxFieldStore` → Everything is Box核心
+- `Adopt/Release` → 所有権移管の明示
+
+#### **弱参照完全対応**
+- `WeakCheck` → 生存確認の明示
+- `Send/Recv` → Bus操作一次市民化
+
+#### **最適化基盤**
+- `TailCall, MemCopy, AtomicFence` → JIT/AOT準備
+
+## 🗓️ **5段階実装計画**
+
+### **Phase 1: 共存実装 (1週間)**
+**担当**: Copilot + Claude協調
+**期間**: 2025年8月18日-24日
+
+#### **実装範囲**
+- [ ] 新旧命令両対応MIRパーサー
+- [ ] `BoxFieldLoad/BoxFieldStore`新命令追加
+- [ ] `WeakCheck/Send/Recv`新命令追加
+- [ ] `TailCall/Adopt/Release/MemCopy/AtomicFence`新命令追加
+- [ ] 既存命令保持での互換性確保
+
+#### **技術的詳細**
+```rust
+// src/mir/instruction.rs 拡張
+pub enum MirInstruction {
+ // 既存命令(保持)
+ Load { .. },
+ Store { .. },
+
+ // 新命令(追加)
+ BoxFieldLoad { dst: ValueId, box_val: ValueId, field: String },
+ BoxFieldStore { box_val: ValueId, field: String, value: ValueId },
+
+ // ... 他新命令
+}
+```
+
+### **Phase 2: フロントエンド移行 (1週間)**
+**期間**: 2025年8月25日-31日
+
+#### **実装範囲**
+- [ ] AST→MIR生成を新形式のみに変更
+- [ ] `Load/Store`生成停止、`BoxFieldLoad/BoxFieldStore`生成開始
+- [ ] intrinsic化対象を`Call @intrinsic_name`形式で生成
+- [ ] 配列操作の`BoxField`表現実装
+
+#### **検証項目**
+- [ ] 全Nyashプログラムが新MIRで実行可能
+- [ ] Golden MIRテスト準備完了
+
+### **Phase 3: 最適化パス移行 (1週間)**
+**期間**: 2025年9月1日-7日
+
+#### **実装範囲**
+- [ ] 全最適化パスを新命令対応に修正
+- [ ] Effect分類の正確な実装(pure/mut/io/control)
+- [ ] 所有権森検証ルール実装
+- [ ] `BoxFieldLoad/BoxFieldStore`最適化パス
+
+#### **Effect System実装**
+```rust
+// Pure命令の再順序化
+fn optimize_pure_reordering(mir: &mut MirModule) {
+ // BoxFieldLoad, WeakLoad等の安全な再順序化
+}
+
+// Mut命令の依存解析
+fn analyze_mut_dependencies(mir: &MirModule) -> DependencyGraph {
+ // BoxFieldStore間の依存関係解析
+}
+```
+
+### **Phase 4: バックエンド移行 (1週間)**
+**期間**: 2025年9月8日-14日
+
+#### **実装範囲**
+- [ ] Interpreter新命令対応
+- [ ] VM新命令対応(レジスタベース最適化)
+- [ ] WASM新命令対応(memory操作最適化)
+- [ ] intrinsic関数実装(@print, @debug, @type_check等)
+
+#### **intrinsic実装例**
+```rust
+// Interpreterでのintrinsic実装
+fn execute_intrinsic_call(&mut self, name: &str, args: &[Value]) -> Result {
+ match name {
+ "@print" => {
+ println!("{}", args[0]);
+ Ok(Value::Void)
+ },
+ "@array_get" => {
+ let array = &args[0];
+ let index = args[1].as_integer();
+ Ok(array.get_element(index))
+ },
+ // ... 他intrinsic
+ }
+}
+```
+
+### **Phase 5: 旧命令削除・クリーンアップ (1週間)**
+**期間**: 2025年9月15日-21日
+
+#### **実装範囲**
+- [ ] 削除対象17命令の完全除去
+- [ ] 関連コードの完全削除(パーサー・最適化・バックエンド)
+- [ ] テストスイート更新
+- [ ] ドキュメント更新・整備
+
+#### **クリーンアップ項目**
+- [ ] `UnaryOp, Load, Store, Print, Debug`等の完全削除
+- [ ] 関連するテストケース更新
+- [ ] エラーメッセージ更新
+- [ ] APIドキュメント更新
+
+## 🧪 **検証・品質保証**
+
+### **Golden MIR テスト**
+```bash
+# 全バックエンドMIR一致確認
+./scripts/test_golden_mir_26.sh
+```
+
+### **所有権森検証**
+```rust
+// 自動検証システム
+fn verify_ownership_forest_constraints(mir: &MirModule) -> Result<(), VerifyError> {
+ // strong in-degree ≤ 1
+ // DAG構造(強循環禁止)
+ // WeakLoad/WeakCheck決定的挙動
+}
+```
+
+### **回帰テスト**
+- [ ] 全実用アプリケーション動作確認
+- [ ] 性能劣化チェック(ベンチマーク実行)
+- [ ] メモリ使用量確認
+
+## 📊 **成功基準**
+
+### **必須基準(Phase 5完了時)**
+- [ ] **26命令完全実装**: ChatGPT5仕様100%準拠
+- [ ] **機能完全性**: 既存Nyashプログラム100%動作
+- [ ] **性能維持**: 削減前と同等以上の性能
+- [ ] **Golden MIRテスト**: 全バックエンドMIR一致
+- [ ] **所有権森検証**: 強参照森・weak参照安全性保証
+
+### **理想基準(追加価値)**
+- [ ] **最適化効果**: pure再順序化・CSE/LICM動作確認
+- [ ] **メモリ効率**: Adopt/Releaseによる効率的メモリ管理
+- [ ] **コード品質**: 複雑性大幅削減・保守性向上
+
+## 🚨 **リスク管理**
+
+### **高リスク要因**
+1. **大規模リファクタリング**: 全コンポーネント影響
+2. **互換性破綻**: 既存プログラム動作不良
+3. **性能劣化**: 最適化ロジック変更による影響
+4. **バックエンド不整合**: 実装差異による動作違い
+
+### **リスク軽減策**
+- **段階的移行**: 5 Phaseによる漸進的変更
+- **共存期間**: 新旧両対応での安全な移行
+- **包括テスト**: Golden MIR・回帰テスト・性能測定
+- **ロールバック準備**: 各Phase完了時点でのバックアップ
+
+## 👥 **実装体制**
+
+### **主担当**
+- **Copilot**: コード実装(フロントエンド・バックエンド)
+- **Claude**: 設計・レビュー・ドキュメント・テスト戦略
+
+### **専門分担**
+- **Phase 1-2**: フロントエンド(AST→MIR生成)
+- **Phase 3**: 最適化パス・Effect System
+- **Phase 4**: バックエンド(Interpreter/VM/WASM)
+- **Phase 5**: 統合・テスト・クリーンアップ
+
+## 📚 **関連資料**
+
+- **ChatGPT5仕様**: `docs/予定/native-plan/copilot_issues_phase0_to_94.txt`
+- **26命令詳細**: `docs/説明書/mir-26-specification.md`
+- **Gemini分析**: 「極めて健全」「断行推奨」評価レポート
+
+---
+
+**Issue作成**: 2025年8月17日
+**想定完了**: 2025年9月21日(5週間)
+**優先度**: Critical(他全作業に優先)
\ No newline at end of file
diff --git a/docs/説明書/mir-26-specification.md b/docs/説明書/mir-26-specification.md
new file mode 100644
index 00000000..0d3c792b
--- /dev/null
+++ b/docs/説明書/mir-26-specification.md
@@ -0,0 +1,262 @@
+# 🤖 Nyash MIR 26命令仕様書 (ChatGPT5設計版)
+
+*Everything is Box哲学・完璧なIR化実現 - 2025年8月17日版*
+
+## 🎯 **概要**
+
+Nyash MIR 26命令は、ChatGPT5 + AI大会議により設計された、「化け物に伸びる余白」と「実装の現実」の最適バランスを実現する中間表現です。
+
+### **🌟 設計思想**
+- **RISC原則**: 直交性・シンプル性重視
+- **階層化設計**: Tier-0/1/2による段階的実装
+- **Everything is Box**: Box中心のセマンティクス
+- **Effect System**: 最適化安全性の確保
+- **所有権森**: メモリ安全性の言語レベル保証
+
+## 🏗️ **26命令完全仕様**
+
+### **Tier-0: 普遍的コア (8命令)**
+コンパイラ・仮想マシンの基盤となる必須命令
+
+| 命令 | 形式 | 効果 | 説明 |
+|------|------|------|------|
+| **Const** | `%dst = const value` | pure | 定数値生成 |
+| **BinOp** | `%dst = %lhs op %rhs` | pure | 二項演算(+,-,*,/,==,!=,<,>,and,or等) |
+| **Compare** | `%dst = %lhs cmp %rhs` | pure | 比較演算(専用最適化用) |
+| **Branch** | `br %cond -> %then, %else` | control | 条件分岐 |
+| **Jump** | `jmp %target` | control | 無条件ジャンプ |
+| **Phi** | `%dst = phi [%val1:%bb1, %val2:%bb2]` | pure | SSA φ関数 |
+| **Call** | `%dst = call %func(%args...)` | context | 関数呼び出し |
+| **Return** | `ret %value?` | control | 関数戻り |
+
+### **Tier-1: Nyashセマンティクス (13命令)**
+Everything is Box哲学の核心実装
+
+| 命令 | 形式 | 効果 | 説明 |
+|------|------|------|------|
+| **NewBox** | `%dst = new_box "Type"(%args...)` | mut | 強所有Box生成(所有森ノード) |
+| **BoxFieldLoad** | `%dst = %box.field` | pure | Boxフィールド読み取り |
+| **BoxFieldStore** | `%box.field = %value` | mut | Boxフィールド書き込み |
+| **BoxCall** | `%dst = %box.method(%args...)` | context | Boxメソッド呼び出し |
+| **ExternCall** | `%dst = extern %iface.method(%args...)` | context | 外部ライブラリ呼び出し |
+| **Safepoint** | `safepoint` | io | 分割fini・割込み許可ポイント |
+| **RefGet** | `%dst = ref_get %ref` | pure | 参照から値取得 |
+| **RefSet** | `ref_set %ref = %value` | mut | 参照先差し替え(所有規則検証付き) |
+| **WeakNew** | `%dst = weak_new %box` | pure | weak参照生成 |
+| **WeakLoad** | `%dst = weak_load %weak` | pure | weak参照から値取得(失効時null) |
+| **WeakCheck** | `%dst = weak_check %weak` | pure | weak参照生存確認 |
+| **Send** | `send %data -> %target` | io | Bus送信 |
+| **Recv** | `%dst = recv %source` | io | Bus受信 |
+
+### **Tier-2: 実装補助・最適化友好 (5命令)**
+JIT/AOT最適化の基盤
+
+| 命令 | 形式 | 効果 | 説明 |
+|------|------|------|------|
+| **TailCall** | `tail_call %func(%args...)` | control | 末尾呼び出し最適化 |
+| **Adopt** | `adopt %parent <- %child` | mut | 所有権移管(親が子を取り込み) |
+| **Release** | `release %ref` | mut | 強所有解除(weak化/null化) |
+| **MemCopy** | `memcopy %dst <- %src, %size` | mut | 小規模メモリ移動最適化 |
+| **AtomicFence** | `atomic_fence %ordering` | io | 並行時順序保証 |
+
+## 🎭 **Effect System - 最適化基盤**
+
+### **効果分類と最適化ルール**
+
+#### **Pure効果 (8命令)**
+```
+Const, BinOp, Compare, Phi, BoxFieldLoad, RefGet, WeakNew, WeakLoad, WeakCheck
+```
+- ✅ **再順序化可能**: 副作用なし
+- ✅ **共通部分式除去**: 同一計算結果再利用
+- ✅ **不変コード移動**: ループ外移動可能
+
+#### **Mut効果 (5命令)**
+```
+NewBox, BoxFieldStore, RefSet, Adopt, Release, MemCopy
+```
+- ⚠️ **同一リソース順序保持**: 同じBox/同じFieldで依存関係維持
+- ✅ **異なるリソース並列化**: 別Box操作は並列実行可能
+
+#### **Io効果 (4命令)**
+```
+Safepoint, Send, Recv, AtomicFence
+```
+- 🔒 **順序保持必須**: プログラム順序で実行
+- ❌ **再順序化禁止**: 副作用の整合性確保
+
+#### **Control効果 (4命令)**
+```
+Branch, Jump, Return, TailCall
+```
+- 🌊 **制御フロー変更**: 基本ブロック境界制御
+- 📊 **静的解析対象**: CFG構築・到達可能性解析
+
+#### **Context依存効果 (3命令)**
+```
+Call, BoxCall, ExternCall
+```
+- 🔄 **呼び出し先依存**: 関数・メソッドの効果を継承
+- 📝 **BID/型情報**: ExternCallはBID仕様から効果決定
+
+## 🔧 **所有権森システム**
+
+### **強参照森 (Ownership Forest)**
+```rust
+// 基本原則: strong in-degree ≤ 1
+%parent = NewBox "Parent"()
+%child = NewBox "Child"()
+Adopt %parent <- %child // 子を親の強所有に移管
+```
+
+#### **検証ルール**
+- ✅ **DAG構造保証**: 強参照による循環禁止
+- ✅ **単一所有**: 各Boxは最大1つの強参照のみ
+- ✅ **所有移管**: Adopt/Releaseによる安全な移転
+
+### **weak参照システム**
+```rust
+%weak = WeakNew %box // weak参照生成
+%alive = WeakCheck %weak // 生存確認 (bool)
+%value = WeakLoad %weak // 値取得 (失効時null)
+```
+
+#### **決定的挙動**
+- 🎯 **失効時null**: WeakLoadは例外なしでnull返却
+- 🎯 **失効時false**: WeakCheckは例外なしでfalse返却
+- 🔒 **所有権なし**: weakは削除を阻止しない
+
+## 🚀 **削減戦略 - 35命令からの移行**
+
+### **削除対象命令 (17命令)**
+
+#### **BinOpに統合**
+- `UnaryOp` → `BinOp`(not %a → %a xor true)
+
+#### **BoxField操作に統合**
+- `Load/Store` → `BoxFieldLoad/BoxFieldStore`
+- `ArrayGet/ArraySet` → `BoxFieldLoad/BoxFieldStore`(配列もBoxのフィールド)
+
+#### **intrinsic化**
+```rust
+// 削除前
+Print %value
+Debug %value "message"
+
+// 削除後(intrinsic化)
+Call @print, %value
+Call @debug, %value, "message"
+```
+
+#### **完全削除**
+- `Copy, Nop` → 最適化パス専用(MIRから除外)
+- `TypeCheck, Cast` → 型システム・最適化で処理
+- `Throw/Catch` → Call経由例外ハンドリング
+
+#### **統合・置換**
+- `RefNew` → 削除(RefGetで代用)
+- `BarrierRead/BarrierWrite` → `AtomicFence`統合
+- `FutureNew/FutureSet/Await` → `NewBox + BoxCall`実装
+
+### **新規追加命令 (10命令)**
+
+#### **Box操作の明示化**
+- `BoxFieldLoad/BoxFieldStore` → Everything is Box核心
+- `Adopt/Release` → 所有権移管の明示
+
+#### **弱参照完全対応**
+- `WeakCheck` → 生存確認の明示
+- `Send/Recv` → Bus操作の一次市民化
+
+#### **最適化基盤**
+- `TailCall, MemCopy, AtomicFence` → JIT/AOT準備
+
+## 📊 **段階的移行戦略**
+
+### **Phase 1: 共存実装 (1週間)**
+- 新旧命令両対応のMIRパーサー実装
+- `BoxFieldLoad/BoxFieldStore`等の新命令追加
+- 既存命令は保持したまま新形式も受け入れ
+
+### **Phase 2: フロントエンド移行 (1週間)**
+- AST→MIR生成を新形式のみに変更
+- `Load/Store`の代わりに`BoxFieldLoad/BoxFieldStore`生成
+- intrinsic化対象は`Call @intrinsic_name`形式で生成
+
+### **Phase 3: 最適化パス移行 (1週間)**
+- 全最適化パスを新命令対応に修正
+- Effect分類の正確な実装
+- 所有権森検証ルール実装
+
+### **Phase 4: バックエンド移行 (1週間)**
+- Interpreter/VM/WASMの新命令対応
+- intrinsic関数の実装(@print, @debug等)
+- 削除予定命令の段階的無効化
+
+### **Phase 5: 旧命令削除 (1週間)**
+- 削除対象17命令の完全除去
+- テストスイート更新
+- ドキュメント整備
+
+## 🧪 **検証・テスト戦略**
+
+### **Golden MIR テスト**
+```bash
+# 全バックエンドでMIR出力一致確認
+./target/release/nyash --dump-mir-26 program.nyash > golden.mir
+./target/release/nyash --backend vm --dump-mir-26 program.nyash > vm.mir
+./target/release/nyash --backend wasm --dump-mir-26 program.nyash > wasm.mir
+diff golden.mir vm.mir && diff vm.mir wasm.mir
+```
+
+### **所有権森検証**
+```rust
+// 検証項目
+fn verify_ownership_forest(mir: &MirModule) -> Result<(), VerifyError> {
+ // 1. strong in-degree ≤ 1
+ verify_strong_indegree_constraint()?;
+ // 2. 強循環禁止(DAG構造)
+ verify_no_strong_cycles()?;
+ // 3. WeakLoad/WeakCheck決定的挙動
+ verify_weak_determinism()?;
+}
+```
+
+### **Effect System検証**
+```rust
+// 最適化安全性確認
+fn verify_effect_system(mir: &MirModule) -> Result<(), VerifyError> {
+ // Pure命令の再順序化安全性
+ verify_pure_reordering_safety()?;
+ // Mut命令の依存関係保持
+ verify_mut_dependency_preservation()?;
+ // Io命令の順序保証
+ verify_io_order_preservation()?;
+}
+```
+
+## 🎯 **成功基準**
+
+### **必須基準**
+- [ ] **26命令完全実装**: 全命令が仕様通り動作
+- [ ] **Effect System動作**: 4種効果の正確な分類・最適化
+- [ ] **所有権森検証**: 強参照森・weak参照の安全性保証
+- [ ] **Golden MIRテスト**: 全バックエンドでMIR一致
+- [ ] **性能維持**: 削減後も性能劣化なし
+
+### **理想基準**
+- [ ] **最適化効果実証**: pure再順序化・CSE/LICM動作確認
+- [ ] **所有権森活用**: Adopt/Releaseによる効率的メモリ管理
+- [ ] **JIT準備完了**: TailCall/MemCopyの最適化基盤確立
+
+## 📚 **関連ドキュメント**
+
+- **ChatGPT5仕様**: `docs/予定/native-plan/copilot_issues_phase0_to_94.txt`
+- **実装移行計画**: `docs/予定/native-plan/issues/phase_8_5_mir_35_to_26_reduction.md`
+- **Effect System詳細**: `docs/nyir/effect-system-specification.md`
+
+---
+
+**策定**: ChatGPT5 + AI大会議
+**Gemini評価**: 「極めて健全」「断行推奨」
+**実装目標**: 2025年9月完了予定
\ No newline at end of file
diff --git a/docs/説明書/mir-unified-reference.md b/docs/説明書/mir-unified-reference.md
new file mode 100644
index 00000000..a0264e54
--- /dev/null
+++ b/docs/説明書/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/local_tests/benchmark_filebox.nyash b/local_tests/benchmark_filebox.nyash
new file mode 100644
index 00000000..c876f731
--- /dev/null
+++ b/local_tests/benchmark_filebox.nyash
@@ -0,0 +1,87 @@
+// FileBox パフォーマンスベンチマーク
+// 静的版と動的版の速度比較
+
+static box Main {
+ init { console, timer }
+
+ main() {
+ me.console = new ConsoleBox()
+ me.timer = new TimeBox()
+
+ me.console.log("📊 FileBox パフォーマンスベンチマーク開始")
+
+ // テスト設定
+ local iterations
+ iterations = 1000
+ local testFile
+ testFile = "benchmark_test.txt"
+
+ // ベンチマーク1: ファイル作成・削除
+ me.console.log("\n🔧 Test 1: FileBox作成 x " + iterations.toString())
+ local start1
+ start1 = me.timer.now()
+
+ local i
+ i = 0
+ loop(i < iterations) {
+ local file
+ file = new FileBox(testFile + i.toString())
+ i = i + 1
+ }
+
+ local elapsed1
+ elapsed1 = me.timer.elapsed(start1)
+ me.console.log("⏱️ 経過時間: " + elapsed1.toString() + "ms")
+ me.console.log("📈 平均: " + (elapsed1 / iterations).toString() + "ms/操作")
+
+ // ベンチマーク2: 読み書き操作
+ me.console.log("\n🔧 Test 2: 読み書き操作 x " + iterations.toString())
+ local file2
+ file2 = new FileBox(testFile)
+
+ local start2
+ start2 = me.timer.now()
+
+ i = 0
+ loop(i < iterations) {
+ file2.write("Test data " + i.toString())
+ local content
+ content = file2.read()
+ i = i + 1
+ }
+
+ local elapsed2
+ elapsed2 = me.timer.elapsed(start2)
+ me.console.log("⏱️ 経過時間: " + elapsed2.toString() + "ms")
+ me.console.log("📈 平均: " + (elapsed2 / iterations).toString() + "ms/操作")
+
+ // ベンチマーク3: exists()チェック
+ me.console.log("\n🔧 Test 3: exists()チェック x " + iterations.toString())
+ local start3
+ start3 = me.timer.now()
+
+ i = 0
+ loop(i < iterations) {
+ local exists
+ exists = file2.exists()
+ i = i + 1
+ }
+
+ local elapsed3
+ elapsed3 = me.timer.elapsed(start3)
+ me.console.log("⏱️ 経過時間: " + elapsed3.toString() + "ms")
+ me.console.log("📈 平均: " + (elapsed3 / iterations).toString() + "ms/操作")
+
+ // クリーンアップ
+ i = 0
+ loop(i < iterations) {
+ local fileName
+ fileName = testFile + i.toString()
+ // ファイル削除(手動で行う必要があります)
+ i = i + 1
+ }
+
+ me.console.log("\n✅ ベンチマーク完了!")
+ return "done"
+ }
+}
\ No newline at end of file
diff --git a/local_tests/benchmark_filebox_simple.nyash b/local_tests/benchmark_filebox_simple.nyash
new file mode 100644
index 00000000..639b41b3
--- /dev/null
+++ b/local_tests/benchmark_filebox_simple.nyash
@@ -0,0 +1,47 @@
+// FileBox シンプルパフォーマンステスト
+// 動的版と静的版の速度比較用
+
+static box Main {
+ init { console }
+
+ main() {
+ me.console = new ConsoleBox()
+ me.console.log("📊 FileBox パフォーマンステスト")
+
+ // テスト設定
+ local iterations
+ iterations = 100 // 少なめにして手動計測
+
+ me.console.log("🔧 Test: FileBox作成・読み書き x " + iterations.toString())
+ me.console.log("⏱️ 開始時刻を記録してください...")
+
+ // FileBox作成・読み書きテスト
+ local i
+ i = 0
+ loop(i < iterations) {
+ local file
+ file = new FileBox("perf_test_" + i.toString() + ".txt")
+
+ // 書き込み
+ file.write("Performance test data " + i.toString())
+
+ // 読み込み
+ local content
+ content = file.read()
+
+ // 存在確認
+ local exists
+ exists = file.exists()
+
+ i = i + 1
+ }
+
+ me.console.log("⏱️ 終了!経過時間を確認してください")
+ me.console.log("✅ " + iterations.toString() + " 個のファイル操作完了")
+
+ // クリーンアップ用コメント
+ me.console.log("\n🧹 クリーンアップ: rm -f perf_test_*.txt")
+
+ return "done"
+ }
+}
\ No newline at end of file
diff --git a/local_tests/measure_performance.sh b/local_tests/measure_performance.sh
new file mode 100644
index 00000000..c5f5a730
--- /dev/null
+++ b/local_tests/measure_performance.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# パフォーマンス測定スクリプト
+
+echo "🔬 FileBox パフォーマンス測定"
+echo "================================"
+
+# クリーンアップ
+rm -f perf_test_*.txt benchmark_test*.txt
+
+# 動的版の測定
+echo -e "\n📊 動的版 (dynamic-file feature 有効)"
+echo "開始時刻: $(date +%H:%M:%S.%N)"
+START=$(date +%s%N)
+
+RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash 2>/dev/null
+
+END=$(date +%s%N)
+ELAPSED=$((($END - $START) / 1000000))
+echo "終了時刻: $(date +%H:%M:%S.%N)"
+echo "⏱️ 実行時間: ${ELAPSED}ms"
+
+# クリーンアップ
+rm -f perf_test_*.txt
+
+# 静的版のビルド
+echo -e "\n🔧 静的版をビルド中..."
+cargo build --release --no-default-features 2>/dev/null
+
+# 静的版の測定
+echo -e "\n📊 静的版 (dynamic-file feature 無効)"
+echo "開始時刻: $(date +%H:%M:%S.%N)"
+START=$(date +%s%N)
+
+RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash 2>/dev/null
+
+END=$(date +%s%N)
+ELAPSED=$((($END - $START) / 1000000))
+echo "終了時刻: $(date +%H:%M:%S.%N)"
+echo "⏱️ 実行時間: ${ELAPSED}ms"
+
+# クリーンアップ
+rm -f perf_test_*.txt
+
+echo -e "\n✅ 測定完了!"
\ No newline at end of file
diff --git a/local_tests/perf_comparison.sh b/local_tests/perf_comparison.sh
new file mode 100644
index 00000000..88ae8b21
--- /dev/null
+++ b/local_tests/perf_comparison.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# FileBox パフォーマンス比較
+
+echo "🔬 FileBox 静的版 vs 動的版 パフォーマンス比較"
+echo "============================================="
+echo "テスト内容: 100個のファイル作成・書き込み・読み込み・存在確認"
+echo ""
+
+# クリーンアップ
+rm -f perf_test_*.txt
+
+# 動的版(現在)
+echo "1️⃣ 動的版 (dynamic-file feature 有効)"
+echo -n " 実行時間: "
+{ time RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash > /dev/null 2>&1; } 2>&1 | grep real | awk '{print $2}'
+rm -f perf_test_*.txt
+
+# 静的版ビルド
+echo ""
+echo " 静的版をビルド中..."
+cargo build --release --no-default-features -j32 > /dev/null 2>&1
+
+# 静的版
+echo ""
+echo "2️⃣ 静的版 (FileBox組み込み)"
+echo -n " 実行時間: "
+{ time RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash > /dev/null 2>&1; } 2>&1 | grep real | awk '{print $2}'
+rm -f perf_test_*.txt
+
+# 複数回測定
+echo ""
+echo "📊 5回測定の平均:"
+echo ""
+echo "動的版:"
+for i in {1..5}; do
+ echo -n " Run $i: "
+ { time RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash > /dev/null 2>&1; } 2>&1 | grep real | awk '{print $2}'
+ rm -f perf_test_*.txt
+done
+
+# 静的版に切り替え
+cargo build --release --no-default-features -j32 > /dev/null 2>&1
+
+echo ""
+echo "静的版:"
+for i in {1..5}; do
+ echo -n " Run $i: "
+ { time RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash > /dev/null 2>&1; } 2>&1 | grep real | awk '{print $2}'
+ rm -f perf_test_*.txt
+done
+
+# 動的版に戻す
+echo ""
+echo "元の動的版に戻しています..."
+cargo build --release -j32 > /dev/null 2>&1
+
+echo ""
+echo "✅ 測定完了!"
\ No newline at end of file
diff --git a/local_tests/simple_perf_test.sh b/local_tests/simple_perf_test.sh
new file mode 100644
index 00000000..86b054bc
--- /dev/null
+++ b/local_tests/simple_perf_test.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# シンプルなパフォーマンス測定
+
+echo "🔬 FileBox パフォーマンス測定(100回のファイル操作)"
+echo "=================================================="
+
+# クリーンアップ
+rm -f perf_test_*.txt
+
+# 動的版
+echo -e "\n📊 動的版 (現在のビルド)"
+echo "計測開始..."
+time RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash > /dev/null 2>&1
+rm -f perf_test_*.txt
+
+# 静的版ビルド
+echo -e "\n🔧 静的版をビルド中..."
+cargo build --release --no-default-features -j32 > /dev/null 2>&1
+
+# 静的版
+echo -e "\n📊 静的版 (dynamic-file無効)"
+echo "計測開始..."
+time RUST_LOG=error ./target/release/nyash local_tests/benchmark_filebox_simple.nyash > /dev/null 2>&1
+rm -f perf_test_*.txt
+
+# 動的版に戻す
+echo -e "\n🔧 動的版に戻します..."
+cargo build --release -j32 > /dev/null 2>&1
+
+echo -e "\n✅ 測定完了!"
\ No newline at end of file
diff --git a/local_tests/test_debug_print.nyash b/local_tests/test_debug_print.nyash
new file mode 100644
index 00000000..a29ff71e
--- /dev/null
+++ b/local_tests/test_debug_print.nyash
@@ -0,0 +1 @@
+print("Hello MIR\!")
diff --git a/local_tests/test_debug_print.wat b/local_tests/test_debug_print.wat
new file mode 100644
index 00000000..a6e5836c
--- /dev/null
+++ b/local_tests/test_debug_print.wat
@@ -0,0 +1,233 @@
+(module
+ (import "env" "print" (func $print (param i32) ))
+ (import "env" "print_str" (func $print_str (param i32 i32) ))
+ (import "env" "console_log" (func $console_log (param i32 i32) ))
+ (import "env" "canvas_fillRect" (func $canvas_fillRect (param i32 i32 i32 i32 i32 i32 i32 i32) ))
+ (import "env" "canvas_fillText" (func $canvas_fillText (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) ))
+ (import "env" "box_to_string" (func $box_to_string (param i32) (result i32)))
+ (import "env" "box_print" (func $box_print (param i32) ))
+ (import "env" "box_equals" (func $box_equals (param i32 i32) (result i32)))
+ (import "env" "box_clone" (func $box_clone (param i32) (result i32)))
+ (memory (export "memory") 1)
+ (data (i32.const 4096) "\48\65\6c\6c\6f\20\4d\49\52\5c\21")
+ (data (i32.const 4107) "\40\70\72\69\6e\74")
+ (global $heap_ptr (mut i32) (i32.const 2048))
+ (func $malloc (param $size i32) (result i32)
+ (local $ptr i32)
+ (local $aligned_size i32)
+
+ ;; Align size to 4-byte boundary
+ local.get $size
+ i32.const 3
+ i32.add
+ i32.const -4
+ i32.and
+ local.set $aligned_size
+
+ ;; Get current heap pointer
+ global.get $heap_ptr
+ local.set $ptr
+
+ ;; Advance heap pointer by aligned size
+ global.get $heap_ptr
+ local.get $aligned_size
+ i32.add
+ global.set $heap_ptr
+
+ ;; Return allocated pointer
+ local.get $ptr
+ )
+ (func $box_alloc (param $type_id i32) (param $field_count i32) (result i32)
+ (local $ptr i32)
+ (local $total_size i32)
+
+ ;; Calculate total size: header (12) + fields (field_count * 4)
+ local.get $field_count
+ i32.const 4
+ i32.mul
+ i32.const 12
+ i32.add
+ local.set $total_size
+
+ ;; Allocate memory
+ local.get $total_size
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ local.get $type_id
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ local.get $field_count
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_stringbox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 20
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4097
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 2
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_integerbox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 16
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4098
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_boolbox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 16
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4099
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_databox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 16
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4101
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $main (local $0 i32) (local $1 i32) (local $2 i32)
+ nop
+ call $alloc_stringbox
+ local.set $0
+ local.get $0
+ i32.const 12
+ i32.add
+ i32.const 4096
+ i32.store
+ local.get $0
+ i32.const 16
+ i32.add
+ i32.const 11
+ i32.store
+ local.get $0
+ local.set $1
+ call $alloc_stringbox
+ local.set $2
+ local.get $2
+ i32.const 12
+ i32.add
+ i32.const 4107
+ i32.store
+ local.get $2
+ i32.const 16
+ i32.add
+ i32.const 6
+ i32.store
+ local.get $1
+ call $print
+ local.get $1
+ return
+ )
+ (export "main" (func $main))
+)
diff --git a/local_tests/test_math_dynamic.nyash b/local_tests/test_math_dynamic.nyash
new file mode 100644
index 00000000..6e7517e9
--- /dev/null
+++ b/local_tests/test_math_dynamic.nyash
@@ -0,0 +1,60 @@
+// Math系Box動的ライブラリテスト
+
+static box Main {
+ init { console }
+
+ main() {
+ me.console = new ConsoleBox()
+ me.console.log("🧮 Math系Box動的ライブラリテスト")
+
+ // MathBoxテスト
+ me.console.log("\n📐 MathBox テスト:")
+ local math = new MathBox()
+ me.console.log("math.toString(): " + math.toString())
+ me.console.log("math.sqrt(16): " + math.sqrt(16).toString())
+ me.console.log("math.pow(2, 10): " + math.pow(2, 10).toString())
+ me.console.log("math.sin(1.57): " + math.sin(1.57).toString())
+ me.console.log("math.cos(0): " + math.cos(0).toString())
+ me.console.log("math.abs(-42): " + math.abs(-42).toString())
+ me.console.log("math.floor(3.7): " + math.floor(3.7).toString())
+ me.console.log("math.ceil(3.2): " + math.ceil(3.2).toString())
+ me.console.log("math.round(3.5): " + math.round(3.5).toString())
+ me.console.log("math.min(10, 5): " + math.min(10, 5).toString())
+ me.console.log("math.max(10, 5): " + math.max(10, 5).toString())
+
+ // RandomBoxテスト
+ me.console.log("\n🎲 RandomBox テスト:")
+ local random = new RandomBox()
+ me.console.log("random.toString(): " + random.toString())
+ me.console.log("random.next(): " + random.next().toString())
+ me.console.log("random.range(1, 10): " + random.range(1, 10).toString())
+ me.console.log("random.int(1, 100): " + random.int(1, 100).toString())
+
+ // TimeBoxテスト
+ me.console.log("\n⏰ TimeBox テスト:")
+ local time = new TimeBox()
+ me.console.log("time.toString(): " + time.toString())
+ local now = time.now()
+ me.console.log("time.now(): " + now.toString())
+
+ // DateTimeBoxテスト
+ me.console.log("\n📅 DateTimeBox テスト:")
+ local dt = new DateTimeBox()
+ me.console.log("dt.toString(): " + dt.toString())
+ me.console.log("dt.year(): " + dt.year().toString())
+ me.console.log("dt.month(): " + dt.month().toString())
+ me.console.log("dt.day(): " + dt.day().toString())
+ me.console.log("dt.hour(): " + dt.hour().toString())
+ me.console.log("dt.minute(): " + dt.minute().toString())
+ me.console.log("dt.second(): " + dt.second().toString())
+ me.console.log("dt.timestamp(): " + dt.timestamp().toString())
+
+ // 文字列からDateTimeBox作成
+ local dt2 = new DateTimeBox("2025-08-17T12:34:56Z")
+ me.console.log("\nDateTimeBox from string: " + dt2.toString())
+
+ me.console.log("\n✅ 全テスト完了!")
+
+ return "done"
+ }
+}
\ No newline at end of file
diff --git a/local_tests/test_math_minimal.nyash b/local_tests/test_math_minimal.nyash
new file mode 100644
index 00000000..b4a3e2dc
--- /dev/null
+++ b/local_tests/test_math_minimal.nyash
@@ -0,0 +1,19 @@
+// Math系Box最小テスト
+
+static box Main {
+ init { console }
+
+ main() {
+ me.console = new ConsoleBox()
+ me.console.log("🧮 MathBox最小テスト")
+
+ local math = new MathBox()
+ me.console.log("MathBox created: " + math.type_name())
+
+ // 基本的な数学演算テスト
+ local result = math.sqrt(16)
+ me.console.log("sqrt(16) = " + result.toString())
+
+ return "done"
+ }
+}
\ No newline at end of file
diff --git a/local_tests/test_math_simple.nyash b/local_tests/test_math_simple.nyash
new file mode 100644
index 00000000..7c6604f0
--- /dev/null
+++ b/local_tests/test_math_simple.nyash
@@ -0,0 +1,15 @@
+// 最もシンプルなMathBoxテスト
+
+static box Main {
+ init { console }
+
+ main() {
+ me.console = new ConsoleBox()
+ me.console.log("Creating MathBox...")
+
+ local math = new MathBox()
+ me.console.log("MathBox created!")
+
+ return "done"
+ }
+}
\ No newline at end of file
diff --git a/local_tests/test_mir_26_instructions.nyash b/local_tests/test_mir_26_instructions.nyash
new file mode 100644
index 00000000..21549282
--- /dev/null
+++ b/local_tests/test_mir_26_instructions.nyash
@@ -0,0 +1,30 @@
+# MIR 26命令セット完全動作確認テスト
+# Phase 4-3: 新しい26命令セットの基本テスト
+
+# 基本演算テスト
+result = 10 + 5
+print("Basic arithmetic: " + result)
+
+# 比較演算テスト
+comparison = (result > 12)
+print("Comparison result: " + comparison)
+
+# 条件分岐テスト
+if comparison {
+ print("Conditional branch works")
+}
+
+# ループテスト
+counter = 0
+loop(counter < 3) {
+ print("Loop iteration: " + counter)
+ counter = counter + 1
+}
+
+# Box作成・アクセステスト(基本的なEverything is Box)
+local testBox = new MapBox()
+testBox.set("key1", "value1")
+local value = testBox.get("key1")
+print("Box operation result: " + value)
+
+print("MIR 26 instruction test completed successfully!")
\ No newline at end of file
diff --git a/local_tests/test_mir_simple.nyash b/local_tests/test_mir_simple.nyash
index ed90bee5..a29ff71e 100644
--- a/local_tests/test_mir_simple.nyash
+++ b/local_tests/test_mir_simple.nyash
@@ -1,9 +1 @@
-// Simple MIR test
-static box Main {
- main() {
- local result
- result = 42 + 8
- print(result)
- return result
- }
-}
\ No newline at end of file
+print("Hello MIR\!")
diff --git a/local_tests/test_mir_simple.wat b/local_tests/test_mir_simple.wat
new file mode 100644
index 00000000..5f5b7e79
--- /dev/null
+++ b/local_tests/test_mir_simple.wat
@@ -0,0 +1,233 @@
+(module
+ (import "env" "print" (func $print (param i32) ))
+ (import "env" "print_str" (func $print_str (param i32 i32) ))
+ (import "env" "console_log" (func $console_log (param i32 i32) ))
+ (import "env" "canvas_fillRect" (func $canvas_fillRect (param i32 i32 i32 i32 i32 i32 i32 i32) ))
+ (import "env" "canvas_fillText" (func $canvas_fillText (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) ))
+ (import "env" "box_to_string" (func $box_to_string (param i32) (result i32)))
+ (import "env" "box_print" (func $box_print (param i32) ))
+ (import "env" "box_equals" (func $box_equals (param i32 i32) (result i32)))
+ (import "env" "box_clone" (func $box_clone (param i32) (result i32)))
+ (memory (export "memory") 1)
+ (data (i32.const 4107) "\40\70\72\69\6e\74")
+ (data (i32.const 4096) "\48\65\6c\6c\6f\20\4d\49\52\5c\21")
+ (global $heap_ptr (mut i32) (i32.const 2048))
+ (func $malloc (param $size i32) (result i32)
+ (local $ptr i32)
+ (local $aligned_size i32)
+
+ ;; Align size to 4-byte boundary
+ local.get $size
+ i32.const 3
+ i32.add
+ i32.const -4
+ i32.and
+ local.set $aligned_size
+
+ ;; Get current heap pointer
+ global.get $heap_ptr
+ local.set $ptr
+
+ ;; Advance heap pointer by aligned size
+ global.get $heap_ptr
+ local.get $aligned_size
+ i32.add
+ global.set $heap_ptr
+
+ ;; Return allocated pointer
+ local.get $ptr
+ )
+ (func $box_alloc (param $type_id i32) (param $field_count i32) (result i32)
+ (local $ptr i32)
+ (local $total_size i32)
+
+ ;; Calculate total size: header (12) + fields (field_count * 4)
+ local.get $field_count
+ i32.const 4
+ i32.mul
+ i32.const 12
+ i32.add
+ local.set $total_size
+
+ ;; Allocate memory
+ local.get $total_size
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ local.get $type_id
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ local.get $field_count
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_stringbox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 20
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4097
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 2
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_integerbox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 16
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4098
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_boolbox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 16
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4099
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $alloc_databox (result i32)
+ (local $ptr i32)
+
+ ;; Allocate memory for box
+ i32.const 16
+ call $malloc
+ local.set $ptr
+
+ ;; Initialize type_id
+ local.get $ptr
+ i32.const 4101
+ i32.store
+
+ ;; Initialize ref_count to 1
+ local.get $ptr
+ i32.const 4
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Initialize field_count
+ local.get $ptr
+ i32.const 8
+ i32.add
+ i32.const 1
+ i32.store
+
+ ;; Return box pointer
+ local.get $ptr
+ )
+ (func $main (local $0 i32) (local $1 i32) (local $2 i32)
+ nop
+ call $alloc_stringbox
+ local.set $0
+ local.get $0
+ i32.const 12
+ i32.add
+ i32.const 4096
+ i32.store
+ local.get $0
+ i32.const 16
+ i32.add
+ i32.const 11
+ i32.store
+ local.get $0
+ local.set $1
+ call $alloc_stringbox
+ local.set $2
+ local.get $2
+ i32.const 12
+ i32.add
+ i32.const 4107
+ i32.store
+ local.get $2
+ i32.const 16
+ i32.add
+ i32.const 6
+ i32.store
+ local.get $1
+ call $print
+ local.get $1
+ return
+ )
+ (export "main" (func $main))
+)
diff --git a/local_tests/test_phase2_conversions.nyash b/local_tests/test_phase2_conversions.nyash
new file mode 100644
index 00000000..a9fc9189
--- /dev/null
+++ b/local_tests/test_phase2_conversions.nyash
@@ -0,0 +1,23 @@
+// Phase 2 MIR conversion test
+static box Main {
+ init { console, result }
+
+ main() {
+ me.console = new ConsoleBox()
+
+ // Test print statement (should use @print intrinsic)
+ print("Testing Phase 2 conversions!")
+
+ // Test unary operations (should use @unary_* intrinsics)
+ local x = 42
+ local negated = -x // @unary_neg
+ local flag = true
+ local inverted = not flag // @unary_not
+
+ me.console.log("Negated: " + negated.toString())
+ me.console.log("Inverted: " + inverted.toString())
+
+ me.result = "Phase 2 test completed"
+ return me.result
+ }
+}
\ No newline at end of file
diff --git a/local_tests/test_string_assignment.nyash b/local_tests/test_string_assignment.nyash
new file mode 100644
index 00000000..ae2da9a8
--- /dev/null
+++ b/local_tests/test_string_assignment.nyash
@@ -0,0 +1 @@
+local x = "Hello MIR\!"
diff --git a/local_tests/test_wasm_execution.sh b/local_tests/test_wasm_execution.sh
new file mode 100644
index 00000000..0a7ade96
--- /dev/null
+++ b/local_tests/test_wasm_execution.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# WASM execution test script
+
+echo "🎯 Testing WASM compilation and execution with host functions"
+
+# First compile to WAT
+echo "📝 Compiling test_mir_simple.nyash to WASM..."
+../target/release/nyash --compile-wasm test_mir_simple.nyash
+
+# Check if WAT was generated
+if [ -f "test_mir_simple.wat" ]; then
+ echo "✅ WAT file generated successfully"
+ echo "📄 WAT content preview:"
+ head -20 test_mir_simple.wat
+ echo "..."
+
+ # Now we need a custom WASM runner that provides host functions
+ echo ""
+ echo "🚀 To execute WASM with host functions, we need to build a custom runner"
+ echo " that provides the required imports (env::print, etc.)"
+else
+ echo "❌ WAT file generation failed"
+ exit 1
+fi
\ No newline at end of file
diff --git a/plugins/nyash-math/Cargo.toml b/plugins/nyash-math/Cargo.toml
new file mode 100644
index 00000000..c7610775
--- /dev/null
+++ b/plugins/nyash-math/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "nyash-math"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+chrono = "0.4"
+rand = "0.8"
+libc = "0.2"
+
+[features]
+default = []
\ No newline at end of file
diff --git a/plugins/nyash-math/src/lib.rs b/plugins/nyash-math/src/lib.rs
new file mode 100644
index 00000000..b1c7a350
--- /dev/null
+++ b/plugins/nyash-math/src/lib.rs
@@ -0,0 +1,328 @@
+use std::ffi::{c_char, c_void, CStr, CString};
+use std::ptr;
+use chrono::{DateTime, Utc, Datelike, Timelike};
+use rand::Rng;
+
+// MathBox構造体
+pub struct MathBox {
+ // MathBoxは状態を持たない
+}
+
+// RandomBox構造体
+pub struct RandomBox {
+ rng: rand::rngs::ThreadRng,
+}
+
+// TimeBox構造体
+pub struct TimeBox {
+ // TimeBoxは状態を持たない
+}
+
+// DateTimeBox構造体
+pub struct DateTimeBox {
+ datetime: DateTime,
+}
+
+// ================== MathBox C API ==================
+
+#[no_mangle]
+pub extern "C" fn nyash_math_create() -> *mut c_void {
+ let math_box = Box::new(MathBox {});
+ Box::into_raw(math_box) as *mut c_void
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_sqrt(value: f64) -> f64 {
+ value.sqrt()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_pow(base: f64, exponent: f64) -> f64 {
+ base.powf(exponent)
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_sin(value: f64) -> f64 {
+ value.sin()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_cos(value: f64) -> f64 {
+ value.cos()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_tan(value: f64) -> f64 {
+ value.tan()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_abs(value: f64) -> f64 {
+ value.abs()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_floor(value: f64) -> f64 {
+ value.floor()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_ceil(value: f64) -> f64 {
+ value.ceil()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_round(value: f64) -> f64 {
+ value.round()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_log(value: f64) -> f64 {
+ value.ln()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_log10(value: f64) -> f64 {
+ value.log10()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_exp(value: f64) -> f64 {
+ value.exp()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_min(a: f64, b: f64) -> f64 {
+ a.min(b)
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_max(a: f64, b: f64) -> f64 {
+ a.max(b)
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_math_free(ptr: *mut c_void) {
+ if ptr.is_null() {
+ return;
+ }
+ unsafe {
+ let _ = Box::from_raw(ptr as *mut MathBox);
+ }
+}
+
+// ================== RandomBox C API ==================
+
+#[no_mangle]
+pub extern "C" fn nyash_random_create() -> *mut c_void {
+ let random_box = Box::new(RandomBox {
+ rng: rand::thread_rng(),
+ });
+ Box::into_raw(random_box) as *mut c_void
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_random_next(ptr: *mut c_void) -> f64 {
+ if ptr.is_null() {
+ return 0.0;
+ }
+ unsafe {
+ let random_box = &mut *(ptr as *mut RandomBox);
+ random_box.rng.gen()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_random_range(ptr: *mut c_void, min: f64, max: f64) -> f64 {
+ if ptr.is_null() {
+ return min;
+ }
+ unsafe {
+ let random_box = &mut *(ptr as *mut RandomBox);
+ random_box.rng.gen_range(min..=max)
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_random_int(ptr: *mut c_void, min: i64, max: i64) -> i64 {
+ if ptr.is_null() {
+ return min;
+ }
+ unsafe {
+ let random_box = &mut *(ptr as *mut RandomBox);
+ random_box.rng.gen_range(min..=max)
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_random_free(ptr: *mut c_void) {
+ if ptr.is_null() {
+ return;
+ }
+ unsafe {
+ let _ = Box::from_raw(ptr as *mut RandomBox);
+ }
+}
+
+// ================== TimeBox C API ==================
+
+#[no_mangle]
+pub extern "C" fn nyash_time_create() -> *mut c_void {
+ let time_box = Box::new(TimeBox {});
+ Box::into_raw(time_box) as *mut c_void
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_time_now() -> *mut c_void {
+ let datetime = Box::new(DateTimeBox {
+ datetime: Utc::now(),
+ });
+ Box::into_raw(datetime) as *mut c_void
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_time_parse(time_str: *const c_char) -> *mut c_void {
+ if time_str.is_null() {
+ return ptr::null_mut();
+ }
+
+ unsafe {
+ let c_str = CStr::from_ptr(time_str);
+ if let Ok(rust_str) = c_str.to_str() {
+ // ISO 8601形式をパース
+ if let Ok(datetime) = rust_str.parse::>() {
+ let datetime_box = Box::new(DateTimeBox { datetime });
+ return Box::into_raw(datetime_box) as *mut c_void;
+ }
+ }
+ }
+
+ ptr::null_mut()
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_time_free(ptr: *mut c_void) {
+ if ptr.is_null() {
+ return;
+ }
+ unsafe {
+ let _ = Box::from_raw(ptr as *mut TimeBox);
+ }
+}
+
+// ================== DateTimeBox C API ==================
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_to_string(ptr: *mut c_void) -> *mut c_char {
+ if ptr.is_null() {
+ return ptr::null_mut();
+ }
+
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ let datetime_str = datetime_box.datetime.to_rfc3339();
+
+ if let Ok(c_string) = CString::new(datetime_str) {
+ c_string.into_raw()
+ } else {
+ ptr::null_mut()
+ }
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_year(ptr: *mut c_void) -> i32 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.year()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_month(ptr: *mut c_void) -> u32 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.month()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_day(ptr: *mut c_void) -> u32 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.day()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_hour(ptr: *mut c_void) -> u32 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.hour()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_minute(ptr: *mut c_void) -> u32 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.minute()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_second(ptr: *mut c_void) -> u32 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.second()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_timestamp(ptr: *mut c_void) -> i64 {
+ if ptr.is_null() {
+ return 0;
+ }
+ unsafe {
+ let datetime_box = &*(ptr as *mut DateTimeBox);
+ datetime_box.datetime.timestamp()
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_datetime_free(ptr: *mut c_void) {
+ if ptr.is_null() {
+ return;
+ }
+ unsafe {
+ let _ = Box::from_raw(ptr as *mut DateTimeBox);
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn nyash_string_free(ptr: *mut c_char) {
+ if ptr.is_null() {
+ return;
+ }
+ unsafe {
+ let _ = CString::from_raw(ptr);
+ }
+}
\ No newline at end of file
diff --git a/src/backend/aot/compiler.rs b/src/backend/aot/compiler.rs
index 90352bca..93181efd 100644
--- a/src/backend/aot/compiler.rs
+++ b/src/backend/aot/compiler.rs
@@ -53,6 +53,8 @@ impl AotCompiler {
WasmError::UnsupportedInstruction(msg) => AotError::CompilationError(format!("Unsupported MIR instruction: {}", msg)),
WasmError::WasmValidationError(msg) => AotError::CompilationError(format!("WASM validation failed: {}", msg)),
WasmError::IOError(msg) => AotError::IOError(msg),
+ WasmError::RuntimeError(msg) => AotError::RuntimeError(msg),
+ WasmError::CompilationError(msg) => AotError::CompilationError(msg),
})?;
self.stats.wasm_size = wasm_bytes.len();
diff --git a/src/backend/vm.rs b/src/backend/vm.rs
index 3b589607..e596cdfd 100644
--- a/src/backend/vm.rs
+++ b/src/backend/vm.rs
@@ -435,10 +435,31 @@ impl VM {
// Phase 6: Box reference operations
MirInstruction::RefNew { dst, box_val } => {
- // For now, a reference is just the same as the box value
- // In a real implementation, this would create a proper reference
+ // Get the box type/value from the previous Const instruction
let box_value = self.get_value(*box_val)?;
- self.values.insert(*dst, box_value);
+
+ // If this is a Box type name (like "StringBox", "IntegerBox"), create an appropriate default value
+ // In the context of Everything is Box, this should create the actual Box instance
+ let ref_value = match &box_value {
+ VMValue::String(type_name) => {
+ match type_name.as_str() {
+ "StringBox" => {
+ // For StringBox, we need the actual string content from previous context
+ // For now, create an empty string - this should be improved to use the actual value
+ VMValue::String(String::new())
+ },
+ "IntegerBox" => VMValue::Integer(0),
+ "BoolBox" => VMValue::Bool(false),
+ _ => {
+ // If it's a regular string (not a type name), use it as-is
+ VMValue::String(type_name.clone())
+ }
+ }
+ },
+ _ => box_value, // For non-string values, use as-is
+ };
+
+ self.values.insert(*dst, ref_value);
Ok(ControlFlow::Continue)
},
diff --git a/src/backend/wasm/codegen.rs b/src/backend/wasm/codegen.rs
index 960e00d3..8514b39c 100644
--- a/src/backend/wasm/codegen.rs
+++ b/src/backend/wasm/codegen.rs
@@ -492,6 +492,11 @@ impl WasmCodegen {
Ok(vec!["nop".to_string()])
},
+ // Phase 4: Call instruction for intrinsic functions
+ MirInstruction::Call { dst, func, args, effects: _ } => {
+ self.generate_call_instruction(dst.as_ref(), *func, args)
+ },
+
// Unsupported instructions
_ => Err(WasmError::UnsupportedInstruction(
format!("Instruction not yet supported: {:?}", instruction)
@@ -770,6 +775,36 @@ impl WasmCodegen {
Ok(instructions)
}
+
+ /// Generate Call instruction for intrinsic functions (Phase 4)
+ fn generate_call_instruction(&mut self, dst: Option<&ValueId>, func: ValueId, args: &[ValueId]) -> Result, WasmError> {
+ // Get the function name from the func ValueId
+ // In MIR, intrinsic function names are stored as string constants
+ let mut instructions = Vec::new();
+
+ // For intrinsic functions, we handle them based on their name
+ // The func ValueId should contain a string constant like "@print"
+
+ // For now, assume all calls are @print intrinsic
+ // TODO: Implement proper function name resolution from ValueId
+
+ // Load all arguments onto stack in order
+ for arg in args {
+ instructions.push(format!("local.get ${}", self.get_local_index(*arg)?));
+ }
+
+ // Call the print function (assuming it's imported as $print)
+ instructions.push("call $print".to_string());
+
+ // Store result if destination is provided
+ if let Some(dst) = dst {
+ // Intrinsic functions typically return void, but we provide a dummy value
+ instructions.push("i32.const 0".to_string()); // Void result
+ instructions.push(format!("local.set ${}", self.get_local_index(*dst)?));
+ }
+
+ Ok(instructions)
+ }
}
#[cfg(test)]
diff --git a/src/backend/wasm/executor.rs b/src/backend/wasm/executor.rs
new file mode 100644
index 00000000..950c5d0c
--- /dev/null
+++ b/src/backend/wasm/executor.rs
@@ -0,0 +1,114 @@
+/*!
+ * WASM Executor - Execute compiled WASM modules with host functions
+ *
+ * Phase 4-3c: Provides wasmtime-based execution for Nyash WASM modules
+ */
+
+use wasmtime::*;
+use std::path::Path;
+use super::{WasmError, host::{HostState, create_host_functions}};
+
+/// WASM module executor
+pub struct WasmExecutor {
+ engine: Engine,
+}
+
+impl WasmExecutor {
+ /// Create new WASM executor
+ pub fn new() -> Result {
+ let engine = Engine::default();
+ Ok(Self { engine })
+ }
+
+ /// Execute a WAT file
+ pub fn execute_wat_file>(&self, wat_path: P) -> Result {
+ // Read WAT file
+ let wat_content = std::fs::read_to_string(&wat_path)
+ .map_err(|e| WasmError::IOError(e.to_string()))?;
+
+ self.execute_wat(&wat_content)
+ }
+
+ /// Execute WAT content
+ pub fn execute_wat(&self, wat_content: &str) -> Result {
+ // Create store with host state
+ let mut store = Store::new(&self.engine, HostState::new());
+
+ // Compile WAT to module
+ let module = Module::new(&self.engine, wat_content)
+ .map_err(|e| WasmError::CompilationError(format!("Failed to compile WAT: {}", e)))?;
+
+ // Create host functions
+ let host_functions = create_host_functions(&mut store)
+ .map_err(|e| WasmError::RuntimeError(format!("Failed to create host functions: {}", e)))?;
+
+ // Create imports list
+ let mut imports = Vec::new();
+ for (module_name, func_name, func) in host_functions {
+ imports.push(func);
+ }
+
+ // Instantiate module with imports
+ let instance = Instance::new(&mut store, &module, &imports)
+ .map_err(|e| WasmError::RuntimeError(format!("Failed to instantiate module: {}", e)))?;
+
+ // Get main function
+ let main_func = instance
+ .get_func(&mut store, "main")
+ .ok_or_else(|| WasmError::RuntimeError("No main function found".to_string()))?;
+
+ // Call main function
+ let results = main_func
+ .call(&mut store, &[], &mut [])
+ .map_err(|e| WasmError::RuntimeError(format!("Failed to execute main: {}", e)))?;
+
+ // Return success message
+ Ok("WASM execution completed successfully".to_string())
+ }
+
+ /// Execute a WASM binary file
+ pub fn execute_wasm_file>(&self, wasm_path: P) -> Result {
+ // Read WASM file
+ let wasm_bytes = std::fs::read(&wasm_path)
+ .map_err(|e| WasmError::IOError(e.to_string()))?;
+
+ self.execute_wasm(&wasm_bytes)
+ }
+
+ /// Execute WASM bytes
+ pub fn execute_wasm(&self, wasm_bytes: &[u8]) -> Result {
+ // Create store with host state
+ let mut store = Store::new(&self.engine, HostState::new());
+
+ // Create module from bytes
+ let module = Module::new(&self.engine, wasm_bytes)
+ .map_err(|e| WasmError::CompilationError(format!("Failed to load WASM: {}", e)))?;
+
+ // Create host functions
+ let host_functions = create_host_functions(&mut store)
+ .map_err(|e| WasmError::RuntimeError(format!("Failed to create host functions: {}", e)))?;
+
+ // Create imports list
+ let mut imports = Vec::new();
+ for (module_name, func_name, func) in host_functions {
+ imports.push(func);
+ }
+
+ // Instantiate module with imports
+ let instance = Instance::new(&mut store, &module, &imports)
+ .map_err(|e| WasmError::RuntimeError(format!("Failed to instantiate module: {}", e)))?;
+
+ // Get main function
+ let main_func = instance
+ .get_func(&mut store, "main")
+ .ok_or_else(|| WasmError::RuntimeError("No main function found".to_string()))?;
+
+ // Call main function
+ let results = main_func
+ .call(&mut store, &[], &mut [])
+ .map_err(|e| WasmError::RuntimeError(format!("Failed to execute main: {}", e)))?;
+
+ // Return success message
+ Ok("WASM execution completed successfully".to_string())
+ }
+}
\ No newline at end of file
diff --git a/src/backend/wasm/host.rs b/src/backend/wasm/host.rs
new file mode 100644
index 00000000..c4f8880b
--- /dev/null
+++ b/src/backend/wasm/host.rs
@@ -0,0 +1,201 @@
+/*!
+ * WASM Host Functions - Implementation of host functions for WASM execution
+ *
+ * Phase 4-3c: Provides actual implementations for env::print and other imports
+ * Enables WASM modules to interact with the host environment
+ */
+
+use wasmtime::*;
+use std::sync::{Arc, Mutex};
+
+/// Host state for WASM execution
+pub struct HostState {
+ /// Output buffer for captured prints
+ pub output: Arc>,
+}
+
+impl HostState {
+ pub fn new() -> Self {
+ Self {
+ output: Arc::new(Mutex::new(String::new())),
+ }
+ }
+}
+
+/// Create host functions for WASM imports
+pub fn create_host_functions(store: &mut Store) -> Result, Error> {
+ let mut imports = Vec::new();
+
+ // env::print - print a Box value (expecting a StringBox pointer)
+ let print_func = Func::wrap(&mut *store, |mut caller: Caller<'_, HostState>, box_ptr: i32| {
+ // Try to read StringBox content from WASM memory
+ if let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) {
+ let data = mem.data(&caller);
+ let box_offset = box_ptr as usize;
+
+ // StringBox layout: [type_id:4][ref_count:4][field_count:4][data_ptr:4][length:4]
+ if box_offset + 20 <= data.len() {
+ // Read data pointer (offset 12)
+ let data_ptr = i32::from_le_bytes([
+ data[box_offset + 12],
+ data[box_offset + 13],
+ data[box_offset + 14],
+ data[box_offset + 15],
+ ]);
+
+ // Read length (offset 16)
+ let length = i32::from_le_bytes([
+ data[box_offset + 16],
+ data[box_offset + 17],
+ data[box_offset + 18],
+ data[box_offset + 19],
+ ]);
+
+ // Read actual string content
+ let str_start = data_ptr as usize;
+ let str_end = str_start + length as usize;
+
+ if str_end <= data.len() {
+ if let Ok(s) = std::str::from_utf8(&data[str_start..str_end]) {
+ println!("{}", s);
+ return;
+ }
+ }
+ }
+ }
+
+ // Fallback: print as pointer
+ println!("Box[{}]", box_ptr);
+ });
+ imports.push(("env".to_string(), "print".to_string(), Extern::Func(print_func)));
+
+ // env::print_str - print a string from memory (ptr, len)
+ let print_str_func = Func::wrap(&mut *store, |mut caller: Caller<'_, HostState>, ptr: i32, len: i32| {
+ if let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) {
+ let data = mem.data(&caller);
+ let start = ptr as usize;
+ let end = start + len as usize;
+
+ if end <= data.len() {
+ if let Ok(s) = std::str::from_utf8(&data[start..end]) {
+ println!("{}", s);
+ // Note: Output capture removed for simplicity
+ }
+ }
+ }
+ });
+ imports.push(("env".to_string(), "print_str".to_string(), Extern::Func(print_str_func)));
+
+ // env::console_log - console logging (similar to print_str)
+ let console_log_func = Func::wrap(&mut *store, |mut caller: Caller<'_, HostState>, ptr: i32, len: i32| {
+ if let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) {
+ let data = mem.data(&caller);
+ let start = ptr as usize;
+ let end = start + len as usize;
+
+ if end <= data.len() {
+ if let Ok(s) = std::str::from_utf8(&data[start..end]) {
+ println!("[console.log] {}", s);
+ // Note: Output capture removed for simplicity
+ }
+ }
+ }
+ });
+ imports.push(("env".to_string(), "console_log".to_string(), Extern::Func(console_log_func)));
+
+ // env::canvas_fillRect - stub implementation
+ let canvas_fill_rect = Func::wrap(&mut *store, |_caller: Caller<'_, HostState>, _x: i32, _y: i32, _w: i32, _h: i32, _r: i32, _g: i32, _b: i32, _a: i32| {
+ // Stub - in a real implementation, this would draw to a canvas
+ });
+ imports.push(("env".to_string(), "canvas_fillRect".to_string(), Extern::Func(canvas_fill_rect)));
+
+ // env::canvas_fillText - stub implementation
+ let canvas_fill_text = Func::wrap(&mut *store, |_caller: Caller<'_, HostState>, _ptr: i32, _len: i32, _x: i32, _y: i32, _size: i32, _r: i32, _g: i32, _b: i32, _a: i32, _align: i32| {
+ // Stub - in a real implementation, this would draw text
+ });
+ imports.push(("env".to_string(), "canvas_fillText".to_string(), Extern::Func(canvas_fill_text)));
+
+ // env::box_to_string - convert Box to string representation
+ let box_to_string = Func::wrap(&mut *store, |_caller: Caller<'_, HostState>, box_ptr: i32| -> i32 {
+ // For now, return the same pointer - in a real implementation,
+ // this would convert the Box to its string representation
+ box_ptr
+ });
+ imports.push(("env".to_string(), "box_to_string".to_string(), Extern::Func(box_to_string)));
+
+ // env::box_print - print a Box value
+ let box_print = Func::wrap(&mut *store, |mut caller: Caller<'_, HostState>, box_ptr: i32| {
+ // Read Box type from memory
+ if let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) {
+ let data = mem.data(&caller);
+ let type_id_offset = box_ptr as usize;
+
+ if type_id_offset + 4 <= data.len() {
+ let type_id = i32::from_le_bytes([
+ data[type_id_offset],
+ data[type_id_offset + 1],
+ data[type_id_offset + 2],
+ data[type_id_offset + 3],
+ ]);
+
+ match type_id {
+ 0x1001 => { // StringBox
+ // Read string pointer and length from Box fields
+ let str_ptr_offset = type_id_offset + 12;
+ let str_len_offset = type_id_offset + 16;
+
+ if str_len_offset + 4 <= data.len() {
+ let str_ptr = i32::from_le_bytes([
+ data[str_ptr_offset],
+ data[str_ptr_offset + 1],
+ data[str_ptr_offset + 2],
+ data[str_ptr_offset + 3],
+ ]);
+
+ let str_len = i32::from_le_bytes([
+ data[str_len_offset],
+ data[str_len_offset + 1],
+ data[str_len_offset + 2],
+ data[str_len_offset + 3],
+ ]);
+
+ // Read actual string content
+ let str_start = str_ptr as usize;
+ let str_end = str_start + str_len as usize;
+
+ if str_end <= data.len() {
+ if let Ok(s) = std::str::from_utf8(&data[str_start..str_end]) {
+ println!("{}", s);
+ // Note: Output capture removed for simplicity
+ return;
+ }
+ }
+ }
+ },
+ _ => {
+ println!("Box[type=0x{:x}]", type_id);
+ }
+ }
+ }
+ }
+
+ println!("Box[unknown]");
+ });
+ imports.push(("env".to_string(), "box_print".to_string(), Extern::Func(box_print)));
+
+ // env::box_equals - check Box equality
+ let box_equals = Func::wrap(&mut *store, |_caller: Caller<'_, HostState>, _box1: i32, _box2: i32| -> i32 {
+ // Stub - for now always return 0 (false)
+ 0
+ });
+ imports.push(("env".to_string(), "box_equals".to_string(), Extern::Func(box_equals)));
+
+ // env::box_clone - clone a Box
+ let box_clone = Func::wrap(&mut *store, |_caller: Caller<'_, HostState>, box_ptr: i32| -> i32 {
+ // Stub - for now return the same pointer
+ box_ptr
+ });
+ imports.push(("env".to_string(), "box_clone".to_string(), Extern::Func(box_clone)));
+
+ Ok(imports)
+}
\ No newline at end of file
diff --git a/src/backend/wasm/mod.rs b/src/backend/wasm/mod.rs
index 40f503e0..5ce068ef 100644
--- a/src/backend/wasm/mod.rs
+++ b/src/backend/wasm/mod.rs
@@ -8,10 +8,13 @@
mod codegen;
mod memory;
mod runtime;
+mod host;
+mod executor;
pub use codegen::{WasmCodegen, WasmModule};
pub use memory::{MemoryManager, BoxLayout};
pub use runtime::RuntimeImports;
+pub use executor::WasmExecutor;
use crate::mir::MirModule;
@@ -23,6 +26,8 @@ pub enum WasmError {
UnsupportedInstruction(String),
WasmValidationError(String),
IOError(String),
+ RuntimeError(String),
+ CompilationError(String),
}
impl std::fmt::Display for WasmError {
@@ -33,6 +38,8 @@ impl std::fmt::Display for WasmError {
WasmError::UnsupportedInstruction(msg) => write!(f, "Unsupported instruction: {}", msg),
WasmError::WasmValidationError(msg) => write!(f, "WASM validation error: {}", msg),
WasmError::IOError(msg) => write!(f, "IO error: {}", msg),
+ WasmError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
+ WasmError::CompilationError(msg) => write!(f, "Compilation error: {}", msg),
}
}
}
diff --git a/src/bin/nyash-wasm-run.rs b/src/bin/nyash-wasm-run.rs
new file mode 100644
index 00000000..481d1796
--- /dev/null
+++ b/src/bin/nyash-wasm-run.rs
@@ -0,0 +1,51 @@
+/*!
+ * Nyash WASM Runner - Execute Nyash WASM modules with host functions
+ *
+ * Phase 4-3c: Standalone WASM executor for testing
+ */
+
+use nyash_rust::backend::wasm::{WasmExecutor, WasmError};
+use std::env;
+use std::path::Path;
+
+fn main() -> Result<(), Box> {
+ let args: Vec = env::args().collect();
+
+ if args.len() != 2 {
+ eprintln!("Usage: {} ", args[0]);
+ eprintln!("");
+ eprintln!("Execute a Nyash WASM module with host functions");
+ std::process::exit(1);
+ }
+
+ let wat_file = &args[1];
+
+ if !Path::new(wat_file).exists() {
+ eprintln!("❌ File not found: {}", wat_file);
+ std::process::exit(1);
+ }
+
+ println!("🚀 Nyash WASM Runner - Executing: {} 🚀", wat_file);
+ println!("");
+
+ // Create executor
+ let executor = WasmExecutor::new()?;
+
+ // Execute WAT file
+ match executor.execute_wat_file(wat_file) {
+ Ok(output) => {
+ if !output.is_empty() {
+ println!("📝 Program output:");
+ println!("{}", output);
+ }
+ println!("");
+ println!("✅ Execution completed successfully!");
+ },
+ Err(e) => {
+ eprintln!("❌ Execution error: {}", e);
+ std::process::exit(1);
+ }
+ }
+
+ Ok(())
+}
\ No newline at end of file
diff --git a/src/interpreter/method_dispatch.rs b/src/interpreter/method_dispatch.rs
index a0fb4f10..28765faf 100644
--- a/src/interpreter/method_dispatch.rs
+++ b/src/interpreter/method_dispatch.rs
@@ -8,7 +8,10 @@
use super::*;
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
+#[cfg(not(feature = "dynamic-file"))]
use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
+#[cfg(feature = "dynamic-file")]
+use crate::boxes::{FloatBox, ConsoleBox, SoundBox, DebugBox, MapBox};
use std::sync::Arc;
impl NyashInterpreter {
@@ -238,25 +241,43 @@ impl NyashInterpreter {
}
// MathBox method calls
+ #[cfg(not(feature = "dynamic-file"))]
if let Some(math_box) = obj_value.as_any().downcast_ref::() {
return self.execute_math_method(math_box, method, arguments);
}
+ #[cfg(feature = "dynamic-file")]
+ if let Some(math_proxy) = obj_value.as_any().downcast_ref::() {
+ return self.execute_math_proxy_method(math_proxy, method, arguments);
+ }
+
// NullBox method calls
if let Some(null_box) = obj_value.as_any().downcast_ref::() {
return self.execute_null_method(null_box, method, arguments);
}
// TimeBox method calls
+ #[cfg(not(feature = "dynamic-file"))]
if let Some(time_box) = obj_value.as_any().downcast_ref::() {
return self.execute_time_method(time_box, method, arguments);
}
+ #[cfg(feature = "dynamic-file")]
+ if let Some(time_proxy) = obj_value.as_any().downcast_ref::() {
+ return self.execute_time_proxy_method(time_proxy, method, arguments);
+ }
+
// DateTimeBox method calls
+ #[cfg(not(feature = "dynamic-file"))]
if let Some(datetime_box) = obj_value.as_any().downcast_ref::() {
return self.execute_datetime_method(datetime_box, method, arguments);
}
+ #[cfg(feature = "dynamic-file")]
+ if let Some(datetime_proxy) = obj_value.as_any().downcast_ref::() {
+ return self.execute_datetime_proxy_method(datetime_proxy, method, arguments);
+ }
+
// TimerBox method calls
if let Some(timer_box) = obj_value.as_any().downcast_ref::() {
return self.execute_timer_method(timer_box, method, arguments);
@@ -268,10 +289,16 @@ impl NyashInterpreter {
}
// RandomBox method calls
+ #[cfg(not(feature = "dynamic-file"))]
if let Some(random_box) = obj_value.as_any().downcast_ref::() {
return self.execute_random_method(random_box, method, arguments);
}
+ #[cfg(feature = "dynamic-file")]
+ if let Some(random_proxy) = obj_value.as_any().downcast_ref::() {
+ return self.execute_random_proxy_method(random_proxy, method, arguments);
+ }
+
// SoundBox method calls
if let Some(sound_box) = obj_value.as_any().downcast_ref::() {
return self.execute_sound_method(sound_box, method, arguments);
diff --git a/src/interpreter/methods/math_methods.rs b/src/interpreter/methods/math_methods.rs
new file mode 100644
index 00000000..27d883f4
--- /dev/null
+++ b/src/interpreter/methods/math_methods.rs
@@ -0,0 +1,379 @@
+/*!
+ * Math Methods Module
+ *
+ * MathBox, RandomBox, TimeBox, DateTimeBoxのメソッド実装
+ * Phase 9.75f-2: 動的ライブラリ化対応
+ */
+
+use crate::interpreter::{NyashInterpreter, RuntimeError};
+use crate::ast::ASTNode;
+use crate::box_trait::{NyashBox, IntegerBox, BoolBox, StringBox};
+use crate::boxes::FloatBox;
+
+#[cfg(feature = "dynamic-file")]
+use crate::interpreter::plugin_loader::{MathBoxProxy, RandomBoxProxy, TimeBoxProxy, DateTimeBoxProxy};
+
+#[cfg(not(feature = "dynamic-file"))]
+use crate::boxes::{MathBox, RandomBox, TimeBox, DateTimeBox};
+
+impl NyashInterpreter {
+ /// MathBox用メソッドを実行(動的ライブラリ対応)
+ #[cfg(feature = "dynamic-file")]
+ pub fn execute_math_proxy_method(&mut self,
+ _math_box: &MathBoxProxy,
+ method: &str,
+ arguments: &[ASTNode]) -> Result, RuntimeError> {
+
+ match method {
+ "sqrt" => {
+ if arguments.len() != 1 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("sqrt() expects 1 argument, got {}", arguments.len()),
+ });
+ }
+ let arg = self.execute_expression(&arguments[0])?;
+ let value = self.to_float(&arg)?;
+
+ let cache = crate::interpreter::plugin_loader::PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(sqrt_fn) = plugin.library.get:: f64>>(b"nyash_math_sqrt\0") {
+ let result = sqrt_fn(value);
+ return Ok(Box::new(FloatBox::new(result)));
+ }
+ }
+ }
+
+ Err(RuntimeError::InvalidOperation {
+ message: "Failed to call sqrt".to_string(),
+ })
+ }
+ "pow" => {
+ if arguments.len() != 2 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("pow() expects 2 arguments, got {}", arguments.len()),
+ });
+ }
+ let base_value = self.execute_expression(&arguments[0])?;
+ let exp_value = self.execute_expression(&arguments[1])?;
+ let base = self.to_float(&base_value)?;
+ let exp = self.to_float(&exp_value)?;
+
+ let cache = crate::interpreter::plugin_loader::PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(pow_fn) = plugin.library.get:: f64>>(b"nyash_math_pow\0") {
+ let result = pow_fn(base, exp);
+ return Ok(Box::new(FloatBox::new(result)));
+ }
+ }
+ }
+
+ Err(RuntimeError::InvalidOperation {
+ message: "Failed to call pow".to_string(),
+ })
+ }
+ "sin" => self.call_unary_math_fn("nyash_math_sin", arguments),
+ "cos" => self.call_unary_math_fn("nyash_math_cos", arguments),
+ "tan" => self.call_unary_math_fn("nyash_math_tan", arguments),
+ "abs" => self.call_unary_math_fn("nyash_math_abs", arguments),
+ "floor" => self.call_unary_math_fn("nyash_math_floor", arguments),
+ "ceil" => self.call_unary_math_fn("nyash_math_ceil", arguments),
+ "round" => self.call_unary_math_fn("nyash_math_round", arguments),
+ "log" => self.call_unary_math_fn("nyash_math_log", arguments),
+ "log10" => self.call_unary_math_fn("nyash_math_log10", arguments),
+ "exp" => self.call_unary_math_fn("nyash_math_exp", arguments),
+ "min" => self.call_binary_math_fn("nyash_math_min", arguments),
+ "max" => self.call_binary_math_fn("nyash_math_max", arguments),
+ "toString" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("toString() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ Ok(Box::new(_math_box.to_string_box()))
+ }
+ "type_name" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("type_name() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ Ok(Box::new(StringBox::new(_math_box.type_name())))
+ }
+ _ => Err(RuntimeError::InvalidOperation {
+ message: format!("Unknown MathBox method: {}", method),
+ }),
+ }
+ }
+
+ /// RandomBox用メソッドを実行(動的ライブラリ対応)
+ #[cfg(feature = "dynamic-file")]
+ pub fn execute_random_proxy_method(&mut self,
+ random_box: &RandomBoxProxy,
+ method: &str,
+ arguments: &[ASTNode]) -> Result, RuntimeError> {
+
+ match method {
+ "next" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("next() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ random_box.next()
+ }
+ "range" => {
+ if arguments.len() != 2 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("range() expects 2 arguments, got {}", arguments.len()),
+ });
+ }
+ let min_value = self.execute_expression(&arguments[0])?;
+ let max_value = self.execute_expression(&arguments[1])?;
+ let min = self.to_float(&min_value)?;
+ let max = self.to_float(&max_value)?;
+ random_box.range(min, max)
+ }
+ "int" => {
+ if arguments.len() != 2 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("int() expects 2 arguments, got {}", arguments.len()),
+ });
+ }
+ let min_value = self.execute_expression(&arguments[0])?;
+ let max_value = self.execute_expression(&arguments[1])?;
+ let min = self.to_integer(&min_value)?;
+ let max = self.to_integer(&max_value)?;
+ random_box.int(min, max)
+ }
+ "toString" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("toString() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ Ok(Box::new(random_box.to_string_box()))
+ }
+ "type_name" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("type_name() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ Ok(Box::new(StringBox::new(random_box.type_name())))
+ }
+ _ => Err(RuntimeError::InvalidOperation {
+ message: format!("Unknown RandomBox method: {}", method),
+ }),
+ }
+ }
+
+ /// TimeBox用メソッドを実行(動的ライブラリ対応)
+ #[cfg(feature = "dynamic-file")]
+ pub fn execute_time_proxy_method(&mut self,
+ _time_box: &TimeBoxProxy,
+ method: &str,
+ arguments: &[ASTNode]) -> Result, RuntimeError> {
+
+ match method {
+ "now" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("now() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ crate::interpreter::plugin_loader::PluginLoader::create_datetime_now()
+ }
+ "parse" => {
+ if arguments.len() != 1 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("parse() expects 1 argument, got {}", arguments.len()),
+ });
+ }
+ let time_str = self.execute_expression(&arguments[0])?.to_string_box().value;
+ crate::interpreter::plugin_loader::PluginLoader::create_datetime_from_string(&time_str)
+ }
+ "toString" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("toString() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ Ok(Box::new(_time_box.to_string_box()))
+ }
+ "type_name" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("type_name() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ Ok(Box::new(StringBox::new(_time_box.type_name())))
+ }
+ _ => Err(RuntimeError::InvalidOperation {
+ message: format!("Unknown TimeBox method: {}", method),
+ }),
+ }
+ }
+
+ /// DateTimeBox用メソッドを実行(動的ライブラリ対応)
+ #[cfg(feature = "dynamic-file")]
+ pub fn execute_datetime_proxy_method(&mut self,
+ datetime_box: &DateTimeBoxProxy,
+ method: &str,
+ arguments: &[ASTNode]) -> Result, RuntimeError> {
+
+ // type_name と toString は引数チェックを個別で行う
+ if !arguments.is_empty() && method != "type_name" && method != "toString" {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("{}() expects 0 arguments, got {}", method, arguments.len()),
+ });
+ }
+
+ let cache = crate::interpreter::plugin_loader::PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ match method {
+ "year" => {
+ if let Ok(year_fn) = plugin.library.get:: i32>>(b"nyash_datetime_year\0") {
+ let year = year_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(year as i64)));
+ }
+ }
+ "month" => {
+ if let Ok(month_fn) = plugin.library.get:: u32>>(b"nyash_datetime_month\0") {
+ let month = month_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(month as i64)));
+ }
+ }
+ "day" => {
+ if let Ok(day_fn) = plugin.library.get:: u32>>(b"nyash_datetime_day\0") {
+ let day = day_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(day as i64)));
+ }
+ }
+ "hour" => {
+ if let Ok(hour_fn) = plugin.library.get:: u32>>(b"nyash_datetime_hour\0") {
+ let hour = hour_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(hour as i64)));
+ }
+ }
+ "minute" => {
+ if let Ok(minute_fn) = plugin.library.get:: u32>>(b"nyash_datetime_minute\0") {
+ let minute = minute_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(minute as i64)));
+ }
+ }
+ "second" => {
+ if let Ok(second_fn) = plugin.library.get:: u32>>(b"nyash_datetime_second\0") {
+ let second = second_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(second as i64)));
+ }
+ }
+ "timestamp" => {
+ if let Ok(timestamp_fn) = plugin.library.get:: i64>>(b"nyash_datetime_timestamp\0") {
+ let timestamp = timestamp_fn(datetime_box.handle.ptr);
+ return Ok(Box::new(IntegerBox::new(timestamp)));
+ }
+ }
+ "toString" => {
+ return Ok(Box::new(datetime_box.to_string_box()));
+ }
+ "type_name" => {
+ if !arguments.is_empty() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("type_name() expects 0 arguments, got {}", arguments.len()),
+ });
+ }
+ return Ok(Box::new(StringBox::new(datetime_box.type_name())));
+ }
+ _ => {}
+ }
+ }
+ }
+
+ Err(RuntimeError::InvalidOperation {
+ message: format!("Unknown DateTimeBox method: {}", method),
+ })
+ }
+
+ // ヘルパーメソッド
+ #[cfg(feature = "dynamic-file")]
+ fn call_unary_math_fn(&mut self, fn_name: &str, arguments: &[ASTNode]) -> Result, RuntimeError> {
+ if arguments.len() != 1 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("{}() expects 1 argument, got {}", fn_name.strip_prefix("nyash_math_").unwrap_or(fn_name), arguments.len()),
+ });
+ }
+ let arg_value = self.execute_expression(&arguments[0])?;
+ let value = self.to_float(&arg_value)?;
+
+ let cache = crate::interpreter::plugin_loader::PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let fn_name_bytes = format!("{}\0", fn_name);
+ if let Ok(math_fn) = plugin.library.get:: f64>>(fn_name_bytes.as_bytes()) {
+ let result = math_fn(value);
+ return Ok(Box::new(FloatBox::new(result)));
+ }
+ }
+ }
+
+ Err(RuntimeError::InvalidOperation {
+ message: format!("Failed to call {}", fn_name),
+ })
+ }
+
+ #[cfg(feature = "dynamic-file")]
+ fn call_binary_math_fn(&mut self, fn_name: &str, arguments: &[ASTNode]) -> Result, RuntimeError> {
+ if arguments.len() != 2 {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("{}() expects 2 arguments, got {}", fn_name.strip_prefix("nyash_math_").unwrap_or(fn_name), arguments.len()),
+ });
+ }
+ let a_value = self.execute_expression(&arguments[0])?;
+ let b_value = self.execute_expression(&arguments[1])?;
+ let a = self.to_float(&a_value)?;
+ let b = self.to_float(&b_value)?;
+
+ let cache = crate::interpreter::plugin_loader::PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let fn_name_bytes = format!("{}\0", fn_name);
+ if let Ok(math_fn) = plugin.library.get:: f64>>(fn_name_bytes.as_bytes()) {
+ let result = math_fn(a, b);
+ return Ok(Box::new(FloatBox::new(result)));
+ }
+ }
+ }
+
+ Err(RuntimeError::InvalidOperation {
+ message: format!("Failed to call {}", fn_name),
+ })
+ }
+
+ // 型変換ヘルパー
+ fn to_float(&self, value: &Box) -> Result {
+ if let Some(float_box) = value.as_any().downcast_ref::() {
+ Ok(float_box.value)
+ } else if let Some(int_box) = value.as_any().downcast_ref::() {
+ Ok(int_box.value as f64)
+ } else {
+ Err(RuntimeError::TypeError {
+ message: "Value must be a number".to_string(),
+ })
+ }
+ }
+
+ fn to_integer(&self, value: &Box) -> Result {
+ if let Some(int_box) = value.as_any().downcast_ref::() {
+ Ok(int_box.value)
+ } else if let Some(float_box) = value.as_any().downcast_ref::() {
+ Ok(float_box.value as i64)
+ } else {
+ Err(RuntimeError::TypeError {
+ message: "Value must be a number".to_string(),
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/interpreter/methods/mod.rs b/src/interpreter/methods/mod.rs
index a4cb03b4..5cf881d5 100644
--- a/src/interpreter/methods/mod.rs
+++ b/src/interpreter/methods/mod.rs
@@ -23,5 +23,6 @@ pub mod data_methods; // BufferBox, JSONBox, RegexBox
pub mod network_methods; // HttpClientBox, StreamBox
pub mod p2p_methods; // IntentBox, P2PBox
pub mod http_methods; // SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox
+pub mod math_methods; // MathBox, RandomBox, TimeBox, DateTimeBox
// Re-export methods for easy access
diff --git a/src/interpreter/objects.rs b/src/interpreter/objects.rs
index 18fb0d1b..793ffeaf 100644
--- a/src/interpreter/objects.rs
+++ b/src/interpreter/objects.rs
@@ -7,9 +7,11 @@
*/
use super::*;
-use crate::boxes::{NullBox, ConsoleBox, FloatBox, DateTimeBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
+use crate::boxes::{NullBox, ConsoleBox, FloatBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
#[cfg(not(feature = "dynamic-file"))]
-use crate::boxes::FileBox;
+use crate::boxes::{FileBox, MathBox, RandomBox, TimeBox, DateTimeBox};
+#[cfg(feature = "dynamic-file")]
+use crate::boxes::DateTimeBox;
// use crate::boxes::intent_box_wrapper::IntentBoxWrapper;
use crate::box_trait::SharedNyashBox;
use std::sync::Arc;
@@ -167,9 +169,33 @@ impl NyashInterpreter {
message: format!("MathBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
- let math_box = Box::new(MathBox::new()) as Box;
- // 🌍 革命的実装:Environment tracking廃止
- return Ok(math_box);
+
+ println!("🔧 DEBUG: DYNAMIC-FILE feature check...");
+ #[cfg(feature = "dynamic-file")]
+ {
+ println!("🔌 DEBUG: DYNAMIC-FILE ENABLED - Creating MathBox through dynamic library");
+ log::debug!("🔌 DEBUG: Creating MathBox through dynamic library");
+ match super::plugin_loader::PluginLoader::create_math_box() {
+ Ok(math_box) => {
+ println!("🔌 DEBUG: MathBox created successfully, type_name: {}", math_box.type_name());
+ log::debug!("🔌 DEBUG: MathBox created successfully, type_name: {}", math_box.type_name());
+ return Ok(math_box);
+ }
+ Err(e) => {
+ println!("❌ DEBUG: Failed to create MathBox through dynamic library: {}", e);
+ log::error!("Failed to create MathBox through dynamic library: {}", e);
+ // Fall back to static MathBox
+ let math_box = Box::new(MathBox::new()) as Box;
+ return Ok(math_box);
+ }
+ }
+ }
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ println!("🔌 DEBUG: DYNAMIC-FILE DISABLED - Creating static MathBox");
+ let math_box = Box::new(MathBox::new()) as Box;
+ return Ok(math_box);
+ }
}
"NullBox" => {
// NullBoxは引数なしで作成
@@ -382,25 +408,65 @@ impl NyashInterpreter {
message: format!("TimeBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
- let time_box = Box::new(TimeBox::new()) as Box;
- // 🌍 革命的実装:Environment tracking廃止
- return Ok(time_box);
+ #[cfg(feature = "dynamic-file")]
+ {
+ log::debug!("🔌 DEBUG: Creating TimeBox through dynamic library");
+ let time_box = super::plugin_loader::PluginLoader::create_time_box()?;
+ log::debug!("🔌 DEBUG: TimeBox created successfully, type_name: {}", time_box.type_name());
+ return Ok(time_box);
+ }
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ let time_box = Box::new(TimeBox::new()) as Box;
+ return Ok(time_box);
+ }
}
"DateTimeBox" => {
// DateTimeBoxは引数なしで現在時刻、または引数1個でタイムスタンプ
match arguments.len() {
0 => {
- let datetime_box = Box::new(DateTimeBox::now()) as Box;
- // 🌍 革命的実装:Environment tracking廃止
- return Ok(datetime_box);
+ #[cfg(feature = "dynamic-file")]
+ {
+ log::debug!("🔌 DEBUG: Creating DateTimeBox (now) through dynamic library");
+ let datetime_box = super::plugin_loader::PluginLoader::create_datetime_now()?;
+ log::debug!("🔌 DEBUG: DateTimeBox created successfully, type_name: {}", datetime_box.type_name());
+ return Ok(datetime_box);
+ }
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ let datetime_box = Box::new(DateTimeBox::now()) as Box;
+ return Ok(datetime_box);
+ }
}
1 => {
let timestamp_value = self.execute_expression(&arguments[0])?;
+
+ // Try integer timestamp first
if let Some(int_box) = timestamp_value.as_any().downcast_ref::() {
- let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box;
- // 🌍 革命的実装:Environment tracking廃止
+ #[cfg(feature = "dynamic-file")]
+ {
+ // TODO: Add timestamp creation to plugin
+ let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box;
+ return Ok(datetime_box);
+ }
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box;
+ return Ok(datetime_box);
+ }
+ }
+
+ // Try string parsing
+ let time_str = timestamp_value.to_string_box().value;
+ #[cfg(feature = "dynamic-file")]
+ {
+ log::debug!("🔌 DEBUG: Creating DateTimeBox from string through dynamic library");
+ let datetime_box = super::plugin_loader::PluginLoader::create_datetime_from_string(&time_str)?;
+ log::debug!("🔌 DEBUG: DateTimeBox created successfully, type_name: {}", datetime_box.type_name());
return Ok(datetime_box);
- } else {
+ }
+ #[cfg(not(feature = "dynamic-file"))]
+ {
return Err(RuntimeError::TypeError {
message: "DateTimeBox constructor requires integer timestamp".to_string(),
});
@@ -442,9 +508,18 @@ impl NyashInterpreter {
message: format!("RandomBox constructor expects 0 arguments, got {}", arguments.len()),
});
}
- let random_box = Box::new(RandomBox::new()) as Box;
- // 🌍 革命的実装:Environment tracking廃止
- return Ok(random_box);
+ #[cfg(feature = "dynamic-file")]
+ {
+ log::debug!("🔌 DEBUG: Creating RandomBox through dynamic library");
+ let random_box = super::plugin_loader::PluginLoader::create_random_box()?;
+ log::debug!("🔌 DEBUG: RandomBox created successfully, type_name: {}", random_box.type_name());
+ return Ok(random_box);
+ }
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ let random_box = Box::new(RandomBox::new()) as Box;
+ return Ok(random_box);
+ }
}
"SoundBox" => {
// SoundBoxは引数なしで作成
diff --git a/src/interpreter/plugin_loader.rs b/src/interpreter/plugin_loader.rs
index b70bad2e..61c22e04 100644
--- a/src/interpreter/plugin_loader.rs
+++ b/src/interpreter/plugin_loader.rs
@@ -11,19 +11,20 @@ use std::sync::{Arc, RwLock};
use libloading::{Library, Symbol};
use crate::interpreter::RuntimeError;
-use crate::box_trait::{NyashBox, StringBox, BoolBox, VoidBox, BoxCore, BoxBase};
+use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase, IntegerBox};
+use crate::boxes::FloatBox;
lazy_static::lazy_static! {
/// グローバルプラグインキャッシュ
- static ref PLUGIN_CACHE: RwLock> =
+ pub(crate) static ref PLUGIN_CACHE: RwLock> =
RwLock::new(HashMap::new());
}
/// ロード済みプラグイン情報
#[cfg(feature = "dynamic-file")]
-struct LoadedPlugin {
- library: Library,
- info: PluginInfo,
+pub(crate) struct LoadedPlugin {
+ pub(crate) library: Library,
+ pub(crate) info: PluginInfo,
}
/// プラグイン情報
@@ -61,6 +62,114 @@ impl Drop for FileBoxHandle {
unsafe impl Send for FileBoxHandle {}
unsafe impl Sync for FileBoxHandle {}
+/// MathBoxハンドル
+#[derive(Debug)]
+struct MathBoxHandle {
+ ptr: *mut c_void,
+}
+
+impl Drop for MathBoxHandle {
+ fn drop(&mut self) {
+ #[cfg(feature = "dynamic-file")]
+ {
+ if !self.ptr.is_null() {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(free_fn) = plugin.library.get::>(b"nyash_math_free\0") {
+ free_fn(self.ptr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+unsafe impl Send for MathBoxHandle {}
+unsafe impl Sync for MathBoxHandle {}
+
+/// RandomBoxハンドル
+#[derive(Debug)]
+struct RandomBoxHandle {
+ ptr: *mut c_void,
+}
+
+impl Drop for RandomBoxHandle {
+ fn drop(&mut self) {
+ #[cfg(feature = "dynamic-file")]
+ {
+ if !self.ptr.is_null() {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(free_fn) = plugin.library.get::>(b"nyash_random_free\0") {
+ free_fn(self.ptr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+unsafe impl Send for RandomBoxHandle {}
+unsafe impl Sync for RandomBoxHandle {}
+
+/// TimeBoxハンドル
+#[derive(Debug)]
+struct TimeBoxHandle {
+ ptr: *mut c_void,
+}
+
+impl Drop for TimeBoxHandle {
+ fn drop(&mut self) {
+ #[cfg(feature = "dynamic-file")]
+ {
+ if !self.ptr.is_null() {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(free_fn) = plugin.library.get::>(b"nyash_time_free\0") {
+ free_fn(self.ptr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+unsafe impl Send for TimeBoxHandle {}
+unsafe impl Sync for TimeBoxHandle {}
+
+/// DateTimeBoxハンドル
+#[derive(Debug)]
+pub(crate) struct DateTimeBoxHandle {
+ pub(crate) ptr: *mut c_void,
+}
+
+impl Drop for DateTimeBoxHandle {
+ fn drop(&mut self) {
+ #[cfg(feature = "dynamic-file")]
+ {
+ if !self.ptr.is_null() {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(free_fn) = plugin.library.get::>(b"nyash_datetime_free\0") {
+ free_fn(self.ptr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+unsafe impl Send for DateTimeBoxHandle {}
+unsafe impl Sync for DateTimeBoxHandle {}
+
/// FileBoxプロキシ - 動的ライブラリのFileBoxをラップ
#[derive(Debug)]
pub struct FileBoxProxy {
@@ -251,6 +360,485 @@ impl std::fmt::Display for FileBoxProxy {
}
}
+// ================== MathBoxProxy ==================
+
+/// MathBoxプロキシ - 動的ライブラリのMathBoxをラップ
+#[derive(Debug)]
+pub struct MathBoxProxy {
+ handle: Arc,
+ base: BoxBase,
+}
+
+unsafe impl Send for MathBoxProxy {}
+unsafe impl Sync for MathBoxProxy {}
+
+impl MathBoxProxy {
+ pub fn new(handle: *mut c_void) -> Self {
+ MathBoxProxy {
+ handle: Arc::new(MathBoxHandle { ptr: handle }),
+ base: BoxBase::new(),
+ }
+ }
+}
+
+impl BoxCore for MathBoxProxy {
+ fn box_id(&self) -> u64 {
+ self.base.id
+ }
+
+ fn parent_type_id(&self) -> Option {
+ None // プロキシ型は継承しない
+ }
+
+ fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "MathBox")
+ }
+
+ fn as_any(&self) -> &dyn std::any::Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
+ self
+ }
+}
+
+impl NyashBox for MathBoxProxy {
+ fn type_name(&self) -> &'static str {
+ "MathBox"
+ }
+
+ fn clone_box(&self) -> Box {
+ match PluginLoader::create_math_box() {
+ Ok(new_box) => new_box,
+ Err(_) => Box::new(MathBoxProxy {
+ handle: Arc::clone(&self.handle),
+ base: BoxBase::new(),
+ })
+ }
+ }
+
+ fn share_box(&self) -> Box {
+ self.clone_box()
+ }
+
+ fn to_string_box(&self) -> StringBox {
+ StringBox::new("MathBox")
+ }
+
+ fn equals(&self, other: &dyn NyashBox) -> BoolBox {
+ if let Some(_) = other.as_any().downcast_ref::() {
+ BoolBox::new(true)
+ } else {
+ BoolBox::new(false)
+ }
+ }
+}
+
+impl std::fmt::Display for MathBoxProxy {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.fmt_box(f)
+ }
+}
+
+// ================== RandomBoxProxy ==================
+
+/// RandomBoxプロキシ - 動的ライブラリのRandomBoxをラップ
+#[derive(Debug)]
+pub struct RandomBoxProxy {
+ handle: Arc,
+ base: BoxBase,
+}
+
+unsafe impl Send for RandomBoxProxy {}
+unsafe impl Sync for RandomBoxProxy {}
+
+impl RandomBoxProxy {
+ pub fn new(handle: *mut c_void) -> Self {
+ RandomBoxProxy {
+ handle: Arc::new(RandomBoxHandle { ptr: handle }),
+ base: BoxBase::new(),
+ }
+ }
+
+ pub fn next(&self) -> Result, RuntimeError> {
+ #[cfg(feature = "dynamic-file")]
+ {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let next_fn: Symbol f64> =
+ plugin.library.get(b"nyash_random_next\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_random_next: {}", e)
+ }
+ })?;
+
+ let value = next_fn(self.handle.ptr);
+ Ok(Box::new(FloatBox::new(value)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ Err(RuntimeError::InvalidOperation {
+ message: "Dynamic loading not enabled".to_string()
+ })
+ }
+ }
+
+ pub fn range(&self, min: f64, max: f64) -> Result, RuntimeError> {
+ #[cfg(feature = "dynamic-file")]
+ {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let range_fn: Symbol f64> =
+ plugin.library.get(b"nyash_random_range\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_random_range: {}", e)
+ }
+ })?;
+
+ let value = range_fn(self.handle.ptr, min, max);
+ Ok(Box::new(FloatBox::new(value)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ Err(RuntimeError::InvalidOperation {
+ message: "Dynamic loading not enabled".to_string()
+ })
+ }
+ }
+
+ pub fn int(&self, min: i64, max: i64) -> Result, RuntimeError> {
+ #[cfg(feature = "dynamic-file")]
+ {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let int_fn: Symbol i64> =
+ plugin.library.get(b"nyash_random_int\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_random_int: {}", e)
+ }
+ })?;
+
+ let value = int_fn(self.handle.ptr, min, max);
+ Ok(Box::new(IntegerBox::new(value)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ #[cfg(not(feature = "dynamic-file"))]
+ {
+ Err(RuntimeError::InvalidOperation {
+ message: "Dynamic loading not enabled".to_string()
+ })
+ }
+ }
+}
+
+impl BoxCore for RandomBoxProxy {
+ fn box_id(&self) -> u64 {
+ self.base.id
+ }
+
+ fn parent_type_id(&self) -> Option {
+ None // プロキシ型は継承しない
+ }
+
+ fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "RandomBox")
+ }
+
+ fn as_any(&self) -> &dyn std::any::Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
+ self
+ }
+}
+
+impl NyashBox for RandomBoxProxy {
+ fn type_name(&self) -> &'static str {
+ "RandomBox"
+ }
+
+ fn clone_box(&self) -> Box {
+ match PluginLoader::create_random_box() {
+ Ok(new_box) => new_box,
+ Err(_) => Box::new(RandomBoxProxy {
+ handle: Arc::clone(&self.handle),
+ base: BoxBase::new(),
+ })
+ }
+ }
+
+ fn share_box(&self) -> Box {
+ self.clone_box()
+ }
+
+ fn to_string_box(&self) -> StringBox {
+ StringBox::new("RandomBox")
+ }
+
+ fn equals(&self, other: &dyn NyashBox) -> BoolBox {
+ if let Some(_) = other.as_any().downcast_ref::() {
+ BoolBox::new(true)
+ } else {
+ BoolBox::new(false)
+ }
+ }
+}
+
+impl std::fmt::Display for RandomBoxProxy {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.fmt_box(f)
+ }
+}
+
+// ================== TimeBoxProxy ==================
+
+/// TimeBoxプロキシ - 動的ライブラリのTimeBoxをラップ
+#[derive(Debug)]
+pub struct TimeBoxProxy {
+ handle: Arc,
+ base: BoxBase,
+}
+
+unsafe impl Send for TimeBoxProxy {}
+unsafe impl Sync for TimeBoxProxy {}
+
+impl TimeBoxProxy {
+ pub fn new(handle: *mut c_void) -> Self {
+ TimeBoxProxy {
+ handle: Arc::new(TimeBoxHandle { ptr: handle }),
+ base: BoxBase::new(),
+ }
+ }
+}
+
+impl BoxCore for TimeBoxProxy {
+ fn box_id(&self) -> u64 {
+ self.base.id
+ }
+
+ fn parent_type_id(&self) -> Option {
+ None // プロキシ型は継承しない
+ }
+
+ fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "TimeBox")
+ }
+
+ fn as_any(&self) -> &dyn std::any::Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
+ self
+ }
+}
+
+impl NyashBox for TimeBoxProxy {
+ fn type_name(&self) -> &'static str {
+ "TimeBox"
+ }
+
+ fn clone_box(&self) -> Box {
+ match PluginLoader::create_time_box() {
+ Ok(new_box) => new_box,
+ Err(_) => Box::new(TimeBoxProxy {
+ handle: Arc::clone(&self.handle),
+ base: BoxBase::new(),
+ })
+ }
+ }
+
+ fn share_box(&self) -> Box {
+ self.clone_box()
+ }
+
+ fn to_string_box(&self) -> StringBox {
+ StringBox::new("TimeBox")
+ }
+
+ fn equals(&self, other: &dyn NyashBox) -> BoolBox {
+ if let Some(_) = other.as_any().downcast_ref::() {
+ BoolBox::new(true)
+ } else {
+ BoolBox::new(false)
+ }
+ }
+}
+
+impl std::fmt::Display for TimeBoxProxy {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.fmt_box(f)
+ }
+}
+
+// ================== DateTimeBoxProxy ==================
+
+/// DateTimeBoxプロキシ - 動的ライブラリのDateTimeBoxをラップ
+#[derive(Debug)]
+pub struct DateTimeBoxProxy {
+ pub(crate) handle: Arc,
+ base: BoxBase,
+}
+
+unsafe impl Send for DateTimeBoxProxy {}
+unsafe impl Sync for DateTimeBoxProxy {}
+
+impl DateTimeBoxProxy {
+ pub fn new(handle: *mut c_void) -> Self {
+ DateTimeBoxProxy {
+ handle: Arc::new(DateTimeBoxHandle { ptr: handle }),
+ base: BoxBase::new(),
+ }
+ }
+}
+
+impl BoxCore for DateTimeBoxProxy {
+ fn box_id(&self) -> u64 {
+ self.base.id
+ }
+
+ fn parent_type_id(&self) -> Option {
+ None // プロキシ型は継承しない
+ }
+
+ fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ #[cfg(feature = "dynamic-file")]
+ {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(to_string_fn) = plugin.library.get:: *mut c_char>>(b"nyash_datetime_to_string\0") {
+ let str_ptr = to_string_fn(self.handle.ptr);
+ if !str_ptr.is_null() {
+ let c_str = CStr::from_ptr(str_ptr);
+ if let Ok(rust_str) = c_str.to_str() {
+ let result = write!(f, "{}", rust_str);
+
+ // 文字列を解放
+ if let Ok(free_fn) = plugin.library.get::>(b"nyash_string_free\0") {
+ free_fn(str_ptr);
+ }
+
+ return result;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ write!(f, "DateTimeBox")
+ }
+
+ fn as_any(&self) -> &dyn std::any::Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
+ self
+ }
+}
+
+impl NyashBox for DateTimeBoxProxy {
+ fn type_name(&self) -> &'static str {
+ "DateTimeBox"
+ }
+
+ fn clone_box(&self) -> Box {
+ // DateTimeBoxは不変なので、ハンドルを共有
+ Box::new(DateTimeBoxProxy {
+ handle: Arc::clone(&self.handle),
+ base: BoxBase::new(),
+ })
+ }
+
+ fn share_box(&self) -> Box {
+ self.clone_box()
+ }
+
+ fn to_string_box(&self) -> StringBox {
+ #[cfg(feature = "dynamic-file")]
+ {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(to_string_fn) = plugin.library.get:: *mut c_char>>(b"nyash_datetime_to_string\0") {
+ let str_ptr = to_string_fn(self.handle.ptr);
+ if !str_ptr.is_null() {
+ let c_str = CStr::from_ptr(str_ptr);
+ if let Ok(rust_str) = c_str.to_str() {
+ let result = StringBox::new(rust_str);
+
+ // 文字列を解放
+ if let Ok(free_fn) = plugin.library.get::>(b"nyash_string_free\0") {
+ free_fn(str_ptr);
+ }
+
+ return result;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ StringBox::new("DateTimeBox")
+ }
+
+ fn equals(&self, other: &dyn NyashBox) -> BoolBox {
+ if let Some(other_datetime) = other.as_any().downcast_ref::() {
+ // タイムスタンプで比較
+ #[cfg(feature = "dynamic-file")]
+ {
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ if let Ok(timestamp_fn) = plugin.library.get:: i64>>(b"nyash_datetime_timestamp\0") {
+ let this_ts = timestamp_fn(self.handle.ptr);
+ let other_ts = timestamp_fn(other_datetime.handle.ptr);
+ return BoolBox::new(this_ts == other_ts);
+ }
+ }
+ }
+ }
+ BoolBox::new(false)
+ } else {
+ BoolBox::new(false)
+ }
+ }
+}
+
+impl std::fmt::Display for DateTimeBoxProxy {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.fmt_box(f)
+ }
+}
+
/// プラグインローダー公開API
pub struct PluginLoader;
@@ -402,4 +990,229 @@ impl PluginLoader {
})
}
}
+
+ /// Mathプラグインをロード
+ #[cfg(feature = "dynamic-file")]
+ pub fn load_math_plugin() -> Result<(), RuntimeError> {
+ let mut cache = PLUGIN_CACHE.write().unwrap();
+
+ if cache.contains_key("math") {
+ return Ok(()); // 既にロード済み
+ }
+
+ // プラグインパスを決定(複数の場所を試す)
+ let lib_name = if cfg!(target_os = "windows") {
+ "nyash_math.dll"
+ } else if cfg!(target_os = "macos") {
+ "libnyash_math.dylib"
+ } else {
+ "libnyash_math.so"
+ };
+
+ // 複数のパスを試す
+ let possible_paths = vec![
+ format!("./target/release/{}", lib_name),
+ format!("./target/debug/{}", lib_name),
+ format!("./plugins/{}", lib_name),
+ format!("./{}", lib_name),
+ ];
+
+ let mut lib_path = None;
+ for path in &possible_paths {
+ if std::path::Path::new(path).exists() {
+ lib_path = Some(path.clone());
+ break;
+ }
+ }
+
+ let lib_path = lib_path.ok_or_else(|| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to find math plugin library. Searched paths: {:?}", possible_paths)
+ }
+ })?;
+
+ // ライブラリをロード
+ unsafe {
+ let library = Library::new(&lib_path).map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to load math plugin: {}", e)
+ }
+ })?;
+
+ // プラグイン情報(簡略化)
+ let info = PluginInfo {
+ name: "math".to_string(),
+ version: 1,
+ api_version: 1,
+ };
+
+ cache.insert("math".to_string(), LoadedPlugin {
+ library,
+ info,
+ });
+ }
+
+ Ok(())
+ }
+
+ /// MathBoxを作成
+ #[cfg(feature = "dynamic-file")]
+ pub fn create_math_box() -> Result, RuntimeError> {
+ Self::load_math_plugin()?;
+
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let create_fn: Symbol *mut c_void> =
+ plugin.library.get(b"nyash_math_create\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_math_create: {}", e)
+ }
+ })?;
+
+ let handle = create_fn();
+ if handle.is_null() {
+ return Err(RuntimeError::InvalidOperation {
+ message: "Failed to create MathBox".to_string()
+ });
+ }
+
+ Ok(Box::new(MathBoxProxy::new(handle)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ /// RandomBoxを作成
+ #[cfg(feature = "dynamic-file")]
+ pub fn create_random_box() -> Result, RuntimeError> {
+ Self::load_math_plugin()?;
+
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let create_fn: Symbol *mut c_void> =
+ plugin.library.get(b"nyash_random_create\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_random_create: {}", e)
+ }
+ })?;
+
+ let handle = create_fn();
+ if handle.is_null() {
+ return Err(RuntimeError::InvalidOperation {
+ message: "Failed to create RandomBox".to_string()
+ });
+ }
+
+ Ok(Box::new(RandomBoxProxy::new(handle)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ /// TimeBoxを作成
+ #[cfg(feature = "dynamic-file")]
+ pub fn create_time_box() -> Result, RuntimeError> {
+ Self::load_math_plugin()?;
+
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let create_fn: Symbol *mut c_void> =
+ plugin.library.get(b"nyash_time_create\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_time_create: {}", e)
+ }
+ })?;
+
+ let handle = create_fn();
+ if handle.is_null() {
+ return Err(RuntimeError::InvalidOperation {
+ message: "Failed to create TimeBox".to_string()
+ });
+ }
+
+ Ok(Box::new(TimeBoxProxy::new(handle)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ /// 現在時刻のDateTimeBoxを作成
+ #[cfg(feature = "dynamic-file")]
+ pub fn create_datetime_now() -> Result, RuntimeError> {
+ Self::load_math_plugin()?;
+
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ unsafe {
+ let now_fn: Symbol *mut c_void> =
+ plugin.library.get(b"nyash_time_now\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_time_now: {}", e)
+ }
+ })?;
+
+ let handle = now_fn();
+ if handle.is_null() {
+ return Err(RuntimeError::InvalidOperation {
+ message: "Failed to create DateTimeBox".to_string()
+ });
+ }
+
+ Ok(Box::new(DateTimeBoxProxy::new(handle)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
+
+ /// 文字列からDateTimeBoxを作成
+ #[cfg(feature = "dynamic-file")]
+ pub fn create_datetime_from_string(time_str: &str) -> Result, RuntimeError> {
+ Self::load_math_plugin()?;
+
+ let cache = PLUGIN_CACHE.read().unwrap();
+ if let Some(plugin) = cache.get("math") {
+ let c_str = CString::new(time_str).map_err(|_| {
+ RuntimeError::InvalidOperation {
+ message: "Invalid time string".to_string()
+ }
+ })?;
+
+ unsafe {
+ let parse_fn: Symbol *mut c_void> =
+ plugin.library.get(b"nyash_time_parse\0").map_err(|e| {
+ RuntimeError::InvalidOperation {
+ message: format!("Failed to get nyash_time_parse: {}", e)
+ }
+ })?;
+
+ let handle = parse_fn(c_str.as_ptr());
+ if handle.is_null() {
+ return Err(RuntimeError::InvalidOperation {
+ message: format!("Failed to parse time string: {}", time_str)
+ });
+ }
+
+ Ok(Box::new(DateTimeBoxProxy::new(handle)))
+ }
+ } else {
+ Err(RuntimeError::InvalidOperation {
+ message: "Math plugin not loaded".to_string()
+ })
+ }
+ }
}
\ No newline at end of file
diff --git a/src/mir/builder.rs b/src/mir/builder.rs
index 2cee5c6e..5ed72069 100644
--- a/src/mir/builder.rs
+++ b/src/mir/builder.rs
@@ -291,12 +291,28 @@ impl MirBuilder {
let operand_val = self.build_expression(operand)?;
let dst = self.value_gen.next();
- let mir_op = self.convert_unary_operator(operator)?;
+ // Phase 2: Convert UnaryOp to intrinsic call
+ // Create intrinsic function name based on operator
+ let intrinsic_name = match operator.as_str() {
+ "-" => "@unary_neg",
+ "!" | "not" => "@unary_not",
+ "~" => "@unary_bitnot",
+ _ => return Err(format!("Unsupported unary operator: {}", operator)),
+ };
- self.emit_instruction(MirInstruction::UnaryOp {
- dst,
- op: mir_op,
- operand: operand_val,
+ // Create string constant for intrinsic function name
+ let func_name_id = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst: func_name_id,
+ value: ConstValue::String(intrinsic_name.to_string()),
+ })?;
+
+ // Emit intrinsic call
+ self.emit_instruction(MirInstruction::Call {
+ dst: Some(dst),
+ func: func_name_id,
+ args: vec![operand_val],
+ effects: EffectMask::PURE, // Unary operations are pure
})?;
Ok(dst)
@@ -353,10 +369,20 @@ impl MirBuilder {
fn build_print_statement(&mut self, expression: ASTNode) -> Result {
let value = self.build_expression(expression)?;
- // For now, use a special Print instruction (minimal scope)
- self.emit_instruction(MirInstruction::Print {
- value,
- effects: EffectMask::PURE.add(Effect::Io),
+ // Phase 2: Convert Print to intrinsic call (@print)
+ // Create string constant for intrinsic function name
+ let func_name_id = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst: func_name_id,
+ value: ConstValue::String("@print".to_string()),
+ })?;
+
+ // Emit intrinsic call (print returns void)
+ self.emit_instruction(MirInstruction::Call {
+ dst: None, // Print has no return value
+ func: func_name_id,
+ args: vec![value],
+ effects: EffectMask::PURE.add(Effect::Io), // IO effect for print
})?;
// Return the value that was printed
@@ -530,15 +556,35 @@ impl MirBuilder {
let finally_block = if finally_body.is_some() { Some(self.block_gen.next()) } else { None };
let exit_block = self.block_gen.next();
- // Set up exception handler for the try block (before we enter it)
+ // Phase 2: Convert Catch to intrinsic call (@set_exception_handler)
if let Some(catch_clause) = catch_clauses.first() {
let exception_value = self.value_gen.next();
- // Register catch handler for exceptions that may occur in try block
- self.emit_instruction(MirInstruction::Catch {
- exception_type: catch_clause.exception_type.clone(),
- exception_value,
- handler_bb: catch_block,
+ // Create string constants for intrinsic function name and exception type
+ let func_name_id = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst: func_name_id,
+ value: ConstValue::String("@set_exception_handler".to_string()),
+ })?;
+
+ let exception_type_id = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst: exception_type_id,
+ value: ConstValue::String(catch_clause.exception_type.clone().unwrap_or("*".to_string())),
+ })?;
+
+ let handler_bb_id = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst: handler_bb_id,
+ value: ConstValue::Integer(catch_block.as_u32() as i64),
+ })?;
+
+ // Register catch handler via intrinsic call
+ self.emit_instruction(MirInstruction::Call {
+ dst: Some(exception_value),
+ func: func_name_id,
+ args: vec![exception_type_id, handler_bb_id],
+ effects: EffectMask::CONTROL, // Exception handling has control effects
})?;
}
@@ -609,10 +655,20 @@ impl MirBuilder {
fn build_throw_statement(&mut self, expression: ASTNode) -> Result {
let exception_value = self.build_expression(expression)?;
- // Emit throw instruction with PANIC effect (this is a terminator)
- self.emit_instruction(MirInstruction::Throw {
- exception: exception_value,
- effects: EffectMask::PANIC,
+ // Phase 2: Convert Throw to intrinsic call (@throw)
+ // Create string constant for intrinsic function name
+ let func_name_id = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst: func_name_id,
+ value: ConstValue::String("@throw".to_string()),
+ })?;
+
+ // Emit intrinsic call (throw has PANIC effect and doesn't return)
+ self.emit_instruction(MirInstruction::Call {
+ dst: None, // Throw never returns
+ func: func_name_id,
+ args: vec![exception_value],
+ effects: EffectMask::PANIC, // PANIC effect for throw
})?;
// Throw doesn't return normally, but we need to return a value for the type system
@@ -704,11 +760,11 @@ impl MirBuilder {
// First, build the object expression to get its ValueId
let object_value = self.build_expression(object)?;
- // Get the field from the object using RefGet
+ // Get the field from the object using BoxFieldLoad (Phase 8.5 new instruction)
let result_id = self.value_gen.next();
- self.emit_instruction(MirInstruction::RefGet {
+ self.emit_instruction(MirInstruction::BoxFieldLoad {
dst: result_id,
- reference: object_value,
+ box_val: object_value,
field,
})?;
@@ -716,7 +772,29 @@ impl MirBuilder {
}
/// Build new expression: new ClassName(arguments)
- fn build_new_expression(&mut self, class: String, _arguments: Vec) -> Result {
+ fn build_new_expression(&mut self, class: String, arguments: Vec) -> Result {
+ // Special handling for StringBox - if it has a string literal argument,
+ // treat it as a string constant, not a box creation
+ if class == "StringBox" && arguments.len() == 1 {
+ if let ASTNode::Literal { value: LiteralValue::String(s), .. } = &arguments[0] {
+ // Just create a string constant
+ let dst = self.value_gen.next();
+ self.emit_instruction(MirInstruction::Const {
+ dst,
+ value: ConstValue::String(s.clone()),
+ })?;
+
+ // Create RefNew for the StringBox
+ let string_box_dst = self.value_gen.next();
+ self.emit_instruction(MirInstruction::RefNew {
+ dst: string_box_dst,
+ box_val: dst,
+ })?;
+
+ return Ok(string_box_dst);
+ }
+ }
+
// For Phase 6.1, we'll create a simple RefNew without processing arguments
// In a full implementation, arguments would be used for constructor calls
let dst = self.value_gen.next();
@@ -743,9 +821,9 @@ impl MirBuilder {
let object_value = self.build_expression(object)?;
let value_result = self.build_expression(value)?;
- // Set the field using RefSet
- self.emit_instruction(MirInstruction::RefSet {
- reference: object_value,
+ // Set the field using BoxFieldStore (Phase 8.5 new instruction)
+ self.emit_instruction(MirInstruction::BoxFieldStore {
+ box_val: object_value,
field,
value: value_result,
})?;
@@ -809,11 +887,12 @@ impl MirBuilder {
// Evaluate the expression
let expression_value = self.build_expression(expression)?;
- // Create a new Future with the evaluated expression as the initial value
+ // Phase 2: Convert FutureNew to NewBox + BoxCall implementation
let future_id = self.value_gen.next();
- self.emit_instruction(MirInstruction::FutureNew {
+ self.emit_instruction(MirInstruction::NewBox {
dst: future_id,
- value: expression_value,
+ box_type: "FutureBox".to_string(),
+ args: vec![expression_value],
})?;
// Store the future in the variable
@@ -827,13 +906,16 @@ impl MirBuilder {
// Evaluate the expression (should be a Future)
let future_value = self.build_expression(expression)?;
- // Create destination for await result
+ // Phase 2: Convert Await to BoxCall implementation
let result_id = self.value_gen.next();
- // Emit await instruction
- self.emit_instruction(MirInstruction::Await {
- dst: result_id,
- future: future_value,
+ // Emit await as a method call on the future box
+ self.emit_instruction(MirInstruction::BoxCall {
+ dst: Some(result_id),
+ box_val: future_value,
+ method: "await".to_string(),
+ args: vec![],
+ effects: EffectMask::IO.add(Effect::Control), // Await has IO and control effects
})?;
Ok(result_id)
diff --git a/src/mir/instruction.rs b/src/mir/instruction.rs
index c87ee362..afe121c7 100644
--- a/src/mir/instruction.rs
+++ b/src/mir/instruction.rs
@@ -285,6 +285,80 @@ pub enum MirInstruction {
args: Vec,
effects: EffectMask,
},
+
+ // === Phase 8.5: MIR 26-instruction reduction (NEW) ===
+
+ /// Box field load operation (replaces Load)
+ /// `%dst = %box.field`
+ BoxFieldLoad {
+ dst: ValueId,
+ box_val: ValueId,
+ field: String,
+ },
+
+ /// Box field store operation (replaces Store)
+ /// `%box.field = %value`
+ BoxFieldStore {
+ box_val: ValueId,
+ field: String,
+ value: ValueId,
+ },
+
+ /// Check weak reference validity
+ /// `%dst = weak_check %weak_ref`
+ WeakCheck {
+ dst: ValueId,
+ weak_ref: ValueId,
+ },
+
+ /// Send data via Bus
+ /// `send %data -> %target`
+ Send {
+ data: ValueId,
+ target: ValueId,
+ },
+
+ /// Receive data from Bus
+ /// `%dst = recv %source`
+ Recv {
+ dst: ValueId,
+ source: ValueId,
+ },
+
+ /// Tail call optimization
+ /// `tail_call %func(%args...)`
+ TailCall {
+ func: ValueId,
+ args: Vec,
+ effects: EffectMask,
+ },
+
+ /// Adopt ownership (parent takes child)
+ /// `adopt %parent <- %child`
+ Adopt {
+ parent: ValueId,
+ child: ValueId,
+ },
+
+ /// Release strong ownership
+ /// `release %ref`
+ Release {
+ reference: ValueId,
+ },
+
+ /// Memory copy optimization
+ /// `memcopy %dst <- %src, %size`
+ MemCopy {
+ dst: ValueId,
+ src: ValueId,
+ size: ValueId,
+ },
+
+ /// Atomic memory fence
+ /// `atomic_fence %ordering`
+ AtomicFence {
+ ordering: AtomicOrdering,
+ },
}
/// Constant values in MIR
@@ -344,6 +418,16 @@ pub enum MirType {
Unknown,
}
+/// Atomic memory ordering for fence operations
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum AtomicOrdering {
+ Relaxed,
+ Acquire,
+ Release,
+ AcqRel,
+ SeqCst,
+}
+
impl MirInstruction {
/// Get the effect mask for this instruction
pub fn effects(&self) -> EffectMask {
@@ -404,6 +488,18 @@ impl MirInstruction {
// Phase 9.7: External Function Calls
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask
+
+ // Phase 8.5: MIR 26-instruction reduction (NEW)
+ MirInstruction::BoxFieldLoad { .. } => EffectMask::READ, // Box field read
+ MirInstruction::BoxFieldStore { .. } => EffectMask::WRITE, // Box field write
+ MirInstruction::WeakCheck { .. } => EffectMask::PURE, // Check is pure
+ MirInstruction::Send { .. } => EffectMask::IO, // Bus send has IO effects
+ MirInstruction::Recv { .. } => EffectMask::IO, // Bus recv has IO effects
+ MirInstruction::TailCall { effects, .. } => *effects, // Use provided effect mask
+ MirInstruction::Adopt { .. } => EffectMask::WRITE, // Ownership change has write effects
+ MirInstruction::Release { .. } => EffectMask::WRITE, // Ownership release has write effects
+ MirInstruction::MemCopy { .. } => EffectMask::WRITE, // Memory copy has write effects
+ MirInstruction::AtomicFence { .. } => EffectMask::IO.add(Effect::Barrier), // Fence has barrier + IO
}
}
@@ -432,6 +528,12 @@ impl MirInstruction {
MirInstruction::BoxCall { dst, .. } |
MirInstruction::ExternCall { dst, .. } => *dst,
+ // Phase 8.5: MIR 26-instruction reduction (NEW)
+ MirInstruction::BoxFieldLoad { dst, .. } |
+ MirInstruction::WeakCheck { dst, .. } |
+ MirInstruction::Recv { dst, .. } |
+ MirInstruction::MemCopy { dst, .. } => Some(*dst),
+
MirInstruction::Store { .. } |
MirInstruction::Branch { .. } |
MirInstruction::Jump { .. } |
@@ -447,6 +549,14 @@ impl MirInstruction {
MirInstruction::Safepoint |
MirInstruction::Nop => None,
+ // Phase 8.5: Non-value producing instructions
+ MirInstruction::BoxFieldStore { .. } |
+ MirInstruction::Send { .. } |
+ MirInstruction::TailCall { .. } |
+ MirInstruction::Adopt { .. } |
+ MirInstruction::Release { .. } |
+ MirInstruction::AtomicFence { .. } => None,
+
MirInstruction::Catch { exception_value, .. } => Some(*exception_value),
}
}
@@ -519,6 +629,22 @@ impl MirInstruction {
// Phase 9.7: External Function Calls
MirInstruction::ExternCall { args, .. } => args.clone(),
+
+ // Phase 8.5: MIR 26-instruction reduction (NEW)
+ MirInstruction::BoxFieldLoad { box_val, .. } => vec![*box_val],
+ MirInstruction::BoxFieldStore { box_val, value, .. } => vec![*box_val, *value],
+ MirInstruction::WeakCheck { weak_ref, .. } => vec![*weak_ref],
+ MirInstruction::Send { data, target } => vec![*data, *target],
+ MirInstruction::Recv { source, .. } => vec![*source],
+ MirInstruction::TailCall { func, args, .. } => {
+ let mut used = vec![*func];
+ used.extend(args);
+ used
+ },
+ MirInstruction::Adopt { parent, child } => vec![*parent, *child],
+ MirInstruction::Release { reference } => vec![*reference],
+ MirInstruction::MemCopy { dst, src, size } => vec![*dst, *src, *size],
+ MirInstruction::AtomicFence { .. } => Vec::new(), // Fence doesn't use values
}
}
}
@@ -602,6 +728,39 @@ impl fmt::Display for MirInstruction {
effects)
}
},
+ // Phase 8.5: MIR 26-instruction reduction (NEW)
+ MirInstruction::BoxFieldLoad { dst, box_val, field } => {
+ write!(f, "{} = {}.{}", dst, box_val, field)
+ },
+ MirInstruction::BoxFieldStore { box_val, field, value } => {
+ write!(f, "{}.{} = {}", box_val, field, value)
+ },
+ MirInstruction::WeakCheck { dst, weak_ref } => {
+ write!(f, "{} = weak_check {}", dst, weak_ref)
+ },
+ MirInstruction::Send { data, target } => {
+ write!(f, "send {} -> {}", data, target)
+ },
+ MirInstruction::Recv { dst, source } => {
+ write!(f, "{} = recv {}", dst, source)
+ },
+ MirInstruction::TailCall { func, args, effects } => {
+ write!(f, "tail_call {}({}); effects: {}", func,
+ args.iter().map(|v| format!("{}", v)).collect::>().join(", "),
+ effects)
+ },
+ MirInstruction::Adopt { parent, child } => {
+ write!(f, "adopt {} <- {}", parent, child)
+ },
+ MirInstruction::Release { reference } => {
+ write!(f, "release {}", reference)
+ },
+ MirInstruction::MemCopy { dst, src, size } => {
+ write!(f, "memcopy {} <- {}, {}", dst, src, size)
+ },
+ MirInstruction::AtomicFence { ordering } => {
+ write!(f, "atomic_fence {:?}", ordering)
+ },
_ => write!(f, "{:?}", self), // Fallback for other instructions
}
}
@@ -620,6 +779,18 @@ impl fmt::Display for ConstValue {
}
}
+impl fmt::Display for AtomicOrdering {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ AtomicOrdering::Relaxed => write!(f, "relaxed"),
+ AtomicOrdering::Acquire => write!(f, "acquire"),
+ AtomicOrdering::Release => write!(f, "release"),
+ AtomicOrdering::AcqRel => write!(f, "acq_rel"),
+ AtomicOrdering::SeqCst => write!(f, "seq_cst"),
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/mir/printer.rs b/src/mir/printer.rs
index 92816100..dd044263 100644
--- a/src/mir/printer.rs
+++ b/src/mir/printer.rs
@@ -371,6 +371,39 @@ impl MirPrinter {
format!("extern_call {}.{}({}) [effects: {}]", iface_name, method_name, args_str, effects)
}
},
+
+ // Phase 8.5: MIR 26-instruction reduction (NEW)
+ MirInstruction::BoxFieldLoad { dst, box_val, field } => {
+ format!("{} = {}.{}", dst, box_val, field)
+ },
+ MirInstruction::BoxFieldStore { box_val, field, value } => {
+ format!("{}.{} = {}", box_val, field, value)
+ },
+ MirInstruction::WeakCheck { dst, weak_ref } => {
+ format!("{} = weak_check {}", dst, weak_ref)
+ },
+ MirInstruction::Send { data, target } => {
+ format!("send {} -> {}", data, target)
+ },
+ MirInstruction::Recv { dst, source } => {
+ format!("{} = recv {}", dst, source)
+ },
+ MirInstruction::TailCall { func, args, effects } => {
+ let args_str = args.iter().map(|v| format!("{}", v)).collect::>().join(", ");
+ format!("tail_call {}({}) [effects: {}]", func, args_str, effects)
+ },
+ MirInstruction::Adopt { parent, child } => {
+ format!("adopt {} <- {}", parent, child)
+ },
+ MirInstruction::Release { reference } => {
+ format!("release {}", reference)
+ },
+ MirInstruction::MemCopy { dst, src, size } => {
+ format!("memcopy {} <- {}, {}", dst, src, size)
+ },
+ MirInstruction::AtomicFence { ordering } => {
+ format!("atomic_fence {:?}", ordering)
+ },
}
}