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:
19
Cargo.toml
19
Cargo.toml
@ -16,8 +16,6 @@ cli = []
|
||||
gui = ["dep:egui", "dep:eframe", "dep:egui_extras", "dep:image"]
|
||||
gui-examples = ["gui"]
|
||||
all-examples = ["gui-examples"]
|
||||
# 動的ライブラリサポート
|
||||
dynamic-file = ["dep:libloading"]
|
||||
|
||||
[lib]
|
||||
name = "nyash_rust"
|
||||
@ -29,11 +27,6 @@ crate-type = ["cdylib", "rlib"]
|
||||
name = "nyash"
|
||||
path = "src/main.rs"
|
||||
|
||||
# WASM runner executable
|
||||
[[bin]]
|
||||
name = "nyash-wasm-run"
|
||||
path = "src/bin/nyash-wasm-run.rs"
|
||||
|
||||
# Examples for development - only available as examples, not bins
|
||||
[[example]]
|
||||
name = "gui_simple_notepad"
|
||||
@ -120,9 +113,6 @@ js-sys = "0.3"
|
||||
wabt = "0.10"
|
||||
wasmtime = "35.0.0"
|
||||
|
||||
# 動的ライブラリロード(Phase 9.75f)
|
||||
libloading = { version = "0.8", optional = true }
|
||||
|
||||
# GUI フレームワーク - only when gui feature is enabled
|
||||
egui = { version = "0.29", optional = true }
|
||||
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true }
|
||||
@ -179,12 +169,3 @@ panic = "abort"
|
||||
# 開発用設定
|
||||
opt-level = 0
|
||||
debug = true
|
||||
|
||||
# Workspace configuration
|
||||
[workspace]
|
||||
members = [
|
||||
".", # メインのnyash-rustプロジェクト
|
||||
"plugins/nyash-file", # FileBoxプラグイン
|
||||
"plugins/nyash-math", # Math/Time系プラグイン
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
1363
build_errors.txt
1363
build_errors.txt
File diff suppressed because it is too large
Load Diff
@ -61,7 +61,7 @@
|
||||
- ✅ libloadingプラグイン動的ロード基盤
|
||||
- ✅ **プラグインシステム統合テスト(14/14合格!)** 🎉
|
||||
|
||||
### 🎯 **Day 5 90%完了!** (2025-08-17)
|
||||
### 🎯 **Day 5 一時中断** (2025-08-18)
|
||||
**目標**: 実際のプラグインライブラリ作成と統合
|
||||
|
||||
**実装戦略**:
|
||||
@ -75,8 +75,15 @@
|
||||
- ✅ Nyashインタープリターのプラグインロード統合
|
||||
- ✅ 透過的切り替え実動作確認(PluginBox生成確認)
|
||||
|
||||
**残作業(最後の10%)**:
|
||||
- ⏳ PluginBoxのtoString等メソッド実装修正
|
||||
**中断理由**:
|
||||
- 🚨 **古いプラグインシステムのコードが混在していた**
|
||||
- 🔧 ソースコードをcommit 3f7d71f(古いプラグイン実装前)に巻き戻し
|
||||
- 📚 docsフォルダは最新状態を維持
|
||||
- ✅ nyashバイナリの基本動作確認完了
|
||||
|
||||
**再開時の作業**:
|
||||
- ⏳ BID-FFIシステムをクリーンに再実装
|
||||
- ⏳ PluginBoxのtoString等メソッド実装
|
||||
- ⏳ 実際のファイル操作メソッド(open/read/write)動作確認
|
||||
|
||||
### 🎯 今週の実装計画(段階的戦略に更新)
|
||||
@ -153,27 +160,35 @@ cargo build --release -j32
|
||||
```
|
||||
|
||||
---
|
||||
**最終更新**: 2025-08-17 26:30
|
||||
**次回レビュー**: 2025-08-18(Day 5-6完了時)
|
||||
**最終更新**: 2025-08-18 08:30 JST
|
||||
**次回レビュー**: 2025-08-18(BID-FFI再実装開始時)
|
||||
|
||||
## 🎯 **Day 5 最終段階の詳細**
|
||||
## 🎯 **現在の状況** (2025-08-18)
|
||||
|
||||
### 現在の動作状況
|
||||
1. **nyash.tomlなし**: ビルトインFileBox動作 ✅
|
||||
2. **nyash.tomlあり**: プラグインFileBoxロード成功 ✅
|
||||
3. **PluginBox生成**: 成功(type_name: PluginBox) ✅
|
||||
4. **toString呼び出し**: エラー(PluginBoxプロキシが未完成) ❌
|
||||
### クリーンアップ完了
|
||||
1. **古いプラグインシステム削除**: ソースコードをcommit 3f7d71fに巻き戻し ✅
|
||||
2. **ドキュメント保持**: docs/は最新の状態を維持 ✅
|
||||
3. **基本動作確認**: nyashバイナリが正常動作 ✅
|
||||
4. **ビルド成功**: `cargo build --release --bin nyash` 完了 ✅
|
||||
|
||||
### 残作業詳細
|
||||
1. **PluginBox完全実装**
|
||||
- toStringメソッドのプラグイン呼び出し
|
||||
- ファイル操作メソッド(open/read/write/close)転送
|
||||
### BID-FFI実装状況
|
||||
- **仕様**: 完成済み(docs/説明書/reference/box-design/ffi-abi-specification.md)
|
||||
- **設計**: 完成済み(docs/説明書/reference/box-design/plugin-system.md)
|
||||
- **基盤コード**: src/bid/モジュールは削除済み(再実装必要)
|
||||
- **プラグイン**: plugins/nyash-filebox-pluginも削除済み(再作成必要)
|
||||
|
||||
### 次のステップ
|
||||
1. **BID-FFIシステムをクリーンに再実装**
|
||||
- src/bid/モジュール作成
|
||||
- TLVエンコード/デコード実装
|
||||
- プラグインローダー実装
|
||||
|
||||
2. **BID-FFI統合**
|
||||
- TLVエンコード/デコードの実際の動作
|
||||
- メソッドディスパッチの実装
|
||||
2. **FileBoxプラグイン作成**
|
||||
- plugins/nyash-filebox-plugin/再作成
|
||||
- C FFI実装
|
||||
- ビルドシステム構築
|
||||
|
||||
### 実証成功の証拠
|
||||
- プラグイン動的ロード: `✅ Plugin library loaded: nyash_filebox_plugin`
|
||||
- BoxFactoryRegistry統合: FileBox → PluginBox自動切り替え
|
||||
- プラグインシステム基盤: 90%完成!
|
||||
3. **統合テスト**
|
||||
- nyash.tomlによる切り替え
|
||||
- プラグイン動的ロード確認
|
||||
- メソッド呼び出し動作確認
|
||||
13
dump.txt
13
dump.txt
@ -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
|
||||
}
|
||||
|
||||
|
||||
0
plugins/nyash-filebox-plugin/final_build_debug.txt
Normal file
0
plugins/nyash-filebox-plugin/final_build_debug.txt
Normal file
2
plugins/nyash-filebox-plugin/nyash.toml
Normal file
2
plugins/nyash-filebox-plugin/nyash.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[plugins]
|
||||
FileBox = "nyash_filebox_plugin"
|
||||
0
plugins/nyash-filebox-plugin/plugin_debug_log.txt
Normal file
0
plugins/nyash-filebox-plugin/plugin_debug_log.txt
Normal file
@ -53,8 +53,6 @@ impl AotCompiler {
|
||||
WasmError::UnsupportedInstruction(msg) => AotError::CompilationError(format!("Unsupported MIR instruction: {}", msg)),
|
||||
WasmError::WasmValidationError(msg) => AotError::CompilationError(format!("WASM validation failed: {}", msg)),
|
||||
WasmError::IOError(msg) => AotError::IOError(msg),
|
||||
WasmError::RuntimeError(msg) => AotError::RuntimeError(msg),
|
||||
WasmError::CompilationError(msg) => AotError::CompilationError(msg),
|
||||
})?;
|
||||
|
||||
self.stats.wasm_size = wasm_bytes.len();
|
||||
|
||||
@ -231,7 +231,12 @@ impl VM {
|
||||
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 } => {
|
||||
let left = self.get_value(*lhs)?;
|
||||
@ -241,7 +246,11 @@ impl VM {
|
||||
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 } => {
|
||||
let return_value = if let Some(val_id) = value {
|
||||
@ -280,30 +289,26 @@ impl VM {
|
||||
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: _ } => {
|
||||
// Phase 2: Handle intrinsic function calls
|
||||
let func_value = self.get_value(*func)?;
|
||||
|
||||
if let VMValue::String(func_name) = func_value {
|
||||
if func_name.starts_with('@') {
|
||||
// This is an intrinsic call
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
MirInstruction::Store { value, ptr } => {
|
||||
// For now, storing just updates the ptr with the value
|
||||
let val = self.get_value(*value)?;
|
||||
self.values.insert(*ptr, val);
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
MirInstruction::Call { dst, func: _, args: _, effects: _ } => {
|
||||
// For now, function calls return void
|
||||
// TODO: Implement proper function call handling
|
||||
if let Some(dst_id) = dst {
|
||||
self.values.insert(*dst_id, VMValue::Void);
|
||||
}
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
@ -364,27 +369,67 @@ impl VM {
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
// 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(VMError::InvalidInstruction(
|
||||
"Phase 5: Deprecated instruction - use 26-instruction set replacements".to_string()
|
||||
))
|
||||
MirInstruction::TypeCheck { dst, value: _, expected_type: _ } => {
|
||||
// For now, type checks always return true
|
||||
// TODO: Implement proper type checking
|
||||
self.values.insert(*dst, VMValue::Bool(true));
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
// Phase 5: Removed instructions - Throw, Catch
|
||||
#[allow(deprecated)]
|
||||
MirInstruction::Throw { .. } |
|
||||
MirInstruction::Catch { .. } => {
|
||||
Err(VMError::InvalidInstruction(
|
||||
"Phase 5: Exception handling via intrinsics - use Call with @throw/@catch".to_string()
|
||||
))
|
||||
MirInstruction::Cast { dst, value, target_type: _ } => {
|
||||
// For now, casting just copies the value
|
||||
// TODO: Implement proper type casting
|
||||
let val = self.get_value(*value)?;
|
||||
self.values.insert(*dst, val);
|
||||
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 => {
|
||||
@ -393,15 +438,49 @@ impl VM {
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
// Phase 5: Removed instruction - RefNew
|
||||
#[allow(deprecated)]
|
||||
MirInstruction::RefNew { .. } => {
|
||||
Err(VMError::InvalidInstruction(
|
||||
"Phase 5: RefNew deprecated - RefGet is sufficient".to_string()
|
||||
))
|
||||
// Phase 6: Box reference operations
|
||||
MirInstruction::RefNew { dst, box_val } => {
|
||||
// For now, a reference is just the same as the box value
|
||||
// In a real implementation, this would create a proper reference
|
||||
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 } => {
|
||||
// For now, a weak reference is just a copy of the value
|
||||
@ -419,23 +498,61 @@ impl VM {
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
// Phase 5: Removed instructions - BarrierRead, BarrierWrite
|
||||
#[allow(deprecated)]
|
||||
MirInstruction::BarrierRead { .. } |
|
||||
MirInstruction::BarrierWrite { .. } => {
|
||||
Err(VMError::InvalidInstruction(
|
||||
"Phase 5: Memory barriers deprecated - use AtomicFence".to_string()
|
||||
))
|
||||
MirInstruction::BarrierRead { ptr: _ } => {
|
||||
// Memory barrier read is a no-op for now
|
||||
// In a real implementation, this would ensure memory ordering
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
// Phase 5: Removed instructions - FutureNew, FutureSet, Await
|
||||
#[allow(deprecated)]
|
||||
MirInstruction::FutureNew { .. } |
|
||||
MirInstruction::FutureSet { .. } |
|
||||
MirInstruction::Await { .. } => {
|
||||
Err(VMError::InvalidInstruction(
|
||||
"Phase 5: Future operations deprecated - use NewBox + BoxCall".to_string()
|
||||
))
|
||||
MirInstruction::BarrierWrite { ptr: _ } => {
|
||||
// Memory barrier write is a no-op for now
|
||||
// In a real implementation, this would ensure memory ordering
|
||||
Ok(ControlFlow::Continue)
|
||||
},
|
||||
|
||||
// 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
|
||||
@ -468,134 +585,6 @@ impl VM {
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@ -244,18 +244,47 @@ impl WasmCodegen {
|
||||
self.generate_return(value.as_ref())
|
||||
},
|
||||
|
||||
// Phase 3: Print removed - now handled by Call intrinsic (@print)
|
||||
|
||||
// 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()
|
||||
))
|
||||
MirInstruction::Print { value, .. } => {
|
||||
self.generate_print(*value)
|
||||
},
|
||||
|
||||
// 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 } => {
|
||||
// Create a new Box using the generic allocator
|
||||
@ -294,54 +323,29 @@ impl WasmCodegen {
|
||||
},
|
||||
|
||||
// Phase 8.4 PoC3: Extension stubs
|
||||
MirInstruction::WeakNew { dst, box_val } => {
|
||||
// WeakNew is still part of 26-instruction set
|
||||
MirInstruction::WeakNew { dst, box_val } |
|
||||
MirInstruction::FutureNew { dst, value: box_val } => {
|
||||
// Treat as regular reference for now
|
||||
Ok(vec![
|
||||
format!("local.get ${}", self.get_local_index(*box_val)?),
|
||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
||||
])
|
||||
},
|
||||
|
||||
// Phase 5: FutureNew deprecated - use NewBox "Future"
|
||||
#[allow(deprecated)]
|
||||
MirInstruction::FutureNew { .. } => {
|
||||
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
|
||||
MirInstruction::WeakLoad { dst, weak_ref } |
|
||||
MirInstruction::Await { dst, future: weak_ref } => {
|
||||
// Always succeed for now
|
||||
Ok(vec![
|
||||
format!("local.get ${}", self.get_local_index(*weak_ref)?),
|
||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
||||
])
|
||||
},
|
||||
|
||||
// Phase 5: Await deprecated - use BoxCall Future.await()
|
||||
#[allow(deprecated)]
|
||||
MirInstruction::Await { .. } => {
|
||||
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::BarrierRead { .. } |
|
||||
MirInstruction::BarrierWrite { .. } |
|
||||
MirInstruction::FutureSet { .. } |
|
||||
MirInstruction::Safepoint => {
|
||||
// Safepoint is still valid - no-op for now
|
||||
// No-op for now
|
||||
Ok(vec!["nop".to_string()])
|
||||
},
|
||||
|
||||
@ -404,189 +408,6 @@ impl WasmCodegen {
|
||||
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
|
||||
_ => Err(WasmError::UnsupportedInstruction(
|
||||
format!("Instruction not yet supported: {:?}", instruction)
|
||||
@ -865,36 +686,6 @@ impl WasmCodegen {
|
||||
|
||||
Ok(instructions)
|
||||
}
|
||||
|
||||
/// Generate Call instruction for intrinsic functions (Phase 4)
|
||||
fn generate_call_instruction(&mut self, dst: Option<&ValueId>, func: ValueId, args: &[ValueId]) -> Result<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)]
|
||||
|
||||
@ -8,13 +8,10 @@
|
||||
mod codegen;
|
||||
mod memory;
|
||||
mod runtime;
|
||||
mod host;
|
||||
mod executor;
|
||||
|
||||
pub use codegen::{WasmCodegen, WasmModule};
|
||||
pub use memory::{MemoryManager, BoxLayout};
|
||||
pub use runtime::RuntimeImports;
|
||||
pub use executor::WasmExecutor;
|
||||
|
||||
use crate::mir::MirModule;
|
||||
|
||||
@ -26,8 +23,6 @@ pub enum WasmError {
|
||||
UnsupportedInstruction(String),
|
||||
WasmValidationError(String),
|
||||
IOError(String),
|
||||
RuntimeError(String),
|
||||
CompilationError(String),
|
||||
}
|
||||
|
||||
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::WasmValidationError(msg) => write!(f, "WASM validation error: {}", msg),
|
||||
WasmError::IOError(msg) => write!(f, "IO error: {}", msg),
|
||||
WasmError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
|
||||
WasmError::CompilationError(msg) => write!(f, "Compilation error: {}", msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// 参考: 既存Boxの設計思想
|
||||
|
||||
use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase};
|
||||
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
|
||||
use std::any::Any;
|
||||
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
|
||||
pub type FutureBox = NyashFutureBox;
|
||||
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
*/
|
||||
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
||||
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
|
||||
use std::any::Any;
|
||||
use std::fmt::Display;
|
||||
|
||||
@ -117,23 +116,4 @@ impl Display for IntegerBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,7 +28,6 @@
|
||||
* ```
|
||||
*/
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
||||
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
|
||||
use std::any::Any;
|
||||
use std::fmt::Display;
|
||||
|
||||
@ -185,23 +184,4 @@ impl Display for StringBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -516,7 +516,7 @@ mod tests {
|
||||
|
||||
// フィールドに値を設定
|
||||
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();
|
||||
|
||||
@ -350,13 +350,13 @@ impl NyashInterpreter {
|
||||
|
||||
// 2. local変数をチェック
|
||||
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() で参照共有
|
||||
let shared_value = Arc::clone(local_value);
|
||||
|
||||
eprintln!("✅ RESOLVE_VARIABLE shared reference: {} id={}, type: {}",
|
||||
name, shared_value.box_id(), shared_value.type_name());
|
||||
eprintln!("✅ RESOLVE_VARIABLE shared reference: {} id={}",
|
||||
name, shared_value.box_id());
|
||||
|
||||
return Ok(shared_value);
|
||||
}
|
||||
@ -478,12 +478,7 @@ impl NyashInterpreter {
|
||||
|
||||
/// local変数を宣言(関数内でのみ有効)
|
||||
pub(super) fn declare_local_variable(&mut self, name: &str, value: Box<dyn NyashBox>) {
|
||||
eprintln!("🔍 DEBUG: declare_local_variable '{}' with type: {}, id: {}",
|
||||
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);
|
||||
self.local_vars.insert(name.to_string(), Arc::from(value));
|
||||
}
|
||||
|
||||
/// outbox変数を宣言(static関数内で所有権移転)
|
||||
|
||||
@ -13,8 +13,6 @@ use crate::instance::InstanceBox;
|
||||
use crate::channel_box::ChannelBox;
|
||||
use crate::interpreter::core::{NyashInterpreter, RuntimeError};
|
||||
use crate::interpreter::finalization;
|
||||
#[cfg(feature = "dynamic-file")]
|
||||
use crate::interpreter::plugin_loader::FileBoxProxy;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl NyashInterpreter {
|
||||
@ -257,18 +255,6 @@ impl NyashInterpreter {
|
||||
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
|
||||
if let Some(result_box) = obj_value.as_any().downcast_ref::<crate::box_trait::ResultBox>() {
|
||||
return self.execute_result_method(result_box, method, arguments);
|
||||
|
||||
@ -8,10 +8,7 @@
|
||||
|
||||
use super::*;
|
||||
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
|
||||
#[cfg(feature = "dynamic-file")]
|
||||
use crate::boxes::{FloatBox, ConsoleBox, SoundBox, DebugBox, MapBox};
|
||||
use std::sync::Arc;
|
||||
|
||||
impl NyashInterpreter {
|
||||
@ -241,43 +238,25 @@ impl NyashInterpreter {
|
||||
}
|
||||
|
||||
// MathBox method calls
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
// TimeBox method calls
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() {
|
||||
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
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() {
|
||||
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
|
||||
if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() {
|
||||
return self.execute_timer_method(timer_box, method, arguments);
|
||||
@ -289,16 +268,10 @@ impl NyashInterpreter {
|
||||
}
|
||||
|
||||
// RandomBox method calls
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() {
|
||||
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
|
||||
if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() {
|
||||
return self.execute_sound_method(sound_box, method, arguments);
|
||||
|
||||
@ -10,64 +10,11 @@
|
||||
use super::super::*;
|
||||
use crate::box_trait::{ResultBox, StringBox, NyashBox};
|
||||
use crate::boxes::FileBox;
|
||||
#[cfg(feature = "dynamic-file")]
|
||||
use crate::interpreter::plugin_loader::FileBoxProxy;
|
||||
|
||||
impl NyashInterpreter {
|
||||
/// FileBoxのメソッド呼び出しを実行
|
||||
/// 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])
|
||||
-> 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> {
|
||||
match method {
|
||||
"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 {
|
||||
message: format!("Unknown method '{}' for FileBox", method),
|
||||
})
|
||||
|
||||
@ -23,6 +23,5 @@ pub mod data_methods; // BufferBox, JSONBox, RegexBox
|
||||
pub mod network_methods; // HttpClientBox, StreamBox
|
||||
pub mod p2p_methods; // IntentBox, P2PBox
|
||||
pub mod http_methods; // SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox
|
||||
pub mod math_methods; // MathBox, RandomBox, TimeBox, DateTimeBox
|
||||
|
||||
// Re-export methods for easy access
|
||||
|
||||
@ -7,9 +7,7 @@
|
||||
|
||||
// Import all necessary dependencies
|
||||
use crate::ast::{ASTNode, CatchClause};
|
||||
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, ArrayBox, ResultBox, ErrorBox, BoxCore};
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
use crate::box_trait::FileBox;
|
||||
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, ArrayBox, FileBox, ResultBox, ErrorBox, BoxCore};
|
||||
use crate::boxes::FutureBox;
|
||||
use crate::instance::InstanceBox;
|
||||
use crate::channel_box::ChannelBox;
|
||||
@ -42,16 +40,10 @@ mod math_methods;
|
||||
mod system_methods;
|
||||
mod web_methods;
|
||||
mod special_methods;
|
||||
#[cfg(feature = "dynamic-file")]
|
||||
mod plugin_loader;
|
||||
|
||||
// Main interpreter implementation - will be moved from interpreter.rs
|
||||
pub use core::NyashInterpreter;
|
||||
|
||||
// Dynamic plugin support
|
||||
#[cfg(feature = "dynamic-file")]
|
||||
pub use plugin_loader::{PluginLoader, FileBoxProxy};
|
||||
|
||||
|
||||
/// 実行制御フロー
|
||||
#[derive(Debug)]
|
||||
|
||||
@ -7,11 +7,7 @@
|
||||
*/
|
||||
|
||||
use super::*;
|
||||
use crate::boxes::{NullBox, ConsoleBox, FloatBox, 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::{NullBox, ConsoleBox, FloatBox, DateTimeBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
||||
// use crate::boxes::intent_box_wrapper::IntentBoxWrapper;
|
||||
use crate::box_trait::SharedNyashBox;
|
||||
use std::sync::Arc;
|
||||
@ -98,18 +94,16 @@ impl NyashInterpreter {
|
||||
message: format!("FileBox constructor expects 1 argument, got {}", arguments.len()),
|
||||
});
|
||||
}
|
||||
// BoxFactoryRegistryを使用して作成(プラグイン対応)
|
||||
use crate::runtime::get_global_registry;
|
||||
let registry = get_global_registry();
|
||||
|
||||
// 引数を評価
|
||||
let mut evaluated_args = Vec::new();
|
||||
for arg in arguments {
|
||||
evaluated_args.push(self.execute_expression(arg)?);
|
||||
let path_value = self.execute_expression(&arguments[0])?;
|
||||
if let Some(path_str) = path_value.as_any().downcast_ref::<StringBox>() {
|
||||
let file_box = Box::new(FileBox::new(&path_str.value)) as Box<dyn NyashBox>;
|
||||
// 🌍 革命的実装:Environment tracking廃止
|
||||
return Ok(file_box);
|
||||
} else {
|
||||
return Err(RuntimeError::TypeError {
|
||||
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は引数1個(成功値)で作成
|
||||
@ -153,33 +147,9 @@ impl NyashInterpreter {
|
||||
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>;
|
||||
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);
|
||||
}
|
||||
let math_box = Box::new(MathBox::new()) as Box<dyn NyashBox>;
|
||||
// 🌍 革命的実装:Environment tracking廃止
|
||||
return Ok(math_box);
|
||||
}
|
||||
"NullBox" => {
|
||||
// NullBoxは引数なしで作成
|
||||
@ -392,65 +362,25 @@ impl NyashInterpreter {
|
||||
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>;
|
||||
return Ok(time_box);
|
||||
}
|
||||
let time_box = Box::new(TimeBox::new()) as Box<dyn NyashBox>;
|
||||
// 🌍 革命的実装:Environment tracking廃止
|
||||
return Ok(time_box);
|
||||
}
|
||||
"DateTimeBox" => {
|
||||
// DateTimeBoxは引数なしで現在時刻、または引数1個でタイムスタンプ
|
||||
match arguments.len() {
|
||||
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>;
|
||||
return Ok(datetime_box);
|
||||
}
|
||||
let datetime_box = Box::new(DateTimeBox::now()) as Box<dyn NyashBox>;
|
||||
// 🌍 革命的実装:Environment tracking廃止
|
||||
return Ok(datetime_box);
|
||||
}
|
||||
1 => {
|
||||
let timestamp_value = self.execute_expression(&arguments[0])?;
|
||||
|
||||
// Try integer timestamp first
|
||||
if let Some(int_box) = timestamp_value.as_any().downcast_ref::<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>;
|
||||
return Ok(datetime_box);
|
||||
}
|
||||
#[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());
|
||||
let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>;
|
||||
// 🌍 革命的実装:Environment tracking廃止
|
||||
return Ok(datetime_box);
|
||||
}
|
||||
#[cfg(not(feature = "dynamic-file"))]
|
||||
{
|
||||
} else {
|
||||
return Err(RuntimeError::TypeError {
|
||||
message: "DateTimeBox constructor requires integer timestamp".to_string(),
|
||||
});
|
||||
@ -492,18 +422,9 @@ impl NyashInterpreter {
|
||||
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>;
|
||||
return Ok(random_box);
|
||||
}
|
||||
let random_box = Box::new(RandomBox::new()) as Box<dyn NyashBox>;
|
||||
// 🌍 革命的実装:Environment tracking廃止
|
||||
return Ok(random_box);
|
||||
}
|
||||
"SoundBox" => {
|
||||
// SoundBoxは引数なしで作成
|
||||
|
||||
@ -145,7 +145,6 @@ impl NyashInterpreter {
|
||||
if let Some(Some(init_expr)) = initial_values.get(i) {
|
||||
// 🚀 初期化付きlocal宣言: local x = value
|
||||
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);
|
||||
} else {
|
||||
// 従来のlocal宣言: local x
|
||||
|
||||
@ -29,12 +29,6 @@ pub mod box_arithmetic; // 🚀 Arithmetic operations moved from box_trait.rs
|
||||
// 🔥 NyashValue Revolutionary System (NEW!)
|
||||
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!)
|
||||
pub mod messaging;
|
||||
pub mod transport;
|
||||
|
||||
@ -38,12 +38,6 @@ pub mod backend;
|
||||
// 📊 Performance 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
|
||||
pub mod cli;
|
||||
pub mod runner;
|
||||
|
||||
@ -291,28 +291,12 @@ impl MirBuilder {
|
||||
let operand_val = self.build_expression(operand)?;
|
||||
let dst = self.value_gen.next();
|
||||
|
||||
// Phase 2: Convert UnaryOp to intrinsic call
|
||||
// Create intrinsic function name based on operator
|
||||
let intrinsic_name = match operator.as_str() {
|
||||
"-" => "@unary_neg",
|
||||
"!" | "not" => "@unary_not",
|
||||
"~" => "@unary_bitnot",
|
||||
_ => return Err(format!("Unsupported unary operator: {}", operator)),
|
||||
};
|
||||
let mir_op = self.convert_unary_operator(operator)?;
|
||||
|
||||
// Create string constant for intrinsic function name
|
||||
let func_name_id = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: func_name_id,
|
||||
value: ConstValue::String(intrinsic_name.to_string()),
|
||||
})?;
|
||||
|
||||
// Emit intrinsic call
|
||||
self.emit_instruction(MirInstruction::Call {
|
||||
dst: Some(dst),
|
||||
func: func_name_id,
|
||||
args: vec![operand_val],
|
||||
effects: EffectMask::PURE, // Unary operations are pure
|
||||
self.emit_instruction(MirInstruction::UnaryOp {
|
||||
dst,
|
||||
op: mir_op,
|
||||
operand: operand_val,
|
||||
})?;
|
||||
|
||||
Ok(dst)
|
||||
@ -369,20 +353,10 @@ impl MirBuilder {
|
||||
fn build_print_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
||||
let value = self.build_expression(expression)?;
|
||||
|
||||
// Phase 2: Convert Print to intrinsic call (@print)
|
||||
// Create string constant for intrinsic function name
|
||||
let func_name_id = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: func_name_id,
|
||||
value: ConstValue::String("@print".to_string()),
|
||||
})?;
|
||||
|
||||
// Emit intrinsic call (print returns void)
|
||||
self.emit_instruction(MirInstruction::Call {
|
||||
dst: None, // Print has no return value
|
||||
func: func_name_id,
|
||||
args: vec![value],
|
||||
effects: EffectMask::PURE.add(Effect::Io), // IO effect for print
|
||||
// For now, use a special Print instruction (minimal scope)
|
||||
self.emit_instruction(MirInstruction::Print {
|
||||
value,
|
||||
effects: EffectMask::PURE.add(Effect::Io),
|
||||
})?;
|
||||
|
||||
// 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 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() {
|
||||
let exception_value = self.value_gen.next();
|
||||
|
||||
// Create string constants for intrinsic function name and exception type
|
||||
let func_name_id = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: func_name_id,
|
||||
value: ConstValue::String("@set_exception_handler".to_string()),
|
||||
})?;
|
||||
|
||||
let exception_type_id = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: exception_type_id,
|
||||
value: ConstValue::String(catch_clause.exception_type.clone().unwrap_or("*".to_string())),
|
||||
})?;
|
||||
|
||||
let handler_bb_id = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: handler_bb_id,
|
||||
value: ConstValue::Integer(catch_block.as_u32() as i64),
|
||||
})?;
|
||||
|
||||
// Register catch handler via intrinsic call
|
||||
self.emit_instruction(MirInstruction::Call {
|
||||
dst: Some(exception_value),
|
||||
func: func_name_id,
|
||||
args: vec![exception_type_id, handler_bb_id],
|
||||
effects: EffectMask::CONTROL, // Exception handling has control effects
|
||||
// Register catch handler for exceptions that may occur in try block
|
||||
self.emit_instruction(MirInstruction::Catch {
|
||||
exception_type: catch_clause.exception_type.clone(),
|
||||
exception_value,
|
||||
handler_bb: catch_block,
|
||||
})?;
|
||||
}
|
||||
|
||||
@ -655,20 +609,10 @@ impl MirBuilder {
|
||||
fn build_throw_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
||||
let exception_value = self.build_expression(expression)?;
|
||||
|
||||
// Phase 2: Convert Throw to intrinsic call (@throw)
|
||||
// Create string constant for intrinsic function name
|
||||
let func_name_id = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: func_name_id,
|
||||
value: ConstValue::String("@throw".to_string()),
|
||||
})?;
|
||||
|
||||
// Emit intrinsic call (throw has PANIC effect and doesn't return)
|
||||
self.emit_instruction(MirInstruction::Call {
|
||||
dst: None, // Throw never returns
|
||||
func: func_name_id,
|
||||
args: vec![exception_value],
|
||||
effects: EffectMask::PANIC, // PANIC effect for throw
|
||||
// Emit throw instruction with PANIC effect (this is a terminator)
|
||||
self.emit_instruction(MirInstruction::Throw {
|
||||
exception: exception_value,
|
||||
effects: EffectMask::PANIC,
|
||||
})?;
|
||||
|
||||
// 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
|
||||
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();
|
||||
self.emit_instruction(MirInstruction::BoxFieldLoad {
|
||||
self.emit_instruction(MirInstruction::RefGet {
|
||||
dst: result_id,
|
||||
box_val: object_value,
|
||||
reference: object_value,
|
||||
field,
|
||||
})?;
|
||||
|
||||
@ -772,45 +716,22 @@ impl MirBuilder {
|
||||
}
|
||||
|
||||
/// Build new expression: new ClassName(arguments)
|
||||
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,
|
||||
// treat it as a string constant, not a box creation
|
||||
if class == "StringBox" && arguments.len() == 1 {
|
||||
if let ASTNode::Literal { value: LiteralValue::String(s), .. } = &arguments[0] {
|
||||
// Just create a string constant
|
||||
let dst = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::String(s.clone()),
|
||||
})?;
|
||||
|
||||
// Phase 5-3: RefNew is deprecated - use NewBox instead
|
||||
let string_box_dst = self.value_gen.next();
|
||||
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
|
||||
fn build_new_expression(&mut self, class: String, _arguments: Vec<ASTNode>) -> Result<ValueId, String> {
|
||||
// For Phase 6.1, we'll create a simple RefNew without processing arguments
|
||||
// In a full implementation, arguments would be used for constructor calls
|
||||
let dst = self.value_gen.next();
|
||||
|
||||
// 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);
|
||||
}
|
||||
// For now, create a "box type" value representing the class
|
||||
let type_value = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Const {
|
||||
dst: type_value,
|
||||
value: ConstValue::String(class),
|
||||
})?;
|
||||
|
||||
// Create NewBox instruction
|
||||
self.emit_instruction(MirInstruction::NewBox {
|
||||
// Create the reference using RefNew
|
||||
self.emit_instruction(MirInstruction::RefNew {
|
||||
dst,
|
||||
box_type: class,
|
||||
args: arg_values,
|
||||
box_val: type_value,
|
||||
})?;
|
||||
|
||||
Ok(dst)
|
||||
@ -822,9 +743,9 @@ impl MirBuilder {
|
||||
let object_value = self.build_expression(object)?;
|
||||
let value_result = self.build_expression(value)?;
|
||||
|
||||
// Set the field using BoxFieldStore (Phase 8.5 new instruction)
|
||||
self.emit_instruction(MirInstruction::BoxFieldStore {
|
||||
box_val: object_value,
|
||||
// Set the field using RefSet
|
||||
self.emit_instruction(MirInstruction::RefSet {
|
||||
reference: object_value,
|
||||
field,
|
||||
value: value_result,
|
||||
})?;
|
||||
@ -888,12 +809,11 @@ impl MirBuilder {
|
||||
// Evaluate the 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();
|
||||
self.emit_instruction(MirInstruction::NewBox {
|
||||
self.emit_instruction(MirInstruction::FutureNew {
|
||||
dst: future_id,
|
||||
box_type: "FutureBox".to_string(),
|
||||
args: vec![expression_value],
|
||||
value: expression_value,
|
||||
})?;
|
||||
|
||||
// Store the future in the variable
|
||||
@ -907,16 +827,13 @@ impl MirBuilder {
|
||||
// Evaluate the expression (should be a Future)
|
||||
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();
|
||||
|
||||
// Emit await as a method call on the future box
|
||||
self.emit_instruction(MirInstruction::BoxCall {
|
||||
dst: Some(result_id),
|
||||
box_val: future_value,
|
||||
method: "await".to_string(),
|
||||
args: vec![],
|
||||
effects: EffectMask::IO.add(Effect::Control), // Await has IO and control effects
|
||||
// Emit await instruction
|
||||
self.emit_instruction(MirInstruction::Await {
|
||||
dst: result_id,
|
||||
future: future_value,
|
||||
})?;
|
||||
|
||||
Ok(result_id)
|
||||
|
||||
@ -31,8 +31,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Unary operation
|
||||
/// `%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 {
|
||||
dst: ValueId,
|
||||
op: UnaryOp,
|
||||
@ -52,8 +50,6 @@ pub enum MirInstruction {
|
||||
// === Memory Operations ===
|
||||
/// Load from memory/variable
|
||||
/// `%dst = load %ptr`
|
||||
/// DEPRECATED: Phase 5 - Use BoxFieldLoad instead
|
||||
#[deprecated(since = "Phase 5", note = "Use BoxFieldLoad instead")]
|
||||
Load {
|
||||
dst: ValueId,
|
||||
ptr: ValueId,
|
||||
@ -61,8 +57,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Store to memory/variable
|
||||
/// `store %value -> %ptr`
|
||||
/// DEPRECATED: Phase 5 - Use BoxFieldStore instead
|
||||
#[deprecated(since = "Phase 5", note = "Use BoxFieldStore instead")]
|
||||
Store {
|
||||
value: ValueId,
|
||||
ptr: ValueId,
|
||||
@ -128,8 +122,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Check Box type
|
||||
/// `%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 {
|
||||
dst: ValueId,
|
||||
value: ValueId,
|
||||
@ -139,8 +131,6 @@ pub enum MirInstruction {
|
||||
// === Type Conversion ===
|
||||
/// Convert between types
|
||||
/// `%dst = cast %value as Type`
|
||||
/// DEPRECATED: Phase 5 - Use Call with @cast intrinsic
|
||||
#[deprecated(since = "Phase 5", note = "Use Call with @cast intrinsic")]
|
||||
Cast {
|
||||
dst: ValueId,
|
||||
value: ValueId,
|
||||
@ -150,8 +140,6 @@ pub enum MirInstruction {
|
||||
// === Array Operations ===
|
||||
/// Get array element
|
||||
/// `%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 {
|
||||
dst: ValueId,
|
||||
array: ValueId,
|
||||
@ -160,8 +148,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Set array element
|
||||
/// `%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 {
|
||||
array: ValueId,
|
||||
index: ValueId,
|
||||
@ -171,8 +157,6 @@ pub enum MirInstruction {
|
||||
// === Special Operations ===
|
||||
/// Copy a value (for optimization passes)
|
||||
/// `%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 {
|
||||
dst: ValueId,
|
||||
src: ValueId,
|
||||
@ -180,8 +164,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Debug/introspection instruction
|
||||
/// `debug %value "message"`
|
||||
/// DEPRECATED: Phase 5 - Use Call with @debug intrinsic
|
||||
#[deprecated(since = "Phase 5", note = "Use Call with @debug intrinsic")]
|
||||
Debug {
|
||||
value: ValueId,
|
||||
message: String,
|
||||
@ -189,24 +171,18 @@ pub enum MirInstruction {
|
||||
|
||||
/// Print instruction for console output
|
||||
/// `print %value`
|
||||
/// DEPRECATED: Phase 5 - Use Call with @print intrinsic
|
||||
#[deprecated(since = "Phase 5", note = "Use Call with @print intrinsic")]
|
||||
Print {
|
||||
value: ValueId,
|
||||
effects: EffectMask,
|
||||
},
|
||||
|
||||
/// 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,
|
||||
|
||||
// === Control Flow & Exception Handling (Phase 5) ===
|
||||
|
||||
/// Throw an exception
|
||||
/// `throw %exception_value`
|
||||
/// DEPRECATED: Phase 5 - Use Call with @throw intrinsic
|
||||
#[deprecated(since = "Phase 5", note = "Use Call with @throw intrinsic")]
|
||||
Throw {
|
||||
exception: ValueId,
|
||||
effects: EffectMask,
|
||||
@ -214,8 +190,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Catch handler setup (landing pad for exceptions)
|
||||
/// `catch %exception_type -> %handler_bb`
|
||||
/// DEPRECATED: Phase 5 - Use Call with @catch intrinsic
|
||||
#[deprecated(since = "Phase 5", note = "Use Call with @catch intrinsic")]
|
||||
Catch {
|
||||
exception_type: Option<String>, // None = catch-all
|
||||
exception_value: ValueId, // Where to store caught exception
|
||||
@ -230,8 +204,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Create a new reference to a Box
|
||||
/// `%dst = ref_new %box`
|
||||
/// DEPRECATED: Phase 5 - RefGet is sufficient
|
||||
#[deprecated(since = "Phase 5", note = "RefGet is sufficient")]
|
||||
RefNew {
|
||||
dst: ValueId,
|
||||
box_val: ValueId,
|
||||
@ -269,16 +241,12 @@ pub enum MirInstruction {
|
||||
|
||||
/// Memory barrier read (no-op for now, proper effect annotation)
|
||||
/// `barrier_read %ptr`
|
||||
/// DEPRECATED: Phase 5 - Use AtomicFence instead
|
||||
#[deprecated(since = "Phase 5", note = "Use AtomicFence instead")]
|
||||
BarrierRead {
|
||||
ptr: ValueId,
|
||||
},
|
||||
|
||||
/// Memory barrier write (no-op for now, proper effect annotation)
|
||||
/// `barrier_write %ptr`
|
||||
/// DEPRECATED: Phase 5 - Use AtomicFence instead
|
||||
#[deprecated(since = "Phase 5", note = "Use AtomicFence instead")]
|
||||
BarrierWrite {
|
||||
ptr: ValueId,
|
||||
},
|
||||
@ -287,8 +255,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Create a new Future with initial value
|
||||
/// `%dst = future_new %value`
|
||||
/// DEPRECATED: Phase 5 - Use NewBox + BoxCall
|
||||
#[deprecated(since = "Phase 5", note = "Use NewBox + BoxCall")]
|
||||
FutureNew {
|
||||
dst: ValueId,
|
||||
value: ValueId,
|
||||
@ -296,8 +262,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Set Future value and mark as ready
|
||||
/// `future_set %future = %value`
|
||||
/// DEPRECATED: Phase 5 - Use BoxCall
|
||||
#[deprecated(since = "Phase 5", note = "Use BoxCall")]
|
||||
FutureSet {
|
||||
future: ValueId,
|
||||
value: ValueId,
|
||||
@ -305,8 +269,6 @@ pub enum MirInstruction {
|
||||
|
||||
/// Wait for Future completion and get value
|
||||
/// `%dst = await %future`
|
||||
/// DEPRECATED: Phase 5 - Use BoxCall
|
||||
#[deprecated(since = "Phase 5", note = "Use BoxCall")]
|
||||
Await {
|
||||
dst: ValueId,
|
||||
future: ValueId,
|
||||
@ -323,80 +285,6 @@ pub enum MirInstruction {
|
||||
args: Vec<ValueId>,
|
||||
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
|
||||
@ -456,16 +344,6 @@ pub enum MirType {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Atomic memory ordering for fence operations
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum AtomicOrdering {
|
||||
Relaxed,
|
||||
Acquire,
|
||||
Release,
|
||||
AcqRel,
|
||||
SeqCst,
|
||||
}
|
||||
|
||||
impl MirInstruction {
|
||||
/// Get the effect mask for this instruction
|
||||
pub fn effects(&self) -> EffectMask {
|
||||
@ -526,18 +404,6 @@ impl MirInstruction {
|
||||
|
||||
// Phase 9.7: External Function Calls
|
||||
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask
|
||||
|
||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
||||
MirInstruction::BoxFieldLoad { .. } => EffectMask::READ, // Box field read
|
||||
MirInstruction::BoxFieldStore { .. } => EffectMask::WRITE, // Box field write
|
||||
MirInstruction::WeakCheck { .. } => EffectMask::PURE, // Check is pure
|
||||
MirInstruction::Send { .. } => EffectMask::IO, // Bus send has IO effects
|
||||
MirInstruction::Recv { .. } => EffectMask::IO, // Bus recv has IO effects
|
||||
MirInstruction::TailCall { effects, .. } => *effects, // Use provided effect mask
|
||||
MirInstruction::Adopt { .. } => EffectMask::WRITE, // Ownership change has write effects
|
||||
MirInstruction::Release { .. } => EffectMask::WRITE, // Ownership release has write effects
|
||||
MirInstruction::MemCopy { .. } => EffectMask::WRITE, // Memory copy has write effects
|
||||
MirInstruction::AtomicFence { .. } => EffectMask::IO.add(Effect::Barrier), // Fence has barrier + IO
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,12 +432,6 @@ impl MirInstruction {
|
||||
MirInstruction::BoxCall { dst, .. } |
|
||||
MirInstruction::ExternCall { dst, .. } => *dst,
|
||||
|
||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
||||
MirInstruction::BoxFieldLoad { dst, .. } |
|
||||
MirInstruction::WeakCheck { dst, .. } |
|
||||
MirInstruction::Recv { dst, .. } |
|
||||
MirInstruction::MemCopy { dst, .. } => Some(*dst),
|
||||
|
||||
MirInstruction::Store { .. } |
|
||||
MirInstruction::Branch { .. } |
|
||||
MirInstruction::Jump { .. } |
|
||||
@ -587,14 +447,6 @@ impl MirInstruction {
|
||||
MirInstruction::Safepoint |
|
||||
MirInstruction::Nop => None,
|
||||
|
||||
// Phase 8.5: Non-value producing instructions
|
||||
MirInstruction::BoxFieldStore { .. } |
|
||||
MirInstruction::Send { .. } |
|
||||
MirInstruction::TailCall { .. } |
|
||||
MirInstruction::Adopt { .. } |
|
||||
MirInstruction::Release { .. } |
|
||||
MirInstruction::AtomicFence { .. } => None,
|
||||
|
||||
MirInstruction::Catch { exception_value, .. } => Some(*exception_value),
|
||||
}
|
||||
}
|
||||
@ -667,22 +519,6 @@ impl MirInstruction {
|
||||
|
||||
// Phase 9.7: External Function Calls
|
||||
MirInstruction::ExternCall { args, .. } => args.clone(),
|
||||
|
||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
||||
MirInstruction::BoxFieldLoad { box_val, .. } => vec![*box_val],
|
||||
MirInstruction::BoxFieldStore { box_val, value, .. } => vec![*box_val, *value],
|
||||
MirInstruction::WeakCheck { weak_ref, .. } => vec![*weak_ref],
|
||||
MirInstruction::Send { data, target } => vec![*data, *target],
|
||||
MirInstruction::Recv { source, .. } => vec![*source],
|
||||
MirInstruction::TailCall { func, args, .. } => {
|
||||
let mut used = vec![*func];
|
||||
used.extend(args);
|
||||
used
|
||||
},
|
||||
MirInstruction::Adopt { parent, child } => vec![*parent, *child],
|
||||
MirInstruction::Release { reference } => vec![*reference],
|
||||
MirInstruction::MemCopy { dst, src, size } => vec![*dst, *src, *size],
|
||||
MirInstruction::AtomicFence { .. } => Vec::new(), // Fence doesn't use values
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -766,39 +602,6 @@ impl fmt::Display for MirInstruction {
|
||||
effects)
|
||||
}
|
||||
},
|
||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
||||
MirInstruction::BoxFieldLoad { dst, box_val, field } => {
|
||||
write!(f, "{} = {}.{}", dst, box_val, field)
|
||||
},
|
||||
MirInstruction::BoxFieldStore { box_val, field, value } => {
|
||||
write!(f, "{}.{} = {}", box_val, field, value)
|
||||
},
|
||||
MirInstruction::WeakCheck { dst, weak_ref } => {
|
||||
write!(f, "{} = weak_check {}", dst, weak_ref)
|
||||
},
|
||||
MirInstruction::Send { data, target } => {
|
||||
write!(f, "send {} -> {}", data, target)
|
||||
},
|
||||
MirInstruction::Recv { dst, source } => {
|
||||
write!(f, "{} = recv {}", dst, source)
|
||||
},
|
||||
MirInstruction::TailCall { func, args, effects } => {
|
||||
write!(f, "tail_call {}({}); effects: {}", func,
|
||||
args.iter().map(|v| format!("{}", v)).collect::<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
|
||||
}
|
||||
}
|
||||
@ -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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@ -13,7 +13,6 @@ pub mod builder;
|
||||
pub mod verification;
|
||||
pub mod ownership_verifier_simple; // Simple ownership forest verification for current MIR
|
||||
pub mod printer;
|
||||
pub mod optimizer; // Phase 3: Effect System based optimization passes
|
||||
pub mod value_id;
|
||||
pub mod effect;
|
||||
|
||||
@ -26,7 +25,6 @@ pub use builder::MirBuilder;
|
||||
pub use verification::{MirVerifier, VerificationError};
|
||||
pub use ownership_verifier_simple::{OwnershipVerifier, OwnershipError, OwnershipStats}; // Simple ownership forest verification
|
||||
pub use printer::MirPrinter;
|
||||
pub use optimizer::{MirOptimizer, OptimizationStats}; // Phase 3: Effect System optimizations
|
||||
pub use value_id::{ValueId, LocalId, ValueIdGenerator};
|
||||
pub use effect::{EffectMask, Effect};
|
||||
|
||||
|
||||
@ -371,39 +371,6 @@ impl MirPrinter {
|
||||
format!("extern_call {}.{}({}) [effects: {}]", iface_name, method_name, args_str, effects)
|
||||
}
|
||||
},
|
||||
|
||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
||||
MirInstruction::BoxFieldLoad { dst, box_val, field } => {
|
||||
format!("{} = {}.{}", dst, box_val, field)
|
||||
},
|
||||
MirInstruction::BoxFieldStore { box_val, field, value } => {
|
||||
format!("{}.{} = {}", box_val, field, value)
|
||||
},
|
||||
MirInstruction::WeakCheck { dst, weak_ref } => {
|
||||
format!("{} = weak_check {}", dst, weak_ref)
|
||||
},
|
||||
MirInstruction::Send { data, target } => {
|
||||
format!("send {} -> {}", data, target)
|
||||
},
|
||||
MirInstruction::Recv { dst, source } => {
|
||||
format!("{} = recv {}", dst, source)
|
||||
},
|
||||
MirInstruction::TailCall { func, args, effects } => {
|
||||
let args_str = args.iter().map(|v| format!("{}", v)).collect::<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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ use crate::{
|
||||
interpreter::NyashInterpreter,
|
||||
mir::{MirCompiler, MirPrinter},
|
||||
backend::{VM, wasm::WasmBackend, aot::AotBackend},
|
||||
runtime::{PluginConfig, get_global_registry},
|
||||
};
|
||||
use std::{fs, process};
|
||||
|
||||
@ -26,88 +25,8 @@ pub struct NyashRunner {
|
||||
impl NyashRunner {
|
||||
/// Create a new runner with the given configuration
|
||||
pub fn new(config: CliConfig) -> Self {
|
||||
// 🔌 プラグインシステム初期化
|
||||
Self::initialize_plugin_system();
|
||||
|
||||
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(®istry);
|
||||
|
||||
// プラグイン設定を適用
|
||||
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(®istry);
|
||||
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
|
||||
pub fn run(&self) {
|
||||
|
||||
19
test_simple.nyash
Normal file
19
test_simple.nyash
Normal 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())
|
||||
@ -6,10 +6,10 @@
|
||||
|
||||
use nyash_rust::mir::{
|
||||
MirModule, MirFunction, FunctionSignature, MirType, EffectMask,
|
||||
BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue, AtomicOrdering
|
||||
BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue
|
||||
};
|
||||
use nyash_rust::backend::VM;
|
||||
use nyash_rust::box_trait::IntegerBox;
|
||||
use nyash_rust::backend::{VM, VMValue};
|
||||
use nyash_rust::box_trait::{IntegerBox, NyashBox};
|
||||
|
||||
#[test]
|
||||
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 one_val = ValueId::new(2);
|
||||
let x_val = ValueId::new(3);
|
||||
let print_func = ValueId::new(4);
|
||||
|
||||
// Add instructions
|
||||
|
||||
@ -55,18 +54,10 @@ fn test_mir_phase6_vm_ref_ops() {
|
||||
value: ConstValue::String("Obj".to_string()),
|
||||
});
|
||||
|
||||
// %4 = const "@print" (for intrinsic call)
|
||||
block.add_instruction(MirInstruction::Const {
|
||||
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 {
|
||||
// %1 = ref_new %0
|
||||
block.add_instruction(MirInstruction::RefNew {
|
||||
dst: obj_ref,
|
||||
box_type: "Obj".to_string(),
|
||||
args: vec![],
|
||||
box_val: obj_type_val,
|
||||
});
|
||||
|
||||
// %2 = const 1
|
||||
@ -75,34 +66,28 @@ fn test_mir_phase6_vm_ref_ops() {
|
||||
value: ConstValue::Integer(1),
|
||||
});
|
||||
|
||||
// atomic_fence release
|
||||
// Phase 5: BarrierWrite is deprecated - use AtomicFence instead
|
||||
block.add_instruction(MirInstruction::AtomicFence {
|
||||
ordering: AtomicOrdering::Release,
|
||||
// barrier_write %1
|
||||
block.add_instruction(MirInstruction::BarrierWrite {
|
||||
ptr: obj_ref,
|
||||
});
|
||||
|
||||
// %1.x = %2
|
||||
// Phase 5: RefSet is deprecated - use BoxFieldStore instead
|
||||
block.add_instruction(MirInstruction::BoxFieldStore {
|
||||
box_val: obj_ref,
|
||||
// ref_set %1, "x", %2
|
||||
block.add_instruction(MirInstruction::RefSet {
|
||||
reference: obj_ref,
|
||||
field: "x".to_string(),
|
||||
value: one_val,
|
||||
});
|
||||
|
||||
// %3 = %1.x
|
||||
// Phase 5: RefGet is deprecated - use BoxFieldLoad instead
|
||||
block.add_instruction(MirInstruction::BoxFieldLoad {
|
||||
// %3 = ref_get %1, "x"
|
||||
block.add_instruction(MirInstruction::RefGet {
|
||||
dst: x_val,
|
||||
box_val: obj_ref,
|
||||
reference: obj_ref,
|
||||
field: "x".to_string(),
|
||||
});
|
||||
|
||||
// call @print(%3)
|
||||
// Phase 5: Print is deprecated - use Call @print instead
|
||||
block.add_instruction(MirInstruction::Call {
|
||||
dst: None,
|
||||
func: print_func,
|
||||
args: vec![x_val],
|
||||
// print %3
|
||||
block.add_instruction(MirInstruction::Print {
|
||||
value: x_val,
|
||||
effects: EffectMask::IO,
|
||||
});
|
||||
|
||||
@ -183,14 +168,13 @@ fn test_barrier_no_op() {
|
||||
value: ConstValue::Integer(42),
|
||||
});
|
||||
|
||||
// Test atomic fence instructions (replace barriers)
|
||||
// Phase 5: BarrierRead/BarrierWrite are deprecated - use AtomicFence
|
||||
block.add_instruction(MirInstruction::AtomicFence {
|
||||
ordering: AtomicOrdering::Acquire,
|
||||
// Test barrier instructions (should be no-ops)
|
||||
block.add_instruction(MirInstruction::BarrierRead {
|
||||
ptr: test_val,
|
||||
});
|
||||
|
||||
block.add_instruction(MirInstruction::AtomicFence {
|
||||
ordering: AtomicOrdering::Release,
|
||||
block.add_instruction(MirInstruction::BarrierWrite {
|
||||
ptr: test_val,
|
||||
});
|
||||
|
||||
block.add_instruction(MirInstruction::Return {
|
||||
|
||||
@ -107,17 +107,17 @@ fn test_mir_phase7_basic_nowait_await() {
|
||||
.flat_map(|block| &block.instructions)
|
||||
.collect();
|
||||
|
||||
// Phase 5: FutureNew is deprecated - should contain NewBox "FutureBox" instead
|
||||
let has_future_box = instructions.iter().any(|inst| {
|
||||
matches!(inst, nyash_rust::mir::MirInstruction::NewBox { box_type, .. } if box_type == "FutureBox")
|
||||
// Should contain FutureNew instruction
|
||||
let has_future_new = instructions.iter().any(|inst| {
|
||||
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
|
||||
let has_await_call = instructions.iter().any(|inst| {
|
||||
matches!(inst, nyash_rust::mir::MirInstruction::BoxCall { method, .. } if method == "await")
|
||||
// Should contain Await instruction
|
||||
let has_await = instructions.iter().any(|inst| {
|
||||
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
|
||||
let mut vm = VM::new();
|
||||
|
||||
334
tests/wasm_poc2_box_operations.rs
Normal file
334
tests/wasm_poc2_box_operations.rs
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user