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 = ["dep:egui", "dep:eframe", "dep:egui_extras", "dep:image"]
|
||||||
gui-examples = ["gui"]
|
gui-examples = ["gui"]
|
||||||
all-examples = ["gui-examples"]
|
all-examples = ["gui-examples"]
|
||||||
# 動的ライブラリサポート
|
|
||||||
dynamic-file = ["dep:libloading"]
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "nyash_rust"
|
name = "nyash_rust"
|
||||||
@ -29,11 +27,6 @@ crate-type = ["cdylib", "rlib"]
|
|||||||
name = "nyash"
|
name = "nyash"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
# WASM runner executable
|
|
||||||
[[bin]]
|
|
||||||
name = "nyash-wasm-run"
|
|
||||||
path = "src/bin/nyash-wasm-run.rs"
|
|
||||||
|
|
||||||
# Examples for development - only available as examples, not bins
|
# Examples for development - only available as examples, not bins
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "gui_simple_notepad"
|
name = "gui_simple_notepad"
|
||||||
@ -120,9 +113,6 @@ js-sys = "0.3"
|
|||||||
wabt = "0.10"
|
wabt = "0.10"
|
||||||
wasmtime = "35.0.0"
|
wasmtime = "35.0.0"
|
||||||
|
|
||||||
# 動的ライブラリロード(Phase 9.75f)
|
|
||||||
libloading = { version = "0.8", optional = true }
|
|
||||||
|
|
||||||
# GUI フレームワーク - only when gui feature is enabled
|
# GUI フレームワーク - only when gui feature is enabled
|
||||||
egui = { version = "0.29", optional = true }
|
egui = { version = "0.29", optional = true }
|
||||||
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true }
|
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true }
|
||||||
@ -179,12 +169,3 @@ panic = "abort"
|
|||||||
# 開発用設定
|
# 開発用設定
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
# Workspace configuration
|
|
||||||
[workspace]
|
|
||||||
members = [
|
|
||||||
".", # メインのnyash-rustプロジェクト
|
|
||||||
"plugins/nyash-file", # FileBoxプラグイン
|
|
||||||
"plugins/nyash-math", # Math/Time系プラグイン
|
|
||||||
]
|
|
||||||
resolver = "2"
|
|
||||||
|
|||||||
1363
build_errors.txt
1363
build_errors.txt
File diff suppressed because it is too large
Load Diff
@ -61,7 +61,7 @@
|
|||||||
- ✅ libloadingプラグイン動的ロード基盤
|
- ✅ libloadingプラグイン動的ロード基盤
|
||||||
- ✅ **プラグインシステム統合テスト(14/14合格!)** 🎉
|
- ✅ **プラグインシステム統合テスト(14/14合格!)** 🎉
|
||||||
|
|
||||||
### 🎯 **Day 5 90%完了!** (2025-08-17)
|
### 🎯 **Day 5 一時中断** (2025-08-18)
|
||||||
**目標**: 実際のプラグインライブラリ作成と統合
|
**目標**: 実際のプラグインライブラリ作成と統合
|
||||||
|
|
||||||
**実装戦略**:
|
**実装戦略**:
|
||||||
@ -75,8 +75,15 @@
|
|||||||
- ✅ Nyashインタープリターのプラグインロード統合
|
- ✅ Nyashインタープリターのプラグインロード統合
|
||||||
- ✅ 透過的切り替え実動作確認(PluginBox生成確認)
|
- ✅ 透過的切り替え実動作確認(PluginBox生成確認)
|
||||||
|
|
||||||
**残作業(最後の10%)**:
|
**中断理由**:
|
||||||
- ⏳ PluginBoxのtoString等メソッド実装修正
|
- 🚨 **古いプラグインシステムのコードが混在していた**
|
||||||
|
- 🔧 ソースコードをcommit 3f7d71f(古いプラグイン実装前)に巻き戻し
|
||||||
|
- 📚 docsフォルダは最新状態を維持
|
||||||
|
- ✅ nyashバイナリの基本動作確認完了
|
||||||
|
|
||||||
|
**再開時の作業**:
|
||||||
|
- ⏳ BID-FFIシステムをクリーンに再実装
|
||||||
|
- ⏳ PluginBoxのtoString等メソッド実装
|
||||||
- ⏳ 実際のファイル操作メソッド(open/read/write)動作確認
|
- ⏳ 実際のファイル操作メソッド(open/read/write)動作確認
|
||||||
|
|
||||||
### 🎯 今週の実装計画(段階的戦略に更新)
|
### 🎯 今週の実装計画(段階的戦略に更新)
|
||||||
@ -153,27 +160,35 @@ cargo build --release -j32
|
|||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
**最終更新**: 2025-08-17 26:30
|
**最終更新**: 2025-08-18 08:30 JST
|
||||||
**次回レビュー**: 2025-08-18(Day 5-6完了時)
|
**次回レビュー**: 2025-08-18(BID-FFI再実装開始時)
|
||||||
|
|
||||||
## 🎯 **Day 5 最終段階の詳細**
|
## 🎯 **現在の状況** (2025-08-18)
|
||||||
|
|
||||||
### 現在の動作状況
|
### クリーンアップ完了
|
||||||
1. **nyash.tomlなし**: ビルトインFileBox動作 ✅
|
1. **古いプラグインシステム削除**: ソースコードをcommit 3f7d71fに巻き戻し ✅
|
||||||
2. **nyash.tomlあり**: プラグインFileBoxロード成功 ✅
|
2. **ドキュメント保持**: docs/は最新の状態を維持 ✅
|
||||||
3. **PluginBox生成**: 成功(type_name: PluginBox) ✅
|
3. **基本動作確認**: nyashバイナリが正常動作 ✅
|
||||||
4. **toString呼び出し**: エラー(PluginBoxプロキシが未完成) ❌
|
4. **ビルド成功**: `cargo build --release --bin nyash` 完了 ✅
|
||||||
|
|
||||||
### 残作業詳細
|
### BID-FFI実装状況
|
||||||
1. **PluginBox完全実装**
|
- **仕様**: 完成済み(docs/説明書/reference/box-design/ffi-abi-specification.md)
|
||||||
- toStringメソッドのプラグイン呼び出し
|
- **設計**: 完成済み(docs/説明書/reference/box-design/plugin-system.md)
|
||||||
- ファイル操作メソッド(open/read/write/close)転送
|
- **基盤コード**: src/bid/モジュールは削除済み(再実装必要)
|
||||||
|
- **プラグイン**: plugins/nyash-filebox-pluginも削除済み(再作成必要)
|
||||||
|
|
||||||
2. **BID-FFI統合**
|
### 次のステップ
|
||||||
- TLVエンコード/デコードの実際の動作
|
1. **BID-FFIシステムをクリーンに再実装**
|
||||||
- メソッドディスパッチの実装
|
- src/bid/モジュール作成
|
||||||
|
- TLVエンコード/デコード実装
|
||||||
|
- プラグインローダー実装
|
||||||
|
|
||||||
### 実証成功の証拠
|
2. **FileBoxプラグイン作成**
|
||||||
- プラグイン動的ロード: `✅ Plugin library loaded: nyash_filebox_plugin`
|
- plugins/nyash-filebox-plugin/再作成
|
||||||
- BoxFactoryRegistry統合: FileBox → PluginBox自動切り替え
|
- C FFI実装
|
||||||
- プラグインシステム基盤: 90%完成!
|
- ビルドシステム構築
|
||||||
|
|
||||||
|
3. **統合テスト**
|
||||||
|
- nyash.tomlによる切り替え
|
||||||
|
- プラグイン動的ロード確認
|
||||||
|
- メソッド呼び出し動作確認
|
||||||
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::UnsupportedInstruction(msg) => AotError::CompilationError(format!("Unsupported MIR instruction: {}", msg)),
|
||||||
WasmError::WasmValidationError(msg) => AotError::CompilationError(format!("WASM validation failed: {}", msg)),
|
WasmError::WasmValidationError(msg) => AotError::CompilationError(format!("WASM validation failed: {}", msg)),
|
||||||
WasmError::IOError(msg) => AotError::IOError(msg),
|
WasmError::IOError(msg) => AotError::IOError(msg),
|
||||||
WasmError::RuntimeError(msg) => AotError::RuntimeError(msg),
|
|
||||||
WasmError::CompilationError(msg) => AotError::CompilationError(msg),
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.stats.wasm_size = wasm_bytes.len();
|
self.stats.wasm_size = wasm_bytes.len();
|
||||||
|
|||||||
@ -231,7 +231,12 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 3: UnaryOp removed - now handled by Call intrinsics (@unary_neg, @unary_not, etc.)
|
MirInstruction::UnaryOp { dst, op, operand } => {
|
||||||
|
let operand_val = self.get_value(*operand)?;
|
||||||
|
let result = self.execute_unary_op(op, &operand_val)?;
|
||||||
|
self.values.insert(*dst, result);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
MirInstruction::Compare { dst, op, lhs, rhs } => {
|
MirInstruction::Compare { dst, op, lhs, rhs } => {
|
||||||
let left = self.get_value(*lhs)?;
|
let left = self.get_value(*lhs)?;
|
||||||
@ -241,7 +246,11 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 3: Print removed - now handled by Call intrinsic (@print)
|
MirInstruction::Print { value, .. } => {
|
||||||
|
let val = self.get_value(*value)?;
|
||||||
|
println!("{}", val.to_string());
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
MirInstruction::Return { value } => {
|
MirInstruction::Return { value } => {
|
||||||
let return_value = if let Some(val_id) = value {
|
let return_value = if let Some(val_id) = value {
|
||||||
@ -280,31 +289,27 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 3: Load/Store removed - now handled by BoxFieldLoad/BoxFieldStore
|
// Missing instructions that need basic implementations
|
||||||
|
MirInstruction::Load { dst, ptr } => {
|
||||||
|
// For now, loading is the same as getting the value
|
||||||
|
let value = self.get_value(*ptr)?;
|
||||||
|
self.values.insert(*dst, value);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
MirInstruction::Call { dst, func, args, effects: _ } => {
|
MirInstruction::Store { value, ptr } => {
|
||||||
// Phase 2: Handle intrinsic function calls
|
// For now, storing just updates the ptr with the value
|
||||||
let func_value = self.get_value(*func)?;
|
let val = self.get_value(*value)?;
|
||||||
|
self.values.insert(*ptr, val);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
if let VMValue::String(func_name) = func_value {
|
MirInstruction::Call { dst, func: _, args: _, effects: _ } => {
|
||||||
if func_name.starts_with('@') {
|
// For now, function calls return void
|
||||||
// This is an intrinsic call
|
// TODO: Implement proper function call handling
|
||||||
let result = self.execute_intrinsic(&func_name, args)?;
|
|
||||||
if let Some(dst_id) = dst {
|
|
||||||
self.values.insert(*dst_id, result);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Regular function call - not implemented yet
|
|
||||||
if let Some(dst_id) = dst {
|
if let Some(dst_id) = dst {
|
||||||
self.values.insert(*dst_id, VMValue::Void);
|
self.values.insert(*dst_id, VMValue::Void);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Non-string function - not implemented yet
|
|
||||||
if let Some(dst_id) = dst {
|
|
||||||
self.values.insert(*dst_id, VMValue::Void);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -364,27 +369,67 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: Removed instructions - TypeCheck, Cast, ArrayGet, ArraySet, Copy, Debug, Nop
|
MirInstruction::TypeCheck { dst, value: _, expected_type: _ } => {
|
||||||
#[allow(deprecated)]
|
// For now, type checks always return true
|
||||||
MirInstruction::TypeCheck { .. } |
|
// TODO: Implement proper type checking
|
||||||
MirInstruction::Cast { .. } |
|
self.values.insert(*dst, VMValue::Bool(true));
|
||||||
MirInstruction::ArrayGet { .. } |
|
Ok(ControlFlow::Continue)
|
||||||
MirInstruction::ArraySet { .. } |
|
|
||||||
MirInstruction::Copy { .. } |
|
|
||||||
MirInstruction::Debug { .. } |
|
|
||||||
MirInstruction::Nop => {
|
|
||||||
Err(VMError::InvalidInstruction(
|
|
||||||
"Phase 5: Deprecated instruction - use 26-instruction set replacements".to_string()
|
|
||||||
))
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: Removed instructions - Throw, Catch
|
MirInstruction::Cast { dst, value, target_type: _ } => {
|
||||||
#[allow(deprecated)]
|
// For now, casting just copies the value
|
||||||
MirInstruction::Throw { .. } |
|
// TODO: Implement proper type casting
|
||||||
MirInstruction::Catch { .. } => {
|
let val = self.get_value(*value)?;
|
||||||
Err(VMError::InvalidInstruction(
|
self.values.insert(*dst, val);
|
||||||
"Phase 5: Exception handling via intrinsics - use Call with @throw/@catch".to_string()
|
Ok(ControlFlow::Continue)
|
||||||
))
|
},
|
||||||
|
|
||||||
|
MirInstruction::ArrayGet { dst, array: _, index: _ } => {
|
||||||
|
// For now, array access returns a placeholder
|
||||||
|
// TODO: Implement proper array access
|
||||||
|
self.values.insert(*dst, VMValue::Integer(0));
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::ArraySet { array: _, index: _, value: _ } => {
|
||||||
|
// For now, array setting is a no-op
|
||||||
|
// TODO: Implement proper array setting
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::Copy { dst, src } => {
|
||||||
|
// Copy instruction - duplicate the source value
|
||||||
|
let val = self.get_value(*src)?;
|
||||||
|
self.values.insert(*dst, val);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::Debug { value, message: _ } => {
|
||||||
|
// Debug instruction - print value for debugging
|
||||||
|
let val = self.get_value(*value)?;
|
||||||
|
println!("DEBUG: {}", val.to_string());
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::Nop => {
|
||||||
|
// No-op instruction
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Phase 5: Control flow & exception handling
|
||||||
|
MirInstruction::Throw { exception, effects: _ } => {
|
||||||
|
let exception_val = self.get_value(*exception)?;
|
||||||
|
// For now, convert throw to error return (simplified exception handling)
|
||||||
|
// In a full implementation, this would unwind the stack looking for catch handlers
|
||||||
|
println!("Exception thrown: {}", exception_val.to_string());
|
||||||
|
Err(VMError::InvalidInstruction(format!("Unhandled exception: {}", exception_val.to_string())))
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::Catch { exception_type: _, exception_value, handler_bb: _ } => {
|
||||||
|
// For now, catch is a no-op since we don't have full exception handling
|
||||||
|
// In a real implementation, this would set up exception handling metadata
|
||||||
|
self.values.insert(*exception_value, VMValue::Void);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
MirInstruction::Safepoint => {
|
MirInstruction::Safepoint => {
|
||||||
@ -393,15 +438,49 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: Removed instruction - RefNew
|
// Phase 6: Box reference operations
|
||||||
#[allow(deprecated)]
|
MirInstruction::RefNew { dst, box_val } => {
|
||||||
MirInstruction::RefNew { .. } => {
|
// For now, a reference is just the same as the box value
|
||||||
Err(VMError::InvalidInstruction(
|
// In a real implementation, this would create a proper reference
|
||||||
"Phase 5: RefNew deprecated - RefGet is sufficient".to_string()
|
let box_value = self.get_value(*box_val)?;
|
||||||
))
|
self.values.insert(*dst, box_value);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 3: RefGet/RefSet removed - now handled by BoxFieldLoad/BoxFieldStore
|
MirInstruction::RefGet { dst, reference, field } => {
|
||||||
|
// Get field value from object
|
||||||
|
let field_value = if let Some(fields) = self.object_fields.get(reference) {
|
||||||
|
if let Some(value) = fields.get(field) {
|
||||||
|
value.clone()
|
||||||
|
} else {
|
||||||
|
// Field not set yet, return default
|
||||||
|
VMValue::Integer(0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Object has no fields yet, return default
|
||||||
|
VMValue::Integer(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.values.insert(*dst, field_value);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::RefSet { reference, field, value } => {
|
||||||
|
// Get the value to set
|
||||||
|
let new_value = self.get_value(*value)?;
|
||||||
|
|
||||||
|
// Ensure object has field storage
|
||||||
|
if !self.object_fields.contains_key(reference) {
|
||||||
|
self.object_fields.insert(*reference, HashMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the field
|
||||||
|
if let Some(fields) = self.object_fields.get_mut(reference) {
|
||||||
|
fields.insert(field.clone(), new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
MirInstruction::WeakNew { dst, box_val } => {
|
MirInstruction::WeakNew { dst, box_val } => {
|
||||||
// For now, a weak reference is just a copy of the value
|
// For now, a weak reference is just a copy of the value
|
||||||
@ -419,23 +498,61 @@ impl VM {
|
|||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: Removed instructions - BarrierRead, BarrierWrite
|
MirInstruction::BarrierRead { ptr: _ } => {
|
||||||
#[allow(deprecated)]
|
// Memory barrier read is a no-op for now
|
||||||
MirInstruction::BarrierRead { .. } |
|
// In a real implementation, this would ensure memory ordering
|
||||||
MirInstruction::BarrierWrite { .. } => {
|
Ok(ControlFlow::Continue)
|
||||||
Err(VMError::InvalidInstruction(
|
|
||||||
"Phase 5: Memory barriers deprecated - use AtomicFence".to_string()
|
|
||||||
))
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: Removed instructions - FutureNew, FutureSet, Await
|
MirInstruction::BarrierWrite { ptr: _ } => {
|
||||||
#[allow(deprecated)]
|
// Memory barrier write is a no-op for now
|
||||||
MirInstruction::FutureNew { .. } |
|
// In a real implementation, this would ensure memory ordering
|
||||||
MirInstruction::FutureSet { .. } |
|
Ok(ControlFlow::Continue)
|
||||||
MirInstruction::Await { .. } => {
|
},
|
||||||
Err(VMError::InvalidInstruction(
|
|
||||||
"Phase 5: Future operations deprecated - use NewBox + BoxCall".to_string()
|
// Phase 7: Async/Future Operations
|
||||||
))
|
MirInstruction::FutureNew { dst, value } => {
|
||||||
|
let initial_value = self.get_value(*value)?;
|
||||||
|
println!("FutureNew: initial_value = {:?}", initial_value);
|
||||||
|
let future = crate::boxes::future::FutureBox::new();
|
||||||
|
// Convert VMValue to NyashBox and set it in the future
|
||||||
|
let nyash_box = initial_value.to_nyash_box();
|
||||||
|
println!("FutureNew: converted to NyashBox type = {}", nyash_box.type_name());
|
||||||
|
future.set_result(nyash_box);
|
||||||
|
self.values.insert(*dst, VMValue::Future(future));
|
||||||
|
println!("FutureNew: stored Future in dst = {:?}", dst);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::FutureSet { future, value } => {
|
||||||
|
let future_val = self.get_value(*future)?;
|
||||||
|
let new_value = self.get_value(*value)?;
|
||||||
|
|
||||||
|
if let VMValue::Future(ref future_box) = future_val {
|
||||||
|
future_box.set_result(new_value.to_nyash_box());
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
} else {
|
||||||
|
Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val)))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::Await { dst, future } => {
|
||||||
|
let future_val = self.get_value(*future)?;
|
||||||
|
println!("Await: future_val = {:?}", future_val);
|
||||||
|
|
||||||
|
if let VMValue::Future(ref future_box) = future_val {
|
||||||
|
// This blocks until the future is ready
|
||||||
|
let result = future_box.get();
|
||||||
|
println!("Await: future.get() returned type = {}", result.type_name());
|
||||||
|
println!("Await: future.get() string = {}", result.to_string_box().value);
|
||||||
|
// Convert NyashBox back to VMValue
|
||||||
|
let vm_value = VMValue::from_nyash_box(result);
|
||||||
|
println!("Await: converted back to VMValue = {:?}", vm_value);
|
||||||
|
self.values.insert(*dst, vm_value);
|
||||||
|
Ok(ControlFlow::Continue)
|
||||||
|
} else {
|
||||||
|
Err(VMError::TypeError(format!("Expected Future, got {:?}", future_val)))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 9.7: External Function Calls
|
// Phase 9.7: External Function Calls
|
||||||
@ -468,134 +585,6 @@ impl VM {
|
|||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
Ok(ControlFlow::Continue)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { dst, box_val, field } => {
|
|
||||||
// Load field from box (Everything is Box principle)
|
|
||||||
let box_value = self.get_value(*box_val)?;
|
|
||||||
|
|
||||||
// For now, simulate field access - in full implementation,
|
|
||||||
// this would access actual Box structure fields
|
|
||||||
let field_value = match field.as_str() {
|
|
||||||
"value" => box_value.clone(), // Default field
|
|
||||||
"type" => VMValue::String(format!("{}Field", box_val)),
|
|
||||||
_ => VMValue::String(format!("field_{}", field)),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.values.insert(*dst, field_value);
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::BoxFieldStore { box_val, field: _, value } => {
|
|
||||||
// Store field in box (Everything is Box principle)
|
|
||||||
let _box_value = self.get_value(*box_val)?;
|
|
||||||
let _store_value = self.get_value(*value)?;
|
|
||||||
|
|
||||||
// For now, this is a no-op - in full implementation,
|
|
||||||
// this would modify actual Box structure fields
|
|
||||||
// println!("Storing {} in {}.{}", store_value, box_val, field);
|
|
||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::WeakCheck { dst, weak_ref } => {
|
|
||||||
// Check if weak reference is still alive
|
|
||||||
let _weak_value = self.get_value(*weak_ref)?;
|
|
||||||
|
|
||||||
// For now, always return true - in full implementation,
|
|
||||||
// this would check actual weak reference validity
|
|
||||||
self.values.insert(*dst, VMValue::Bool(true));
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Send { data, target } => {
|
|
||||||
// Send data via Bus system
|
|
||||||
let _data_value = self.get_value(*data)?;
|
|
||||||
let _target_value = self.get_value(*target)?;
|
|
||||||
|
|
||||||
// For now, this is a no-op - in full implementation,
|
|
||||||
// this would use the Bus communication system
|
|
||||||
// println!("Sending {} to {}", data_value, target_value);
|
|
||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Recv { dst, source } => {
|
|
||||||
// Receive data from Bus system
|
|
||||||
let _source_value = self.get_value(*source)?;
|
|
||||||
|
|
||||||
// For now, return a placeholder - in full implementation,
|
|
||||||
// this would receive from actual Bus communication
|
|
||||||
self.values.insert(*dst, VMValue::String("received_data".to_string()));
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::TailCall { func, args, effects: _ } => {
|
|
||||||
// Tail call optimization - call function and return immediately
|
|
||||||
let _func_value = self.get_value(*func)?;
|
|
||||||
let _arg_values: Result<Vec<_>, _> = args.iter().map(|arg| self.get_value(*arg)).collect();
|
|
||||||
|
|
||||||
// For now, this is simplified - in full implementation,
|
|
||||||
// this would optimize the call stack
|
|
||||||
// println!("Tail calling function with {} args", args.len());
|
|
||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Adopt { parent, child } => {
|
|
||||||
// Adopt ownership (parent takes child)
|
|
||||||
let _parent_value = self.get_value(*parent)?;
|
|
||||||
let _child_value = self.get_value(*child)?;
|
|
||||||
|
|
||||||
// For now, this is a no-op - in full implementation,
|
|
||||||
// this would modify ownership relationships
|
|
||||||
// println!("Parent {} adopts child {}", parent, child);
|
|
||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Release { reference } => {
|
|
||||||
// Release strong ownership
|
|
||||||
let _ref_value = self.get_value(*reference)?;
|
|
||||||
|
|
||||||
// For now, this is a no-op - in full implementation,
|
|
||||||
// this would release strong ownership and potentially weak-ify
|
|
||||||
// println!("Releasing ownership of {}", reference);
|
|
||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::MemCopy { dst, src, size } => {
|
|
||||||
// Memory copy optimization
|
|
||||||
let src_value = self.get_value(*src)?;
|
|
||||||
let _size_value = self.get_value(*size)?;
|
|
||||||
|
|
||||||
// For now, just copy the source value
|
|
||||||
self.values.insert(*dst, src_value);
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::AtomicFence { ordering: _ } => {
|
|
||||||
// Atomic memory fence
|
|
||||||
|
|
||||||
// For now, this is a no-op - in full implementation,
|
|
||||||
// this would ensure proper memory ordering for parallel execution
|
|
||||||
// println!("Memory fence with ordering: {:?}", ordering);
|
|
||||||
|
|
||||||
Ok(ControlFlow::Continue)
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 3: Removed instructions that are no longer generated by frontend
|
|
||||||
MirInstruction::UnaryOp { .. } |
|
|
||||||
MirInstruction::Print { .. } |
|
|
||||||
MirInstruction::Load { .. } |
|
|
||||||
MirInstruction::Store { .. } |
|
|
||||||
MirInstruction::RefGet { .. } |
|
|
||||||
MirInstruction::RefSet { .. } => {
|
|
||||||
Err(VMError::InvalidInstruction(
|
|
||||||
"Old instruction format no longer supported - use new intrinsic/BoxField format".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,86 +791,6 @@ impl VM {
|
|||||||
// Default: return void for any unrecognized box type or method
|
// Default: return void for any unrecognized box type or method
|
||||||
Ok(Box::new(VoidBox::new()))
|
Ok(Box::new(VoidBox::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute intrinsic function call (Phase 2 addition)
|
|
||||||
fn execute_intrinsic(&mut self, intrinsic_name: &str, args: &[ValueId]) -> Result<VMValue, VMError> {
|
|
||||||
match intrinsic_name {
|
|
||||||
"@print" => {
|
|
||||||
// Print intrinsic - output the first argument
|
|
||||||
if let Some(arg_id) = args.first() {
|
|
||||||
let value = self.get_value(*arg_id)?;
|
|
||||||
match value {
|
|
||||||
VMValue::String(s) => println!("{}", s),
|
|
||||||
VMValue::Integer(i) => println!("{}", i),
|
|
||||||
VMValue::Float(f) => println!("{}", f),
|
|
||||||
VMValue::Bool(b) => println!("{}", b),
|
|
||||||
VMValue::Void => println!("void"),
|
|
||||||
VMValue::Future(_) => println!("Future"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(VMValue::Void) // Print returns void
|
|
||||||
},
|
|
||||||
|
|
||||||
"@unary_neg" => {
|
|
||||||
// Unary negation intrinsic
|
|
||||||
if let Some(arg_id) = args.first() {
|
|
||||||
let value = self.get_value(*arg_id)?;
|
|
||||||
match value {
|
|
||||||
VMValue::Integer(i) => Ok(VMValue::Integer(-i)),
|
|
||||||
VMValue::Float(f) => Ok(VMValue::Float(-f)),
|
|
||||||
_ => Err(VMError::TypeError(format!("Cannot negate {:?}", value))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(VMError::TypeError("@unary_neg requires 1 argument".to_string()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"@unary_not" => {
|
|
||||||
// Unary logical NOT intrinsic
|
|
||||||
if let Some(arg_id) = args.first() {
|
|
||||||
let value = self.get_value(*arg_id)?;
|
|
||||||
match value {
|
|
||||||
VMValue::Bool(b) => Ok(VMValue::Bool(!b)),
|
|
||||||
VMValue::Integer(i) => Ok(VMValue::Bool(i == 0)), // 0 is false, non-zero is true
|
|
||||||
_ => Err(VMError::TypeError(format!("Cannot apply NOT to {:?}", value))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(VMError::TypeError("@unary_not requires 1 argument".to_string()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"@unary_bitnot" => {
|
|
||||||
// Unary bitwise NOT intrinsic
|
|
||||||
if let Some(arg_id) = args.first() {
|
|
||||||
let value = self.get_value(*arg_id)?;
|
|
||||||
match value {
|
|
||||||
VMValue::Integer(i) => Ok(VMValue::Integer(!i)),
|
|
||||||
_ => Err(VMError::TypeError(format!("Cannot apply bitwise NOT to {:?}", value))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(VMError::TypeError("@unary_bitnot requires 1 argument".to_string()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"@throw" => {
|
|
||||||
// Throw intrinsic - for now just print the exception
|
|
||||||
if let Some(arg_id) = args.first() {
|
|
||||||
let value = self.get_value(*arg_id)?;
|
|
||||||
println!("Exception thrown: {:?}", value);
|
|
||||||
}
|
|
||||||
Err(VMError::InvalidInstruction("Exception thrown".to_string()))
|
|
||||||
},
|
|
||||||
|
|
||||||
"@set_exception_handler" => {
|
|
||||||
// Exception handler setup - for now just return success
|
|
||||||
Ok(VMValue::Void)
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
Err(VMError::InvalidInstruction(format!("Unknown intrinsic: {}", intrinsic_name)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Control flow result from instruction execution
|
/// Control flow result from instruction execution
|
||||||
|
|||||||
@ -244,18 +244,47 @@ impl WasmCodegen {
|
|||||||
self.generate_return(value.as_ref())
|
self.generate_return(value.as_ref())
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 3: Print removed - now handled by Call intrinsic (@print)
|
MirInstruction::Print { value, .. } => {
|
||||||
|
self.generate_print(*value)
|
||||||
// Phase 8.3 PoC2: Reference operations
|
|
||||||
// Phase 5: RefNew deprecated - just use the value directly
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::RefNew { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: RefNew deprecated - references are handled implicitly".to_string()
|
|
||||||
))
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 3: RefGet/RefSet removed - now handled by BoxFieldLoad/BoxFieldStore
|
// Phase 8.3 PoC2: Reference operations
|
||||||
|
MirInstruction::RefNew { dst, box_val } => {
|
||||||
|
// Create a new reference to a Box by copying the Box value
|
||||||
|
// This assumes box_val contains a Box pointer already
|
||||||
|
Ok(vec![
|
||||||
|
format!("local.get ${}", self.get_local_index(*box_val)?),
|
||||||
|
format!("local.set ${}", self.get_local_index(*dst)?),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::RefGet { dst, reference, field: _ } => {
|
||||||
|
// Load field value from Box through reference
|
||||||
|
// reference contains Box pointer, field is the field name
|
||||||
|
// For now, assume all fields are at offset 12 (first field after header)
|
||||||
|
// TODO: Add proper field offset calculation
|
||||||
|
Ok(vec![
|
||||||
|
format!("local.get ${}", self.get_local_index(*reference)?),
|
||||||
|
"i32.const 12".to_string(), // Offset: header (12 bytes) + first field
|
||||||
|
"i32.add".to_string(),
|
||||||
|
"i32.load".to_string(),
|
||||||
|
format!("local.set ${}", self.get_local_index(*dst)?),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
|
||||||
|
MirInstruction::RefSet { reference, field: _, value } => {
|
||||||
|
// Store field value to Box through reference
|
||||||
|
// reference contains Box pointer, field is the field name, value is new value
|
||||||
|
// For now, assume all fields are at offset 12 (first field after header)
|
||||||
|
// TODO: Add proper field offset calculation
|
||||||
|
Ok(vec![
|
||||||
|
format!("local.get ${}", self.get_local_index(*reference)?),
|
||||||
|
"i32.const 12".to_string(), // Offset: header (12 bytes) + first field
|
||||||
|
"i32.add".to_string(),
|
||||||
|
format!("local.get ${}", self.get_local_index(*value)?),
|
||||||
|
"i32.store".to_string(),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
|
||||||
MirInstruction::NewBox { dst, box_type, args } => {
|
MirInstruction::NewBox { dst, box_type, args } => {
|
||||||
// Create a new Box using the generic allocator
|
// Create a new Box using the generic allocator
|
||||||
@ -294,54 +323,29 @@ impl WasmCodegen {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Phase 8.4 PoC3: Extension stubs
|
// Phase 8.4 PoC3: Extension stubs
|
||||||
MirInstruction::WeakNew { dst, box_val } => {
|
MirInstruction::WeakNew { dst, box_val } |
|
||||||
// WeakNew is still part of 26-instruction set
|
MirInstruction::FutureNew { dst, value: box_val } => {
|
||||||
|
// Treat as regular reference for now
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
format!("local.get ${}", self.get_local_index(*box_val)?),
|
format!("local.get ${}", self.get_local_index(*box_val)?),
|
||||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
format!("local.set ${}", self.get_local_index(*dst)?),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: FutureNew deprecated - use NewBox "Future"
|
MirInstruction::WeakLoad { dst, weak_ref } |
|
||||||
#[allow(deprecated)]
|
MirInstruction::Await { dst, future: weak_ref } => {
|
||||||
MirInstruction::FutureNew { .. } => {
|
// Always succeed for now
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: FutureNew deprecated - use 'NewBox \"Future\"' instead".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::WeakLoad { dst, weak_ref } => {
|
|
||||||
// WeakLoad is still part of 26-instruction set
|
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
format!("local.get ${}", self.get_local_index(*weak_ref)?),
|
format!("local.get ${}", self.get_local_index(*weak_ref)?),
|
||||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
format!("local.set ${}", self.get_local_index(*dst)?),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 5: Await deprecated - use BoxCall Future.await()
|
MirInstruction::BarrierRead { .. } |
|
||||||
#[allow(deprecated)]
|
MirInstruction::BarrierWrite { .. } |
|
||||||
MirInstruction::Await { .. } => {
|
MirInstruction::FutureSet { .. } |
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Await deprecated - use 'BoxCall Future.await()' instead".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: BarrierRead/BarrierWrite deprecated - use AtomicFence
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::BarrierRead { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: BarrierRead deprecated - use AtomicFence with acquire ordering".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::BarrierWrite { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: BarrierWrite deprecated - use AtomicFence with release ordering".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Safepoint => {
|
MirInstruction::Safepoint => {
|
||||||
// Safepoint is still valid - no-op for now
|
// No-op for now
|
||||||
Ok(vec!["nop".to_string()])
|
Ok(vec!["nop".to_string()])
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -404,189 +408,6 @@ impl WasmCodegen {
|
|||||||
self.generate_box_call(*dst, *box_val, method, args)
|
self.generate_box_call(*dst, *box_val, method, args)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { dst, box_val, field: _ } => {
|
|
||||||
// Load field from box (similar to RefGet but with explicit Box semantics)
|
|
||||||
// For now, assume all fields are at offset 12 (first field after header)
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*box_val)?),
|
|
||||||
"i32.const 12".to_string(), // Box header + first field offset
|
|
||||||
"i32.add".to_string(),
|
|
||||||
"i32.load".to_string(),
|
|
||||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::BoxFieldStore { box_val, field: _, value } => {
|
|
||||||
// Store field to box (similar to RefSet but with explicit Box semantics)
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*box_val)?),
|
|
||||||
"i32.const 12".to_string(), // Box header + first field offset
|
|
||||||
"i32.add".to_string(),
|
|
||||||
format!("local.get ${}", self.get_local_index(*value)?),
|
|
||||||
"i32.store".to_string(),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::WeakCheck { dst, weak_ref } => {
|
|
||||||
// Check if weak reference is still alive
|
|
||||||
// For now, always return 1 (true) - in full implementation,
|
|
||||||
// this would check actual weak reference validity
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*weak_ref)?), // Touch the ref
|
|
||||||
"drop".to_string(), // Ignore the actual value
|
|
||||||
"i32.const 1".to_string(), // Always alive for now
|
|
||||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Send { data, target } => {
|
|
||||||
// Send data via Bus system - no-op for now
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*data)?),
|
|
||||||
format!("local.get ${}", self.get_local_index(*target)?),
|
|
||||||
"drop".to_string(), // Drop target
|
|
||||||
"drop".to_string(), // Drop data
|
|
||||||
"nop".to_string(), // No actual send operation
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Recv { dst, source } => {
|
|
||||||
// Receive data from Bus system - return constant for now
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*source)?), // Touch source
|
|
||||||
"drop".to_string(), // Ignore source
|
|
||||||
"i32.const 42".to_string(), // Placeholder received data
|
|
||||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::TailCall { func, args, effects: _ } => {
|
|
||||||
// Tail call optimization - simplified as regular call for now
|
|
||||||
let mut instructions = Vec::new();
|
|
||||||
|
|
||||||
// Load all arguments
|
|
||||||
for arg in args {
|
|
||||||
instructions.push(format!("local.get ${}", self.get_local_index(*arg)?));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call function (assuming it's a function index)
|
|
||||||
instructions.push(format!("local.get ${}", self.get_local_index(*func)?));
|
|
||||||
instructions.push("call_indirect".to_string());
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Adopt { parent, child } => {
|
|
||||||
// Adopt ownership - no-op for now in WASM
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*parent)?),
|
|
||||||
format!("local.get ${}", self.get_local_index(*child)?),
|
|
||||||
"drop".to_string(), // Drop child
|
|
||||||
"drop".to_string(), // Drop parent
|
|
||||||
"nop".to_string(), // No actual adoption
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::Release { reference } => {
|
|
||||||
// Release strong ownership - no-op for now
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*reference)?),
|
|
||||||
"drop".to_string(), // Drop reference
|
|
||||||
"nop".to_string(), // No actual release
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::MemCopy { dst, src, size } => {
|
|
||||||
// Memory copy optimization - simple copy for now
|
|
||||||
Ok(vec![
|
|
||||||
format!("local.get ${}", self.get_local_index(*src)?),
|
|
||||||
format!("local.set ${}", self.get_local_index(*dst)?),
|
|
||||||
// Size is ignored for now - in full implementation,
|
|
||||||
// this would use memory.copy instruction
|
|
||||||
format!("local.get ${}", self.get_local_index(*size)?),
|
|
||||||
"drop".to_string(),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
MirInstruction::AtomicFence { ordering: _ } => {
|
|
||||||
// Atomic memory fence - no-op for now
|
|
||||||
// WASM doesn't have direct memory fence instructions
|
|
||||||
// In full implementation, this might use atomic wait/notify
|
|
||||||
Ok(vec!["nop".to_string()])
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 4: Call instruction for intrinsic functions
|
|
||||||
MirInstruction::Call { dst, func, args, effects: _ } => {
|
|
||||||
self.generate_call_instruction(dst.as_ref(), *func, args)
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: Removed instructions - TypeCheck, Cast, ArrayGet, ArraySet, Copy, Debug, Nop
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::TypeCheck { .. } |
|
|
||||||
MirInstruction::Cast { .. } |
|
|
||||||
MirInstruction::ArrayGet { .. } |
|
|
||||||
MirInstruction::ArraySet { .. } |
|
|
||||||
MirInstruction::Copy { .. } |
|
|
||||||
MirInstruction::Debug { .. } |
|
|
||||||
MirInstruction::Nop => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Deprecated instruction - use 26-instruction set replacements".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: Removed instructions - UnaryOp (use BinOp instead)
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::UnaryOp { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: UnaryOp deprecated - use BinOp (e.g., 'not x' -> 'x xor true', 'neg x' -> '0 sub x')".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: Removed instructions - Load/Store (use BoxFieldLoad/BoxFieldStore)
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::Load { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Load deprecated - use BoxFieldLoad for field access".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::Store { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Store deprecated - use BoxFieldStore for field updates".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: Removed instructions - Print (use Call @print)
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::Print { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Print deprecated - use 'Call @print' intrinsic function".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: Removed instructions - Throw/Catch (use Call @throw/@catch)
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::Throw { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Throw deprecated - use 'Call @throw' intrinsic function".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::Catch { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: Catch deprecated - use 'Call @catch' intrinsic function".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Phase 5: Removed FutureSet - use BoxCall instead
|
|
||||||
#[allow(deprecated)]
|
|
||||||
MirInstruction::FutureSet { .. } => {
|
|
||||||
Err(WasmError::UnsupportedInstruction(
|
|
||||||
"Phase 5: FutureSet deprecated - use BoxCall method for Future.set()".to_string()
|
|
||||||
))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Unsupported instructions
|
// Unsupported instructions
|
||||||
_ => Err(WasmError::UnsupportedInstruction(
|
_ => Err(WasmError::UnsupportedInstruction(
|
||||||
format!("Instruction not yet supported: {:?}", instruction)
|
format!("Instruction not yet supported: {:?}", instruction)
|
||||||
@ -865,36 +686,6 @@ impl WasmCodegen {
|
|||||||
|
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate Call instruction for intrinsic functions (Phase 4)
|
|
||||||
fn generate_call_instruction(&mut self, dst: Option<&ValueId>, func: ValueId, args: &[ValueId]) -> Result<Vec<String>, WasmError> {
|
|
||||||
// Get the function name from the func ValueId
|
|
||||||
// In MIR, intrinsic function names are stored as string constants
|
|
||||||
let mut instructions = Vec::new();
|
|
||||||
|
|
||||||
// For intrinsic functions, we handle them based on their name
|
|
||||||
// The func ValueId should contain a string constant like "@print"
|
|
||||||
|
|
||||||
// For now, assume all calls are @print intrinsic
|
|
||||||
// TODO: Implement proper function name resolution from ValueId
|
|
||||||
|
|
||||||
// Load all arguments onto stack in order
|
|
||||||
for arg in args {
|
|
||||||
instructions.push(format!("local.get ${}", self.get_local_index(*arg)?));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the print function (assuming it's imported as $print)
|
|
||||||
instructions.push("call $print".to_string());
|
|
||||||
|
|
||||||
// Store result if destination is provided
|
|
||||||
if let Some(dst) = dst {
|
|
||||||
// Intrinsic functions typically return void, but we provide a dummy value
|
|
||||||
instructions.push("i32.const 0".to_string()); // Void result
|
|
||||||
instructions.push(format!("local.set ${}", self.get_local_index(*dst)?));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -8,13 +8,10 @@
|
|||||||
mod codegen;
|
mod codegen;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod host;
|
|
||||||
mod executor;
|
|
||||||
|
|
||||||
pub use codegen::{WasmCodegen, WasmModule};
|
pub use codegen::{WasmCodegen, WasmModule};
|
||||||
pub use memory::{MemoryManager, BoxLayout};
|
pub use memory::{MemoryManager, BoxLayout};
|
||||||
pub use runtime::RuntimeImports;
|
pub use runtime::RuntimeImports;
|
||||||
pub use executor::WasmExecutor;
|
|
||||||
|
|
||||||
use crate::mir::MirModule;
|
use crate::mir::MirModule;
|
||||||
|
|
||||||
@ -26,8 +23,6 @@ pub enum WasmError {
|
|||||||
UnsupportedInstruction(String),
|
UnsupportedInstruction(String),
|
||||||
WasmValidationError(String),
|
WasmValidationError(String),
|
||||||
IOError(String),
|
IOError(String),
|
||||||
RuntimeError(String),
|
|
||||||
CompilationError(String),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for WasmError {
|
impl std::fmt::Display for WasmError {
|
||||||
@ -38,8 +33,6 @@ impl std::fmt::Display for WasmError {
|
|||||||
WasmError::UnsupportedInstruction(msg) => write!(f, "Unsupported instruction: {}", msg),
|
WasmError::UnsupportedInstruction(msg) => write!(f, "Unsupported instruction: {}", msg),
|
||||||
WasmError::WasmValidationError(msg) => write!(f, "WASM validation error: {}", msg),
|
WasmError::WasmValidationError(msg) => write!(f, "WASM validation error: {}", msg),
|
||||||
WasmError::IOError(msg) => write!(f, "IO error: {}", msg),
|
WasmError::IOError(msg) => write!(f, "IO error: {}", msg),
|
||||||
WasmError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
|
|
||||||
WasmError::CompilationError(msg) => write!(f, "Compilation error: {}", msg),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
// 参考: 既存Boxの設計思想
|
// 参考: 既存Boxの設計思想
|
||||||
|
|
||||||
use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase};
|
use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase};
|
||||||
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
@ -147,25 +146,6 @@ impl std::fmt::Display for NyashFutureBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BidBridge for NyashFutureBox {
|
|
||||||
fn to_bid_handle(&self, registry: &mut BoxRegistry) -> Result<BidHandle, BidError> {
|
|
||||||
use std::sync::Arc;
|
|
||||||
let arc_box: Arc<dyn NyashBox> = Arc::new(self.clone());
|
|
||||||
let handle = registry.register_box(
|
|
||||||
crate::bid::types::BoxTypeId::FutureBox as u32,
|
|
||||||
arc_box
|
|
||||||
);
|
|
||||||
Ok(handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bid_type(&self) -> BidType {
|
|
||||||
BidType::Handle {
|
|
||||||
type_id: crate::bid::types::BoxTypeId::FutureBox as u32,
|
|
||||||
instance_id: 0 // Will be filled by registry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export NyashFutureBox as FutureBox for consistency
|
// Export NyashFutureBox as FutureBox for consistency
|
||||||
pub type FutureBox = NyashFutureBox;
|
pub type FutureBox = NyashFutureBox;
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
||||||
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
@ -118,22 +117,3 @@ impl Display for IntegerBox {
|
|||||||
self.fmt_box(f)
|
self.fmt_box(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BidBridge for IntegerBox {
|
|
||||||
fn to_bid_handle(&self, registry: &mut BoxRegistry) -> Result<BidHandle, BidError> {
|
|
||||||
use std::sync::Arc;
|
|
||||||
let arc_box: Arc<dyn NyashBox> = Arc::new(self.clone());
|
|
||||||
let handle = registry.register_box(
|
|
||||||
crate::bid::types::BoxTypeId::IntegerBox as u32,
|
|
||||||
arc_box
|
|
||||||
);
|
|
||||||
Ok(handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bid_type(&self) -> BidType {
|
|
||||||
BidType::Handle {
|
|
||||||
type_id: crate::bid::types::BoxTypeId::IntegerBox as u32,
|
|
||||||
instance_id: 0 // Will be filled by registry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -28,7 +28,6 @@
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
||||||
use crate::bid::{BidBridge, BidHandle, BidType, BidError, BoxRegistry};
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
@ -186,22 +185,3 @@ impl Display for StringBox {
|
|||||||
self.fmt_box(f)
|
self.fmt_box(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BidBridge for StringBox {
|
|
||||||
fn to_bid_handle(&self, registry: &mut BoxRegistry) -> Result<BidHandle, BidError> {
|
|
||||||
use std::sync::Arc;
|
|
||||||
let arc_box: Arc<dyn NyashBox> = Arc::new(self.clone());
|
|
||||||
let handle = registry.register_box(
|
|
||||||
crate::bid::types::BoxTypeId::StringBox as u32,
|
|
||||||
arc_box
|
|
||||||
);
|
|
||||||
Ok(handle)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bid_type(&self) -> BidType {
|
|
||||||
BidType::Handle {
|
|
||||||
type_id: crate::bid::types::BoxTypeId::StringBox as u32,
|
|
||||||
instance_id: 0 // Will be filled by registry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -516,7 +516,7 @@ mod tests {
|
|||||||
|
|
||||||
// フィールドに値を設定
|
// フィールドに値を設定
|
||||||
let int_value = Box::new(IntegerBox::new(42)) as Box<dyn NyashBox>;
|
let int_value = Box::new(IntegerBox::new(42)) as Box<dyn NyashBox>;
|
||||||
instance.set_field("value", int_value.into()).unwrap();
|
instance.set_field("value", int_value).unwrap();
|
||||||
|
|
||||||
// フィールドの値を取得
|
// フィールドの値を取得
|
||||||
let retrieved = instance.get_field("value").unwrap();
|
let retrieved = instance.get_field("value").unwrap();
|
||||||
|
|||||||
@ -350,13 +350,13 @@ impl NyashInterpreter {
|
|||||||
|
|
||||||
// 2. local変数をチェック
|
// 2. local変数をチェック
|
||||||
if let Some(local_value) = self.local_vars.get(name) {
|
if let Some(local_value) = self.local_vars.get(name) {
|
||||||
eprintln!("🔍 DEBUG: Found '{}' in local_vars, type: {}", name, local_value.type_name());
|
eprintln!("🔍 DEBUG: Found '{}' in local_vars", name);
|
||||||
|
|
||||||
// 🔧 修正:clone_box() → Arc::clone() で参照共有
|
// 🔧 修正:clone_box() → Arc::clone() で参照共有
|
||||||
let shared_value = Arc::clone(local_value);
|
let shared_value = Arc::clone(local_value);
|
||||||
|
|
||||||
eprintln!("✅ RESOLVE_VARIABLE shared reference: {} id={}, type: {}",
|
eprintln!("✅ RESOLVE_VARIABLE shared reference: {} id={}",
|
||||||
name, shared_value.box_id(), shared_value.type_name());
|
name, shared_value.box_id());
|
||||||
|
|
||||||
return Ok(shared_value);
|
return Ok(shared_value);
|
||||||
}
|
}
|
||||||
@ -478,12 +478,7 @@ impl NyashInterpreter {
|
|||||||
|
|
||||||
/// local変数を宣言(関数内でのみ有効)
|
/// local変数を宣言(関数内でのみ有効)
|
||||||
pub(super) fn declare_local_variable(&mut self, name: &str, value: Box<dyn NyashBox>) {
|
pub(super) fn declare_local_variable(&mut self, name: &str, value: Box<dyn NyashBox>) {
|
||||||
eprintln!("🔍 DEBUG: declare_local_variable '{}' with type: {}, id: {}",
|
self.local_vars.insert(name.to_string(), Arc::from(value));
|
||||||
name, value.type_name(), value.box_id());
|
|
||||||
let arc_value: Arc<dyn NyashBox> = Arc::from(value);
|
|
||||||
eprintln!("🔍 DEBUG: After Arc::from, type: {}, id: {}",
|
|
||||||
arc_value.type_name(), arc_value.box_id());
|
|
||||||
self.local_vars.insert(name.to_string(), arc_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// outbox変数を宣言(static関数内で所有権移転)
|
/// outbox変数を宣言(static関数内で所有権移転)
|
||||||
|
|||||||
@ -13,8 +13,6 @@ use crate::instance::InstanceBox;
|
|||||||
use crate::channel_box::ChannelBox;
|
use crate::channel_box::ChannelBox;
|
||||||
use crate::interpreter::core::{NyashInterpreter, RuntimeError};
|
use crate::interpreter::core::{NyashInterpreter, RuntimeError};
|
||||||
use crate::interpreter::finalization;
|
use crate::interpreter::finalization;
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
use crate::interpreter::plugin_loader::FileBoxProxy;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
impl NyashInterpreter {
|
impl NyashInterpreter {
|
||||||
@ -257,18 +255,6 @@ impl NyashInterpreter {
|
|||||||
return self.execute_file_method(file_box, method, arguments);
|
return self.execute_file_method(file_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileBoxProxy method calls (動的ライブラリ版)
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
eprintln!("🔍 DEBUG: Checking if object is FileBoxProxy, type_name: {}", obj_value.type_name());
|
|
||||||
if let Some(file_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::FileBoxProxy>() {
|
|
||||||
eprintln!("✅ DEBUG: Object is FileBoxProxy, calling execute_file_proxy_method");
|
|
||||||
return self.execute_file_proxy_method(file_proxy, method, arguments);
|
|
||||||
} else {
|
|
||||||
eprintln!("❌ DEBUG: Object is NOT FileBoxProxy");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResultBox method calls
|
// ResultBox method calls
|
||||||
if let Some(result_box) = obj_value.as_any().downcast_ref::<crate::box_trait::ResultBox>() {
|
if let Some(result_box) = obj_value.as_any().downcast_ref::<crate::box_trait::ResultBox>() {
|
||||||
return self.execute_result_method(result_box, method, arguments);
|
return self.execute_result_method(result_box, method, arguments);
|
||||||
|
|||||||
@ -8,10 +8,7 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
use crate::boxes::{buffer::BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox, IntentBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
|
use crate::boxes::{FloatBox, MathBox, ConsoleBox, TimeBox, DateTimeBox, RandomBox, SoundBox, DebugBox, file::FileBox, MapBox};
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
use crate::boxes::{FloatBox, ConsoleBox, SoundBox, DebugBox, MapBox};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
impl NyashInterpreter {
|
impl NyashInterpreter {
|
||||||
@ -241,43 +238,25 @@ impl NyashInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MathBox method calls
|
// MathBox method calls
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
|
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
|
||||||
return self.execute_math_method(math_box, method, arguments);
|
return self.execute_math_method(math_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
if let Some(math_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::MathBoxProxy>() {
|
|
||||||
return self.execute_math_proxy_method(math_proxy, method, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NullBox method calls
|
// NullBox method calls
|
||||||
if let Some(null_box) = obj_value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>() {
|
if let Some(null_box) = obj_value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>() {
|
||||||
return self.execute_null_method(null_box, method, arguments);
|
return self.execute_null_method(null_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimeBox method calls
|
// TimeBox method calls
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() {
|
if let Some(time_box) = obj_value.as_any().downcast_ref::<TimeBox>() {
|
||||||
return self.execute_time_method(time_box, method, arguments);
|
return self.execute_time_method(time_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
if let Some(time_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::TimeBoxProxy>() {
|
|
||||||
return self.execute_time_proxy_method(time_proxy, method, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DateTimeBox method calls
|
// DateTimeBox method calls
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() {
|
if let Some(datetime_box) = obj_value.as_any().downcast_ref::<DateTimeBox>() {
|
||||||
return self.execute_datetime_method(datetime_box, method, arguments);
|
return self.execute_datetime_method(datetime_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
if let Some(datetime_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::DateTimeBoxProxy>() {
|
|
||||||
return self.execute_datetime_proxy_method(datetime_proxy, method, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimerBox method calls
|
// TimerBox method calls
|
||||||
if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() {
|
if let Some(timer_box) = obj_value.as_any().downcast_ref::<TimerBox>() {
|
||||||
return self.execute_timer_method(timer_box, method, arguments);
|
return self.execute_timer_method(timer_box, method, arguments);
|
||||||
@ -289,16 +268,10 @@ impl NyashInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RandomBox method calls
|
// RandomBox method calls
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() {
|
if let Some(random_box) = obj_value.as_any().downcast_ref::<RandomBox>() {
|
||||||
return self.execute_random_method(random_box, method, arguments);
|
return self.execute_random_method(random_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
if let Some(random_proxy) = obj_value.as_any().downcast_ref::<crate::interpreter::plugin_loader::RandomBoxProxy>() {
|
|
||||||
return self.execute_random_proxy_method(random_proxy, method, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SoundBox method calls
|
// SoundBox method calls
|
||||||
if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() {
|
if let Some(sound_box) = obj_value.as_any().downcast_ref::<SoundBox>() {
|
||||||
return self.execute_sound_method(sound_box, method, arguments);
|
return self.execute_sound_method(sound_box, method, arguments);
|
||||||
|
|||||||
@ -10,64 +10,11 @@
|
|||||||
use super::super::*;
|
use super::super::*;
|
||||||
use crate::box_trait::{ResultBox, StringBox, NyashBox};
|
use crate::box_trait::{ResultBox, StringBox, NyashBox};
|
||||||
use crate::boxes::FileBox;
|
use crate::boxes::FileBox;
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
use crate::interpreter::plugin_loader::FileBoxProxy;
|
|
||||||
|
|
||||||
impl NyashInterpreter {
|
impl NyashInterpreter {
|
||||||
/// FileBoxのメソッド呼び出しを実行
|
/// FileBoxのメソッド呼び出しを実行
|
||||||
/// Handles file I/O operations including read, write, exists, delete, and copy
|
/// Handles file I/O operations including read, write, exists, delete, and copy
|
||||||
pub(in crate::interpreter) fn execute_file_method(&mut self, file_box: &FileBox, method: &str, arguments: &[ASTNode])
|
pub(in crate::interpreter) fn execute_file_method(&mut self, file_box: &FileBox, method: &str, arguments: &[ASTNode])
|
||||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
|
||||||
self.execute_file_method_static(file_box, method, arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FileBoxProxyのメソッド呼び出しを実行(動的ライブラリ版)
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
pub(in crate::interpreter) fn execute_file_proxy_method(&mut self, file_box: &FileBoxProxy, method: &str, arguments: &[ASTNode])
|
|
||||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
|
||||||
eprintln!("🔍 DEBUG: execute_file_proxy_method called with method: '{}'", method);
|
|
||||||
match method {
|
|
||||||
"read" => {
|
|
||||||
if !arguments.is_empty() {
|
|
||||||
return Err(RuntimeError::InvalidOperation {
|
|
||||||
message: format!("read() expects 0 arguments, got {}", arguments.len()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
file_box.read()
|
|
||||||
}
|
|
||||||
"write" => {
|
|
||||||
if arguments.len() != 1 {
|
|
||||||
return Err(RuntimeError::InvalidOperation {
|
|
||||||
message: format!("write() expects 1 argument, got {}", arguments.len()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let content = self.execute_expression(&arguments[0])?;
|
|
||||||
file_box.write(content)
|
|
||||||
}
|
|
||||||
"exists" => {
|
|
||||||
if !arguments.is_empty() {
|
|
||||||
return Err(RuntimeError::InvalidOperation {
|
|
||||||
message: format!("exists() expects 0 arguments, got {}", arguments.len()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
file_box.exists()
|
|
||||||
}
|
|
||||||
"toString" => {
|
|
||||||
if !arguments.is_empty() {
|
|
||||||
return Err(RuntimeError::InvalidOperation {
|
|
||||||
message: format!("toString() expects 0 arguments, got {}", arguments.len()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(Box::new(file_box.to_string_box()))
|
|
||||||
}
|
|
||||||
_ => Err(RuntimeError::InvalidOperation {
|
|
||||||
message: format!("Undefined method '{}' for FileBox", method),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 静的FileBoxのメソッド実装
|
|
||||||
fn execute_file_method_static(&mut self, file_box: &FileBox, method: &str, arguments: &[ASTNode])
|
|
||||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||||
match method {
|
match method {
|
||||||
"read" => {
|
"read" => {
|
||||||
@ -118,14 +65,6 @@ impl NyashInterpreter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"toString" => {
|
|
||||||
if !arguments.is_empty() {
|
|
||||||
return Err(RuntimeError::InvalidOperation {
|
|
||||||
message: format!("toString() expects 0 arguments, got {}", arguments.len()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(Box::new(file_box.to_string_box()))
|
|
||||||
}
|
|
||||||
_ => Err(RuntimeError::InvalidOperation {
|
_ => Err(RuntimeError::InvalidOperation {
|
||||||
message: format!("Unknown method '{}' for FileBox", method),
|
message: format!("Unknown method '{}' for FileBox", method),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -23,6 +23,5 @@ pub mod data_methods; // BufferBox, JSONBox, RegexBox
|
|||||||
pub mod network_methods; // HttpClientBox, StreamBox
|
pub mod network_methods; // HttpClientBox, StreamBox
|
||||||
pub mod p2p_methods; // IntentBox, P2PBox
|
pub mod p2p_methods; // IntentBox, P2PBox
|
||||||
pub mod http_methods; // SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox
|
pub mod http_methods; // SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox
|
||||||
pub mod math_methods; // MathBox, RandomBox, TimeBox, DateTimeBox
|
|
||||||
|
|
||||||
// Re-export methods for easy access
|
// Re-export methods for easy access
|
||||||
|
|||||||
@ -7,9 +7,7 @@
|
|||||||
|
|
||||||
// Import all necessary dependencies
|
// Import all necessary dependencies
|
||||||
use crate::ast::{ASTNode, CatchClause};
|
use crate::ast::{ASTNode, CatchClause};
|
||||||
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, ArrayBox, ResultBox, ErrorBox, BoxCore};
|
use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, ArrayBox, FileBox, ResultBox, ErrorBox, BoxCore};
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
use crate::box_trait::FileBox;
|
|
||||||
use crate::boxes::FutureBox;
|
use crate::boxes::FutureBox;
|
||||||
use crate::instance::InstanceBox;
|
use crate::instance::InstanceBox;
|
||||||
use crate::channel_box::ChannelBox;
|
use crate::channel_box::ChannelBox;
|
||||||
@ -42,16 +40,10 @@ mod math_methods;
|
|||||||
mod system_methods;
|
mod system_methods;
|
||||||
mod web_methods;
|
mod web_methods;
|
||||||
mod special_methods;
|
mod special_methods;
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
mod plugin_loader;
|
|
||||||
|
|
||||||
// Main interpreter implementation - will be moved from interpreter.rs
|
// Main interpreter implementation - will be moved from interpreter.rs
|
||||||
pub use core::NyashInterpreter;
|
pub use core::NyashInterpreter;
|
||||||
|
|
||||||
// Dynamic plugin support
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
pub use plugin_loader::{PluginLoader, FileBoxProxy};
|
|
||||||
|
|
||||||
|
|
||||||
/// 実行制御フロー
|
/// 実行制御フロー
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@ -7,11 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::boxes::{NullBox, ConsoleBox, FloatBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
use crate::boxes::{NullBox, ConsoleBox, FloatBox, DateTimeBox, SocketBox, HTTPServerBox, HTTPRequestBox, HTTPResponseBox};
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
use crate::boxes::{FileBox, MathBox, RandomBox, TimeBox, DateTimeBox};
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
use crate::boxes::DateTimeBox;
|
|
||||||
// use crate::boxes::intent_box_wrapper::IntentBoxWrapper;
|
// use crate::boxes::intent_box_wrapper::IntentBoxWrapper;
|
||||||
use crate::box_trait::SharedNyashBox;
|
use crate::box_trait::SharedNyashBox;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -98,18 +94,16 @@ impl NyashInterpreter {
|
|||||||
message: format!("FileBox constructor expects 1 argument, got {}", arguments.len()),
|
message: format!("FileBox constructor expects 1 argument, got {}", arguments.len()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// BoxFactoryRegistryを使用して作成(プラグイン対応)
|
let path_value = self.execute_expression(&arguments[0])?;
|
||||||
use crate::runtime::get_global_registry;
|
if let Some(path_str) = path_value.as_any().downcast_ref::<StringBox>() {
|
||||||
let registry = get_global_registry();
|
let file_box = Box::new(FileBox::new(&path_str.value)) as Box<dyn NyashBox>;
|
||||||
|
// 🌍 革命的実装:Environment tracking廃止
|
||||||
// 引数を評価
|
return Ok(file_box);
|
||||||
let mut evaluated_args = Vec::new();
|
} else {
|
||||||
for arg in arguments {
|
return Err(RuntimeError::TypeError {
|
||||||
evaluated_args.push(self.execute_expression(arg)?);
|
message: "FileBox constructor requires string path argument".to_string(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return registry.create_box("FileBox", &evaluated_args)
|
|
||||||
.map_err(|e| RuntimeError::InvalidOperation { message: e });
|
|
||||||
}
|
}
|
||||||
"ResultBox" => {
|
"ResultBox" => {
|
||||||
// ResultBoxは引数1個(成功値)で作成
|
// ResultBoxは引数1個(成功値)で作成
|
||||||
@ -153,34 +147,10 @@ impl NyashInterpreter {
|
|||||||
message: format!("MathBox constructor expects 0 arguments, got {}", arguments.len()),
|
message: format!("MathBox constructor expects 0 arguments, got {}", arguments.len()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("🔧 DEBUG: DYNAMIC-FILE feature check...");
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
println!("🔌 DEBUG: DYNAMIC-FILE ENABLED - Creating MathBox through dynamic library");
|
|
||||||
log::debug!("🔌 DEBUG: Creating MathBox through dynamic library");
|
|
||||||
match super::plugin_loader::PluginLoader::create_math_box() {
|
|
||||||
Ok(math_box) => {
|
|
||||||
println!("🔌 DEBUG: MathBox created successfully, type_name: {}", math_box.type_name());
|
|
||||||
log::debug!("🔌 DEBUG: MathBox created successfully, type_name: {}", math_box.type_name());
|
|
||||||
return Ok(math_box);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!("❌ DEBUG: Failed to create MathBox through dynamic library: {}", e);
|
|
||||||
log::error!("Failed to create MathBox through dynamic library: {}", e);
|
|
||||||
// Fall back to static MathBox
|
|
||||||
let math_box = Box::new(MathBox::new()) as Box<dyn NyashBox>;
|
let math_box = Box::new(MathBox::new()) as Box<dyn NyashBox>;
|
||||||
|
// 🌍 革命的実装:Environment tracking廃止
|
||||||
return Ok(math_box);
|
return Ok(math_box);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
{
|
|
||||||
println!("🔌 DEBUG: DYNAMIC-FILE DISABLED - Creating static MathBox");
|
|
||||||
let math_box = Box::new(MathBox::new()) as Box<dyn NyashBox>;
|
|
||||||
return Ok(math_box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"NullBox" => {
|
"NullBox" => {
|
||||||
// NullBoxは引数なしで作成
|
// NullBoxは引数なしで作成
|
||||||
if !arguments.is_empty() {
|
if !arguments.is_empty() {
|
||||||
@ -392,65 +362,25 @@ impl NyashInterpreter {
|
|||||||
message: format!("TimeBox constructor expects 0 arguments, got {}", arguments.len()),
|
message: format!("TimeBox constructor expects 0 arguments, got {}", arguments.len()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
log::debug!("🔌 DEBUG: Creating TimeBox through dynamic library");
|
|
||||||
let time_box = super::plugin_loader::PluginLoader::create_time_box()?;
|
|
||||||
log::debug!("🔌 DEBUG: TimeBox created successfully, type_name: {}", time_box.type_name());
|
|
||||||
return Ok(time_box);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
{
|
|
||||||
let time_box = Box::new(TimeBox::new()) as Box<dyn NyashBox>;
|
let time_box = Box::new(TimeBox::new()) as Box<dyn NyashBox>;
|
||||||
|
// 🌍 革命的実装:Environment tracking廃止
|
||||||
return Ok(time_box);
|
return Ok(time_box);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
"DateTimeBox" => {
|
"DateTimeBox" => {
|
||||||
// DateTimeBoxは引数なしで現在時刻、または引数1個でタイムスタンプ
|
// DateTimeBoxは引数なしで現在時刻、または引数1個でタイムスタンプ
|
||||||
match arguments.len() {
|
match arguments.len() {
|
||||||
0 => {
|
0 => {
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
log::debug!("🔌 DEBUG: Creating DateTimeBox (now) through dynamic library");
|
|
||||||
let datetime_box = super::plugin_loader::PluginLoader::create_datetime_now()?;
|
|
||||||
log::debug!("🔌 DEBUG: DateTimeBox created successfully, type_name: {}", datetime_box.type_name());
|
|
||||||
return Ok(datetime_box);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
{
|
|
||||||
let datetime_box = Box::new(DateTimeBox::now()) as Box<dyn NyashBox>;
|
let datetime_box = Box::new(DateTimeBox::now()) as Box<dyn NyashBox>;
|
||||||
|
// 🌍 革命的実装:Environment tracking廃止
|
||||||
return Ok(datetime_box);
|
return Ok(datetime_box);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
1 => {
|
1 => {
|
||||||
let timestamp_value = self.execute_expression(&arguments[0])?;
|
let timestamp_value = self.execute_expression(&arguments[0])?;
|
||||||
|
|
||||||
// Try integer timestamp first
|
|
||||||
if let Some(int_box) = timestamp_value.as_any().downcast_ref::<IntegerBox>() {
|
if let Some(int_box) = timestamp_value.as_any().downcast_ref::<IntegerBox>() {
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
// TODO: Add timestamp creation to plugin
|
|
||||||
let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>;
|
let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>;
|
||||||
|
// 🌍 革命的実装:Environment tracking廃止
|
||||||
return Ok(datetime_box);
|
return Ok(datetime_box);
|
||||||
}
|
} else {
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
{
|
|
||||||
let datetime_box = Box::new(DateTimeBox::from_timestamp(int_box.value)) as Box<dyn NyashBox>;
|
|
||||||
return Ok(datetime_box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try string parsing
|
|
||||||
let time_str = timestamp_value.to_string_box().value;
|
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
log::debug!("🔌 DEBUG: Creating DateTimeBox from string through dynamic library");
|
|
||||||
let datetime_box = super::plugin_loader::PluginLoader::create_datetime_from_string(&time_str)?;
|
|
||||||
log::debug!("🔌 DEBUG: DateTimeBox created successfully, type_name: {}", datetime_box.type_name());
|
|
||||||
return Ok(datetime_box);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
{
|
|
||||||
return Err(RuntimeError::TypeError {
|
return Err(RuntimeError::TypeError {
|
||||||
message: "DateTimeBox constructor requires integer timestamp".to_string(),
|
message: "DateTimeBox constructor requires integer timestamp".to_string(),
|
||||||
});
|
});
|
||||||
@ -492,19 +422,10 @@ impl NyashInterpreter {
|
|||||||
message: format!("RandomBox constructor expects 0 arguments, got {}", arguments.len()),
|
message: format!("RandomBox constructor expects 0 arguments, got {}", arguments.len()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dynamic-file")]
|
|
||||||
{
|
|
||||||
log::debug!("🔌 DEBUG: Creating RandomBox through dynamic library");
|
|
||||||
let random_box = super::plugin_loader::PluginLoader::create_random_box()?;
|
|
||||||
log::debug!("🔌 DEBUG: RandomBox created successfully, type_name: {}", random_box.type_name());
|
|
||||||
return Ok(random_box);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "dynamic-file"))]
|
|
||||||
{
|
|
||||||
let random_box = Box::new(RandomBox::new()) as Box<dyn NyashBox>;
|
let random_box = Box::new(RandomBox::new()) as Box<dyn NyashBox>;
|
||||||
|
// 🌍 革命的実装:Environment tracking廃止
|
||||||
return Ok(random_box);
|
return Ok(random_box);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
"SoundBox" => {
|
"SoundBox" => {
|
||||||
// SoundBoxは引数なしで作成
|
// SoundBoxは引数なしで作成
|
||||||
if !arguments.is_empty() {
|
if !arguments.is_empty() {
|
||||||
|
|||||||
@ -145,7 +145,6 @@ impl NyashInterpreter {
|
|||||||
if let Some(Some(init_expr)) = initial_values.get(i) {
|
if let Some(Some(init_expr)) = initial_values.get(i) {
|
||||||
// 🚀 初期化付きlocal宣言: local x = value
|
// 🚀 初期化付きlocal宣言: local x = value
|
||||||
let init_value = self.execute_expression(init_expr)?;
|
let init_value = self.execute_expression(init_expr)?;
|
||||||
eprintln!("🔍 DEBUG: Local variable '{}' initialized with type: {}", var_name, init_value.type_name());
|
|
||||||
self.declare_local_variable(var_name, init_value);
|
self.declare_local_variable(var_name, init_value);
|
||||||
} else {
|
} else {
|
||||||
// 従来のlocal宣言: local x
|
// 従来のlocal宣言: local x
|
||||||
|
|||||||
@ -29,12 +29,6 @@ pub mod box_arithmetic; // 🚀 Arithmetic operations moved from box_trait.rs
|
|||||||
// 🔥 NyashValue Revolutionary System (NEW!)
|
// 🔥 NyashValue Revolutionary System (NEW!)
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
// 🚀 BID-FFI: Box Interface Definition with FFI (NEW!)
|
|
||||||
pub mod bid;
|
|
||||||
|
|
||||||
// 🔌 Runtime: Plugin System and Box Management (NEW!)
|
|
||||||
pub mod runtime;
|
|
||||||
|
|
||||||
// 🌐 P2P Communication Infrastructure (NEW!)
|
// 🌐 P2P Communication Infrastructure (NEW!)
|
||||||
pub mod messaging;
|
pub mod messaging;
|
||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|||||||
@ -38,12 +38,6 @@ pub mod backend;
|
|||||||
// 📊 Performance Benchmarks
|
// 📊 Performance Benchmarks
|
||||||
pub mod benchmarks;
|
pub mod benchmarks;
|
||||||
|
|
||||||
// 🚀 BID-FFI: Box Interface Definition with FFI
|
|
||||||
pub mod bid;
|
|
||||||
|
|
||||||
// 🔌 Runtime: Plugin System (Day 5)
|
|
||||||
pub mod runtime;
|
|
||||||
|
|
||||||
// 🚀 Refactored modules for better organization
|
// 🚀 Refactored modules for better organization
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod runner;
|
pub mod runner;
|
||||||
|
|||||||
@ -291,28 +291,12 @@ impl MirBuilder {
|
|||||||
let operand_val = self.build_expression(operand)?;
|
let operand_val = self.build_expression(operand)?;
|
||||||
let dst = self.value_gen.next();
|
let dst = self.value_gen.next();
|
||||||
|
|
||||||
// Phase 2: Convert UnaryOp to intrinsic call
|
let mir_op = self.convert_unary_operator(operator)?;
|
||||||
// Create intrinsic function name based on operator
|
|
||||||
let intrinsic_name = match operator.as_str() {
|
|
||||||
"-" => "@unary_neg",
|
|
||||||
"!" | "not" => "@unary_not",
|
|
||||||
"~" => "@unary_bitnot",
|
|
||||||
_ => return Err(format!("Unsupported unary operator: {}", operator)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create string constant for intrinsic function name
|
self.emit_instruction(MirInstruction::UnaryOp {
|
||||||
let func_name_id = self.value_gen.next();
|
dst,
|
||||||
self.emit_instruction(MirInstruction::Const {
|
op: mir_op,
|
||||||
dst: func_name_id,
|
operand: operand_val,
|
||||||
value: ConstValue::String(intrinsic_name.to_string()),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Emit intrinsic call
|
|
||||||
self.emit_instruction(MirInstruction::Call {
|
|
||||||
dst: Some(dst),
|
|
||||||
func: func_name_id,
|
|
||||||
args: vec![operand_val],
|
|
||||||
effects: EffectMask::PURE, // Unary operations are pure
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(dst)
|
Ok(dst)
|
||||||
@ -369,20 +353,10 @@ impl MirBuilder {
|
|||||||
fn build_print_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
fn build_print_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
||||||
let value = self.build_expression(expression)?;
|
let value = self.build_expression(expression)?;
|
||||||
|
|
||||||
// Phase 2: Convert Print to intrinsic call (@print)
|
// For now, use a special Print instruction (minimal scope)
|
||||||
// Create string constant for intrinsic function name
|
self.emit_instruction(MirInstruction::Print {
|
||||||
let func_name_id = self.value_gen.next();
|
value,
|
||||||
self.emit_instruction(MirInstruction::Const {
|
effects: EffectMask::PURE.add(Effect::Io),
|
||||||
dst: func_name_id,
|
|
||||||
value: ConstValue::String("@print".to_string()),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Emit intrinsic call (print returns void)
|
|
||||||
self.emit_instruction(MirInstruction::Call {
|
|
||||||
dst: None, // Print has no return value
|
|
||||||
func: func_name_id,
|
|
||||||
args: vec![value],
|
|
||||||
effects: EffectMask::PURE.add(Effect::Io), // IO effect for print
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Return the value that was printed
|
// Return the value that was printed
|
||||||
@ -556,35 +530,15 @@ impl MirBuilder {
|
|||||||
let finally_block = if finally_body.is_some() { Some(self.block_gen.next()) } else { None };
|
let finally_block = if finally_body.is_some() { Some(self.block_gen.next()) } else { None };
|
||||||
let exit_block = self.block_gen.next();
|
let exit_block = self.block_gen.next();
|
||||||
|
|
||||||
// Phase 2: Convert Catch to intrinsic call (@set_exception_handler)
|
// Set up exception handler for the try block (before we enter it)
|
||||||
if let Some(catch_clause) = catch_clauses.first() {
|
if let Some(catch_clause) = catch_clauses.first() {
|
||||||
let exception_value = self.value_gen.next();
|
let exception_value = self.value_gen.next();
|
||||||
|
|
||||||
// Create string constants for intrinsic function name and exception type
|
// Register catch handler for exceptions that may occur in try block
|
||||||
let func_name_id = self.value_gen.next();
|
self.emit_instruction(MirInstruction::Catch {
|
||||||
self.emit_instruction(MirInstruction::Const {
|
exception_type: catch_clause.exception_type.clone(),
|
||||||
dst: func_name_id,
|
exception_value,
|
||||||
value: ConstValue::String("@set_exception_handler".to_string()),
|
handler_bb: catch_block,
|
||||||
})?;
|
|
||||||
|
|
||||||
let exception_type_id = self.value_gen.next();
|
|
||||||
self.emit_instruction(MirInstruction::Const {
|
|
||||||
dst: exception_type_id,
|
|
||||||
value: ConstValue::String(catch_clause.exception_type.clone().unwrap_or("*".to_string())),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let handler_bb_id = self.value_gen.next();
|
|
||||||
self.emit_instruction(MirInstruction::Const {
|
|
||||||
dst: handler_bb_id,
|
|
||||||
value: ConstValue::Integer(catch_block.as_u32() as i64),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Register catch handler via intrinsic call
|
|
||||||
self.emit_instruction(MirInstruction::Call {
|
|
||||||
dst: Some(exception_value),
|
|
||||||
func: func_name_id,
|
|
||||||
args: vec![exception_type_id, handler_bb_id],
|
|
||||||
effects: EffectMask::CONTROL, // Exception handling has control effects
|
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,20 +609,10 @@ impl MirBuilder {
|
|||||||
fn build_throw_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
fn build_throw_statement(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
||||||
let exception_value = self.build_expression(expression)?;
|
let exception_value = self.build_expression(expression)?;
|
||||||
|
|
||||||
// Phase 2: Convert Throw to intrinsic call (@throw)
|
// Emit throw instruction with PANIC effect (this is a terminator)
|
||||||
// Create string constant for intrinsic function name
|
self.emit_instruction(MirInstruction::Throw {
|
||||||
let func_name_id = self.value_gen.next();
|
exception: exception_value,
|
||||||
self.emit_instruction(MirInstruction::Const {
|
effects: EffectMask::PANIC,
|
||||||
dst: func_name_id,
|
|
||||||
value: ConstValue::String("@throw".to_string()),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Emit intrinsic call (throw has PANIC effect and doesn't return)
|
|
||||||
self.emit_instruction(MirInstruction::Call {
|
|
||||||
dst: None, // Throw never returns
|
|
||||||
func: func_name_id,
|
|
||||||
args: vec![exception_value],
|
|
||||||
effects: EffectMask::PANIC, // PANIC effect for throw
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Throw doesn't return normally, but we need to return a value for the type system
|
// Throw doesn't return normally, but we need to return a value for the type system
|
||||||
@ -760,11 +704,11 @@ impl MirBuilder {
|
|||||||
// First, build the object expression to get its ValueId
|
// First, build the object expression to get its ValueId
|
||||||
let object_value = self.build_expression(object)?;
|
let object_value = self.build_expression(object)?;
|
||||||
|
|
||||||
// Get the field from the object using BoxFieldLoad (Phase 8.5 new instruction)
|
// Get the field from the object using RefGet
|
||||||
let result_id = self.value_gen.next();
|
let result_id = self.value_gen.next();
|
||||||
self.emit_instruction(MirInstruction::BoxFieldLoad {
|
self.emit_instruction(MirInstruction::RefGet {
|
||||||
dst: result_id,
|
dst: result_id,
|
||||||
box_val: object_value,
|
reference: object_value,
|
||||||
field,
|
field,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -772,45 +716,22 @@ impl MirBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build new expression: new ClassName(arguments)
|
/// Build new expression: new ClassName(arguments)
|
||||||
fn build_new_expression(&mut self, class: String, arguments: Vec<ASTNode>) -> Result<ValueId, String> {
|
fn build_new_expression(&mut self, class: String, _arguments: Vec<ASTNode>) -> Result<ValueId, String> {
|
||||||
// Special handling for StringBox - if it has a string literal argument,
|
// For Phase 6.1, we'll create a simple RefNew without processing arguments
|
||||||
// treat it as a string constant, not a box creation
|
// In a full implementation, arguments would be used for constructor calls
|
||||||
if class == "StringBox" && arguments.len() == 1 {
|
|
||||||
if let ASTNode::Literal { value: LiteralValue::String(s), .. } = &arguments[0] {
|
|
||||||
// Just create a string constant
|
|
||||||
let dst = self.value_gen.next();
|
let dst = self.value_gen.next();
|
||||||
|
|
||||||
|
// For now, create a "box type" value representing the class
|
||||||
|
let type_value = self.value_gen.next();
|
||||||
self.emit_instruction(MirInstruction::Const {
|
self.emit_instruction(MirInstruction::Const {
|
||||||
dst,
|
dst: type_value,
|
||||||
value: ConstValue::String(s.clone()),
|
value: ConstValue::String(class),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Phase 5-3: RefNew is deprecated - use NewBox instead
|
// Create the reference using RefNew
|
||||||
let string_box_dst = self.value_gen.next();
|
self.emit_instruction(MirInstruction::RefNew {
|
||||||
self.emit_instruction(MirInstruction::NewBox {
|
|
||||||
dst: string_box_dst,
|
|
||||||
box_type: "StringBox".to_string(),
|
|
||||||
args: vec![dst],
|
|
||||||
})?;
|
|
||||||
|
|
||||||
return Ok(string_box_dst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 5-3: Create NewBox with processed arguments
|
|
||||||
let dst = self.value_gen.next();
|
|
||||||
|
|
||||||
// Process all arguments
|
|
||||||
let mut arg_values = Vec::new();
|
|
||||||
for arg in arguments {
|
|
||||||
let arg_value = self.build_expression(arg)?;
|
|
||||||
arg_values.push(arg_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create NewBox instruction
|
|
||||||
self.emit_instruction(MirInstruction::NewBox {
|
|
||||||
dst,
|
dst,
|
||||||
box_type: class,
|
box_val: type_value,
|
||||||
args: arg_values,
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(dst)
|
Ok(dst)
|
||||||
@ -822,9 +743,9 @@ impl MirBuilder {
|
|||||||
let object_value = self.build_expression(object)?;
|
let object_value = self.build_expression(object)?;
|
||||||
let value_result = self.build_expression(value)?;
|
let value_result = self.build_expression(value)?;
|
||||||
|
|
||||||
// Set the field using BoxFieldStore (Phase 8.5 new instruction)
|
// Set the field using RefSet
|
||||||
self.emit_instruction(MirInstruction::BoxFieldStore {
|
self.emit_instruction(MirInstruction::RefSet {
|
||||||
box_val: object_value,
|
reference: object_value,
|
||||||
field,
|
field,
|
||||||
value: value_result,
|
value: value_result,
|
||||||
})?;
|
})?;
|
||||||
@ -888,12 +809,11 @@ impl MirBuilder {
|
|||||||
// Evaluate the expression
|
// Evaluate the expression
|
||||||
let expression_value = self.build_expression(expression)?;
|
let expression_value = self.build_expression(expression)?;
|
||||||
|
|
||||||
// Phase 2: Convert FutureNew to NewBox + BoxCall implementation
|
// Create a new Future with the evaluated expression as the initial value
|
||||||
let future_id = self.value_gen.next();
|
let future_id = self.value_gen.next();
|
||||||
self.emit_instruction(MirInstruction::NewBox {
|
self.emit_instruction(MirInstruction::FutureNew {
|
||||||
dst: future_id,
|
dst: future_id,
|
||||||
box_type: "FutureBox".to_string(),
|
value: expression_value,
|
||||||
args: vec![expression_value],
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Store the future in the variable
|
// Store the future in the variable
|
||||||
@ -907,16 +827,13 @@ impl MirBuilder {
|
|||||||
// Evaluate the expression (should be a Future)
|
// Evaluate the expression (should be a Future)
|
||||||
let future_value = self.build_expression(expression)?;
|
let future_value = self.build_expression(expression)?;
|
||||||
|
|
||||||
// Phase 2: Convert Await to BoxCall implementation
|
// Create destination for await result
|
||||||
let result_id = self.value_gen.next();
|
let result_id = self.value_gen.next();
|
||||||
|
|
||||||
// Emit await as a method call on the future box
|
// Emit await instruction
|
||||||
self.emit_instruction(MirInstruction::BoxCall {
|
self.emit_instruction(MirInstruction::Await {
|
||||||
dst: Some(result_id),
|
dst: result_id,
|
||||||
box_val: future_value,
|
future: future_value,
|
||||||
method: "await".to_string(),
|
|
||||||
args: vec![],
|
|
||||||
effects: EffectMask::IO.add(Effect::Control), // Await has IO and control effects
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(result_id)
|
Ok(result_id)
|
||||||
|
|||||||
@ -31,8 +31,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Unary operation
|
/// Unary operation
|
||||||
/// `%dst = op %operand`
|
/// `%dst = op %operand`
|
||||||
/// DEPRECATED: Phase 5 - Use BinOp instead (e.g., `not %a` → `%a xor true`, `neg %a` → `0 sub %a`)
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BinOp instead")]
|
|
||||||
UnaryOp {
|
UnaryOp {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
op: UnaryOp,
|
op: UnaryOp,
|
||||||
@ -52,8 +50,6 @@ pub enum MirInstruction {
|
|||||||
// === Memory Operations ===
|
// === Memory Operations ===
|
||||||
/// Load from memory/variable
|
/// Load from memory/variable
|
||||||
/// `%dst = load %ptr`
|
/// `%dst = load %ptr`
|
||||||
/// DEPRECATED: Phase 5 - Use BoxFieldLoad instead
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BoxFieldLoad instead")]
|
|
||||||
Load {
|
Load {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
ptr: ValueId,
|
ptr: ValueId,
|
||||||
@ -61,8 +57,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Store to memory/variable
|
/// Store to memory/variable
|
||||||
/// `store %value -> %ptr`
|
/// `store %value -> %ptr`
|
||||||
/// DEPRECATED: Phase 5 - Use BoxFieldStore instead
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BoxFieldStore instead")]
|
|
||||||
Store {
|
Store {
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
ptr: ValueId,
|
ptr: ValueId,
|
||||||
@ -128,8 +122,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Check Box type
|
/// Check Box type
|
||||||
/// `%dst = type_check %box "BoxType"`
|
/// `%dst = type_check %box "BoxType"`
|
||||||
/// DEPRECATED: Phase 5 - Use Call with @type_check intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use Call with @type_check intrinsic")]
|
|
||||||
TypeCheck {
|
TypeCheck {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
@ -139,8 +131,6 @@ pub enum MirInstruction {
|
|||||||
// === Type Conversion ===
|
// === Type Conversion ===
|
||||||
/// Convert between types
|
/// Convert between types
|
||||||
/// `%dst = cast %value as Type`
|
/// `%dst = cast %value as Type`
|
||||||
/// DEPRECATED: Phase 5 - Use Call with @cast intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use Call with @cast intrinsic")]
|
|
||||||
Cast {
|
Cast {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
@ -150,8 +140,6 @@ pub enum MirInstruction {
|
|||||||
// === Array Operations ===
|
// === Array Operations ===
|
||||||
/// Get array element
|
/// Get array element
|
||||||
/// `%dst = %array[%index]`
|
/// `%dst = %array[%index]`
|
||||||
/// DEPRECATED: Phase 5 - Use BoxFieldLoad or Call with @array_get intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BoxFieldLoad or Call with @array_get intrinsic")]
|
|
||||||
ArrayGet {
|
ArrayGet {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
array: ValueId,
|
array: ValueId,
|
||||||
@ -160,8 +148,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Set array element
|
/// Set array element
|
||||||
/// `%array[%index] = %value`
|
/// `%array[%index] = %value`
|
||||||
/// DEPRECATED: Phase 5 - Use BoxFieldStore or Call with @array_set intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BoxFieldStore or Call with @array_set intrinsic")]
|
|
||||||
ArraySet {
|
ArraySet {
|
||||||
array: ValueId,
|
array: ValueId,
|
||||||
index: ValueId,
|
index: ValueId,
|
||||||
@ -171,8 +157,6 @@ pub enum MirInstruction {
|
|||||||
// === Special Operations ===
|
// === Special Operations ===
|
||||||
/// Copy a value (for optimization passes)
|
/// Copy a value (for optimization passes)
|
||||||
/// `%dst = copy %src`
|
/// `%dst = copy %src`
|
||||||
/// DEPRECATED: Phase 5 - Optimization pass only, not needed in IR
|
|
||||||
#[deprecated(since = "Phase 5", note = "Optimization pass only, not needed in IR")]
|
|
||||||
Copy {
|
Copy {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
src: ValueId,
|
src: ValueId,
|
||||||
@ -180,8 +164,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Debug/introspection instruction
|
/// Debug/introspection instruction
|
||||||
/// `debug %value "message"`
|
/// `debug %value "message"`
|
||||||
/// DEPRECATED: Phase 5 - Use Call with @debug intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use Call with @debug intrinsic")]
|
|
||||||
Debug {
|
Debug {
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
message: String,
|
message: String,
|
||||||
@ -189,24 +171,18 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Print instruction for console output
|
/// Print instruction for console output
|
||||||
/// `print %value`
|
/// `print %value`
|
||||||
/// DEPRECATED: Phase 5 - Use Call with @print intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use Call with @print intrinsic")]
|
|
||||||
Print {
|
Print {
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
effects: EffectMask,
|
effects: EffectMask,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// No-op instruction (for optimization placeholders)
|
/// No-op instruction (for optimization placeholders)
|
||||||
/// DEPRECATED: Phase 5 - Not needed in final IR
|
|
||||||
#[deprecated(since = "Phase 5", note = "Not needed in final IR")]
|
|
||||||
Nop,
|
Nop,
|
||||||
|
|
||||||
// === Control Flow & Exception Handling (Phase 5) ===
|
// === Control Flow & Exception Handling (Phase 5) ===
|
||||||
|
|
||||||
/// Throw an exception
|
/// Throw an exception
|
||||||
/// `throw %exception_value`
|
/// `throw %exception_value`
|
||||||
/// DEPRECATED: Phase 5 - Use Call with @throw intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use Call with @throw intrinsic")]
|
|
||||||
Throw {
|
Throw {
|
||||||
exception: ValueId,
|
exception: ValueId,
|
||||||
effects: EffectMask,
|
effects: EffectMask,
|
||||||
@ -214,8 +190,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Catch handler setup (landing pad for exceptions)
|
/// Catch handler setup (landing pad for exceptions)
|
||||||
/// `catch %exception_type -> %handler_bb`
|
/// `catch %exception_type -> %handler_bb`
|
||||||
/// DEPRECATED: Phase 5 - Use Call with @catch intrinsic
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use Call with @catch intrinsic")]
|
|
||||||
Catch {
|
Catch {
|
||||||
exception_type: Option<String>, // None = catch-all
|
exception_type: Option<String>, // None = catch-all
|
||||||
exception_value: ValueId, // Where to store caught exception
|
exception_value: ValueId, // Where to store caught exception
|
||||||
@ -230,8 +204,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Create a new reference to a Box
|
/// Create a new reference to a Box
|
||||||
/// `%dst = ref_new %box`
|
/// `%dst = ref_new %box`
|
||||||
/// DEPRECATED: Phase 5 - RefGet is sufficient
|
|
||||||
#[deprecated(since = "Phase 5", note = "RefGet is sufficient")]
|
|
||||||
RefNew {
|
RefNew {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
box_val: ValueId,
|
box_val: ValueId,
|
||||||
@ -269,16 +241,12 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Memory barrier read (no-op for now, proper effect annotation)
|
/// Memory barrier read (no-op for now, proper effect annotation)
|
||||||
/// `barrier_read %ptr`
|
/// `barrier_read %ptr`
|
||||||
/// DEPRECATED: Phase 5 - Use AtomicFence instead
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use AtomicFence instead")]
|
|
||||||
BarrierRead {
|
BarrierRead {
|
||||||
ptr: ValueId,
|
ptr: ValueId,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Memory barrier write (no-op for now, proper effect annotation)
|
/// Memory barrier write (no-op for now, proper effect annotation)
|
||||||
/// `barrier_write %ptr`
|
/// `barrier_write %ptr`
|
||||||
/// DEPRECATED: Phase 5 - Use AtomicFence instead
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use AtomicFence instead")]
|
|
||||||
BarrierWrite {
|
BarrierWrite {
|
||||||
ptr: ValueId,
|
ptr: ValueId,
|
||||||
},
|
},
|
||||||
@ -287,8 +255,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Create a new Future with initial value
|
/// Create a new Future with initial value
|
||||||
/// `%dst = future_new %value`
|
/// `%dst = future_new %value`
|
||||||
/// DEPRECATED: Phase 5 - Use NewBox + BoxCall
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use NewBox + BoxCall")]
|
|
||||||
FutureNew {
|
FutureNew {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
@ -296,8 +262,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Set Future value and mark as ready
|
/// Set Future value and mark as ready
|
||||||
/// `future_set %future = %value`
|
/// `future_set %future = %value`
|
||||||
/// DEPRECATED: Phase 5 - Use BoxCall
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BoxCall")]
|
|
||||||
FutureSet {
|
FutureSet {
|
||||||
future: ValueId,
|
future: ValueId,
|
||||||
value: ValueId,
|
value: ValueId,
|
||||||
@ -305,8 +269,6 @@ pub enum MirInstruction {
|
|||||||
|
|
||||||
/// Wait for Future completion and get value
|
/// Wait for Future completion and get value
|
||||||
/// `%dst = await %future`
|
/// `%dst = await %future`
|
||||||
/// DEPRECATED: Phase 5 - Use BoxCall
|
|
||||||
#[deprecated(since = "Phase 5", note = "Use BoxCall")]
|
|
||||||
Await {
|
Await {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
future: ValueId,
|
future: ValueId,
|
||||||
@ -323,80 +285,6 @@ pub enum MirInstruction {
|
|||||||
args: Vec<ValueId>,
|
args: Vec<ValueId>,
|
||||||
effects: EffectMask,
|
effects: EffectMask,
|
||||||
},
|
},
|
||||||
|
|
||||||
// === Phase 8.5: MIR 26-instruction reduction (NEW) ===
|
|
||||||
|
|
||||||
/// Box field load operation (replaces Load)
|
|
||||||
/// `%dst = %box.field`
|
|
||||||
BoxFieldLoad {
|
|
||||||
dst: ValueId,
|
|
||||||
box_val: ValueId,
|
|
||||||
field: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Box field store operation (replaces Store)
|
|
||||||
/// `%box.field = %value`
|
|
||||||
BoxFieldStore {
|
|
||||||
box_val: ValueId,
|
|
||||||
field: String,
|
|
||||||
value: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Check weak reference validity
|
|
||||||
/// `%dst = weak_check %weak_ref`
|
|
||||||
WeakCheck {
|
|
||||||
dst: ValueId,
|
|
||||||
weak_ref: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Send data via Bus
|
|
||||||
/// `send %data -> %target`
|
|
||||||
Send {
|
|
||||||
data: ValueId,
|
|
||||||
target: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Receive data from Bus
|
|
||||||
/// `%dst = recv %source`
|
|
||||||
Recv {
|
|
||||||
dst: ValueId,
|
|
||||||
source: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Tail call optimization
|
|
||||||
/// `tail_call %func(%args...)`
|
|
||||||
TailCall {
|
|
||||||
func: ValueId,
|
|
||||||
args: Vec<ValueId>,
|
|
||||||
effects: EffectMask,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Adopt ownership (parent takes child)
|
|
||||||
/// `adopt %parent <- %child`
|
|
||||||
Adopt {
|
|
||||||
parent: ValueId,
|
|
||||||
child: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Release strong ownership
|
|
||||||
/// `release %ref`
|
|
||||||
Release {
|
|
||||||
reference: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Memory copy optimization
|
|
||||||
/// `memcopy %dst <- %src, %size`
|
|
||||||
MemCopy {
|
|
||||||
dst: ValueId,
|
|
||||||
src: ValueId,
|
|
||||||
size: ValueId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Atomic memory fence
|
|
||||||
/// `atomic_fence %ordering`
|
|
||||||
AtomicFence {
|
|
||||||
ordering: AtomicOrdering,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constant values in MIR
|
/// Constant values in MIR
|
||||||
@ -456,16 +344,6 @@ pub enum MirType {
|
|||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Atomic memory ordering for fence operations
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum AtomicOrdering {
|
|
||||||
Relaxed,
|
|
||||||
Acquire,
|
|
||||||
Release,
|
|
||||||
AcqRel,
|
|
||||||
SeqCst,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MirInstruction {
|
impl MirInstruction {
|
||||||
/// Get the effect mask for this instruction
|
/// Get the effect mask for this instruction
|
||||||
pub fn effects(&self) -> EffectMask {
|
pub fn effects(&self) -> EffectMask {
|
||||||
@ -526,18 +404,6 @@ impl MirInstruction {
|
|||||||
|
|
||||||
// Phase 9.7: External Function Calls
|
// Phase 9.7: External Function Calls
|
||||||
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask
|
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask
|
||||||
|
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { .. } => EffectMask::READ, // Box field read
|
|
||||||
MirInstruction::BoxFieldStore { .. } => EffectMask::WRITE, // Box field write
|
|
||||||
MirInstruction::WeakCheck { .. } => EffectMask::PURE, // Check is pure
|
|
||||||
MirInstruction::Send { .. } => EffectMask::IO, // Bus send has IO effects
|
|
||||||
MirInstruction::Recv { .. } => EffectMask::IO, // Bus recv has IO effects
|
|
||||||
MirInstruction::TailCall { effects, .. } => *effects, // Use provided effect mask
|
|
||||||
MirInstruction::Adopt { .. } => EffectMask::WRITE, // Ownership change has write effects
|
|
||||||
MirInstruction::Release { .. } => EffectMask::WRITE, // Ownership release has write effects
|
|
||||||
MirInstruction::MemCopy { .. } => EffectMask::WRITE, // Memory copy has write effects
|
|
||||||
MirInstruction::AtomicFence { .. } => EffectMask::IO.add(Effect::Barrier), // Fence has barrier + IO
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,12 +432,6 @@ impl MirInstruction {
|
|||||||
MirInstruction::BoxCall { dst, .. } |
|
MirInstruction::BoxCall { dst, .. } |
|
||||||
MirInstruction::ExternCall { dst, .. } => *dst,
|
MirInstruction::ExternCall { dst, .. } => *dst,
|
||||||
|
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { dst, .. } |
|
|
||||||
MirInstruction::WeakCheck { dst, .. } |
|
|
||||||
MirInstruction::Recv { dst, .. } |
|
|
||||||
MirInstruction::MemCopy { dst, .. } => Some(*dst),
|
|
||||||
|
|
||||||
MirInstruction::Store { .. } |
|
MirInstruction::Store { .. } |
|
||||||
MirInstruction::Branch { .. } |
|
MirInstruction::Branch { .. } |
|
||||||
MirInstruction::Jump { .. } |
|
MirInstruction::Jump { .. } |
|
||||||
@ -587,14 +447,6 @@ impl MirInstruction {
|
|||||||
MirInstruction::Safepoint |
|
MirInstruction::Safepoint |
|
||||||
MirInstruction::Nop => None,
|
MirInstruction::Nop => None,
|
||||||
|
|
||||||
// Phase 8.5: Non-value producing instructions
|
|
||||||
MirInstruction::BoxFieldStore { .. } |
|
|
||||||
MirInstruction::Send { .. } |
|
|
||||||
MirInstruction::TailCall { .. } |
|
|
||||||
MirInstruction::Adopt { .. } |
|
|
||||||
MirInstruction::Release { .. } |
|
|
||||||
MirInstruction::AtomicFence { .. } => None,
|
|
||||||
|
|
||||||
MirInstruction::Catch { exception_value, .. } => Some(*exception_value),
|
MirInstruction::Catch { exception_value, .. } => Some(*exception_value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,22 +519,6 @@ impl MirInstruction {
|
|||||||
|
|
||||||
// Phase 9.7: External Function Calls
|
// Phase 9.7: External Function Calls
|
||||||
MirInstruction::ExternCall { args, .. } => args.clone(),
|
MirInstruction::ExternCall { args, .. } => args.clone(),
|
||||||
|
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { box_val, .. } => vec![*box_val],
|
|
||||||
MirInstruction::BoxFieldStore { box_val, value, .. } => vec![*box_val, *value],
|
|
||||||
MirInstruction::WeakCheck { weak_ref, .. } => vec![*weak_ref],
|
|
||||||
MirInstruction::Send { data, target } => vec![*data, *target],
|
|
||||||
MirInstruction::Recv { source, .. } => vec![*source],
|
|
||||||
MirInstruction::TailCall { func, args, .. } => {
|
|
||||||
let mut used = vec![*func];
|
|
||||||
used.extend(args);
|
|
||||||
used
|
|
||||||
},
|
|
||||||
MirInstruction::Adopt { parent, child } => vec![*parent, *child],
|
|
||||||
MirInstruction::Release { reference } => vec![*reference],
|
|
||||||
MirInstruction::MemCopy { dst, src, size } => vec![*dst, *src, *size],
|
|
||||||
MirInstruction::AtomicFence { .. } => Vec::new(), // Fence doesn't use values
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -766,39 +602,6 @@ impl fmt::Display for MirInstruction {
|
|||||||
effects)
|
effects)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { dst, box_val, field } => {
|
|
||||||
write!(f, "{} = {}.{}", dst, box_val, field)
|
|
||||||
},
|
|
||||||
MirInstruction::BoxFieldStore { box_val, field, value } => {
|
|
||||||
write!(f, "{}.{} = {}", box_val, field, value)
|
|
||||||
},
|
|
||||||
MirInstruction::WeakCheck { dst, weak_ref } => {
|
|
||||||
write!(f, "{} = weak_check {}", dst, weak_ref)
|
|
||||||
},
|
|
||||||
MirInstruction::Send { data, target } => {
|
|
||||||
write!(f, "send {} -> {}", data, target)
|
|
||||||
},
|
|
||||||
MirInstruction::Recv { dst, source } => {
|
|
||||||
write!(f, "{} = recv {}", dst, source)
|
|
||||||
},
|
|
||||||
MirInstruction::TailCall { func, args, effects } => {
|
|
||||||
write!(f, "tail_call {}({}); effects: {}", func,
|
|
||||||
args.iter().map(|v| format!("{}", v)).collect::<Vec<_>>().join(", "),
|
|
||||||
effects)
|
|
||||||
},
|
|
||||||
MirInstruction::Adopt { parent, child } => {
|
|
||||||
write!(f, "adopt {} <- {}", parent, child)
|
|
||||||
},
|
|
||||||
MirInstruction::Release { reference } => {
|
|
||||||
write!(f, "release {}", reference)
|
|
||||||
},
|
|
||||||
MirInstruction::MemCopy { dst, src, size } => {
|
|
||||||
write!(f, "memcopy {} <- {}, {}", dst, src, size)
|
|
||||||
},
|
|
||||||
MirInstruction::AtomicFence { ordering } => {
|
|
||||||
write!(f, "atomic_fence {:?}", ordering)
|
|
||||||
},
|
|
||||||
_ => write!(f, "{:?}", self), // Fallback for other instructions
|
_ => write!(f, "{:?}", self), // Fallback for other instructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,18 +620,6 @@ impl fmt::Display for ConstValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for AtomicOrdering {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
AtomicOrdering::Relaxed => write!(f, "relaxed"),
|
|
||||||
AtomicOrdering::Acquire => write!(f, "acquire"),
|
|
||||||
AtomicOrdering::Release => write!(f, "release"),
|
|
||||||
AtomicOrdering::AcqRel => write!(f, "acq_rel"),
|
|
||||||
AtomicOrdering::SeqCst => write!(f, "seq_cst"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@ -13,7 +13,6 @@ pub mod builder;
|
|||||||
pub mod verification;
|
pub mod verification;
|
||||||
pub mod ownership_verifier_simple; // Simple ownership forest verification for current MIR
|
pub mod ownership_verifier_simple; // Simple ownership forest verification for current MIR
|
||||||
pub mod printer;
|
pub mod printer;
|
||||||
pub mod optimizer; // Phase 3: Effect System based optimization passes
|
|
||||||
pub mod value_id;
|
pub mod value_id;
|
||||||
pub mod effect;
|
pub mod effect;
|
||||||
|
|
||||||
@ -26,7 +25,6 @@ pub use builder::MirBuilder;
|
|||||||
pub use verification::{MirVerifier, VerificationError};
|
pub use verification::{MirVerifier, VerificationError};
|
||||||
pub use ownership_verifier_simple::{OwnershipVerifier, OwnershipError, OwnershipStats}; // Simple ownership forest verification
|
pub use ownership_verifier_simple::{OwnershipVerifier, OwnershipError, OwnershipStats}; // Simple ownership forest verification
|
||||||
pub use printer::MirPrinter;
|
pub use printer::MirPrinter;
|
||||||
pub use optimizer::{MirOptimizer, OptimizationStats}; // Phase 3: Effect System optimizations
|
|
||||||
pub use value_id::{ValueId, LocalId, ValueIdGenerator};
|
pub use value_id::{ValueId, LocalId, ValueIdGenerator};
|
||||||
pub use effect::{EffectMask, Effect};
|
pub use effect::{EffectMask, Effect};
|
||||||
|
|
||||||
|
|||||||
@ -371,39 +371,6 @@ impl MirPrinter {
|
|||||||
format!("extern_call {}.{}({}) [effects: {}]", iface_name, method_name, args_str, effects)
|
format!("extern_call {}.{}({}) [effects: {}]", iface_name, method_name, args_str, effects)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phase 8.5: MIR 26-instruction reduction (NEW)
|
|
||||||
MirInstruction::BoxFieldLoad { dst, box_val, field } => {
|
|
||||||
format!("{} = {}.{}", dst, box_val, field)
|
|
||||||
},
|
|
||||||
MirInstruction::BoxFieldStore { box_val, field, value } => {
|
|
||||||
format!("{}.{} = {}", box_val, field, value)
|
|
||||||
},
|
|
||||||
MirInstruction::WeakCheck { dst, weak_ref } => {
|
|
||||||
format!("{} = weak_check {}", dst, weak_ref)
|
|
||||||
},
|
|
||||||
MirInstruction::Send { data, target } => {
|
|
||||||
format!("send {} -> {}", data, target)
|
|
||||||
},
|
|
||||||
MirInstruction::Recv { dst, source } => {
|
|
||||||
format!("{} = recv {}", dst, source)
|
|
||||||
},
|
|
||||||
MirInstruction::TailCall { func, args, effects } => {
|
|
||||||
let args_str = args.iter().map(|v| format!("{}", v)).collect::<Vec<_>>().join(", ");
|
|
||||||
format!("tail_call {}({}) [effects: {}]", func, args_str, effects)
|
|
||||||
},
|
|
||||||
MirInstruction::Adopt { parent, child } => {
|
|
||||||
format!("adopt {} <- {}", parent, child)
|
|
||||||
},
|
|
||||||
MirInstruction::Release { reference } => {
|
|
||||||
format!("release {}", reference)
|
|
||||||
},
|
|
||||||
MirInstruction::MemCopy { dst, src, size } => {
|
|
||||||
format!("memcopy {} <- {}, {}", dst, src, size)
|
|
||||||
},
|
|
||||||
MirInstruction::AtomicFence { ordering } => {
|
|
||||||
format!("atomic_fence {:?}", ordering)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@ use crate::{
|
|||||||
interpreter::NyashInterpreter,
|
interpreter::NyashInterpreter,
|
||||||
mir::{MirCompiler, MirPrinter},
|
mir::{MirCompiler, MirPrinter},
|
||||||
backend::{VM, wasm::WasmBackend, aot::AotBackend},
|
backend::{VM, wasm::WasmBackend, aot::AotBackend},
|
||||||
runtime::{PluginConfig, get_global_registry},
|
|
||||||
};
|
};
|
||||||
use std::{fs, process};
|
use std::{fs, process};
|
||||||
|
|
||||||
@ -26,89 +25,9 @@ pub struct NyashRunner {
|
|||||||
impl NyashRunner {
|
impl NyashRunner {
|
||||||
/// Create a new runner with the given configuration
|
/// Create a new runner with the given configuration
|
||||||
pub fn new(config: CliConfig) -> Self {
|
pub fn new(config: CliConfig) -> Self {
|
||||||
// 🔌 プラグインシステム初期化
|
|
||||||
Self::initialize_plugin_system();
|
|
||||||
|
|
||||||
Self { config }
|
Self { config }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// プラグインシステム初期化(nyash.toml読み込み)
|
|
||||||
fn initialize_plugin_system() {
|
|
||||||
// nyash.tomlが存在するかチェック
|
|
||||||
if std::path::Path::new("nyash.toml").exists() {
|
|
||||||
match std::fs::read_to_string("nyash.toml") {
|
|
||||||
Ok(toml_content) => {
|
|
||||||
match PluginConfig::parse(&toml_content) {
|
|
||||||
Ok(plugin_config) => {
|
|
||||||
println!("🔌 Loading plugin configuration from nyash.toml");
|
|
||||||
let registry = get_global_registry();
|
|
||||||
|
|
||||||
// ビルトインBoxを登録(フォールバック用)
|
|
||||||
Self::register_builtin_boxes(®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
|
/// Run Nyash based on the configuration
|
||||||
pub fn run(&self) {
|
pub fn run(&self) {
|
||||||
// Benchmark mode - can run without a file
|
// Benchmark mode - can run without a file
|
||||||
|
|||||||
19
test_simple.nyash
Normal file
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::{
|
use nyash_rust::mir::{
|
||||||
MirModule, MirFunction, FunctionSignature, MirType, EffectMask,
|
MirModule, MirFunction, FunctionSignature, MirType, EffectMask,
|
||||||
BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue, AtomicOrdering
|
BasicBlock, BasicBlockId, ValueId, MirInstruction, ConstValue
|
||||||
};
|
};
|
||||||
use nyash_rust::backend::VM;
|
use nyash_rust::backend::{VM, VMValue};
|
||||||
use nyash_rust::box_trait::IntegerBox;
|
use nyash_rust::box_trait::{IntegerBox, NyashBox};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mir_phase6_vm_ref_ops() {
|
fn test_mir_phase6_vm_ref_ops() {
|
||||||
@ -45,7 +45,6 @@ fn test_mir_phase6_vm_ref_ops() {
|
|||||||
let obj_ref = ValueId::new(1);
|
let obj_ref = ValueId::new(1);
|
||||||
let one_val = ValueId::new(2);
|
let one_val = ValueId::new(2);
|
||||||
let x_val = ValueId::new(3);
|
let x_val = ValueId::new(3);
|
||||||
let print_func = ValueId::new(4);
|
|
||||||
|
|
||||||
// Add instructions
|
// Add instructions
|
||||||
|
|
||||||
@ -55,18 +54,10 @@ fn test_mir_phase6_vm_ref_ops() {
|
|||||||
value: ConstValue::String("Obj".to_string()),
|
value: ConstValue::String("Obj".to_string()),
|
||||||
});
|
});
|
||||||
|
|
||||||
// %4 = const "@print" (for intrinsic call)
|
// %1 = ref_new %0
|
||||||
block.add_instruction(MirInstruction::Const {
|
block.add_instruction(MirInstruction::RefNew {
|
||||||
dst: print_func,
|
|
||||||
value: ConstValue::String("@print".to_string()),
|
|
||||||
});
|
|
||||||
|
|
||||||
// %1 = new Obj()
|
|
||||||
// Phase 5: RefNew is deprecated - use NewBox instead
|
|
||||||
block.add_instruction(MirInstruction::NewBox {
|
|
||||||
dst: obj_ref,
|
dst: obj_ref,
|
||||||
box_type: "Obj".to_string(),
|
box_val: obj_type_val,
|
||||||
args: vec![],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// %2 = const 1
|
// %2 = const 1
|
||||||
@ -75,34 +66,28 @@ fn test_mir_phase6_vm_ref_ops() {
|
|||||||
value: ConstValue::Integer(1),
|
value: ConstValue::Integer(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
// atomic_fence release
|
// barrier_write %1
|
||||||
// Phase 5: BarrierWrite is deprecated - use AtomicFence instead
|
block.add_instruction(MirInstruction::BarrierWrite {
|
||||||
block.add_instruction(MirInstruction::AtomicFence {
|
ptr: obj_ref,
|
||||||
ordering: AtomicOrdering::Release,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// %1.x = %2
|
// ref_set %1, "x", %2
|
||||||
// Phase 5: RefSet is deprecated - use BoxFieldStore instead
|
block.add_instruction(MirInstruction::RefSet {
|
||||||
block.add_instruction(MirInstruction::BoxFieldStore {
|
reference: obj_ref,
|
||||||
box_val: obj_ref,
|
|
||||||
field: "x".to_string(),
|
field: "x".to_string(),
|
||||||
value: one_val,
|
value: one_val,
|
||||||
});
|
});
|
||||||
|
|
||||||
// %3 = %1.x
|
// %3 = ref_get %1, "x"
|
||||||
// Phase 5: RefGet is deprecated - use BoxFieldLoad instead
|
block.add_instruction(MirInstruction::RefGet {
|
||||||
block.add_instruction(MirInstruction::BoxFieldLoad {
|
|
||||||
dst: x_val,
|
dst: x_val,
|
||||||
box_val: obj_ref,
|
reference: obj_ref,
|
||||||
field: "x".to_string(),
|
field: "x".to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// call @print(%3)
|
// print %3
|
||||||
// Phase 5: Print is deprecated - use Call @print instead
|
block.add_instruction(MirInstruction::Print {
|
||||||
block.add_instruction(MirInstruction::Call {
|
value: x_val,
|
||||||
dst: None,
|
|
||||||
func: print_func,
|
|
||||||
args: vec![x_val],
|
|
||||||
effects: EffectMask::IO,
|
effects: EffectMask::IO,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -183,14 +168,13 @@ fn test_barrier_no_op() {
|
|||||||
value: ConstValue::Integer(42),
|
value: ConstValue::Integer(42),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test atomic fence instructions (replace barriers)
|
// Test barrier instructions (should be no-ops)
|
||||||
// Phase 5: BarrierRead/BarrierWrite are deprecated - use AtomicFence
|
block.add_instruction(MirInstruction::BarrierRead {
|
||||||
block.add_instruction(MirInstruction::AtomicFence {
|
ptr: test_val,
|
||||||
ordering: AtomicOrdering::Acquire,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
block.add_instruction(MirInstruction::AtomicFence {
|
block.add_instruction(MirInstruction::BarrierWrite {
|
||||||
ordering: AtomicOrdering::Release,
|
ptr: test_val,
|
||||||
});
|
});
|
||||||
|
|
||||||
block.add_instruction(MirInstruction::Return {
|
block.add_instruction(MirInstruction::Return {
|
||||||
|
|||||||
@ -107,17 +107,17 @@ fn test_mir_phase7_basic_nowait_await() {
|
|||||||
.flat_map(|block| &block.instructions)
|
.flat_map(|block| &block.instructions)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Phase 5: FutureNew is deprecated - should contain NewBox "FutureBox" instead
|
// Should contain FutureNew instruction
|
||||||
let has_future_box = instructions.iter().any(|inst| {
|
let has_future_new = instructions.iter().any(|inst| {
|
||||||
matches!(inst, nyash_rust::mir::MirInstruction::NewBox { box_type, .. } if box_type == "FutureBox")
|
matches!(inst, nyash_rust::mir::MirInstruction::FutureNew { .. })
|
||||||
});
|
});
|
||||||
assert!(has_future_box, "MIR should contain NewBox FutureBox instruction");
|
assert!(has_future_new, "MIR should contain FutureNew instruction");
|
||||||
|
|
||||||
// Phase 5: Await is deprecated - should contain BoxCall "await" instead
|
// Should contain Await instruction
|
||||||
let has_await_call = instructions.iter().any(|inst| {
|
let has_await = instructions.iter().any(|inst| {
|
||||||
matches!(inst, nyash_rust::mir::MirInstruction::BoxCall { method, .. } if method == "await")
|
matches!(inst, nyash_rust::mir::MirInstruction::Await { .. })
|
||||||
});
|
});
|
||||||
assert!(has_await_call, "MIR should contain BoxCall await instruction");
|
assert!(has_await, "MIR should contain Await instruction");
|
||||||
|
|
||||||
// Test VM execution
|
// Test VM execution
|
||||||
let mut vm = VM::new();
|
let mut vm = VM::new();
|
||||||
|
|||||||
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