Phase 6 WIP: Type conversion helpers (11 sites, 23 lines)

Added conversion_helpers.rs with unified type conversion:
- load_as_box() for reg_load().to_nyash_box()
- load_as_string() for reg_load().to_string()
- load_as_int/bool() for type-checked loads
- load_args_as_boxes/values() for bulk conversion

Files updated (partial):
- boxes.rs: 2 sites (-6 lines)
- calls.rs: 5 sites (-10 lines)
- boxes_plugin.rs: 1 site (-3 lines)
- externals.rs: 3 sites (-4 lines)

Next: boxes_array, boxes_map, boxes_object_fields, boxes_instance

Tests: Phase 21.0 PASS (2/2, 100%)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-07 00:21:42 +09:00
parent 2429627d04
commit 8488df58a8
6 changed files with 137 additions and 27 deletions

View File

@ -13,10 +13,7 @@ impl MirInterpreter {
if let Err(e) = crate::runtime::provider_lock::guard_before_new_box(box_type) { if let Err(e) = crate::runtime::provider_lock::guard_before_new_box(box_type) {
return Err(self.err_invalid(e)); return Err(self.err_invalid(e));
} }
let mut converted: Vec<Box<dyn NyashBox>> = Vec::with_capacity(args.len()); let converted = self.load_args_as_boxes(args)?;
for vid in args {
converted.push(self.reg_load(*vid)?.to_nyash_box());
}
let reg = crate::runtime::unified_registry::get_global_unified_registry(); let reg = crate::runtime::unified_registry::get_global_unified_registry();
let created = reg let created = reg
.lock() .lock()
@ -56,10 +53,7 @@ impl MirInterpreter {
{ {
let host = crate::runtime::plugin_loader_unified::get_global_plugin_host(); let host = crate::runtime::plugin_loader_unified::get_global_plugin_host();
let host = host.read().unwrap(); let host = host.read().unwrap();
let mut argv: Vec<Box<dyn NyashBox>> = Vec::with_capacity(args.len()); let argv = self.load_args_as_boxes(args)?;
for a in args {
argv.push(self.reg_load(*a)?.to_nyash_box());
}
match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) { match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) {
Ok(Some(ret)) => { Ok(Some(ret)) => {
self.write_from_box(dst, ret); self.write_from_box(dst, ret);

View File

@ -41,10 +41,7 @@ pub(super) fn invoke_plugin_box(
} }
let host = crate::runtime::plugin_loader_unified::get_global_plugin_host(); let host = crate::runtime::plugin_loader_unified::get_global_plugin_host();
let host = host.read().unwrap(); let host = host.read().unwrap();
let mut argv: Vec<Box<dyn NyashBox>> = Vec::with_capacity(args.len()); let argv = this.load_args_as_boxes(args)?;
for a in args {
argv.push(this.reg_load(*a)?.to_nyash_box());
}
match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) { match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) {
Ok(Some(ret)) => { Ok(Some(ret)) => {
this.write_from_box(dst, ret); this.write_from_box(dst, ret);

View File

@ -74,7 +74,7 @@ impl MirInterpreter {
"birth" => { return Ok(VMValue::Void); } "birth" => { return Ok(VMValue::Void); }
"push" => { "push" => {
if let Some(a0) = args.get(0) { if let Some(a0) = args.get(0) {
let v = self.reg_load(*a0)?.to_nyash_box(); let v = self.load_as_box(*a0)?;
let _ = arr.push(v); let _ = arr.push(v);
return Ok(VMValue::Void); return Ok(VMValue::Void);
} }
@ -85,15 +85,15 @@ impl MirInterpreter {
} }
"get" => { "get" => {
if let Some(a0) = args.get(0) { if let Some(a0) = args.get(0) {
let idx = self.reg_load(*a0)?.to_nyash_box(); let idx = self.load_as_box(*a0)?;
let ret = arr.get(idx); let ret = arr.get(idx);
return Ok(VMValue::from_nyash_box(ret)); return Ok(VMValue::from_nyash_box(ret));
} }
} }
"set" => { "set" => {
if args.len() >= 2 { if args.len() >= 2 {
let idx = self.reg_load(args[0])?.to_nyash_box(); let idx = self.load_as_box(args[0])?;
let val = self.reg_load(args[1])?.to_nyash_box(); let val = self.load_as_box(args[1])?;
let _ = arr.set(idx, val); let _ = arr.set(idx, val);
return Ok(VMValue::Void); return Ok(VMValue::Void);
} }
@ -774,11 +774,7 @@ impl MirInterpreter {
{ {
let host = crate::runtime::plugin_loader_unified::get_global_plugin_host(); let host = crate::runtime::plugin_loader_unified::get_global_plugin_host();
let host = host.read().unwrap(); let host = host.read().unwrap();
let mut argv: Vec<Box<dyn crate::box_trait::NyashBox>> = let argv = self.load_args_as_boxes(args)?;
Vec::with_capacity(args.len());
for a in args {
argv.push(self.reg_load(*a)?.to_nyash_box());
}
match host.invoke_instance_method( match host.invoke_instance_method(
&p.box_type, &p.box_type,
method, method,

View File

@ -77,8 +77,8 @@ impl MirInterpreter {
("env.future", "new") => { ("env.future", "new") => {
let fut = crate::boxes::future::NyashFutureBox::new(); let fut = crate::boxes::future::NyashFutureBox::new();
if let Some(a0) = args.get(0) { if let Some(a0) = args.get(0) {
let v = self.reg_load(*a0)?; let v = self.load_as_box(*a0)?;
fut.set_result(v.to_nyash_box()); fut.set_result(v);
} }
self.write_result(dst, VMValue::Future(fut)); self.write_result(dst, VMValue::Future(fut));
Ok(()) Ok(())
@ -86,9 +86,9 @@ impl MirInterpreter {
("env.future", "set") => { ("env.future", "set") => {
if args.len() >= 2 { if args.len() >= 2 {
let f = self.reg_load(args[0])?; let f = self.reg_load(args[0])?;
let v = self.reg_load(args[1])?; let v = self.load_as_box(args[1])?;
if let VMValue::Future(fut) = f { if let VMValue::Future(fut) = f {
fut.set_result(v.to_nyash_box()); fut.set_result(v);
} else { } else {
return Err(VMError::TypeError("env.future.set expects Future".into())); return Err(VMError::TypeError("env.future.set expects Future".into()));
} }
@ -118,8 +118,8 @@ impl MirInterpreter {
} }
("env.modules", "set") => { ("env.modules", "set") => {
if args.len() >= 2 { if args.len() >= 2 {
let k = self.reg_load(args[0])?.to_string(); let k = self.load_as_string(args[0])?;
let v = self.reg_load(args[1])?.to_nyash_box(); let v = self.load_as_box(args[1])?;
crate::runtime::modules_registry::set(k, v); crate::runtime::modules_registry::set(k, v);
} }
self.write_void(dst); self.write_void(dst);

View File

@ -0,0 +1,121 @@
//! 型変換ユーティリティ
//!
//! レジスタ値の読み込み+型変換チェーンを統一します。
use super::super::*;
use crate::mir::ValueId;
use crate::box_trait::NyashBox;
impl MirInterpreter {
/// レジスタ値をBox<dyn NyashBox>として読み込む
///
/// # Arguments
/// * `vid` - 読み込むValueId
///
/// # Returns
/// * `Result<Box<dyn NyashBox>, VMError>` - 変換済みのBox
#[inline]
pub(crate) fn load_as_box(&mut self, vid: ValueId) -> Result<Box<dyn NyashBox>, VMError> {
Ok(self.reg_load(vid)?.to_nyash_box())
}
/// レジスタ値をStringとして読み込む
///
/// # Arguments
/// * `vid` - 読み込むValueId
///
/// # Returns
/// * `Result<String, VMError>` - 変換済みのString
#[inline]
pub(crate) fn load_as_string(&mut self, vid: ValueId) -> Result<String, VMError> {
Ok(self.reg_load(vid)?.to_string())
}
/// レジスタ値をi64として読み込む
///
/// # Arguments
/// * `vid` - 読み込むValueId
///
/// # Returns
/// * `Result<i64, VMError>` - 変換済みのi64
///
/// # Errors
/// * 値が整数でない場合はエラー
#[inline]
pub(crate) fn load_as_int(&mut self, vid: ValueId) -> Result<i64, VMError> {
match self.reg_load(vid)? {
VMValue::Integer(i) => Ok(i),
other => {
let type_name = match other {
VMValue::Integer(_) => "Integer",
VMValue::Float(_) => "Float",
VMValue::Bool(_) => "Bool",
VMValue::String(_) => "String",
VMValue::Void => "Void",
VMValue::BoxRef(b) => return Err(self.err_type_mismatch("load_as_int", "Integer", &b.type_name())),
VMValue::Future(_) => "Future",
};
Err(self.err_type_mismatch("load_as_int", "Integer", type_name))
}
}
}
/// レジスタ値をboolとして読み込む
///
/// # Arguments
/// * `vid` - 読み込むValueId
///
/// # Returns
/// * `Result<bool, VMError>` - 変換済みのbool
///
/// # Errors
/// * 値がboolでない場合はエラー
#[inline]
pub(crate) fn load_as_bool(&mut self, vid: ValueId) -> Result<bool, VMError> {
match self.reg_load(vid)? {
VMValue::Bool(b) => Ok(b),
other => {
let type_name = match other {
VMValue::Integer(_) => "Integer",
VMValue::Float(_) => "Float",
VMValue::Bool(_) => "Bool",
VMValue::String(_) => "String",
VMValue::Void => "Void",
VMValue::BoxRef(b) => return Err(self.err_type_mismatch("load_as_bool", "Bool", &b.type_name())),
VMValue::Future(_) => "Future",
};
Err(self.err_type_mismatch("load_as_bool", "Bool", type_name))
}
}
}
/// 複数のレジスタ値をVec<Box<dyn NyashBox>>として読み込む
///
/// # Arguments
/// * `vids` - 読み込むValueIdのスライス
///
/// # Returns
/// * `Result<Vec<Box<dyn NyashBox>>, VMError>` - 変換済みのVec
#[inline]
pub(crate) fn load_args_as_boxes(
&mut self,
vids: &[ValueId],
) -> Result<Vec<Box<dyn NyashBox>>, VMError> {
vids.iter().map(|vid| self.load_as_box(*vid)).collect()
}
/// 複数のレジスタ値をVec<VMValue>として読み込む
///
/// # Arguments
/// * `vids` - 読み込むValueIdのスライス
///
/// # Returns
/// * `Result<Vec<VMValue>, VMError>` - 読み込んだVMValueのVec
#[inline]
pub(crate) fn load_args_as_values(
&mut self,
vids: &[ValueId],
) -> Result<Vec<VMValue>, VMError> {
vids.iter().map(|vid| self.reg_load(*vid)).collect()
}
}

View File

@ -4,9 +4,11 @@ pub mod destination_helpers;
pub mod arg_validation; pub mod arg_validation;
pub mod receiver_helpers; pub mod receiver_helpers;
pub mod error_helpers; pub mod error_helpers;
pub mod conversion_helpers;
// Re-export for convenience // Re-export for convenience
pub use destination_helpers::*; pub use destination_helpers::*;
pub use arg_validation::*; pub use arg_validation::*;
pub use receiver_helpers::*; pub use receiver_helpers::*;
pub use error_helpers::*; pub use error_helpers::*;
pub use conversion_helpers::*;