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

@ -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 receiver_helpers;
pub mod error_helpers;
pub mod conversion_helpers;
// Re-export for convenience
pub use destination_helpers::*;
pub use arg_validation::*;
pub use receiver_helpers::*;
pub use error_helpers::*;
pub use conversion_helpers::*;