Major changes: - LLVM backend initial implementation (compiler.rs, llvm mode) - Semantics layer integration in interpreter (operators.rs) - Phase 12 plugin architecture revision (3-layer system) - Builtin box removal preparation - MIR instruction set documentation (26→Core-15 migration) - Cross-backend testing infrastructure - Await/nowait syntax support New features: - LLVM AOT compilation support (--backend llvm) - Semantics layer for interpreter→VM flow - Tri-backend smoke tests - Plugin-only registry mode Bug fixes: - Interpreter plugin box arithmetic operations - Branch test returns incorrect values Documentation: - Phase 12 README.md updated with new plugin architecture - Removed obsolete NYIR proposals - Added LLVM test programs documentation Co-Authored-By: Claude <noreply@anthropic.com>
3.3 KiB
3.3 KiB
プラグインBoxは既に箱を引数に取れる!
🎯 重要な発見
プラグインBoxは既にC ABIレベルで箱を引数に取ることができます!
📊 実装の詳細
1. TLVプロトコルでのハンドルサポート
// TLVタグ定義
const TAG_HANDLE: u8 = 8; // プラグインハンドル用
// ハンドルエンコード関数
pub fn plugin_handle(buf: &mut Vec<u8>, type_id: u32, instance_id: u32) {
buf.push(TAG_HANDLE);
buf.push(0u8); // reserved
buf.extend_from_slice(&(8u16).to_le_bytes()); // size = 8
buf.extend_from_slice(&type_id.to_le_bytes()); // 4 bytes
buf.extend_from_slice(&instance_id.to_le_bytes()); // 4 bytes
}
2. プラグイン呼び出し時の処理
// Nyashコード
box1.process(box2, box3)
// ↓ VM/プラグインローダーでの処理
for arg in args {
if let Some(p) = arg.as_any().downcast_ref::<PluginBoxV2>() {
// 箱引数はハンドルとしてエンコード
encode::plugin_handle(&mut tlv, p.type_id, p.instance_id);
}
// ... 他の型の処理
}
// ↓ C ABIプラグイン側
int32_t nyash_plugin_invoke(
uint32_t type_id,
uint32_t method_id,
uint32_t instance_id,
const uint8_t* args, // TLVエンコードされた引数
size_t args_len,
uint8_t* result,
size_t* result_len
) {
// TLVデコード
uint8_t tag;
uint32_t arg_type_id, arg_instance_id;
if (decode_handle(args, &tag, &arg_type_id, &arg_instance_id)) {
// ハンドル引数を処理
// arg_type_id と arg_instance_id で箱を特定
}
}
🔄 実際の使用例
Nyashレベル
// FileBoxがStringBoxを引数に取る例
local file = new FileBox()
local path = new StringBox("/tmp/test.txt")
file.open(path) // StringBox(プラグインBox)を引数に!
// ArrayBoxがMapBoxを引数に取る例
local array = new ArrayBox()
local map = new MapBox()
array.push(map) // MapBox(プラグインBox)を引数に!
プラグイン間の相互運用
// NetBoxがJSONBoxを引数に取る例
local net = new NetBox()
local json = new JSONBox()
json.set("url", "https://api.example.com")
net.post(json) // JSONBoxを引数として渡す
💡 重要なポイント
1. ハンドルによる間接参照
- 箱の実体は渡さない(メモリ安全性)
(type_id, instance_id)のペアで識別- プラグイン側でハンドルから実体にアクセス
2. 型安全性
type_idで型を識別可能- 不正な型の場合はエラー返却
3. 所有権管理
- インスタンスIDで参照管理
- プラグイン間でも安全に共有
🎯 結論
C ABIの制約があっても、ハンドル機構により箱は箱を引数に取れる!
これは既に実装済みの機能であり、プラグイン間での高度な連携が可能です。
埋め込みVMへの示唆
既存のTLVハンドル機構をそのまま使えば、埋め込みVMでも同じように箱引数をサポートできます:
- Nyashスクリプト内で箱を引数に使用
- MIRバイトコードにBoxCall命令を含める
- 埋め込みVMがTLVエンコードでC ABIプラグインを呼び出し
- ハンドル経由で箱を渡す
Everything is Box、そしてC ABIでも箱は箱を扱える!