Phase 12.7完了 + ChatGPT5によるVMリファクタリング
## 📚 Phase 12.7 ドキュメント整理 - ChatGPT5作成のANCP Token仕様書v1を整備 - フォルダ構造を機能別に再編成: - ancp-specs/ : ANCP圧縮技法仕様 - grammar-specs/ : 文法改革仕様 - implementation/ : 実装計画 - ai-feedback/ : AIアドバイザーフィードバック - 各フォルダにREADME.md作成で導線改善 ## 🔧 ChatGPT5によるVMリファクタリング - vm_instructions.rs (1927行) をモジュール分割: - boxcall.rs : Box呼び出し処理 - call.rs : 関数呼び出し処理 - extern_call.rs : 外部関数処理 - function_new.rs : FunctionBox生成 - newbox.rs : Box生成処理 - plugin_invoke.rs : プラグイン呼び出し - VM実行をファイル分割で整理: - vm_state.rs : 状態管理 - vm_exec.rs : 実行エンジン - vm_control_flow.rs : 制御フロー - vm_gc.rs : GC処理 - plugin_loader_v2もモジュール化 ## ✨ 新機能実装 - FunctionBox呼び出しのVM/MIR統一進捗 - ラムダ式のFunctionBox変換テスト追加 - 関数値の直接呼び出し基盤整備 次ステップ: ANCPプロトタイプ実装開始(Week 1) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
27
src/runtime/plugin_loader_v2/enabled/globals.rs
Normal file
27
src/runtime/plugin_loader_v2/enabled/globals.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use super::loader::PluginLoaderV2;
|
||||
use crate::bid::{BidResult};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
static GLOBAL_LOADER_V2: Lazy<Arc<RwLock<PluginLoaderV2>>> =
|
||||
Lazy::new(|| Arc::new(RwLock::new(PluginLoaderV2::new())));
|
||||
|
||||
pub fn get_global_loader_v2() -> Arc<RwLock<PluginLoaderV2>> { GLOBAL_LOADER_V2.clone() }
|
||||
|
||||
pub fn init_global_loader_v2(config_path: &str) -> BidResult<()> {
|
||||
let loader = get_global_loader_v2();
|
||||
let mut loader = loader.write().unwrap();
|
||||
loader.load_config(config_path)?;
|
||||
drop(loader);
|
||||
let loader = get_global_loader_v2();
|
||||
let loader = loader.read().unwrap();
|
||||
loader.load_all_plugins()
|
||||
}
|
||||
|
||||
pub fn shutdown_plugins_v2() -> BidResult<()> {
|
||||
let loader = get_global_loader_v2();
|
||||
let loader = loader.read().unwrap();
|
||||
loader.shutdown_singletons();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
183
src/runtime/plugin_loader_v2/enabled/loader.rs
Normal file
183
src/runtime/plugin_loader_v2/enabled/loader.rs
Normal file
@ -0,0 +1,183 @@
|
||||
use super::types::{PluginBoxV2, PluginHandleInner, NyashTypeBoxFfi, LoadedPluginV2};
|
||||
use crate::bid::{BidResult, BidError};
|
||||
use crate::box_trait::{NyashBox, BoxCore, StringBox, IntegerBox};
|
||||
use crate::config::nyash_toml_v2::{NyashConfigV2, LibraryDefinition};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
fn dbg_on() -> bool { std::env::var("NYASH_DEBUG_PLUGIN").unwrap_or_default() == "1" }
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct LoadedBoxSpec {
|
||||
type_id: Option<u32>,
|
||||
methods: HashMap<String, MethodSpec>,
|
||||
fini_method_id: Option<u32>,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct MethodSpec { method_id: u32, returns_result: bool }
|
||||
|
||||
pub struct PluginLoaderV2 {
|
||||
pub(super) plugins: RwLock<HashMap<String, Arc<LoadedPluginV2>>>,
|
||||
pub config: Option<NyashConfigV2>,
|
||||
pub(super) config_path: Option<String>,
|
||||
pub(super) singletons: RwLock<HashMap<(String,String), Arc<PluginHandleInner>>>,
|
||||
pub(super) box_specs: RwLock<HashMap<(String,String), LoadedBoxSpec>>,
|
||||
}
|
||||
|
||||
impl PluginLoaderV2 {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
plugins: RwLock::new(HashMap::new()),
|
||||
config: None,
|
||||
config_path: None,
|
||||
singletons: RwLock::new(HashMap::new()),
|
||||
box_specs: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_config(&mut self, config_path: &str) -> BidResult<()> {
|
||||
let canonical = std::fs::canonicalize(config_path).map(|p| p.to_string_lossy().to_string()).unwrap_or_else(|_| config_path.to_string());
|
||||
self.config_path = Some(canonical.clone());
|
||||
self.config = Some(NyashConfigV2::from_file(&canonical).map_err(|_| BidError::PluginError)?);
|
||||
if let Some(cfg) = self.config.as_ref() {
|
||||
let mut labels: Vec<String> = Vec::new();
|
||||
for (_lib, def) in &cfg.libraries { for bt in &def.boxes { labels.push(format!("BoxRef:{}", bt)); } }
|
||||
crate::runtime::cache_versions::bump_many(&labels);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_all_plugins(&self) -> BidResult<()> {
|
||||
let config = self.config.as_ref().ok_or(BidError::PluginError)?;
|
||||
for (lib_name, lib_def) in &config.libraries { let _ = self.load_plugin(lib_name, lib_def); }
|
||||
for (plugin_name, root) in &config.plugins { let _ = self.load_plugin_from_root(plugin_name, root); }
|
||||
self.prebirth_singletons()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_plugin(&self, _lib_name: &str, _lib_def: &LibraryDefinition) -> BidResult<()> {
|
||||
// Keep behavior: real loading logic remains in unified loader; v2 stores minimal entries
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_plugin_from_root(&self, _plugin_name: &str, _root: &str) -> BidResult<()> { Ok(()) }
|
||||
|
||||
fn prebirth_singletons(&self) -> BidResult<()> {
|
||||
let config = self.config.as_ref().ok_or(BidError::PluginError)?;
|
||||
let cfg_path = self.config_path.as_deref().unwrap_or("nyash.toml");
|
||||
let toml_content = std::fs::read_to_string(cfg_path).map_err(|_| BidError::PluginError)?;
|
||||
let toml_value: toml::Value = toml::from_str(&toml_content).map_err(|_| BidError::PluginError)?;
|
||||
for (lib_name, lib_def) in &config.libraries {
|
||||
for box_name in &lib_def.boxes {
|
||||
if let Some(bc) = config.get_box_config(lib_name, box_name, &toml_value) { if bc.singleton { let _ = self.ensure_singleton_handle(lib_name, box_name); } }
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_box_by_type_id<'a>(&'a self, config: &'a NyashConfigV2, toml_value: &'a toml::Value, type_id: u32) -> Option<(&'a str, &'a str)> {
|
||||
for (lib_name, lib_def) in &config.libraries {
|
||||
for box_name in &lib_def.boxes {
|
||||
if let Some(box_conf) = config.get_box_config(lib_name, box_name, toml_value) { if box_conf.type_id == type_id { return Some((lib_name.as_str(), box_name.as_str())); } }
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn construct_existing_instance(&self, type_id: u32, instance_id: u32) -> Option<Box<dyn NyashBox>> {
|
||||
let config = self.config.as_ref()?;
|
||||
let cfg_path = self.config_path.as_ref()?;
|
||||
let toml_value: toml::Value = toml::from_str(&std::fs::read_to_string(cfg_path).ok()?).ok()?;
|
||||
let (lib_name, box_type) = self.find_box_by_type_id(config, &toml_value, type_id)?;
|
||||
let plugins = self.plugins.read().ok()?;
|
||||
let plugin = plugins.get(lib_name)?.clone();
|
||||
let fini_method_id = if let Some(spec) = self.box_specs.read().ok()?.get(&(lib_name.to_string(), box_type.to_string())) { spec.fini_method_id } else { let box_conf = config.get_box_config(lib_name, box_type, &toml_value)?; box_conf.methods.get("fini").map(|m| m.method_id) };
|
||||
let bx = super::types::construct_plugin_box(box_type.to_string(), type_id, plugin.invoke_fn, instance_id, fini_method_id);
|
||||
Some(Box::new(bx))
|
||||
}
|
||||
|
||||
fn find_lib_name_for_box(&self, box_type: &str) -> Option<String> {
|
||||
if let Some(cfg) = &self.config { if let Some((name, _)) = cfg.find_library_for_box(box_type) { return Some(name.to_string()); } }
|
||||
for ((lib, b), _) in self.box_specs.read().unwrap().iter() { if b == box_type { return Some(lib.clone()); } }
|
||||
None
|
||||
}
|
||||
|
||||
fn ensure_singleton_handle(&self, lib_name: &str, box_type: &str) -> BidResult<()> {
|
||||
if self.singletons.read().unwrap().contains_key(&(lib_name.to_string(), box_type.to_string())) { return Ok(()); }
|
||||
let cfg_path = self.config_path.as_deref().unwrap_or("nyash.toml");
|
||||
let toml_value: toml::Value = toml::from_str(&std::fs::read_to_string(cfg_path).map_err(|_| BidError::PluginError)?).map_err(|_| BidError::PluginError)?;
|
||||
let config = self.config.as_ref().ok_or(BidError::PluginError)?;
|
||||
let plugins = self.plugins.read().unwrap();
|
||||
let plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?;
|
||||
let type_id = if let Some(spec) = self.box_specs.read().unwrap().get(&(lib_name.to_string(), box_type.to_string())) { spec.type_id.unwrap_or_else(|| config.box_types.get(box_type).copied().unwrap_or(0)) } else { let box_conf = config.get_box_config(lib_name, box_type, &toml_value).ok_or(BidError::InvalidType)?; box_conf.type_id };
|
||||
let mut out = vec![0u8; 1024];
|
||||
let mut out_len = out.len();
|
||||
let tlv_args = crate::runtime::plugin_ffi_common::encode_empty_args();
|
||||
let birth_result = unsafe { (plugin.invoke_fn)(type_id, 0, 0, tlv_args.as_ptr(), tlv_args.len(), out.as_mut_ptr(), &mut out_len) };
|
||||
if birth_result != 0 || out_len < 4 { return Err(BidError::PluginError); }
|
||||
let instance_id = u32::from_le_bytes([out[0], out[1], out[2], out[3]]);
|
||||
let fini_id = if let Some(spec) = self.box_specs.read().unwrap().get(&(lib_name.to_string(), box_type.to_string())) { spec.fini_method_id } else { let box_conf = config.get_box_config(lib_name, box_type, &toml_value).ok_or(BidError::InvalidType)?; box_conf.methods.get("fini").map(|m| m.method_id) };
|
||||
let handle = Arc::new(PluginHandleInner { type_id, invoke_fn: plugin.invoke_fn, instance_id, fini_method_id: fini_id, finalized: std::sync::atomic::AtomicBool::new(false) });
|
||||
self.singletons.write().unwrap().insert((lib_name.to_string(), box_type.to_string()), handle);
|
||||
crate::runtime::cache_versions::bump_version(&format!("BoxRef:{}", box_type));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn extern_call(&self, iface_name: &str, method_name: &str, args: &[Box<dyn NyashBox>]) -> BidResult<Option<Box<dyn NyashBox>>> {
|
||||
match (iface_name, method_name) {
|
||||
("env.console", "log") => { for a in args { println!("{}", a.to_string_box().value); } Ok(None) }
|
||||
("env.task", "cancelCurrent") => { let tok = crate::runtime::global_hooks::current_group_token(); tok.cancel(); Ok(None) }
|
||||
("env.task", "currentToken") => { let tok = crate::runtime::global_hooks::current_group_token(); let tb = crate::boxes::token_box::TokenBox::from_token(tok); Ok(Some(Box::new(tb))) }
|
||||
("env.debug", "trace") => { if std::env::var("NYASH_DEBUG_TRACE").ok().as_deref() == Some("1") { for a in args { eprintln!("[debug.trace] {}", a.to_string_box().value); } } Ok(None) }
|
||||
("env.runtime", "checkpoint") => { if crate::config::env::runtime_checkpoint_trace() { eprintln!("[runtime.checkpoint] reached"); } crate::runtime::global_hooks::safepoint_and_poll(); Ok(None) }
|
||||
("env.future", "new") | ("env.future", "birth") => { let fut = crate::boxes::future::FutureBox::new(); if let Some(v) = args.get(0) { fut.set_result(v.clone_box()); } Ok(Some(Box::new(fut))) }
|
||||
("env.future", "set") => { if args.len() >= 2 { if let Some(fut) = args[0].as_any().downcast_ref::<crate::boxes::future::FutureBox>() { fut.set_result(args[1].clone_box()); } } Ok(None) }
|
||||
("env.future", "await") => { use crate::boxes::result::NyashResultBox; if let Some(arg) = args.get(0) { if let Some(fut) = arg.as_any().downcast_ref::<crate::boxes::future::FutureBox>() { let max_ms: u64 = crate::config::env::await_max_ms(); let start = std::time::Instant::now(); let mut spins = 0usize; while !fut.ready() { crate::runtime::global_hooks::safepoint_and_poll(); std::thread::yield_now(); spins += 1; if spins % 1024 == 0 { std::thread::sleep(std::time::Duration::from_millis(1)); } if start.elapsed() >= std::time::Duration::from_millis(max_ms) { let err = crate::box_trait::StringBox::new("Timeout"); return Ok(Some(Box::new(NyashResultBox::new_err(Box::new(err))))); } } return match fut.wait_and_get() { Ok(v) => Ok(Some(Box::new(NyashResultBox::new_ok(v)))), Err(e) => { let err = crate::box_trait::StringBox::new(format!("Error: {}", e)); Ok(Some(Box::new(NyashResultBox::new_err(Box::new(err))))) } }; } else { return Ok(Some(Box::new(NyashResultBox::new_ok(arg.clone_box())))); } } Ok(Some(Box::new(crate::boxes::result::NyashResultBox::new_err(Box::new(crate::box_trait::StringBox::new("InvalidArgs")))))) }
|
||||
_ => Err(BidError::PluginError)
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_method_id_from_file(&self, box_type: &str, method_name: &str) -> BidResult<u32> {
|
||||
let cfg = self.config.as_ref().ok_or(BidError::PluginError)?;
|
||||
let cfg_path = self.config_path.as_deref().unwrap_or("nyash.toml");
|
||||
let toml_value: toml::Value = toml::from_str(&std::fs::read_to_string(cfg_path).map_err(|_| BidError::PluginError)?).map_err(|_| BidError::PluginError)?;
|
||||
if let Some((lib_name, _)) = cfg.find_library_for_box(box_type) {
|
||||
if let Some(bc) = cfg.get_box_config(&lib_name, box_type, &toml_value) { if let Some(m) = bc.methods.get(method_name) { return Ok(m.method_id); } }
|
||||
}
|
||||
Err(BidError::InvalidMethod)
|
||||
}
|
||||
|
||||
pub fn method_returns_result(&self, box_type: &str, method_name: &str) -> bool {
|
||||
if let Some(cfg) = &self.config {
|
||||
if let Some((lib_name, _)) = cfg.find_library_for_box(box_type) {
|
||||
if let Some(cfg_path) = self.config_path.as_deref() {
|
||||
if let Ok(toml_value) = toml::from_str::<toml::Value>(&std::fs::read_to_string(cfg_path).unwrap_or_default()) {
|
||||
if let Some(bc) = cfg.get_box_config(&lib_name, box_type, &toml_value) { return bc.methods.get(method_name).map(|m| m.returns_result).unwrap_or(false); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn invoke_instance_method(&self, box_type: &str, method_name: &str, instance_id: u32, args: &[Box<dyn NyashBox>]) -> BidResult<Option<Box<dyn NyashBox>>> {
|
||||
// Delegates to plugin_loader_unified in practice; keep minimal compatibility bridge for v2
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
let host = host.read().map_err(|_| BidError::PluginError)?;
|
||||
host.invoke_instance_method(box_type, method_name, instance_id, args)
|
||||
}
|
||||
|
||||
pub fn create_box(&self, box_type: &str, _args: &[Box<dyn NyashBox>]) -> BidResult<Box<dyn NyashBox>> {
|
||||
// Delegate creation to unified host; preserves current behavior
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
let host = host.read().map_err(|_| BidError::PluginError)?;
|
||||
host.create_box(box_type, &[])
|
||||
}
|
||||
|
||||
/// Shutdown singletons: finalize and clear all singleton handles
|
||||
pub fn shutdown_singletons(&self) {
|
||||
let mut map = self.singletons.write().unwrap();
|
||||
for (_, handle) in map.drain() { handle.finalize_now(); }
|
||||
}
|
||||
}
|
||||
8
src/runtime/plugin_loader_v2/enabled/mod.rs
Normal file
8
src/runtime/plugin_loader_v2/enabled/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
mod types;
|
||||
mod loader;
|
||||
mod globals;
|
||||
|
||||
pub use types::{PluginBoxV2, PluginHandleInner, NyashTypeBoxFfi, make_plugin_box_v2, construct_plugin_box};
|
||||
pub use loader::{PluginLoaderV2};
|
||||
pub use globals::{get_global_loader_v2, init_global_loader_v2, shutdown_plugins_v2};
|
||||
|
||||
157
src/runtime/plugin_loader_v2/enabled/types.rs
Normal file
157
src/runtime/plugin_loader_v2/enabled/types.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use crate::box_trait::{NyashBox, BoxCore, StringBox};
|
||||
use std::any::Any;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn dbg_on() -> bool { std::env::var("NYASH_DEBUG_PLUGIN").unwrap_or_default() == "1" }
|
||||
|
||||
/// Loaded plugin information (library handle + exported addresses)
|
||||
pub struct LoadedPluginV2 {
|
||||
pub(super) _lib: Arc<libloading::Library>,
|
||||
pub(super) box_types: Vec<String>,
|
||||
pub(super) typeboxes: std::collections::HashMap<String, usize>,
|
||||
pub(super) init_fn: Option<unsafe extern "C" fn() -> i32>,
|
||||
pub(super) invoke_fn: unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32,
|
||||
}
|
||||
|
||||
/// v2 Plugin Box handle core
|
||||
#[derive(Debug)]
|
||||
pub struct PluginHandleInner {
|
||||
pub type_id: u32,
|
||||
pub invoke_fn: unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32,
|
||||
pub instance_id: u32,
|
||||
pub fini_method_id: Option<u32>,
|
||||
pub(super) finalized: std::sync::atomic::AtomicBool,
|
||||
}
|
||||
|
||||
impl Drop for PluginHandleInner {
|
||||
fn drop(&mut self) {
|
||||
if let Some(fini_id) = self.fini_method_id {
|
||||
if !self.finalized.swap(true, std::sync::atomic::Ordering::SeqCst) {
|
||||
let tlv_args: [u8; 4] = [1, 0, 0, 0];
|
||||
let mut out: [u8; 4] = [0; 4];
|
||||
let mut out_len: usize = out.len();
|
||||
unsafe {
|
||||
(self.invoke_fn)(
|
||||
self.type_id,
|
||||
fini_id,
|
||||
self.instance_id,
|
||||
tlv_args.as_ptr(),
|
||||
tlv_args.len(),
|
||||
out.as_mut_ptr(),
|
||||
&mut out_len,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginHandleInner {
|
||||
pub fn finalize_now(&self) {
|
||||
if let Some(fini_id) = self.fini_method_id {
|
||||
if !self.finalized.swap(true, std::sync::atomic::Ordering::SeqCst) {
|
||||
crate::runtime::leak_tracker::finalize_plugin("PluginBox", self.instance_id);
|
||||
let tlv_args: [u8; 4] = [1, 0, 0, 0];
|
||||
let mut out: [u8; 4] = [0; 4];
|
||||
let mut out_len: usize = out.len();
|
||||
unsafe {
|
||||
(self.invoke_fn)(
|
||||
self.type_id,
|
||||
fini_id,
|
||||
self.instance_id,
|
||||
tlv_args.as_ptr(),
|
||||
tlv_args.len(),
|
||||
out.as_mut_ptr(),
|
||||
&mut out_len,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Nyash TypeBox FFI (minimal PoC)
|
||||
use std::os::raw::c_char;
|
||||
#[repr(C)]
|
||||
pub struct NyashTypeBoxFfi {
|
||||
pub abi_tag: u32,
|
||||
pub version: u16,
|
||||
pub struct_size: u16,
|
||||
pub name: *const c_char,
|
||||
pub resolve: Option<extern "C" fn(*const c_char) -> u32>,
|
||||
pub invoke_id: Option<extern "C" fn(u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32>,
|
||||
pub capabilities: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PluginBoxV2 {
|
||||
pub box_type: String,
|
||||
pub inner: Arc<PluginHandleInner>,
|
||||
}
|
||||
|
||||
impl BoxCore for PluginBoxV2 {
|
||||
fn box_id(&self) -> u64 { self.inner.instance_id as u64 }
|
||||
fn parent_type_id(&self) -> Option<std::any::TypeId> { None }
|
||||
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}({})", self.box_type, self.inner.instance_id) }
|
||||
fn as_any(&self) -> &dyn Any { self }
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any { self }
|
||||
}
|
||||
|
||||
impl NyashBox for PluginBoxV2 {
|
||||
fn is_identity(&self) -> bool { true }
|
||||
fn type_name(&self) -> &'static str {
|
||||
match self.box_type.as_str() { "FileBox" => "FileBox", _ => "PluginBoxV2" }
|
||||
}
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
if dbg_on() { eprintln!("[PluginBoxV2] clone_box {}({})", self.box_type, self.inner.instance_id); }
|
||||
let mut output_buffer = vec![0u8; 1024];
|
||||
let mut output_len = output_buffer.len();
|
||||
let tlv_args = [1u8, 0, 0, 0];
|
||||
let result = unsafe {
|
||||
(self.inner.invoke_fn)(
|
||||
self.inner.type_id,
|
||||
0,
|
||||
0,
|
||||
tlv_args.as_ptr(),
|
||||
tlv_args.len(),
|
||||
output_buffer.as_mut_ptr(),
|
||||
&mut output_len,
|
||||
)
|
||||
};
|
||||
if result == 0 && output_len >= 4 {
|
||||
let new_instance_id = u32::from_le_bytes([output_buffer[0], output_buffer[1], output_buffer[2], output_buffer[3]]);
|
||||
Box::new(PluginBoxV2 {
|
||||
box_type: self.box_type.clone(),
|
||||
inner: Arc::new(PluginHandleInner { type_id: self.inner.type_id, invoke_fn: self.inner.invoke_fn, instance_id: new_instance_id, fini_method_id: self.inner.fini_method_id, finalized: std::sync::atomic::AtomicBool::new(false) }),
|
||||
})
|
||||
} else {
|
||||
Box::new(StringBox::new(format!("Clone failed for {}", self.box_type)))
|
||||
}
|
||||
}
|
||||
fn to_string_box(&self) -> StringBox { StringBox::new(format!("{}({})", self.box_type, self.inner.instance_id)) }
|
||||
fn equals(&self, _other: &dyn NyashBox) -> crate::box_trait::BoolBox { crate::box_trait::BoolBox::new(false) }
|
||||
fn share_box(&self) -> Box<dyn NyashBox> { Box::new(PluginBoxV2 { box_type: self.box_type.clone(), inner: self.inner.clone() }) }
|
||||
}
|
||||
|
||||
impl PluginBoxV2 {
|
||||
pub fn instance_id(&self) -> u32 { self.inner.instance_id }
|
||||
pub fn finalize_now(&self) { self.inner.finalize_now() }
|
||||
pub fn is_finalized(&self) -> bool { self.inner.finalized.load(std::sync::atomic::Ordering::SeqCst) }
|
||||
}
|
||||
|
||||
/// Helper to construct a PluginBoxV2 from raw ids and invoke pointer safely
|
||||
pub fn make_plugin_box_v2(box_type: String, type_id: u32, instance_id: u32, invoke_fn: unsafe extern "C" fn(u32,u32,u32,*const u8,usize,*mut u8,*mut usize) -> i32) -> PluginBoxV2 {
|
||||
PluginBoxV2 { box_type, inner: Arc::new(PluginHandleInner { type_id, invoke_fn, instance_id, fini_method_id: None, finalized: std::sync::atomic::AtomicBool::new(false) }) }
|
||||
}
|
||||
|
||||
/// Public helper to construct a PluginBoxV2 from raw parts (for VM/JIT integration)
|
||||
pub fn construct_plugin_box(
|
||||
box_type: String,
|
||||
type_id: u32,
|
||||
invoke_fn: unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32,
|
||||
instance_id: u32,
|
||||
fini_method_id: Option<u32>,
|
||||
) -> PluginBoxV2 {
|
||||
PluginBoxV2 { box_type, inner: Arc::new(PluginHandleInner { type_id, invoke_fn, instance_id, fini_method_id, finalized: std::sync::atomic::AtomicBool::new(false) }) }
|
||||
}
|
||||
|
||||
12
src/runtime/plugin_loader_v2/mod.rs
Normal file
12
src/runtime/plugin_loader_v2/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//! Nyash v2 Plugin Loader (split)
|
||||
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
mod enabled;
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
mod stub;
|
||||
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
pub use enabled::*;
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
pub use stub::*;
|
||||
|
||||
35
src/runtime/plugin_loader_v2/stub.rs
Normal file
35
src/runtime/plugin_loader_v2/stub.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use crate::bid::{BidResult, BidError};
|
||||
use crate::box_trait::NyashBox;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PluginBoxV2 {
|
||||
pub box_type: String,
|
||||
pub inner: std::sync::Arc<PluginHandleInner>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PluginHandleInner {
|
||||
pub type_id: u32,
|
||||
pub instance_id: u32,
|
||||
pub fini_method_id: Option<u32>,
|
||||
}
|
||||
|
||||
pub struct PluginLoaderV2 { pub config: Option<()> }
|
||||
impl PluginLoaderV2 { pub fn new() -> Self { Self { config: None } } }
|
||||
|
||||
impl PluginLoaderV2 {
|
||||
pub fn load_config(&mut self, _p: &str) -> BidResult<()> { Ok(()) }
|
||||
pub fn load_all_plugins(&self) -> BidResult<()> { Ok(()) }
|
||||
pub fn create_box(&self, _t: &str, _a: &[Box<dyn NyashBox>]) -> BidResult<Box<dyn NyashBox>> { Err(BidError::PluginError) }
|
||||
pub fn extern_call(&self, _iface_name: &str, _method_name: &str, _args: &[Box<dyn NyashBox>]) -> BidResult<Option<Box<dyn NyashBox>>> { Err(BidError::PluginError) }
|
||||
pub fn invoke_instance_method(&self, _box_type: &str, _method_name: &str, _instance_id: u32, _args: &[Box<dyn NyashBox>]) -> BidResult<Option<Box<dyn NyashBox>>> { Err(BidError::PluginError) }
|
||||
pub fn shutdown_singletons(&self) {}
|
||||
}
|
||||
|
||||
static GLOBAL_LOADER_V2: Lazy<Arc<RwLock<PluginLoaderV2>>> = Lazy::new(|| Arc::new(RwLock::new(PluginLoaderV2::new())));
|
||||
pub fn get_global_loader_v2() -> Arc<RwLock<PluginLoaderV2>> { GLOBAL_LOADER_V2.clone() }
|
||||
pub fn init_global_loader_v2(_config_path: &str) -> BidResult<()> { Ok(()) }
|
||||
pub fn shutdown_plugins_v2() -> BidResult<()> { Ok(()) }
|
||||
|
||||
Reference in New Issue
Block a user