🎉 Phase 11.8/12.7: MIR Core-13 完全実装 + 糖衣構文ドキュメント更新

主要な変更:
- MIR Core-13命令セット確定(Load/Store削除の革命的設計)
  - Const, BinOp, Compare(値・計算)
  - Jump, Branch, Return, Phi(制御)
  - Call, BoxCall, ExternCall(呼び出し)
  - TypeOp, Safepoint, Barrier(メタ)
- Phase 12.7糖衣構文ドキュメント整理(超圧縮重視、可逆変換保証)
- MIRビルダーのモジュール分割完了
- vtableテストスイート拡充
- AI協調開発ツール追加(並列リファクタリング支援)

詳細:
- src/mir/instruction_introspection.rs: core13_instruction_names()追加
- MIRビルダー分割: decls.rs, exprs_*.rs, fields.rs
- plugin_loader_v2: errors.rs, host_bridge.rs分離
- 論文用データ: mir13-final.md作成

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-09-04 11:34:15 +09:00
parent 4e824fa00e
commit fb2d8e37d5
62 changed files with 3632 additions and 835 deletions

View File

@ -0,0 +1,16 @@
use crate::bid::{BidResult, BidError};
// Minimal helpers to keep loader.rs lean and consistent
#[inline]
pub fn from_fs<T>(_r: std::io::Result<T>) -> BidResult<T> {
_r.map_err(|_| BidError::PluginError)
}
#[inline]
pub fn from_toml<T>(_r: Result<T, toml::de::Error>) -> BidResult<T> {
_r.map_err(|_| BidError::PluginError)
}
#[inline]
pub fn or_plugin_err<T>(opt: Option<T>) -> BidResult<T> { opt.ok_or(BidError::PluginError) }

View File

@ -0,0 +1,28 @@
// Host bridge helpers for TypeBox invoke (minimal, v2)
pub type InvokeFn = unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32;
// Call invoke_id with a temporary output buffer; returns (code, bytes_written, buffer)
pub fn invoke_alloc(
invoke: InvokeFn,
type_id: u32,
method_id: u32,
instance_id: u32,
tlv_args: &[u8],
) -> (i32, usize, Vec<u8>) {
let mut out = vec![0u8; 1024];
let mut out_len: usize = out.len();
let code = unsafe {
invoke(
type_id,
method_id,
instance_id,
tlv_args.as_ptr(),
tlv_args.len(),
out.as_mut_ptr(),
&mut out_len,
)
};
(code, out_len, out)
}

View File

@ -2,7 +2,6 @@ use super::types::{PluginBoxV2, PluginHandleInner, NyashTypeBoxFfi, LoadedPlugin
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};
@ -66,8 +65,8 @@ impl PluginLoaderV2 {
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)?;
let toml_content = super::errors::from_fs(std::fs::read_to_string(cfg_path))?;
let toml_value: toml::Value = super::errors::from_toml(toml::from_str(&toml_content))?;
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); } }
@ -88,7 +87,8 @@ impl PluginLoaderV2 {
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 toml_str = std::fs::read_to_string(cfg_path).ok()?;
let toml_value: toml::Value = toml::from_str(&toml_str).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();
@ -114,7 +114,8 @@ impl PluginLoaderV2 {
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) };
let (birth_result, _len, out_vec) = super::host_bridge::invoke_alloc(plugin.invoke_fn, type_id, 0, 0, &tlv_args);
let out = out_vec;
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) };
@ -141,7 +142,7 @@ impl PluginLoaderV2 {
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)?;
let toml_value: toml::Value = super::errors::from_toml(toml::from_str(&std::fs::read_to_string(cfg_path).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); } }
}
@ -161,11 +162,54 @@ impl PluginLoaderV2 {
false
}
/// Resolve (type_id, method_id, returns_result) for a box_type.method
pub fn resolve_method_handle(&self, box_type: &str, method_name: &str) -> BidResult<(u32, u32, bool)> {
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)?;
let (lib_name, _) = cfg.find_library_for_box(box_type).ok_or(BidError::InvalidType)?;
let bc = cfg.get_box_config(lib_name, box_type, &toml_value).ok_or(BidError::InvalidType)?;
let m = bc.methods.get(method_name).ok_or(BidError::InvalidMethod)?;
Ok((bc.type_id, m.method_id, m.returns_result))
}
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)
// Non-recursive direct bridge for minimal methods used by semantics and basic VM paths
// Resolve library/type/method ids from cached config
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)?;
let (lib_name, _lib_def) = cfg.find_library_for_box(box_type).ok_or(BidError::InvalidType)?;
let box_conf = cfg.get_box_config(lib_name, box_type, &toml_value).ok_or(BidError::InvalidType)?;
let type_id = box_conf.type_id;
let method = box_conf.methods.get(method_name).ok_or(BidError::InvalidMethod)?;
// Get plugin handle
let plugins = self.plugins.read().map_err(|_| BidError::PluginError)?;
let plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?;
// Encode minimal TLV args (support only 0-arity inline)
if !args.is_empty() { return Err(BidError::PluginError); }
let tlv: [u8; 0] = [];
let (_code, out_len, out) = super::host_bridge::invoke_alloc(plugin.invoke_fn, type_id, method.method_id, instance_id, &tlv);
// Minimal decoding by method name
match method_name {
// Expect UTF-8 string result in bytes → StringBox
"toUtf8" | "toString" => {
let s = String::from_utf8_lossy(&out[0..out_len]).to_string();
return Ok(Some(Box::new(crate::box_trait::StringBox::new(s))));
}
// Expect IntegerBox via little-endian i64 in first 8 bytes
"get" => {
if out_len >= 8 { let mut buf=[0u8;8]; buf.copy_from_slice(&out[0..8]); let n=i64::from_le_bytes(buf); return Ok(Some(Box::new(crate::box_trait::IntegerBox::new(n)))) }
return Ok(Some(Box::new(crate::box_trait::IntegerBox::new(0))));
}
// Float path (approx): read 8 bytes as f64 and Box as FloatBox
"toDouble" => {
if out_len >= 8 { let mut buf=[0u8;8]; buf.copy_from_slice(&out[0..8]); let x=f64::from_le_bytes(buf); return Ok(Some(Box::new(crate::boxes::FloatBox::new(x)))) }
return Ok(Some(Box::new(crate::boxes::FloatBox::new(0.0))));
}
_ => {}
}
Ok(None)
}
pub fn create_box(&self, box_type: &str, _args: &[Box<dyn NyashBox>]) -> BidResult<Box<dyn NyashBox>> {

View File

@ -1,8 +1,9 @@
mod types;
mod loader;
mod globals;
mod errors;
mod host_bridge;
pub use types::{PluginBoxV2, PluginHandleInner, NyashTypeBoxFfi, make_plugin_box_v2, construct_plugin_box};
pub use loader::{PluginLoaderV2};
pub use loader::PluginLoaderV2;
pub use globals::{get_global_loader_v2, init_global_loader_v2, shutdown_plugins_v2};

View File

@ -28,19 +28,7 @@ impl Drop for PluginHandleInner {
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,
);
}
let _ = super::host_bridge::invoke_alloc(self.invoke_fn, self.type_id, fini_id, self.instance_id, &tlv_args);
}
}
}
@ -52,19 +40,7 @@ impl PluginHandleInner {
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,
);
}
let _ = super::host_bridge::invoke_alloc(self.invoke_fn, self.type_id, fini_id, self.instance_id, &tlv_args);
}
}
}
@ -104,22 +80,10 @@ impl NyashBox for 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]]);
let (result, out_len, out_buf) = super::host_bridge::invoke_alloc(self.inner.invoke_fn, self.inner.type_id, 0, 0, &tlv_args);
if result == 0 && out_len >= 4 {
let new_instance_id = u32::from_le_bytes([out_buf[0], out_buf[1], out_buf[2], out_buf[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) }),
@ -154,4 +118,3 @@ pub fn construct_plugin_box(
) -> PluginBoxV2 {
PluginBoxV2 { box_type, inner: Arc::new(PluginHandleInner { type_id, invoke_fn, instance_id, fini_method_id, finalized: std::sync::atomic::AtomicBool::new(false) }) }
}