revert: 古いプラグインシステム実装前の状態に巻き戻し

- ソースコードをcommit 3f7d71fの状態に復元(古いプラグインシステム実装前)
- docsフォルダは最新の状態を維持(BID-FFI設計ドキュメント含む)
- nyashバイナリの基本動作確認済み
- BID-FFIシステムをクリーンに再実装する準備完了

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-18 08:34:19 +09:00
parent 75868a5a96
commit bec0e9bc92
35 changed files with 731 additions and 2757 deletions

View File

@ -16,8 +16,6 @@ cli = []
gui = ["dep:egui", "dep:eframe", "dep:egui_extras", "dep:image"] gui = ["dep:egui", "dep:eframe", "dep:egui_extras", "dep:image"]
gui-examples = ["gui"] gui-examples = ["gui"]
all-examples = ["gui-examples"] all-examples = ["gui-examples"]
# 動的ライブラリサポート
dynamic-file = ["dep:libloading"]
[lib] [lib]
name = "nyash_rust" name = "nyash_rust"
@ -29,11 +27,6 @@ crate-type = ["cdylib", "rlib"]
name = "nyash" name = "nyash"
path = "src/main.rs" 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 # Examples for development - only available as examples, not bins
[[example]] [[example]]
name = "gui_simple_notepad" name = "gui_simple_notepad"
@ -120,9 +113,6 @@ js-sys = "0.3"
wabt = "0.10" wabt = "0.10"
wasmtime = "35.0.0" wasmtime = "35.0.0"
# 動的ライブラリロードPhase 9.75f
libloading = { version = "0.8", optional = true }
# GUI フレームワーク - only when gui feature is enabled # GUI フレームワーク - only when gui feature is enabled
egui = { version = "0.29", optional = true } egui = { version = "0.29", optional = true }
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true } eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true }
@ -179,12 +169,3 @@ panic = "abort"
# 開発用設定 # 開発用設定
opt-level = 0 opt-level = 0
debug = true debug = true
# Workspace configuration
[workspace]
members = [
".", # メインのnyash-rustプロジェクト
"plugins/nyash-file", # FileBoxプラグイン
"plugins/nyash-math", # Math/Time系プラグイン
]
resolver = "2"

File diff suppressed because it is too large Load Diff

View File

@ -61,7 +61,7 @@
- ✅ libloadingプラグイン動的ロード基盤 - ✅ libloadingプラグイン動的ロード基盤
-**プラグインシステム統合テスト14/14合格** 🎉 -**プラグインシステム統合テスト14/14合格** 🎉
### 🎯 **Day 5 90%完了!** (2025-08-17) ### 🎯 **Day 5 一時中断** (2025-08-18)
**目標**: 実際のプラグインライブラリ作成と統合 **目標**: 実際のプラグインライブラリ作成と統合
**実装戦略**: **実装戦略**:
@ -75,8 +75,15 @@
- ✅ Nyashインタープリターのプラグインロード統合 - ✅ Nyashインタープリターのプラグインロード統合
- ✅ 透過的切り替え実動作確認PluginBox生成確認 - ✅ 透過的切り替え実動作確認PluginBox生成確認
**残作業最後の10%**: **中断理由**:
- ⏳ PluginBoxのtoString等メソッド実装修正 - 🚨 **古いプラグインシステムのコードが混在していた**
- 🔧 ソースコードをcommit 3f7d71f古いプラグイン実装前に巻き戻し
- 📚 docsフォルダは最新状態を維持
- ✅ nyashバイナリの基本動作確認完了
**再開時の作業**:
- ⏳ BID-FFIシステムをクリーンに再実装
- ⏳ PluginBoxのtoString等メソッド実装
- ⏳ 実際のファイル操作メソッドopen/read/write動作確認 - ⏳ 実際のファイル操作メソッドopen/read/write動作確認
### 🎯 今週の実装計画(段階的戦略に更新) ### 🎯 今週の実装計画(段階的戦略に更新)
@ -153,27 +160,35 @@ cargo build --release -j32
``` ```
--- ---
**最終更新**: 2025-08-17 26:30 **最終更新**: 2025-08-18 08:30 JST
**次回レビュー**: 2025-08-18Day 5-6完了時) **次回レビュー**: 2025-08-18BID-FFI再実装開始時)
## 🎯 **Day 5 最終段階の詳細** ## 🎯 **現在の状況** (2025-08-18)
### 現在の動作状況 ### クリーンアップ完了
1. **nyash.tomlなし**: ビルトインFileBox動作 1. **古いプラグインシステム削除**: ソースコードをcommit 3f7d71fに巻き戻し
2. **nyash.tomlあり**: プラグインFileBoxロード成功 ✅ 2. **ドキュメント保持**: docs/は最新の状態を維持 ✅
3. **PluginBox生成**: 成功type_name: PluginBox 3. **基本動作確認**: nyashバイナリが正常動作
4. **toString呼び出し**: エラーPluginBoxプロキシが未完成 4. **ビルド成功**: `cargo build --release --bin nyash` 完了 ✅
### 残作業詳細 ### BID-FFI実装状況
1. **PluginBox完全実装** - **仕様**: 完成済みdocs/説明書/reference/box-design/ffi-abi-specification.md
- toStringメソッドのプラグイン呼び出し - **設計**: 完成済みdocs/説明書/reference/box-design/plugin-system.md
- ファイル操作メソッドopen/read/write/close転送 - **基盤コード**: src/bid/モジュールは削除済み(再実装必要)
- **プラグイン**: plugins/nyash-filebox-pluginも削除済み再作成必要
2. **BID-FFI統合** ### 次のステップ
- TLVエンコード/デコードの実際の動作 1. **BID-FFIシステムをクリーンに再実装**
- メソッドディスパッチの実装 - src/bid/モジュール作成
- TLVエンコード/デコード実装
- プラグインローダー実装
### 実証成功の証拠 2. **FileBoxプラグイン作成**
- プラグイン動的ロード: `✅ Plugin library loaded: nyash_filebox_plugin` - plugins/nyash-filebox-plugin/再作成
- BoxFactoryRegistry統合: FileBox → PluginBox自動切り替え - C FFI実装
- プラグインシステム基盤: 90%完成! - ビルドシステム構築
3. **統合テスト**
- nyash.tomlによる切り替え
- プラグイン動的ロード確認
- メソッド呼び出し動作確認

View File

@ -1,13 +0,0 @@
🚀 Nyash MIR Compiler - Processing file: local_tests/test_simple_string.nyash 🚀
🚀 MIR Output for local_tests/test_simple_string.nyash:
; MIR Module: main
define void @main() {
bb0:
0: safepoint
1: %0 = const "Hello"
2: %1 = ref_new %0
3: ret %1
}

View File

@ -0,0 +1,2 @@
[plugins]
FileBox = "nyash_filebox_plugin"

View File

@ -53,8 +53,6 @@ impl AotCompiler {
WasmError::UnsupportedInstruction(msg) => AotError::CompilationError(format!("Unsupported MIR instruction: {}", msg)), WasmError::UnsupportedInstruction(msg) => AotError::CompilationError(format!("Unsupported MIR instruction: {}", msg)),
WasmError::WasmValidationError(msg) => AotError::CompilationError(format!("WASM validation failed: {}", msg)), WasmError::WasmValidationError(msg) => AotError::CompilationError(format!("WASM validation failed: {}", msg)),
WasmError::IOError(msg) => AotError::IOError(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(); self.stats.wasm_size = wasm_bytes.len();

View File

@ -231,7 +231,12 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 3: UnaryOp removed - now handled by Call intrinsics (@unary_neg, @unary_not, etc.) MirInstruction::UnaryOp { dst, op, operand } => {
let operand_val = self.get_value(*operand)?;
let result = self.execute_unary_op(op, &operand_val)?;
self.values.insert(*dst, result);
Ok(ControlFlow::Continue)
},
MirInstruction::Compare { dst, op, lhs, rhs } => { MirInstruction::Compare { dst, op, lhs, rhs } => {
let left = self.get_value(*lhs)?; let left = self.get_value(*lhs)?;
@ -241,7 +246,11 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 3: Print removed - now handled by Call intrinsic (@print) MirInstruction::Print { value, .. } => {
let val = self.get_value(*value)?;
println!("{}", val.to_string());
Ok(ControlFlow::Continue)
},
MirInstruction::Return { value } => { MirInstruction::Return { value } => {
let return_value = if let Some(val_id) = value { let return_value = if let Some(val_id) = value {
@ -280,31 +289,27 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 3: Load/Store removed - now handled by BoxFieldLoad/BoxFieldStore // Missing instructions that need basic implementations
MirInstruction::Load { dst, ptr } => {
// For now, loading is the same as getting the value
let value = self.get_value(*ptr)?;
self.values.insert(*dst, value);
Ok(ControlFlow::Continue)
},
MirInstruction::Call { dst, func, args, effects: _ } => { MirInstruction::Store { value, ptr } => {
// Phase 2: Handle intrinsic function calls // For now, storing just updates the ptr with the value
let func_value = self.get_value(*func)?; let val = self.get_value(*value)?;
self.values.insert(*ptr, val);
Ok(ControlFlow::Continue)
},
if let VMValue::String(func_name) = func_value { MirInstruction::Call { dst, func: _, args: _, effects: _ } => {
if func_name.starts_with('@') { // For now, function calls return void
// This is an intrinsic call // TODO: Implement proper function call handling
let result = self.execute_intrinsic(&func_name, args)?;
if let Some(dst_id) = dst {
self.values.insert(*dst_id, result);
}
} else {
// Regular function call - not implemented yet
if let Some(dst_id) = dst { if let Some(dst_id) = dst {
self.values.insert(*dst_id, VMValue::Void); self.values.insert(*dst_id, VMValue::Void);
} }
}
} else {
// Non-string function - not implemented yet
if let Some(dst_id) = dst {
self.values.insert(*dst_id, VMValue::Void);
}
}
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
@ -364,27 +369,67 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 5: Removed instructions - TypeCheck, Cast, ArrayGet, ArraySet, Copy, Debug, Nop MirInstruction::TypeCheck { dst, value: _, expected_type: _ } => {
#[allow(deprecated)] // For now, type checks always return true
MirInstruction::TypeCheck { .. } | // TODO: Implement proper type checking
MirInstruction::Cast { .. } | self.values.insert(*dst, VMValue::Bool(true));
MirInstruction::ArrayGet { .. } | Ok(ControlFlow::Continue)
MirInstruction::ArraySet { .. } |
MirInstruction::Copy { .. } |
MirInstruction::Debug { .. } |
MirInstruction::Nop => {
Err(VMError::InvalidInstruction(
"Phase 5: Deprecated instruction - use 26-instruction set replacements".to_string()
))
}, },
// Phase 5: Removed instructions - Throw, Catch MirInstruction::Cast { dst, value, target_type: _ } => {
#[allow(deprecated)] // For now, casting just copies the value
MirInstruction::Throw { .. } | // TODO: Implement proper type casting
MirInstruction::Catch { .. } => { let val = self.get_value(*value)?;
Err(VMError::InvalidInstruction( self.values.insert(*dst, val);
"Phase 5: Exception handling via intrinsics - use Call with @throw/@catch".to_string() Ok(ControlFlow::Continue)
)) },
MirInstruction::ArrayGet { dst, array: _, index: _ } => {
// For now, array access returns a placeholder
// TODO: Implement proper array access
self.values.insert(*dst, VMValue::Integer(0));
Ok(ControlFlow::Continue)
},
MirInstruction::ArraySet { array: _, index: _, value: _ } => {
// For now, array setting is a no-op
// TODO: Implement proper array setting
Ok(ControlFlow::Continue)
},
MirInstruction::Copy { dst, src } => {
// Copy instruction - duplicate the source value
let val = self.get_value(*src)?;
self.values.insert(*dst, val);
Ok(ControlFlow::Continue)
},
MirInstruction::Debug { value, message: _ } => {
// Debug instruction - print value for debugging
let val = self.get_value(*value)?;
println!("DEBUG: {}", val.to_string());
Ok(ControlFlow::Continue)
},
MirInstruction::Nop => {
// No-op instruction
Ok(ControlFlow::Continue)
},
// Phase 5: Control flow & exception handling
MirInstruction::Throw { exception, effects: _ } => {
let exception_val = self.get_value(*exception)?;
// For now, convert throw to error return (simplified exception handling)
// In a full implementation, this would unwind the stack looking for catch handlers
println!("Exception thrown: {}", exception_val.to_string());
Err(VMError::InvalidInstruction(format!("Unhandled exception: {}", exception_val.to_string())))
},
MirInstruction::Catch { exception_type: _, exception_value, handler_bb: _ } => {
// For now, catch is a no-op since we don't have full exception handling
// In a real implementation, this would set up exception handling metadata
self.values.insert(*exception_value, VMValue::Void);
Ok(ControlFlow::Continue)
}, },
MirInstruction::Safepoint => { MirInstruction::Safepoint => {
@ -393,15 +438,49 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 5: Removed instruction - RefNew // Phase 6: Box reference operations
#[allow(deprecated)] MirInstruction::RefNew { dst, box_val } => {
MirInstruction::RefNew { .. } => { // For now, a reference is just the same as the box value
Err(VMError::InvalidInstruction( // In a real implementation, this would create a proper reference
"Phase 5: RefNew deprecated - RefGet is sufficient".to_string() let box_value = self.get_value(*box_val)?;
)) self.values.insert(*dst, box_value);
Ok(ControlFlow::Continue)
}, },
// Phase 3: RefGet/RefSet removed - now handled by BoxFieldLoad/BoxFieldStore MirInstruction::RefGet { dst, reference, field } => {
// Get field value from object
let field_value = if let Some(fields) = self.object_fields.get(reference) {
if let Some(value) = fields.get(field) {
value.clone()
} else {
// Field not set yet, return default
VMValue::Integer(0)
}
} else {
// Object has no fields yet, return default
VMValue::Integer(0)
};
self.values.insert(*dst, field_value);
Ok(ControlFlow::Continue)
},
MirInstruction::RefSet { reference, field, value } => {
// Get the value to set
let new_value = self.get_value(*value)?;
// Ensure object has field storage
if !self.object_fields.contains_key(reference) {
self.object_fields.insert(*reference, HashMap::new());
}
// Set the field
if let Some(fields) = self.object_fields.get_mut(reference) {
fields.insert(field.clone(), new_value);
}
Ok(ControlFlow::Continue)
},
MirInstruction::WeakNew { dst, box_val } => { MirInstruction::WeakNew { dst, box_val } => {
// For now, a weak reference is just a copy of the value // For now, a weak reference is just a copy of the value
@ -419,23 +498,61 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 5: Removed instructions - BarrierRead, BarrierWrite MirInstruction::BarrierRead { ptr: _ } => {
#[allow(deprecated)] // Memory barrier read is a no-op for now
MirInstruction::BarrierRead { .. } | // In a real implementation, this would ensure memory ordering
MirInstruction::BarrierWrite { .. } => { Ok(ControlFlow::Continue)
Err(VMError::InvalidInstruction(
"Phase 5: Memory barriers deprecated - use AtomicFence".to_string()
))
}, },
// Phase 5: Removed instructions - FutureNew, FutureSet, Await MirInstruction::BarrierWrite { ptr: _ } => {
#[allow(deprecated)] // Memory barrier write is a no-op for now
MirInstruction::FutureNew { .. } | // In a real implementation, this would ensure memory ordering
MirInstruction::FutureSet { .. } | Ok(ControlFlow::Continue)
MirInstruction::Await { .. } => { },
Err(VMError::InvalidInstruction(
"Phase 5: Future operations deprecated - use NewBox + BoxCall".to_string() // Phase 7: Async/Future Operations
)) MirInstruction::FutureNew { dst, value } => {
let initial_value = self.get_value(*value)?;
println!("FutureNew: initial_value = {:?}", initial_value);
let future = crate::boxes::future::FutureBox::new();
// Convert VMValue to NyashBox and set it in the future
let nyash_box = initial_value.to_nyash_box();
println!("FutureNew: converted to NyashBox type = {}", nyash_box.type_name());
future.set_result(nyash_box);
self.values.insert(*dst, VMValue::Future(future));
println!("FutureNew: stored Future in dst = {:?}", dst);
Ok(ControlFlow::Continue)
},
MirInstruction::FutureSet { future, value } => {
let future_val = self.get_value(*future)?;
let new_value = self.get_value(*value)?;
if let VMValue::Future(ref future_box) = future_val {
future_box.set_result(new_value.to_nyash_box());
Ok(ControlFlow::Continue)
} else {
Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val)))
}
},
MirInstruction::Await { dst, future } => {
let future_val = self.get_value(*future)?;
println!("Await: future_val = {:?}", future_val);
if let VMValue::Future(ref future_box) = future_val {
// This blocks until the future is ready
let result = future_box.get();
println!("Await: future.get() returned type = {}", result.type_name());
println!("Await: future.get() string = {}", result.to_string_box().value);
// Convert NyashBox back to VMValue
let vm_value = VMValue::from_nyash_box(result);
println!("Await: converted back to VMValue = {:?}", vm_value);
self.values.insert(*dst, vm_value);
Ok(ControlFlow::Continue)
} else {
Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val)))
}
}, },
// Phase 9.7: External Function Calls // Phase 9.7: External Function Calls
@ -468,134 +585,6 @@ impl VM {
Ok(ControlFlow::Continue) Ok(ControlFlow::Continue)
}, },
// Phase 8.5: MIR 26-instruction reduction (NEW)
MirInstruction::BoxFieldLoad { dst, box_val, field } => {
// Load field from box (Everything is Box principle)
let box_value = self.get_value(*box_val)?;
// For now, simulate field access - in full implementation,
// this would access actual Box structure fields
let field_value = match field.as_str() {
"value" => box_value.clone(), // Default field
"type" => VMValue::String(format!("{}Field", box_val)),
_ => VMValue::String(format!("field_{}", field)),
};
self.values.insert(*dst, field_value);
Ok(ControlFlow::Continue)
},
MirInstruction::BoxFieldStore { box_val, field: _, value } => {
// Store field in box (Everything is Box principle)
let _box_value = self.get_value(*box_val)?;
let _store_value = self.get_value(*value)?;
// For now, this is a no-op - in full implementation,
// this would modify actual Box structure fields
// println!("Storing {} in {}.{}", store_value, box_val, field);
Ok(ControlFlow::Continue)
},
MirInstruction::WeakCheck { dst, weak_ref } => {
// Check if weak reference is still alive
let _weak_value = self.get_value(*weak_ref)?;
// For now, always return true - in full implementation,
// this would check actual weak reference validity
self.values.insert(*dst, VMValue::Bool(true));
Ok(ControlFlow::Continue)
},
MirInstruction::Send { data, target } => {
// Send data via Bus system
let _data_value = self.get_value(*data)?;
let _target_value = self.get_value(*target)?;
// For now, this is a no-op - in full implementation,
// this would use the Bus communication system
// println!("Sending {} to {}", data_value, target_value);
Ok(ControlFlow::Continue)
},
MirInstruction::Recv { dst, source } => {
// Receive data from Bus system
let _source_value = self.get_value(*source)?;
// For now, return a placeholder - in full implementation,
// this would receive from actual Bus communication
self.values.insert(*dst, VMValue::String("received_data".to_string()));
Ok(ControlFlow::Continue)
},
MirInstruction::TailCall { func, args, effects: _ } => {
// Tail call optimization - call function and return immediately
let _func_value = self.get_value(*func)?;
let _arg_values: Result<Vec<_>, _> = args.iter().map(|arg| self.get_value(*arg)).collect();
// For now, this is simplified - in full implementation,
// this would optimize the call stack
// println!("Tail calling function with {} args", args.len());
Ok(ControlFlow::Continue)
},
MirInstruction::Adopt { parent, child } => {
// Adopt ownership (parent takes child)
let _parent_value = self.get_value(*parent)?;
let _child_value = self.get_value(*child)?;
// For now, this is a no-op - in full implementation,
// this would modify ownership relationships
// println!("Parent {} adopts child {}", parent, child);
Ok(ControlFlow::Continue)
},
MirInstruction::Release { reference } => {
// Release strong ownership
let _ref_value = self.get_value(*reference)?;
// For now, this is a no-op - in full implementation,
// this would release strong ownership and potentially weak-ify
// println!("Releasing ownership of {}", reference);
Ok(ControlFlow::Continue)
},
MirInstruction::MemCopy { dst, src, size } => {
// Memory copy optimization
let src_value = self.get_value(*src)?;
let _size_value = self.get_value(*size)?;
// For now, just copy the source value
self.values.insert(*dst, src_value);
Ok(ControlFlow::Continue)
},
MirInstruction::AtomicFence { ordering: _ } => {
// Atomic memory fence
// For now, this is a no-op - in full implementation,
// this would ensure proper memory ordering for parallel execution
// println!("Memory fence with ordering: {:?}", ordering);
Ok(ControlFlow::Continue)
},
// Phase 3: Removed instructions that are no longer generated by frontend
MirInstruction::UnaryOp { .. } |
MirInstruction::Print { .. } |
MirInstruction::Load { .. } |
MirInstruction::Store { .. } |
MirInstruction::RefGet { .. } |
MirInstruction::RefSet { .. } => {
Err(VMError::InvalidInstruction(
"Old instruction format no longer supported - use new intrinsic/BoxField format".to_string()
))
},
} }
} }
@ -802,86 +791,6 @@ impl VM {
// Default: return void for any unrecognized box type or method // Default: return void for any unrecognized box type or method
Ok(Box::new(VoidBox::new())) Ok(Box::new(VoidBox::new()))
} }
/// Execute intrinsic function call (Phase 2 addition)
fn execute_intrinsic(&mut self, intrinsic_name: &str, args: &[ValueId]) -> Result<VMValue, VMError> {
match intrinsic_name {
"@print" => {
// Print intrinsic - output the first argument
if let Some(arg_id) = args.first() {
let value = self.get_value(*arg_id)?;
match value {
VMValue::String(s) => println!("{}", s),
VMValue::Integer(i) => println!("{}", i),
VMValue::Float(f) => println!("{}", f),
VMValue::Bool(b) => println!("{}", b),
VMValue::Void => println!("void"),
VMValue::Future(_) => println!("Future"),
}
}
Ok(VMValue::Void) // Print returns void
},
"@unary_neg" => {
// Unary negation intrinsic
if let Some(arg_id) = args.first() {
let value = self.get_value(*arg_id)?;
match value {
VMValue::Integer(i) => Ok(VMValue::Integer(-i)),
VMValue::Float(f) => Ok(VMValue::Float(-f)),
_ => Err(VMError::TypeError(format!("Cannot negate {:?}", value))),
}
} else {
Err(VMError::TypeError("@unary_neg requires 1 argument".to_string()))
}
},
"@unary_not" => {
// Unary logical NOT intrinsic
if let Some(arg_id) = args.first() {
let value = self.get_value(*arg_id)?;
match value {
VMValue::Bool(b) => Ok(VMValue::Bool(!b)),
VMValue::Integer(i) => Ok(VMValue::Bool(i == 0)), // 0 is false, non-zero is true
_ => Err(VMError::TypeError(format!("Cannot apply NOT to {:?}", value))),
}
} else {
Err(VMError::TypeError("@unary_not requires 1 argument".to_string()))
}
},
"@unary_bitnot" => {
// Unary bitwise NOT intrinsic
if let Some(arg_id) = args.first() {
let value = self.get_value(*arg_id)?;
match value {
VMValue::Integer(i) => Ok(VMValue::Integer(!i)),
_ => Err(VMError::TypeError(format!("Cannot apply bitwise NOT to {:?}", value))),
}
} else {
Err(VMError::TypeError("@unary_bitnot requires 1 argument".to_string()))
}
},
"@throw" => {
// Throw intrinsic - for now just print the exception
if let Some(arg_id) = args.first() {
let value = self.get_value(*arg_id)?;
println!("Exception thrown: {:?}", value);
}
Err(VMError::InvalidInstruction("Exception thrown".to_string()))
},
"@set_exception_handler" => {
// Exception handler setup - for now just return success
Ok(VMValue::Void)
},
_ => {
Err(VMError::InvalidInstruction(format!("Unknown intrinsic: {}", intrinsic_name)))
}
}
}
} }
/// Control flow result from instruction execution /// Control flow result from instruction execution

View File

@ -244,18 +244,47 @@ impl WasmCodegen {
self.generate_return(value.as_ref()) self.generate_return(value.as_ref())
}, },
// Phase 3: Print removed - now handled by Call intrinsic (@print) MirInstruction::Print { value, .. } => {
self.generate_print(*value)
// Phase 8.3 PoC2: Reference operations
// Phase 5: RefNew deprecated - just use the value directly
#[allow(deprecated)]
MirInstruction::RefNew { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: RefNew deprecated - references are handled implicitly".to_string()
))
}, },
// Phase 3: RefGet/RefSet removed - now handled by BoxFieldLoad/BoxFieldStore // Phase 8.3 PoC2: Reference operations
MirInstruction::RefNew { dst, box_val } => {
// Create a new reference to a Box by copying the Box value
// This assumes box_val contains a Box pointer already
Ok(vec![
format!("local.get ${}", self.get_local_index(*box_val)?),
format!("local.set ${}", self.get_local_index(*dst)?),
])
},
MirInstruction::RefGet { dst, reference, field: _ } => {
// Load field value from Box through reference
// reference contains Box pointer, field is the field name
// For now, assume all fields are at offset 12 (first field after header)
// TODO: Add proper field offset calculation
Ok(vec![
format!("local.get ${}", self.get_local_index(*reference)?),
"i32.const 12".to_string(), // Offset: header (12 bytes) + first field
"i32.add".to_string(),
"i32.load".to_string(),
format!("local.set ${}", self.get_local_index(*dst)?),
])
},
MirInstruction::RefSet { reference, field: _, value } => {
// Store field value to Box through reference
// reference contains Box pointer, field is the field name, value is new value
// For now, assume all fields are at offset 12 (first field after header)
// TODO: Add proper field offset calculation
Ok(vec![
format!("local.get ${}", self.get_local_index(*reference)?),
"i32.const 12".to_string(), // Offset: header (12 bytes) + first field
"i32.add".to_string(),
format!("local.get ${}", self.get_local_index(*value)?),
"i32.store".to_string(),
])
},
MirInstruction::NewBox { dst, box_type, args } => { MirInstruction::NewBox { dst, box_type, args } => {
// Create a new Box using the generic allocator // Create a new Box using the generic allocator
@ -294,54 +323,29 @@ impl WasmCodegen {
}, },
// Phase 8.4 PoC3: Extension stubs // Phase 8.4 PoC3: Extension stubs
MirInstruction::WeakNew { dst, box_val } => { MirInstruction::WeakNew { dst, box_val } |
// WeakNew is still part of 26-instruction set MirInstruction::FutureNew { dst, value: box_val } => {
// Treat as regular reference for now
Ok(vec![ Ok(vec![
format!("local.get ${}", self.get_local_index(*box_val)?), format!("local.get ${}", self.get_local_index(*box_val)?),
format!("local.set ${}", self.get_local_index(*dst)?), format!("local.set ${}", self.get_local_index(*dst)?),
]) ])
}, },
// Phase 5: FutureNew deprecated - use NewBox "Future" MirInstruction::WeakLoad { dst, weak_ref } |
#[allow(deprecated)] MirInstruction::Await { dst, future: weak_ref } => {
MirInstruction::FutureNew { .. } => { // Always succeed for now
Err(WasmError::UnsupportedInstruction(
"Phase 5: FutureNew deprecated - use 'NewBox \"Future\"' instead".to_string()
))
},
MirInstruction::WeakLoad { dst, weak_ref } => {
// WeakLoad is still part of 26-instruction set
Ok(vec![ Ok(vec![
format!("local.get ${}", self.get_local_index(*weak_ref)?), format!("local.get ${}", self.get_local_index(*weak_ref)?),
format!("local.set ${}", self.get_local_index(*dst)?), format!("local.set ${}", self.get_local_index(*dst)?),
]) ])
}, },
// Phase 5: Await deprecated - use BoxCall Future.await() MirInstruction::BarrierRead { .. } |
#[allow(deprecated)] MirInstruction::BarrierWrite { .. } |
MirInstruction::Await { .. } => { MirInstruction::FutureSet { .. } |
Err(WasmError::UnsupportedInstruction(
"Phase 5: Await deprecated - use 'BoxCall Future.await()' instead".to_string()
))
},
// Phase 5: BarrierRead/BarrierWrite deprecated - use AtomicFence
#[allow(deprecated)]
MirInstruction::BarrierRead { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: BarrierRead deprecated - use AtomicFence with acquire ordering".to_string()
))
},
#[allow(deprecated)]
MirInstruction::BarrierWrite { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: BarrierWrite deprecated - use AtomicFence with release ordering".to_string()
))
},
MirInstruction::Safepoint => { MirInstruction::Safepoint => {
// Safepoint is still valid - no-op for now // No-op for now
Ok(vec!["nop".to_string()]) Ok(vec!["nop".to_string()])
}, },
@ -404,189 +408,6 @@ impl WasmCodegen {
self.generate_box_call(*dst, *box_val, method, args) self.generate_box_call(*dst, *box_val, method, args)
}, },
// Phase 8.5: MIR 26-instruction reduction (NEW)
MirInstruction::BoxFieldLoad { dst, box_val, field: _ } => {
// Load field from box (similar to RefGet but with explicit Box semantics)
// For now, assume all fields are at offset 12 (first field after header)
Ok(vec![
format!("local.get ${}", self.get_local_index(*box_val)?),
"i32.const 12".to_string(), // Box header + first field offset
"i32.add".to_string(),
"i32.load".to_string(),
format!("local.set ${}", self.get_local_index(*dst)?),
])
},
MirInstruction::BoxFieldStore { box_val, field: _, value } => {
// Store field to box (similar to RefSet but with explicit Box semantics)
Ok(vec![
format!("local.get ${}", self.get_local_index(*box_val)?),
"i32.const 12".to_string(), // Box header + first field offset
"i32.add".to_string(),
format!("local.get ${}", self.get_local_index(*value)?),
"i32.store".to_string(),
])
},
MirInstruction::WeakCheck { dst, weak_ref } => {
// Check if weak reference is still alive
// For now, always return 1 (true) - in full implementation,
// this would check actual weak reference validity
Ok(vec![
format!("local.get ${}", self.get_local_index(*weak_ref)?), // Touch the ref
"drop".to_string(), // Ignore the actual value
"i32.const 1".to_string(), // Always alive for now
format!("local.set ${}", self.get_local_index(*dst)?),
])
},
MirInstruction::Send { data, target } => {
// Send data via Bus system - no-op for now
Ok(vec![
format!("local.get ${}", self.get_local_index(*data)?),
format!("local.get ${}", self.get_local_index(*target)?),
"drop".to_string(), // Drop target
"drop".to_string(), // Drop data
"nop".to_string(), // No actual send operation
])
},
MirInstruction::Recv { dst, source } => {
// Receive data from Bus system - return constant for now
Ok(vec![
format!("local.get ${}", self.get_local_index(*source)?), // Touch source
"drop".to_string(), // Ignore source
"i32.const 42".to_string(), // Placeholder received data
format!("local.set ${}", self.get_local_index(*dst)?),
])
},
MirInstruction::TailCall { func, args, effects: _ } => {
// Tail call optimization - simplified as regular call for now
let mut instructions = Vec::new();
// Load all arguments
for arg in args {
instructions.push(format!("local.get ${}", self.get_local_index(*arg)?));
}
// Call function (assuming it's a function index)
instructions.push(format!("local.get ${}", self.get_local_index(*func)?));
instructions.push("call_indirect".to_string());
Ok(instructions)
},
MirInstruction::Adopt { parent, child } => {
// Adopt ownership - no-op for now in WASM
Ok(vec![
format!("local.get ${}", self.get_local_index(*parent)?),
format!("local.get ${}", self.get_local_index(*child)?),
"drop".to_string(), // Drop child
"drop".to_string(), // Drop parent
"nop".to_string(), // No actual adoption
])
},
MirInstruction::Release { reference } => {
// Release strong ownership - no-op for now
Ok(vec![
format!("local.get ${}", self.get_local_index(*reference)?),
"drop".to_string(), // Drop reference
"nop".to_string(), // No actual release
])
},
MirInstruction::MemCopy { dst, src, size } => {
// Memory copy optimization - simple copy for now
Ok(vec![
format!("local.get ${}", self.get_local_index(*src)?),
format!("local.set ${}", self.get_local_index(*dst)?),
// Size is ignored for now - in full implementation,
// this would use memory.copy instruction
format!("local.get ${}", self.get_local_index(*size)?),
"drop".to_string(),
])
},
MirInstruction::AtomicFence { ordering: _ } => {
// Atomic memory fence - no-op for now
// WASM doesn't have direct memory fence instructions
// In full implementation, this might use atomic wait/notify
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)
},
// Phase 5: Removed instructions - TypeCheck, Cast, ArrayGet, ArraySet, Copy, Debug, Nop
#[allow(deprecated)]
MirInstruction::TypeCheck { .. } |
MirInstruction::Cast { .. } |
MirInstruction::ArrayGet { .. } |
MirInstruction::ArraySet { .. } |
MirInstruction::Copy { .. } |
MirInstruction::Debug { .. } |
MirInstruction::Nop => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: Deprecated instruction - use 26-instruction set replacements".to_string()
))
},
// Phase 5: Removed instructions - UnaryOp (use BinOp instead)
#[allow(deprecated)]
MirInstruction::UnaryOp { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: UnaryOp deprecated - use BinOp (e.g., 'not x' -> 'x xor true', 'neg x' -> '0 sub x')".to_string()
))
},
// Phase 5: Removed instructions - Load/Store (use BoxFieldLoad/BoxFieldStore)
#[allow(deprecated)]
MirInstruction::Load { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: Load deprecated - use BoxFieldLoad for field access".to_string()
))
},
#[allow(deprecated)]
MirInstruction::Store { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: Store deprecated - use BoxFieldStore for field updates".to_string()
))
},
// Phase 5: Removed instructions - Print (use Call @print)
#[allow(deprecated)]
MirInstruction::Print { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: Print deprecated - use 'Call @print' intrinsic function".to_string()
))
},
// Phase 5: Removed instructions - Throw/Catch (use Call @throw/@catch)
#[allow(deprecated)]
MirInstruction::Throw { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: Throw deprecated - use 'Call @throw' intrinsic function".to_string()
))
},
#[allow(deprecated)]
MirInstruction::Catch { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: Catch deprecated - use 'Call @catch' intrinsic function".to_string()
))
},
// Phase 5: Removed FutureSet - use BoxCall instead
#[allow(deprecated)]
MirInstruction::FutureSet { .. } => {
Err(WasmError::UnsupportedInstruction(
"Phase 5: FutureSet deprecated - use BoxCall method for Future.set()".to_string()
))
},
// Unsupported instructions // Unsupported instructions
_ => Err(WasmError::UnsupportedInstruction( _ => Err(WasmError::UnsupportedInstruction(
format!("Instruction not yet supported: {:?}", instruction) format!("Instruction not yet supported: {:?}", instruction)
@ -865,36 +686,6 @@ impl WasmCodegen {
Ok(instructions) Ok(instructions)
} }
/// Generate Call instruction for intrinsic functions (Phase 4)
fn generate_call_instruction(&mut self, dst: Option<&ValueId>, func: ValueId, args: &[ValueId]) -> Result<Vec<String>, 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)] #[cfg(test)]

View File

@ -8,13 +8,10 @@
mod codegen; mod codegen;
mod memory; mod memory;
mod runtime; mod runtime;
mod host;
mod executor;
pub use codegen::{WasmCodegen, WasmModule}; pub use codegen::{WasmCodegen, WasmModule};
pub use memory::{MemoryManager, BoxLayout}; pub use memory::{MemoryManager, BoxLayout};
pub use runtime::RuntimeImports; pub use runtime::RuntimeImports;
pub use executor::WasmExecutor;
use crate::mir::MirModule; use crate::mir::MirModule;
@ -26,8 +23,6 @@ pub enum WasmError {
UnsupportedInstruction(String), UnsupportedInstruction(String),
WasmValidationError(String), WasmValidationError(String),
IOError(String), IOError(String),
RuntimeError(String),
CompilationError(String),
} }
impl std::fmt::Display for WasmError { impl std::fmt::Display for WasmError {
@ -38,8 +33,6 @@ impl std::fmt::Display for WasmError {
WasmError::UnsupportedInstruction(msg) => write!(f, "Unsupported instruction: {}", msg), WasmError::UnsupportedInstruction(msg) => write!(f, "Unsupported instruction: {}", msg),
WasmError::WasmValidationError(msg) => write!(f, "WASM validation error: {}", msg), WasmError::WasmValidationError(msg) => write!(f, "WASM validation error: {}", msg),
WasmError::IOError(msg) => write!(f, "IO 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),
} }
} }
} }

View File

@ -3,7 +3,6 @@
// 参考: 既存Boxの設計思想 // 参考: 既存Boxの設計思想
use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase}; use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase};
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
use std::any::Any; use std::any::Any;
use std::sync::RwLock; use std::sync::RwLock;
@ -147,25 +146,6 @@ impl std::fmt::Display for NyashFutureBox {
} }
} }
impl BidBridge for NyashFutureBox {
fn to_bid_handle(&self, registry: &mut BoxRegistry) -> Result<BidHandle, BidError> {
use std::sync::Arc;
let arc_box: Arc<dyn NyashBox> = Arc::new(self.clone());
let handle = registry.register_box(
crate::bid::types::BoxTypeId::FutureBox as u32,
arc_box
);
Ok(handle)
}
fn bid_type(&self) -> BidType {
BidType::Handle {
type_id: crate::bid::types::BoxTypeId::FutureBox as u32,
instance_id: 0 // Will be filled by registry
}
}
}
// Export NyashFutureBox as FutureBox for consistency // Export NyashFutureBox as FutureBox for consistency
pub type FutureBox = NyashFutureBox; pub type FutureBox = NyashFutureBox;

View File

@ -38,7 +38,6 @@
*/ */
use crate::box_trait::{NyashBox, BoxCore, BoxBase}; use crate::box_trait::{NyashBox, BoxCore, BoxBase};
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
use std::any::Any; use std::any::Any;
use std::fmt::Display; use std::fmt::Display;
@ -118,22 +117,3 @@ impl Display for IntegerBox {
self.fmt_box(f) self.fmt_box(f)
} }
} }
impl BidBridge for IntegerBox {
fn to_bid_handle(&self, registry: &mut BoxRegistry) -> Result<BidHandle, BidError> {
use std::sync::Arc;
let arc_box: Arc<dyn NyashBox> = Arc::new(self.clone());
let handle = registry.register_box(
crate::bid::types::BoxTypeId::IntegerBox as u32,
arc_box
);
Ok(handle)
}
fn bid_type(&self) -> BidType {
BidType::Handle {
type_id: crate::bid::types::BoxTypeId::IntegerBox as u32,
instance_id: 0 // Will be filled by registry
}
}
}

View File

@ -28,7 +28,6 @@
* ``` * ```
*/ */
use crate::box_trait::{NyashBox, BoxCore, BoxBase}; use crate::box_trait::{NyashBox, BoxCore, BoxBase};
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
use std::any::Any; use std::any::Any;
use std::fmt::Display; use std::fmt::Display;
@ -186,22 +185,3 @@ impl Display for StringBox {
self.fmt_box(f) self.fmt_box(f)
} }
} }
impl BidBridge for StringBox {
fn to_bid_handle(&self, registry: &mut BoxRegistry) -> Result<BidHandle, BidError> {
use std::sync::Arc;
let arc_box: Arc<dyn NyashBox> = Arc::new(self.clone());
let handle = registry.register_box(
crate::bid::types::BoxTypeId::StringBox as u32,
arc_box
);
Ok(handle)
}
fn bid_type(&self) -> BidType {
BidType::Handle {
type_id: crate::bid::types::BoxTypeId::StringBox as u32,
instance_id: 0 // Will be filled by registry
}
}
}

View File

@ -516,7 +516,7 @@ mod tests {
// フィールドに値を設定 // フィールドに値を設定
let int_value = Box::new(IntegerBox::new(42)) as Box<dyn NyashBox>; let int_value = Box::new(IntegerBox::new(42)) as Box<dyn NyashBox>;
instance.set_field("value", int_value.into()).unwrap(); instance.set_field("value", int_value).unwrap();
// フィールドの値を取得 // フィールドの値を取得
let retrieved = instance.get_field("value").unwrap(); let retrieved = instance.get_field("value").unwrap();

View File

@ -350,13 +350,13 @@ impl NyashInterpreter {
// 2. local変数をチェック // 2. local変数をチェック
if let Some(local_value) = self.local_vars.get(name) { if let Some(local_value) = self.local_vars.get(name) {
eprintln!("🔍 DEBUG: Found '{}' in local_vars, type: {}", name, local_value.type_name()); eprintln!("🔍 DEBUG: Found '{}' in local_vars", name);
// 🔧 修正clone_box() → Arc::clone() で参照共有 // 🔧 修正clone_box() → Arc::clone() で参照共有
let shared_value = Arc::clone(local_value); let shared_value = Arc::clone(local_value);
eprintln!("✅ RESOLVE_VARIABLE shared reference: {} id={}, type: {}", eprintln!("✅ RESOLVE_VARIABLE shared reference: {} id={}",
name, shared_value.box_id(), shared_value.type_name()); name, shared_value.box_id());
return Ok(shared_value); return Ok(shared_value);
} }
@ -478,12 +478,7 @@ impl NyashInterpreter {
/// local変数を宣言関数内でのみ有効 /// local変数を宣言関数内でのみ有効
pub(super) fn declare_local_variable(&mut self, name: &str, value: Box<dyn NyashBox>) { pub(super) fn declare_local_variable(&mut self, name: &str, value: Box<dyn NyashBox>) {
eprintln!("🔍 DEBUG: declare_local_variable '{}' with type: {}, id: {}", self.local_vars.insert(name.to_string(), Arc::from(value));
name, value.type_name(), value.box_id());
let arc_value: Arc<dyn NyashBox> = Arc::from(value);
eprintln!("🔍 DEBUG: After Arc::from, type: {}, id: {}",
arc_value.type_name(), arc_value.box_id());
self.local_vars.insert(name.to_string(), arc_value);
} }
/// outbox変数を宣言static関数内で所有権移転 /// outbox変数を宣言static関数内で所有権移転

View File

@ -13,8 +13,6 @@ use crate::instance::InstanceBox;
use crate::channel_box::ChannelBox; use crate::channel_box::ChannelBox;
use crate::interpreter::core::{NyashInterpreter, RuntimeError}; use crate::interpreter::core::{NyashInterpreter, RuntimeError};
use crate::interpreter::finalization; use crate::interpreter::finalization;
#[cfg(feature = "dynamic-file")]
use crate::interpreter::plugin_loader::FileBoxProxy;
use std::sync::Arc; use std::sync::Arc;
impl NyashInterpreter { impl NyashInterpreter {
@ -257,18 +255,6 @@ impl NyashInterpreter {
return self.execute_file_method(file_box, method, arguments); return self.execute_file_method(file_box, method, arguments);
} }
// FileBoxProxy method calls (動的ライブラリ版)
#[cfg(feature = "dynamic-file")]
{
eprintln!("🔍 DEBUG: Checking if object is FileBoxProxy, type_name: {}", obj_value.type_name());
if let Some(file_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::FileBoxProxy>() {
eprintln!("✅ DEBUG: Object is FileBoxProxy, calling execute_file_proxy_method");
return self.execute_file_proxy_method(file_proxy, method, arguments);
} else {
eprintln!("❌ DEBUG: Object is NOT FileBoxProxy");
}
}
// ResultBox method calls // ResultBox method calls
if let Some(result_box) = obj_value.as_any().downcast_ref::<crate::box_trait::ResultBox>() { if let Some(result_box) = obj_value.as_any().downcast_ref::<crate::box_trait::ResultBox>() {
return self.execute_result_method(result_box, method, arguments); return self.execute_result_method(result_box, method, arguments);

View File

@ -8,10 +8,7 @@
use super::*; use super::*;
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox}; 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}; 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; use std::sync::Arc;
impl NyashInterpreter { impl NyashInterpreter {
@ -241,43 +238,25 @@ impl NyashInterpreter {
} }
// MathBox method calls // MathBox method calls
#[cfg(not(feature = "dynamic-file"))]
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() { if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
return self.execute_math_method(math_box, method, arguments); return self.execute_math_method(math_box, method, arguments);
} }
#[cfg(feature = "dynamic-file")]
if let Some(math_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::MathBoxProxy>() {
return self.execute_math_proxy_method(math_proxy, method, arguments);
}
// NullBox method calls // NullBox method calls
if let Some(null_box) = obj_value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>() { if let Some(null_box) = obj_value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>() {
return self.execute_null_method(null_box, method, arguments); return self.execute_null_method(null_box, method, arguments);
} }
// TimeBox method calls // TimeBox method calls
#[cfg(not(feature = "dynamic-file"))]
if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() { if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() {
return self.execute_time_method(time_box, method, arguments); return self.execute_time_method(time_box, method, arguments);
} }
#[cfg(feature = "dynamic-file")]
if let Some(time_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::TimeBoxProxy>() {
return self.execute_time_proxy_method(time_proxy, method, arguments);
}
// DateTimeBox method calls // DateTimeBox method calls
#[cfg(not(feature = "dynamic-file"))]
if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() { if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() {
return self.execute_datetime_method(datetime_box, method, arguments); return self.execute_datetime_method(datetime_box, method, arguments);
} }
#[cfg(feature = "dynamic-file")]
if let Some(datetime_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::DateTimeBoxProxy>() {
return self.execute_datetime_proxy_method(datetime_proxy, method, arguments);
}
// TimerBox method calls // TimerBox method calls
if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() { if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() {
return self.execute_timer_method(timer_box, method, arguments); return self.execute_timer_method(timer_box, method, arguments);
@ -289,16 +268,10 @@ impl NyashInterpreter {
} }
// RandomBox method calls // RandomBox method calls
#[cfg(not(feature = "dynamic-file"))]
if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() { if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() {
return self.execute_random_method(random_box, method, arguments); return self.execute_random_method(random_box, method, arguments);
} }
#[cfg(feature = "dynamic-file")]
if let Some(random_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::RandomBoxProxy>() {
return self.execute_random_proxy_method(random_proxy, method, arguments);
}
// SoundBox method calls // SoundBox method calls
if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() { if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() {
return self.execute_sound_method(sound_box, method, arguments); return self.execute_sound_method(sound_box, method, arguments);

View File

@ -10,64 +10,11 @@
use super::super::*; use super::super::*;
use crate::box_trait::{ResultBox, StringBox, NyashBox}; use crate::box_trait::{ResultBox, StringBox, NyashBox};
use crate::boxes::FileBox; use crate::boxes::FileBox;
#[cfg(feature = "dynamic-file")]
use crate::interpreter::plugin_loader::FileBoxProxy;
impl NyashInterpreter { impl NyashInterpreter {
/// FileBoxのメソッド呼び出しを実行 /// FileBoxのメソッド呼び出しを実行
/// Handles file I/O operations including read, write, exists, delete, and copy /// Handles file I/O operations including read, write, exists, delete, and copy
pub(in crate::interpreter) fn execute_file_method(&mut self, file_box: &FileBox, method: &str, arguments: &[ASTNode]) pub(in crate::interpreter) fn execute_file_method(&mut self, file_box: &FileBox, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
self.execute_file_method_static(file_box, method, arguments)
}
/// FileBoxProxyのメソッド呼び出しを実行動的ライブラリ版
#[cfg(feature = "dynamic-file")]
pub(in crate::interpreter) fn execute_file_proxy_method(&mut self, file_box: &FileBoxProxy, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
eprintln!("🔍 DEBUG: execute_file_proxy_method called with method: '{}'", method);
match method {
"read" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("read() expects 0 arguments, got {}", arguments.len()),
});
}
file_box.read()
}
"write" => {
if arguments.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("write() expects 1 argument, got {}", arguments.len()),
});
}
let content = self.execute_expression(&arguments[0])?;
file_box.write(content)
}
"exists" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("exists() expects 0 arguments, got {}", arguments.len()),
});
}
file_box.exists()
}
"toString" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("toString() expects 0 arguments, got {}", arguments.len()),
});
}
Ok(Box::new(file_box.to_string_box()))
}
_ => Err(RuntimeError::InvalidOperation {
message: format!("Undefined method '{}' for FileBox", method),
}),
}
}
/// 静的FileBoxのメソッド実装
fn execute_file_method_static(&mut self, file_box: &FileBox, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> { -> Result<Box<dyn NyashBox>, RuntimeError> {
match method { match method {
"read" => { "read" => {
@ -118,14 +65,6 @@ impl NyashInterpreter {
}) })
} }
} }
"toString" => {
if !arguments.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("toString() expects 0 arguments, got {}", arguments.len()),
});
}
Ok(Box::new(file_box.to_string_box()))
}
_ => Err(RuntimeError::InvalidOperation { _ => Err(RuntimeError::InvalidOperation {
message: format!("Unknown method '{}' for FileBox", method), message: format!("Unknown method '{}' for FileBox", method),
}) })

View File

@ -23,6 +23,5 @@ pub mod data_methods; // BufferBox, JSONBox, RegexBox
pub mod network_methods; // HttpClientBox, StreamBox pub mod network_methods; // HttpClientBox, StreamBox
pub mod p2p_methods; // IntentBox, P2PBox pub mod p2p_methods; // IntentBox, P2PBox
pub mod http_methods; // SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox pub mod http_methods; // SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox
pub mod math_methods; // MathBox, RandomBox, TimeBox, DateTimeBox
// Re-export methods for easy access // Re-export methods for easy access

View File

@ -7,9 +7,7 @@
// Import all necessary dependencies // Import all necessary dependencies
use crate::ast::{ASTNode, CatchClause}; use crate::ast::{ASTNode, CatchClause};
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, ArrayBox, ResultBox, ErrorBox, BoxCore}; use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, ArrayBox, FileBox, ResultBox, ErrorBox, BoxCore};
#[cfg(not(feature = "dynamic-file"))]
use crate::box_trait::FileBox;
use crate::boxes::FutureBox; use crate::boxes::FutureBox;
use crate::instance::InstanceBox; use crate::instance::InstanceBox;
use crate::channel_box::ChannelBox; use crate::channel_box::ChannelBox;
@ -42,16 +40,10 @@ mod math_methods;
mod system_methods; mod system_methods;
mod web_methods; mod web_methods;
mod special_methods; mod special_methods;
#[cfg(feature = "dynamic-file")]
mod plugin_loader;
// Main interpreter implementation - will be moved from interpreter.rs // Main interpreter implementation - will be moved from interpreter.rs
pub use core::NyashInterpreter; pub use core::NyashInterpreter;
// Dynamic plugin support
#[cfg(feature = "dynamic-file")]
pub use plugin_loader::{PluginLoader, FileBoxProxy};
/// 実行制御フロー /// 実行制御フロー
#[derive(Debug)] #[derive(Debug)]

View File

@ -7,11 +7,7 @@
*/ */
use super::*; use super::*;
use crate::boxes::{NullBox, ConsoleBox, FloatBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox}; use crate::boxes::{NullBox, ConsoleBox, FloatBox, DateTimeBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
#[cfg(not(feature = "dynamic-file"))]
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::boxes::intent_box_wrapper::IntentBoxWrapper;
use crate::box_trait::SharedNyashBox; use crate::box_trait::SharedNyashBox;
use std::sync::Arc; use std::sync::Arc;
@ -98,18 +94,16 @@ impl NyashInterpreter {
message: format!("FileBox constructor expects 1 argument, got {}", arguments.len()), message: format!("FileBox constructor expects 1 argument, got {}", arguments.len()),
}); });
} }
// BoxFactoryRegistryを使用して作成プラグイン対応 let path_value = self.execute_expression(&arguments[0])?;
use crate::runtime::get_global_registry; if let Some(path_str) = path_value.as_any().downcast_ref::<StringBox>() {
let registry = get_global_registry(); let file_box = Box::new(FileBox::new(&path_str.value)) as Box<dyn NyashBox>;
// 🌍 革命的実装Environment tracking廃止
// 引数を評価 return Ok(file_box);
let mut evaluated_args = Vec::new(); } else {
for arg in arguments { return Err(RuntimeError::TypeError {
evaluated_args.push(self.execute_expression(arg)?); message: "FileBox constructor requires string path argument".to_string(),
});
} }
return registry.create_box("FileBox", &evaluated_args)
.map_err(|e| RuntimeError::InvalidOperation { message: e });
} }
"ResultBox" => { "ResultBox" => {
// ResultBoxは引数1個成功値で作成 // ResultBoxは引数1個成功値で作成
@ -153,34 +147,10 @@ impl NyashInterpreter {
message: format!("MathBox constructor expects 0 arguments, got {}", arguments.len()), message: format!("MathBox constructor expects 0 arguments, got {}", arguments.len()),
}); });
} }
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<dyn NyashBox>; let math_box = Box::new(MathBox::new()) as Box<dyn NyashBox>;
// 🌍 革命的実装Environment tracking廃止
return Ok(math_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<dyn NyashBox>;
return Ok(math_box);
}
}
"NullBox" => { "NullBox" => {
// NullBoxは引数なしで作成 // NullBoxは引数なしで作成
if !arguments.is_empty() { if !arguments.is_empty() {
@ -392,65 +362,25 @@ impl NyashInterpreter {
message: format!("TimeBox constructor expects 0 arguments, got {}", arguments.len()), message: format!("TimeBox constructor expects 0 arguments, got {}", arguments.len()),
}); });
} }
#[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<dyn NyashBox>; let time_box = Box::new(TimeBox::new()) as Box<dyn NyashBox>;
// 🌍 革命的実装Environment tracking廃止
return Ok(time_box); return Ok(time_box);
} }
}
"DateTimeBox" => { "DateTimeBox" => {
// DateTimeBoxは引数なしで現在時刻、または引数1個でタイムスタンプ // DateTimeBoxは引数なしで現在時刻、または引数1個でタイムスタンプ
match arguments.len() { match arguments.len() {
0 => { 0 => {
#[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<dyn NyashBox>; let datetime_box = Box::new(DateTimeBox::now()) as Box<dyn NyashBox>;
// 🌍 革命的実装Environment tracking廃止
return Ok(datetime_box); return Ok(datetime_box);
} }
}
1 => { 1 => {
let timestamp_value = self.execute_expression(&arguments[0])?; let timestamp_value = self.execute_expression(&arguments[0])?;
// Try integer timestamp first
if let Some(int_box) = timestamp_value.as_any().downcast_ref::<IntegerBox>() { if let Some(int_box) = timestamp_value.as_any().downcast_ref::<IntegerBox>() {
#[cfg(feature = "dynamic-file")]
{
// TODO: Add timestamp creation to plugin
let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>; let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>;
// 🌍 革命的実装Environment tracking廃止
return Ok(datetime_box); return Ok(datetime_box);
} } else {
#[cfg(not(feature = "dynamic-file"))]
{
let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>;
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);
}
#[cfg(not(feature = "dynamic-file"))]
{
return Err(RuntimeError::TypeError { return Err(RuntimeError::TypeError {
message: "DateTimeBox constructor requires integer timestamp".to_string(), message: "DateTimeBox constructor requires integer timestamp".to_string(),
}); });
@ -492,19 +422,10 @@ impl NyashInterpreter {
message: format!("RandomBox constructor expects 0 arguments, got {}", arguments.len()), message: format!("RandomBox constructor expects 0 arguments, got {}", arguments.len()),
}); });
} }
#[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<dyn NyashBox>; let random_box = Box::new(RandomBox::new()) as Box<dyn NyashBox>;
// 🌍 革命的実装Environment tracking廃止
return Ok(random_box); return Ok(random_box);
} }
}
"SoundBox" => { "SoundBox" => {
// SoundBoxは引数なしで作成 // SoundBoxは引数なしで作成
if !arguments.is_empty() { if !arguments.is_empty() {

View File

@ -145,7 +145,6 @@ impl NyashInterpreter {
if let Some(Some(init_expr)) = initial_values.get(i) { if let Some(Some(init_expr)) = initial_values.get(i) {
// 🚀 初期化付きlocal宣言: local x = value // 🚀 初期化付きlocal宣言: local x = value
let init_value = self.execute_expression(init_expr)?; let init_value = self.execute_expression(init_expr)?;
eprintln!("🔍 DEBUG: Local variable '{}' initialized with type: {}", var_name, init_value.type_name());
self.declare_local_variable(var_name, init_value); self.declare_local_variable(var_name, init_value);
} else { } else {
// 従来のlocal宣言: local x // 従来のlocal宣言: local x

View File

@ -29,12 +29,6 @@ pub mod box_arithmetic; // 🚀 Arithmetic operations moved from box_trait.rs
// 🔥 NyashValue Revolutionary System (NEW!) // 🔥 NyashValue Revolutionary System (NEW!)
pub mod value; pub mod value;
// 🚀 BID-FFI: Box Interface Definition with FFI (NEW!)
pub mod bid;
// 🔌 Runtime: Plugin System and Box Management (NEW!)
pub mod runtime;
// 🌐 P2P Communication Infrastructure (NEW!) // 🌐 P2P Communication Infrastructure (NEW!)
pub mod messaging; pub mod messaging;
pub mod transport; pub mod transport;

View File

@ -38,12 +38,6 @@ pub mod backend;
// 📊 Performance Benchmarks // 📊 Performance Benchmarks
pub mod benchmarks; pub mod benchmarks;
// 🚀 BID-FFI: Box Interface Definition with FFI
pub mod bid;
// 🔌 Runtime: Plugin System (Day 5)
pub mod runtime;
// 🚀 Refactored modules for better organization // 🚀 Refactored modules for better organization
pub mod cli; pub mod cli;
pub mod runner; pub mod runner;

View File

@ -291,28 +291,12 @@ impl MirBuilder {
let operand_val = self.build_expression(operand)?; let operand_val = self.build_expression(operand)?;
let dst = self.value_gen.next(); let dst = self.value_gen.next();
// Phase 2: Convert UnaryOp to intrinsic call let mir_op = self.convert_unary_operator(operator)?;
// 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)),
};
// Create string constant for intrinsic function name self.emit_instruction(MirInstruction::UnaryOp {
let func_name_id = self.value_gen.next(); dst,
self.emit_instruction(MirInstruction::Const { op: mir_op,
dst: func_name_id, operand: operand_val,
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) Ok(dst)
@ -369,20 +353,10 @@ impl MirBuilder {
fn build_print_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> { fn build_print_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
let value = self.build_expression(expression)?; let value = self.build_expression(expression)?;
// Phase 2: Convert Print to intrinsic call (@print) // For now, use a special Print instruction (minimal scope)
// Create string constant for intrinsic function name self.emit_instruction(MirInstruction::Print {
let func_name_id = self.value_gen.next(); value,
self.emit_instruction(MirInstruction::Const { effects: EffectMask::PURE.add(Effect::Io),
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 // Return the value that was printed
@ -556,35 +530,15 @@ impl MirBuilder {
let finally_block = if finally_body.is_some() { Some(self.block_gen.next()) } else { None }; let finally_block = if finally_body.is_some() { Some(self.block_gen.next()) } else { None };
let exit_block = self.block_gen.next(); let exit_block = self.block_gen.next();
// Phase 2: Convert Catch to intrinsic call (@set_exception_handler) // Set up exception handler for the try block (before we enter it)
if let Some(catch_clause) = catch_clauses.first() { if let Some(catch_clause) = catch_clauses.first() {
let exception_value = self.value_gen.next(); let exception_value = self.value_gen.next();
// Create string constants for intrinsic function name and exception type // Register catch handler for exceptions that may occur in try block
let func_name_id = self.value_gen.next(); self.emit_instruction(MirInstruction::Catch {
self.emit_instruction(MirInstruction::Const { exception_type: catch_clause.exception_type.clone(),
dst: func_name_id, exception_value,
value: ConstValue::String("@set_exception_handler".to_string()), handler_bb: catch_block,
})?;
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
})?; })?;
} }
@ -655,20 +609,10 @@ impl MirBuilder {
fn build_throw_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> { fn build_throw_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
let exception_value = self.build_expression(expression)?; let exception_value = self.build_expression(expression)?;
// Phase 2: Convert Throw to intrinsic call (@throw) // Emit throw instruction with PANIC effect (this is a terminator)
// Create string constant for intrinsic function name self.emit_instruction(MirInstruction::Throw {
let func_name_id = self.value_gen.next(); exception: exception_value,
self.emit_instruction(MirInstruction::Const { effects: EffectMask::PANIC,
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 // Throw doesn't return normally, but we need to return a value for the type system
@ -760,11 +704,11 @@ impl MirBuilder {
// First, build the object expression to get its ValueId // First, build the object expression to get its ValueId
let object_value = self.build_expression(object)?; let object_value = self.build_expression(object)?;
// Get the field from the object using BoxFieldLoad (Phase 8.5 new instruction) // Get the field from the object using RefGet
let result_id = self.value_gen.next(); let result_id = self.value_gen.next();
self.emit_instruction(MirInstruction::BoxFieldLoad { self.emit_instruction(MirInstruction::RefGet {
dst: result_id, dst: result_id,
box_val: object_value, reference: object_value,
field, field,
})?; })?;
@ -772,45 +716,22 @@ impl MirBuilder {
} }
/// Build new expression: new ClassName(arguments) /// Build new expression: new ClassName(arguments)
fn build_new_expression(&mut self, class: String, arguments: Vec<ASTNode>) -> Result<ValueId, String> { fn build_new_expression(&mut self, class: String, _arguments: Vec<ASTNode>) -> Result<ValueId, String> {
// Special handling for StringBox - if it has a string literal argument, // For Phase 6.1, we'll create a simple RefNew without processing arguments
// treat it as a string constant, not a box creation // In a full implementation, arguments would be used for constructor calls
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(); let dst = self.value_gen.next();
// For now, create a "box type" value representing the class
let type_value = self.value_gen.next();
self.emit_instruction(MirInstruction::Const { self.emit_instruction(MirInstruction::Const {
dst, dst: type_value,
value: ConstValue::String(s.clone()), value: ConstValue::String(class),
})?; })?;
// Phase 5-3: RefNew is deprecated - use NewBox instead // Create the reference using RefNew
let string_box_dst = self.value_gen.next(); self.emit_instruction(MirInstruction::RefNew {
self.emit_instruction(MirInstruction::NewBox {
dst: string_box_dst,
box_type: "StringBox".to_string(),
args: vec![dst],
})?;
return Ok(string_box_dst);
}
}
// Phase 5-3: Create NewBox with processed arguments
let dst = self.value_gen.next();
// Process all arguments
let mut arg_values = Vec::new();
for arg in arguments {
let arg_value = self.build_expression(arg)?;
arg_values.push(arg_value);
}
// Create NewBox instruction
self.emit_instruction(MirInstruction::NewBox {
dst, dst,
box_type: class, box_val: type_value,
args: arg_values,
})?; })?;
Ok(dst) Ok(dst)
@ -822,9 +743,9 @@ impl MirBuilder {
let object_value = self.build_expression(object)?; let object_value = self.build_expression(object)?;
let value_result = self.build_expression(value)?; let value_result = self.build_expression(value)?;
// Set the field using BoxFieldStore (Phase 8.5 new instruction) // Set the field using RefSet
self.emit_instruction(MirInstruction::BoxFieldStore { self.emit_instruction(MirInstruction::RefSet {
box_val: object_value, reference: object_value,
field, field,
value: value_result, value: value_result,
})?; })?;
@ -888,12 +809,11 @@ impl MirBuilder {
// Evaluate the expression // Evaluate the expression
let expression_value = self.build_expression(expression)?; let expression_value = self.build_expression(expression)?;
// Phase 2: Convert FutureNew to NewBox + BoxCall implementation // Create a new Future with the evaluated expression as the initial value
let future_id = self.value_gen.next(); let future_id = self.value_gen.next();
self.emit_instruction(MirInstruction::NewBox { self.emit_instruction(MirInstruction::FutureNew {
dst: future_id, dst: future_id,
box_type: "FutureBox".to_string(), value: expression_value,
args: vec![expression_value],
})?; })?;
// Store the future in the variable // Store the future in the variable
@ -907,16 +827,13 @@ impl MirBuilder {
// Evaluate the expression (should be a Future) // Evaluate the expression (should be a Future)
let future_value = self.build_expression(expression)?; let future_value = self.build_expression(expression)?;
// Phase 2: Convert Await to BoxCall implementation // Create destination for await result
let result_id = self.value_gen.next(); let result_id = self.value_gen.next();
// Emit await as a method call on the future box // Emit await instruction
self.emit_instruction(MirInstruction::BoxCall { self.emit_instruction(MirInstruction::Await {
dst: Some(result_id), dst: result_id,
box_val: future_value, future: future_value,
method: "await".to_string(),
args: vec![],
effects: EffectMask::IO.add(Effect::Control), // Await has IO and control effects
})?; })?;
Ok(result_id) Ok(result_id)

View File

@ -31,8 +31,6 @@ pub enum MirInstruction {
/// Unary operation /// Unary operation
/// `%dst = op %operand` /// `%dst = op %operand`
/// DEPRECATED: Phase 5 - Use BinOp instead (e.g., `not %a` → `%a xor true`, `neg %a` → `0 sub %a`)
#[deprecated(since = "Phase 5", note = "Use BinOp instead")]
UnaryOp { UnaryOp {
dst: ValueId, dst: ValueId,
op: UnaryOp, op: UnaryOp,
@ -52,8 +50,6 @@ pub enum MirInstruction {
// === Memory Operations === // === Memory Operations ===
/// Load from memory/variable /// Load from memory/variable
/// `%dst = load %ptr` /// `%dst = load %ptr`
/// DEPRECATED: Phase 5 - Use BoxFieldLoad instead
#[deprecated(since = "Phase 5", note = "Use BoxFieldLoad instead")]
Load { Load {
dst: ValueId, dst: ValueId,
ptr: ValueId, ptr: ValueId,
@ -61,8 +57,6 @@ pub enum MirInstruction {
/// Store to memory/variable /// Store to memory/variable
/// `store %value -> %ptr` /// `store %value -> %ptr`
/// DEPRECATED: Phase 5 - Use BoxFieldStore instead
#[deprecated(since = "Phase 5", note = "Use BoxFieldStore instead")]
Store { Store {
value: ValueId, value: ValueId,
ptr: ValueId, ptr: ValueId,
@ -128,8 +122,6 @@ pub enum MirInstruction {
/// Check Box type /// Check Box type
/// `%dst = type_check %box "BoxType"` /// `%dst = type_check %box "BoxType"`
/// DEPRECATED: Phase 5 - Use Call with @type_check intrinsic
#[deprecated(since = "Phase 5", note = "Use Call with @type_check intrinsic")]
TypeCheck { TypeCheck {
dst: ValueId, dst: ValueId,
value: ValueId, value: ValueId,
@ -139,8 +131,6 @@ pub enum MirInstruction {
// === Type Conversion === // === Type Conversion ===
/// Convert between types /// Convert between types
/// `%dst = cast %value as Type` /// `%dst = cast %value as Type`
/// DEPRECATED: Phase 5 - Use Call with @cast intrinsic
#[deprecated(since = "Phase 5", note = "Use Call with @cast intrinsic")]
Cast { Cast {
dst: ValueId, dst: ValueId,
value: ValueId, value: ValueId,
@ -150,8 +140,6 @@ pub enum MirInstruction {
// === Array Operations === // === Array Operations ===
/// Get array element /// Get array element
/// `%dst = %array[%index]` /// `%dst = %array[%index]`
/// DEPRECATED: Phase 5 - Use BoxFieldLoad or Call with @array_get intrinsic
#[deprecated(since = "Phase 5", note = "Use BoxFieldLoad or Call with @array_get intrinsic")]
ArrayGet { ArrayGet {
dst: ValueId, dst: ValueId,
array: ValueId, array: ValueId,
@ -160,8 +148,6 @@ pub enum MirInstruction {
/// Set array element /// Set array element
/// `%array[%index] = %value` /// `%array[%index] = %value`
/// DEPRECATED: Phase 5 - Use BoxFieldStore or Call with @array_set intrinsic
#[deprecated(since = "Phase 5", note = "Use BoxFieldStore or Call with @array_set intrinsic")]
ArraySet { ArraySet {
array: ValueId, array: ValueId,
index: ValueId, index: ValueId,
@ -171,8 +157,6 @@ pub enum MirInstruction {
// === Special Operations === // === Special Operations ===
/// Copy a value (for optimization passes) /// Copy a value (for optimization passes)
/// `%dst = copy %src` /// `%dst = copy %src`
/// DEPRECATED: Phase 5 - Optimization pass only, not needed in IR
#[deprecated(since = "Phase 5", note = "Optimization pass only, not needed in IR")]
Copy { Copy {
dst: ValueId, dst: ValueId,
src: ValueId, src: ValueId,
@ -180,8 +164,6 @@ pub enum MirInstruction {
/// Debug/introspection instruction /// Debug/introspection instruction
/// `debug %value "message"` /// `debug %value "message"`
/// DEPRECATED: Phase 5 - Use Call with @debug intrinsic
#[deprecated(since = "Phase 5", note = "Use Call with @debug intrinsic")]
Debug { Debug {
value: ValueId, value: ValueId,
message: String, message: String,
@ -189,24 +171,18 @@ pub enum MirInstruction {
/// Print instruction for console output /// Print instruction for console output
/// `print %value` /// `print %value`
/// DEPRECATED: Phase 5 - Use Call with @print intrinsic
#[deprecated(since = "Phase 5", note = "Use Call with @print intrinsic")]
Print { Print {
value: ValueId, value: ValueId,
effects: EffectMask, effects: EffectMask,
}, },
/// No-op instruction (for optimization placeholders) /// No-op instruction (for optimization placeholders)
/// DEPRECATED: Phase 5 - Not needed in final IR
#[deprecated(since = "Phase 5", note = "Not needed in final IR")]
Nop, Nop,
// === Control Flow & Exception Handling (Phase 5) === // === Control Flow & Exception Handling (Phase 5) ===
/// Throw an exception /// Throw an exception
/// `throw %exception_value` /// `throw %exception_value`
/// DEPRECATED: Phase 5 - Use Call with @throw intrinsic
#[deprecated(since = "Phase 5", note = "Use Call with @throw intrinsic")]
Throw { Throw {
exception: ValueId, exception: ValueId,
effects: EffectMask, effects: EffectMask,
@ -214,8 +190,6 @@ pub enum MirInstruction {
/// Catch handler setup (landing pad for exceptions) /// Catch handler setup (landing pad for exceptions)
/// `catch %exception_type -> %handler_bb` /// `catch %exception_type -> %handler_bb`
/// DEPRECATED: Phase 5 - Use Call with @catch intrinsic
#[deprecated(since = "Phase 5", note = "Use Call with @catch intrinsic")]
Catch { Catch {
exception_type: Option<String>, // None = catch-all exception_type: Option<String>, // None = catch-all
exception_value: ValueId, // Where to store caught exception exception_value: ValueId, // Where to store caught exception
@ -230,8 +204,6 @@ pub enum MirInstruction {
/// Create a new reference to a Box /// Create a new reference to a Box
/// `%dst = ref_new %box` /// `%dst = ref_new %box`
/// DEPRECATED: Phase 5 - RefGet is sufficient
#[deprecated(since = "Phase 5", note = "RefGet is sufficient")]
RefNew { RefNew {
dst: ValueId, dst: ValueId,
box_val: ValueId, box_val: ValueId,
@ -269,16 +241,12 @@ pub enum MirInstruction {
/// Memory barrier read (no-op for now, proper effect annotation) /// Memory barrier read (no-op for now, proper effect annotation)
/// `barrier_read %ptr` /// `barrier_read %ptr`
/// DEPRECATED: Phase 5 - Use AtomicFence instead
#[deprecated(since = "Phase 5", note = "Use AtomicFence instead")]
BarrierRead { BarrierRead {
ptr: ValueId, ptr: ValueId,
}, },
/// Memory barrier write (no-op for now, proper effect annotation) /// Memory barrier write (no-op for now, proper effect annotation)
/// `barrier_write %ptr` /// `barrier_write %ptr`
/// DEPRECATED: Phase 5 - Use AtomicFence instead
#[deprecated(since = "Phase 5", note = "Use AtomicFence instead")]
BarrierWrite { BarrierWrite {
ptr: ValueId, ptr: ValueId,
}, },
@ -287,8 +255,6 @@ pub enum MirInstruction {
/// Create a new Future with initial value /// Create a new Future with initial value
/// `%dst = future_new %value` /// `%dst = future_new %value`
/// DEPRECATED: Phase 5 - Use NewBox + BoxCall
#[deprecated(since = "Phase 5", note = "Use NewBox + BoxCall")]
FutureNew { FutureNew {
dst: ValueId, dst: ValueId,
value: ValueId, value: ValueId,
@ -296,8 +262,6 @@ pub enum MirInstruction {
/// Set Future value and mark as ready /// Set Future value and mark as ready
/// `future_set %future = %value` /// `future_set %future = %value`
/// DEPRECATED: Phase 5 - Use BoxCall
#[deprecated(since = "Phase 5", note = "Use BoxCall")]
FutureSet { FutureSet {
future: ValueId, future: ValueId,
value: ValueId, value: ValueId,
@ -305,8 +269,6 @@ pub enum MirInstruction {
/// Wait for Future completion and get value /// Wait for Future completion and get value
/// `%dst = await %future` /// `%dst = await %future`
/// DEPRECATED: Phase 5 - Use BoxCall
#[deprecated(since = "Phase 5", note = "Use BoxCall")]
Await { Await {
dst: ValueId, dst: ValueId,
future: ValueId, future: ValueId,
@ -323,80 +285,6 @@ pub enum MirInstruction {
args: Vec<ValueId>, args: Vec<ValueId>,
effects: EffectMask, 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<ValueId>,
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 /// Constant values in MIR
@ -456,16 +344,6 @@ pub enum MirType {
Unknown, Unknown,
} }
/// Atomic memory ordering for fence operations
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AtomicOrdering {
Relaxed,
Acquire,
Release,
AcqRel,
SeqCst,
}
impl MirInstruction { impl MirInstruction {
/// Get the effect mask for this instruction /// Get the effect mask for this instruction
pub fn effects(&self) -> EffectMask { pub fn effects(&self) -> EffectMask {
@ -526,18 +404,6 @@ impl MirInstruction {
// Phase 9.7: External Function Calls // Phase 9.7: External Function Calls
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask 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
} }
} }
@ -566,12 +432,6 @@ impl MirInstruction {
MirInstruction::BoxCall { dst, .. } | MirInstruction::BoxCall { dst, .. } |
MirInstruction::ExternCall { dst, .. } => *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::Store { .. } |
MirInstruction::Branch { .. } | MirInstruction::Branch { .. } |
MirInstruction::Jump { .. } | MirInstruction::Jump { .. } |
@ -587,14 +447,6 @@ impl MirInstruction {
MirInstruction::Safepoint | MirInstruction::Safepoint |
MirInstruction::Nop => None, 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), MirInstruction::Catch { exception_value, .. } => Some(*exception_value),
} }
} }
@ -667,22 +519,6 @@ impl MirInstruction {
// Phase 9.7: External Function Calls // Phase 9.7: External Function Calls
MirInstruction::ExternCall { args, .. } => args.clone(), 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
} }
} }
} }
@ -766,39 +602,6 @@ impl fmt::Display for MirInstruction {
effects) 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::<Vec<_>>().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 _ => write!(f, "{:?}", self), // Fallback for other instructions
} }
} }
@ -817,18 +620,6 @@ 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -13,7 +13,6 @@ pub mod builder;
pub mod verification; pub mod verification;
pub mod ownership_verifier_simple; // Simple ownership forest verification for current MIR pub mod ownership_verifier_simple; // Simple ownership forest verification for current MIR
pub mod printer; pub mod printer;
pub mod optimizer; // Phase 3: Effect System based optimization passes
pub mod value_id; pub mod value_id;
pub mod effect; pub mod effect;
@ -26,7 +25,6 @@ pub use builder::MirBuilder;
pub use verification::{MirVerifier, VerificationError}; pub use verification::{MirVerifier, VerificationError};
pub use ownership_verifier_simple::{OwnershipVerifier, OwnershipError, OwnershipStats}; // Simple ownership forest verification pub use ownership_verifier_simple::{OwnershipVerifier, OwnershipError, OwnershipStats}; // Simple ownership forest verification
pub use printer::MirPrinter; pub use printer::MirPrinter;
pub use optimizer::{MirOptimizer, OptimizationStats}; // Phase 3: Effect System optimizations
pub use value_id::{ValueId, LocalId, ValueIdGenerator}; pub use value_id::{ValueId, LocalId, ValueIdGenerator};
pub use effect::{EffectMask, Effect}; pub use effect::{EffectMask, Effect};

View File

@ -371,39 +371,6 @@ impl MirPrinter {
format!("extern_call {}.{}({}) [effects: {}]", iface_name, method_name, args_str, effects) 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::<Vec<_>>().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)
},
} }
} }

View File

@ -14,7 +14,6 @@ use crate::{
interpreter::NyashInterpreter, interpreter::NyashInterpreter,
mir::{MirCompiler, MirPrinter}, mir::{MirCompiler, MirPrinter},
backend::{VM, wasm::WasmBackend, aot::AotBackend}, backend::{VM, wasm::WasmBackend, aot::AotBackend},
runtime::{PluginConfig, get_global_registry},
}; };
use std::{fs, process}; use std::{fs, process};
@ -26,89 +25,9 @@ pub struct NyashRunner {
impl NyashRunner { impl NyashRunner {
/// Create a new runner with the given configuration /// Create a new runner with the given configuration
pub fn new(config: CliConfig) -> Self { pub fn new(config: CliConfig) -> Self {
// 🔌 プラグインシステム初期化
Self::initialize_plugin_system();
Self { config } Self { config }
} }
/// プラグインシステム初期化nyash.toml読み込み
fn initialize_plugin_system() {
// nyash.tomlが存在するかチェック
if std::path::Path::new("nyash.toml").exists() {
match std::fs::read_to_string("nyash.toml") {
Ok(toml_content) => {
match PluginConfig::parse(&toml_content) {
Ok(plugin_config) => {
println!("🔌 Loading plugin configuration from nyash.toml");
let registry = get_global_registry();
// ビルトインBoxを登録フォールバック用
Self::register_builtin_boxes(&registry);
// プラグイン設定を適用
registry.apply_plugin_config(&plugin_config);
// プラグインライブラリをロード
#[cfg(feature = "dynamic-file")]
{
use crate::runtime::get_global_loader;
let loader = get_global_loader();
for (box_name, plugin_name) in &plugin_config.plugins {
// プラグインライブラリパスを構築
let lib_path = format!("plugins/{}/target/release/lib{}.so",
plugin_name.replace('_', "-"), plugin_name);
println!("🔍 Loading plugin library: {}", lib_path);
if let Err(e) = loader.load_plugin(plugin_name, &lib_path) {
eprintln!("⚠️ Failed to load plugin {}: {}", plugin_name, e);
} else {
println!("✅ Plugin library loaded: {}", plugin_name);
}
}
}
println!("✅ Plugin system initialized: {} plugins configured",
plugin_config.plugins.len());
}
Err(e) => {
eprintln!("⚠️ Failed to parse nyash.toml: {}", e);
eprintln!(" Using builtin boxes only");
}
}
}
Err(e) => {
eprintln!("⚠️ Failed to read nyash.toml: {}", e);
eprintln!(" Using builtin boxes only");
}
}
} else {
// nyash.tomlがない場合はビルトインのみ
let registry = get_global_registry();
Self::register_builtin_boxes(&registry);
println!("📦 Using builtin boxes only (no nyash.toml found)");
}
}
/// ビルトインBox登録フォールバック用
fn register_builtin_boxes(registry: &crate::runtime::BoxFactoryRegistry) {
// FileBoxビルトイン版のコンストラクタ
fn builtin_filebox_constructor(args: &[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, String> {
// 簡易実装StringBoxとして扱う実際のビルトインFileBoxが必要
if args.is_empty() {
Ok(Box::new(StringBox::new("BuiltinFileBox")))
} else {
let path = args[0].to_string_box().value;
Ok(Box::new(StringBox::new(&format!("BuiltinFileBox({})", path))))
}
}
registry.register_builtin("FileBox", builtin_filebox_constructor);
println!(" 📁 FileBox (builtin) registered");
}
/// Run Nyash based on the configuration /// Run Nyash based on the configuration
pub fn run(&self) { pub fn run(&self) {
// Benchmark mode - can run without a file // Benchmark mode - can run without a file

19
test_simple.nyash Normal file
View File

@ -0,0 +1,19 @@
// 簡単なNyashテストプログラム
print("🎉 Nyash is working!")
print("Everything is Box!")
// 基本的な演算
local a = 10
local b = 20
local result = a + b
print("10 + 20 = " + result.toString())
// StringBox
local greeting = "Hello, Nyash!"
print(greeting)
// ArrayBox
local arr = new ArrayBox()
arr.push("First")
arr.push("Second")
print("Array length: " + arr.length().toString())

View File

@ -6,10 +6,10 @@
use nyash_rust::mir::{ use nyash_rust::mir::{
MirModule, MirFunction, FunctionSignature, MirType, EffectMask, MirModule, MirFunction, FunctionSignature, MirType, EffectMask,
BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue, AtomicOrdering BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue
}; };
use nyash_rust::backend::VM; use nyash_rust::backend::{VM, VMValue};
use nyash_rust::box_trait::IntegerBox; use nyash_rust::box_trait::{IntegerBox, NyashBox};
#[test] #[test]
fn test_mir_phase6_vm_ref_ops() { fn test_mir_phase6_vm_ref_ops() {
@ -45,7 +45,6 @@ fn test_mir_phase6_vm_ref_ops() {
let obj_ref = ValueId::new(1); let obj_ref = ValueId::new(1);
let one_val = ValueId::new(2); let one_val = ValueId::new(2);
let x_val = ValueId::new(3); let x_val = ValueId::new(3);
let print_func = ValueId::new(4);
// Add instructions // Add instructions
@ -55,18 +54,10 @@ fn test_mir_phase6_vm_ref_ops() {
value: ConstValue::String("Obj".to_string()), value: ConstValue::String("Obj".to_string()),
}); });
// %4 = const "@print" (for intrinsic call) // %1 = ref_new %0
block.add_instruction(MirInstruction::Const { block.add_instruction(MirInstruction::RefNew {
dst: print_func,
value: ConstValue::String("@print".to_string()),
});
// %1 = new Obj()
// Phase 5: RefNew is deprecated - use NewBox instead
block.add_instruction(MirInstruction::NewBox {
dst: obj_ref, dst: obj_ref,
box_type: "Obj".to_string(), box_val: obj_type_val,
args: vec![],
}); });
// %2 = const 1 // %2 = const 1
@ -75,34 +66,28 @@ fn test_mir_phase6_vm_ref_ops() {
value: ConstValue::Integer(1), value: ConstValue::Integer(1),
}); });
// atomic_fence release // barrier_write %1
// Phase 5: BarrierWrite is deprecated - use AtomicFence instead block.add_instruction(MirInstruction::BarrierWrite {
block.add_instruction(MirInstruction::AtomicFence { ptr: obj_ref,
ordering: AtomicOrdering::Release,
}); });
// %1.x = %2 // ref_set %1, "x", %2
// Phase 5: RefSet is deprecated - use BoxFieldStore instead block.add_instruction(MirInstruction::RefSet {
block.add_instruction(MirInstruction::BoxFieldStore { reference: obj_ref,
box_val: obj_ref,
field: "x".to_string(), field: "x".to_string(),
value: one_val, value: one_val,
}); });
// %3 = %1.x // %3 = ref_get %1, "x"
// Phase 5: RefGet is deprecated - use BoxFieldLoad instead block.add_instruction(MirInstruction::RefGet {
block.add_instruction(MirInstruction::BoxFieldLoad {
dst: x_val, dst: x_val,
box_val: obj_ref, reference: obj_ref,
field: "x".to_string(), field: "x".to_string(),
}); });
// call @print(%3) // print %3
// Phase 5: Print is deprecated - use Call @print instead block.add_instruction(MirInstruction::Print {
block.add_instruction(MirInstruction::Call { value: x_val,
dst: None,
func: print_func,
args: vec![x_val],
effects: EffectMask::IO, effects: EffectMask::IO,
}); });
@ -183,14 +168,13 @@ fn test_barrier_no_op() {
value: ConstValue::Integer(42), value: ConstValue::Integer(42),
}); });
// Test atomic fence instructions (replace barriers) // Test barrier instructions (should be no-ops)
// Phase 5: BarrierRead/BarrierWrite are deprecated - use AtomicFence block.add_instruction(MirInstruction::BarrierRead {
block.add_instruction(MirInstruction::AtomicFence { ptr: test_val,
ordering: AtomicOrdering::Acquire,
}); });
block.add_instruction(MirInstruction::AtomicFence { block.add_instruction(MirInstruction::BarrierWrite {
ordering: AtomicOrdering::Release, ptr: test_val,
}); });
block.add_instruction(MirInstruction::Return { block.add_instruction(MirInstruction::Return {

View File

@ -107,17 +107,17 @@ fn test_mir_phase7_basic_nowait_await() {
.flat_map(|block| &block.instructions) .flat_map(|block| &block.instructions)
.collect(); .collect();
// Phase 5: FutureNew is deprecated - should contain NewBox "FutureBox" instead // Should contain FutureNew instruction
let has_future_box = instructions.iter().any(|inst| { let has_future_new = instructions.iter().any(|inst| {
matches!(inst, nyash_rust::mir::MirInstruction::NewBox { box_type, .. } if box_type == "FutureBox") matches!(inst, nyash_rust::mir::MirInstruction::FutureNew { .. })
}); });
assert!(has_future_box, "MIR should contain NewBox FutureBox instruction"); assert!(has_future_new, "MIR should contain FutureNew instruction");
// Phase 5: Await is deprecated - should contain BoxCall "await" instead // Should contain Await instruction
let has_await_call = instructions.iter().any(|inst| { let has_await = instructions.iter().any(|inst| {
matches!(inst, nyash_rust::mir::MirInstruction::BoxCall { method, .. } if method == "await") matches!(inst, nyash_rust::mir::MirInstruction::Await { .. })
}); });
assert!(has_await_call, "MIR should contain BoxCall await instruction"); assert!(has_await, "MIR should contain Await instruction");
// Test VM execution // Test VM execution
let mut vm = VM::new(); let mut vm = VM::new();

View File

@ -0,0 +1,334 @@
/*!
* Phase 8.3 PoC2 Integration Test - Box Operations in WASM
*
* Tests end-to-end MIR→WASM compilation and execution for:
* - RefNew: Box creation and reference assignment
* - RefGet: Field reading from Box objects
* - RefSet: Field writing to Box objects
* - NewBox: Direct Box allocation with type information
*
* Validates the "Everything is Box" philosophy in WASM
*/
use nyash_rust::mir::{
MirModule, MirFunction, FunctionSignature, MirType, EffectMask,
BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue
};
use nyash_rust::backend::wasm::WasmBackend;
#[test]
fn test_wasm_poc2_refnew_basic() {
// Build MIR equivalent to:
// function main() {
// %box = new_box "DataBox"(42)
// %ref = ref_new %box
// return %ref // Should return box pointer
// }
let mut backend = WasmBackend::new();
let mir_module = build_refnew_mir_module();
// Generate WAT text for debugging
let wat_result = backend.compile_to_wat(mir_module.clone());
assert!(wat_result.is_ok(), "WAT generation should succeed");
let wat_text = wat_result.unwrap();
// Verify WAT contains expected elements
assert!(wat_text.contains("(module"), "Should contain module declaration");
assert!(wat_text.contains("$malloc"), "Should contain malloc function");
assert!(wat_text.contains("$alloc_databox"), "Should contain DataBox allocator");
assert!(wat_text.contains("call $alloc_databox"), "Should call DataBox allocator");
assert!(wat_text.contains("i32.store"), "Should store field values");
// Compile to WASM binary and execute
let wasm_result = backend.compile_module(mir_module);
if let Err(e) = &wasm_result {
println!("WASM compilation error: {}", e);
}
assert!(wasm_result.is_ok(), "WASM compilation should succeed");
let wasm_bytes = wasm_result.unwrap();
assert!(!wasm_bytes.is_empty(), "WASM bytes should not be empty");
// Execute with wasmtime
let execution_result = backend.execute_wasm(&wasm_bytes);
assert!(execution_result.is_ok(), "WASM execution should succeed");
let return_value = execution_result.unwrap();
// Should return a valid pointer (greater than heap start 0x800)
assert!(return_value >= 0x800, "Should return valid Box pointer: {}", return_value);
}
#[test]
fn test_wasm_poc2_refget_refset() {
// Build MIR equivalent to:
// function main() {
// %box = new_box "DataBox"(10)
// %ref = ref_new %box
// ref_set %ref.value = 42
// %result = ref_get %ref.value
// return %result // Should return 42
// }
let mut backend = WasmBackend::new();
let mir_module = build_refget_refset_mir_module();
let wasm_result = backend.compile_module(mir_module);
assert!(wasm_result.is_ok(), "WASM compilation should succeed");
let return_value = backend.execute_wasm(&wasm_result.unwrap()).unwrap();
assert_eq!(return_value, 42, "Should return updated field value");
}
#[test]
fn test_wasm_poc2_complete_box_workflow() {
// Build MIR equivalent to:
// function main() {
// %box1 = new_box "DataBox"(100)
// %box2 = new_box "DataBox"(200)
// %ref1 = ref_new %box1
// %ref2 = ref_new %box2
// %val1 = ref_get %ref1.value
// %val2 = ref_get %ref2.value
// %sum = %val1 + %val2
// ref_set %ref1.value = %sum
// %result = ref_get %ref1.value
// return %result // Should return 300
// }
let mut backend = WasmBackend::new();
let mir_module = build_complete_workflow_mir_module();
let wasm_result = backend.compile_module(mir_module);
assert!(wasm_result.is_ok(), "WASM compilation should succeed");
let return_value = backend.execute_wasm(&wasm_result.unwrap()).unwrap();
assert_eq!(return_value, 300, "Should return sum of Box values");
}
/// Build MIR module for basic RefNew test
fn build_refnew_mir_module() -> MirModule {
let mut module = MirModule::new("test_refnew".to_string());
let main_signature = FunctionSignature {
name: "main".to_string(),
params: vec![],
return_type: MirType::Integer,
effects: EffectMask::PURE,
};
let entry_block = BasicBlockId::new(0);
let mut main_function = MirFunction::new(main_signature, entry_block);
let mut block = BasicBlock::new(entry_block);
let init_val = ValueId::new(0); // 42
let box_ptr = ValueId::new(1); // DataBox pointer
let ref_ptr = ValueId::new(2); // Reference to DataBox
// Create constant for initialization
block.add_instruction(MirInstruction::Const {
dst: init_val,
value: ConstValue::Integer(42),
});
// Create DataBox with initial value
block.add_instruction(MirInstruction::NewBox {
dst: box_ptr,
box_type: "DataBox".to_string(),
args: vec![init_val],
});
// Create reference to the Box
block.add_instruction(MirInstruction::RefNew {
dst: ref_ptr,
box_val: box_ptr,
});
// Return the reference
block.set_terminator(MirInstruction::Return {
value: Some(ref_ptr),
});
main_function.add_block(block);
module.add_function(main_function);
module
}
/// Build MIR module for RefGet/RefSet test
fn build_refget_refset_mir_module() -> MirModule {
let mut module = MirModule::new("test_refget_refset".to_string());
let main_signature = FunctionSignature {
name: "main".to_string(),
params: vec![],
return_type: MirType::Integer,
effects: EffectMask::PURE,
};
let entry_block = BasicBlockId::new(0);
let mut main_function = MirFunction::new(main_signature, entry_block);
let mut block = BasicBlock::new(entry_block);
let init_val = ValueId::new(0); // 10
let new_val = ValueId::new(1); // 42
let box_ptr = ValueId::new(2); // DataBox pointer
let ref_ptr = ValueId::new(3); // Reference to DataBox
let result = ValueId::new(4); // Read back value
// Create constants
block.add_instruction(MirInstruction::Const {
dst: init_val,
value: ConstValue::Integer(10),
});
block.add_instruction(MirInstruction::Const {
dst: new_val,
value: ConstValue::Integer(42),
});
// Create DataBox with initial value
block.add_instruction(MirInstruction::NewBox {
dst: box_ptr,
box_type: "DataBox".to_string(),
args: vec![init_val],
});
// Create reference to the Box
block.add_instruction(MirInstruction::RefNew {
dst: ref_ptr,
box_val: box_ptr,
});
// Set field value
block.add_instruction(MirInstruction::RefSet {
reference: ref_ptr,
field: "value".to_string(),
value: new_val,
});
// Get field value
block.add_instruction(MirInstruction::RefGet {
dst: result,
reference: ref_ptr,
field: "value".to_string(),
});
// Return the result
block.set_terminator(MirInstruction::Return {
value: Some(result),
});
main_function.add_block(block);
module.add_function(main_function);
module
}
/// Build MIR module for complete Box workflow test
fn build_complete_workflow_mir_module() -> MirModule {
let mut module = MirModule::new("test_complete_workflow".to_string());
let main_signature = FunctionSignature {
name: "main".to_string(),
params: vec![],
return_type: MirType::Integer,
effects: EffectMask::PURE,
};
let entry_block = BasicBlockId::new(0);
let mut main_function = MirFunction::new(main_signature, entry_block);
let mut block = BasicBlock::new(entry_block);
let val1_init = ValueId::new(0); // 100
let val2_init = ValueId::new(1); // 200
let box1_ptr = ValueId::new(2); // DataBox 1 pointer
let box2_ptr = ValueId::new(3); // DataBox 2 pointer
let ref1_ptr = ValueId::new(4); // Reference to DataBox 1
let ref2_ptr = ValueId::new(5); // Reference to DataBox 2
let val1 = ValueId::new(6); // Value from box1
let val2 = ValueId::new(7); // Value from box2
let sum = ValueId::new(8); // Sum of values
let result = ValueId::new(9); // Final result
// Create constants
block.add_instruction(MirInstruction::Const {
dst: val1_init,
value: ConstValue::Integer(100),
});
block.add_instruction(MirInstruction::Const {
dst: val2_init,
value: ConstValue::Integer(200),
});
// Create DataBoxes
block.add_instruction(MirInstruction::NewBox {
dst: box1_ptr,
box_type: "DataBox".to_string(),
args: vec![val1_init],
});
block.add_instruction(MirInstruction::NewBox {
dst: box2_ptr,
box_type: "DataBox".to_string(),
args: vec![val2_init],
});
// Create references
block.add_instruction(MirInstruction::RefNew {
dst: ref1_ptr,
box_val: box1_ptr,
});
block.add_instruction(MirInstruction::RefNew {
dst: ref2_ptr,
box_val: box2_ptr,
});
// Get values from both boxes
block.add_instruction(MirInstruction::RefGet {
dst: val1,
reference: ref1_ptr,
field: "value".to_string(),
});
block.add_instruction(MirInstruction::RefGet {
dst: val2,
reference: ref2_ptr,
field: "value".to_string(),
});
// Add values
block.add_instruction(MirInstruction::BinOp {
dst: sum,
op: nyash_rust::mir::BinaryOp::Add,
lhs: val1,
rhs: val2,
});
// Store sum back to first box
block.add_instruction(MirInstruction::RefSet {
reference: ref1_ptr,
field: "value".to_string(),
value: sum,
});
// Read back the result
block.add_instruction(MirInstruction::RefGet {
dst: result,
reference: ref1_ptr,
field: "value".to_string(),
});
// Return the result
block.set_terminator(MirInstruction::Return {
value: Some(result),
});
main_function.add_block(block);
module.add_function(main_function);
module
}