diff --git a/src/backend/mir_interpreter/handlers/boxes.rs b/src/backend/mir_interpreter/handlers/boxes.rs index fb3d3816..7d168879 100644 --- a/src/backend/mir_interpreter/handlers/boxes.rs +++ b/src/backend/mir_interpreter/handlers/boxes.rs @@ -13,10 +13,7 @@ impl MirInterpreter { if let Err(e) = crate::runtime::provider_lock::guard_before_new_box(box_type) { return Err(self.err_invalid(e)); } - let mut converted: Vec> = Vec::with_capacity(args.len()); - for vid in args { - converted.push(self.reg_load(*vid)?.to_nyash_box()); - } + let converted = self.load_args_as_boxes(args)?; let reg = crate::runtime::unified_registry::get_global_unified_registry(); let created = reg .lock() @@ -56,10 +53,7 @@ impl MirInterpreter { { let host = crate::runtime::plugin_loader_unified::get_global_plugin_host(); let host = host.read().unwrap(); - let mut argv: Vec> = Vec::with_capacity(args.len()); - for a in args { - argv.push(self.reg_load(*a)?.to_nyash_box()); - } + let argv = self.load_args_as_boxes(args)?; match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) { Ok(Some(ret)) => { self.write_from_box(dst, ret); diff --git a/src/backend/mir_interpreter/handlers/boxes_plugin.rs b/src/backend/mir_interpreter/handlers/boxes_plugin.rs index fea069f3..b19f46b4 100644 --- a/src/backend/mir_interpreter/handlers/boxes_plugin.rs +++ b/src/backend/mir_interpreter/handlers/boxes_plugin.rs @@ -41,10 +41,7 @@ pub(super) fn invoke_plugin_box( } let host = crate::runtime::plugin_loader_unified::get_global_plugin_host(); let host = host.read().unwrap(); - let mut argv: Vec> = Vec::with_capacity(args.len()); - for a in args { - argv.push(this.reg_load(*a)?.to_nyash_box()); - } + let argv = this.load_args_as_boxes(args)?; match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) { Ok(Some(ret)) => { this.write_from_box(dst, ret); diff --git a/src/backend/mir_interpreter/handlers/calls.rs b/src/backend/mir_interpreter/handlers/calls.rs index f7fda0de..d830edb0 100644 --- a/src/backend/mir_interpreter/handlers/calls.rs +++ b/src/backend/mir_interpreter/handlers/calls.rs @@ -74,7 +74,7 @@ impl MirInterpreter { "birth" => { return Ok(VMValue::Void); } "push" => { 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); return Ok(VMValue::Void); } @@ -85,15 +85,15 @@ impl MirInterpreter { } "get" => { 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); return Ok(VMValue::from_nyash_box(ret)); } } "set" => { if args.len() >= 2 { - let idx = self.reg_load(args[0])?.to_nyash_box(); - let val = self.reg_load(args[1])?.to_nyash_box(); + let idx = self.load_as_box(args[0])?; + let val = self.load_as_box(args[1])?; let _ = arr.set(idx, val); return Ok(VMValue::Void); } @@ -774,11 +774,7 @@ impl MirInterpreter { { let host = crate::runtime::plugin_loader_unified::get_global_plugin_host(); let host = host.read().unwrap(); - let mut argv: Vec> = - Vec::with_capacity(args.len()); - for a in args { - argv.push(self.reg_load(*a)?.to_nyash_box()); - } + let argv = self.load_args_as_boxes(args)?; match host.invoke_instance_method( &p.box_type, method, diff --git a/src/backend/mir_interpreter/handlers/externals.rs b/src/backend/mir_interpreter/handlers/externals.rs index 1ccd1185..13855ff9 100644 --- a/src/backend/mir_interpreter/handlers/externals.rs +++ b/src/backend/mir_interpreter/handlers/externals.rs @@ -77,8 +77,8 @@ impl MirInterpreter { ("env.future", "new") => { let fut = crate::boxes::future::NyashFutureBox::new(); if let Some(a0) = args.get(0) { - let v = self.reg_load(*a0)?; - fut.set_result(v.to_nyash_box()); + let v = self.load_as_box(*a0)?; + fut.set_result(v); } self.write_result(dst, VMValue::Future(fut)); Ok(()) @@ -86,9 +86,9 @@ impl MirInterpreter { ("env.future", "set") => { if args.len() >= 2 { 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 { - fut.set_result(v.to_nyash_box()); + fut.set_result(v); } else { return Err(VMError::TypeError("env.future.set expects Future".into())); } @@ -118,8 +118,8 @@ impl MirInterpreter { } ("env.modules", "set") => { if args.len() >= 2 { - let k = self.reg_load(args[0])?.to_string(); - let v = self.reg_load(args[1])?.to_nyash_box(); + let k = self.load_as_string(args[0])?; + let v = self.load_as_box(args[1])?; crate::runtime::modules_registry::set(k, v); } self.write_void(dst); diff --git a/src/backend/mir_interpreter/utils/conversion_helpers.rs b/src/backend/mir_interpreter/utils/conversion_helpers.rs new file mode 100644 index 00000000..db6c9012 --- /dev/null +++ b/src/backend/mir_interpreter/utils/conversion_helpers.rs @@ -0,0 +1,121 @@ +//! 型変換ユーティリティ +//! +//! レジスタ値の読み込み+型変換チェーンを統一します。 + +use super::super::*; +use crate::mir::ValueId; +use crate::box_trait::NyashBox; + +impl MirInterpreter { + /// レジスタ値をBoxとして読み込む + /// + /// # Arguments + /// * `vid` - 読み込むValueId + /// + /// # Returns + /// * `Result, VMError>` - 変換済みのBox + #[inline] + pub(crate) fn load_as_box(&mut self, vid: ValueId) -> Result, VMError> { + Ok(self.reg_load(vid)?.to_nyash_box()) + } + + /// レジスタ値をStringとして読み込む + /// + /// # Arguments + /// * `vid` - 読み込むValueId + /// + /// # Returns + /// * `Result` - 変換済みのString + #[inline] + pub(crate) fn load_as_string(&mut self, vid: ValueId) -> Result { + Ok(self.reg_load(vid)?.to_string()) + } + + /// レジスタ値をi64として読み込む + /// + /// # Arguments + /// * `vid` - 読み込むValueId + /// + /// # Returns + /// * `Result` - 変換済みのi64 + /// + /// # Errors + /// * 値が整数でない場合はエラー + #[inline] + pub(crate) fn load_as_int(&mut self, vid: ValueId) -> Result { + 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 + /// + /// # Errors + /// * 値がboolでない場合はエラー + #[inline] + pub(crate) fn load_as_bool(&mut self, vid: ValueId) -> Result { + 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>として読み込む + /// + /// # Arguments + /// * `vids` - 読み込むValueIdのスライス + /// + /// # Returns + /// * `Result>, VMError>` - 変換済みのVec + #[inline] + pub(crate) fn load_args_as_boxes( + &mut self, + vids: &[ValueId], + ) -> Result>, VMError> { + vids.iter().map(|vid| self.load_as_box(*vid)).collect() + } + + /// 複数のレジスタ値をVecとして読み込む + /// + /// # Arguments + /// * `vids` - 読み込むValueIdのスライス + /// + /// # Returns + /// * `Result, VMError>` - 読み込んだVMValueのVec + #[inline] + pub(crate) fn load_args_as_values( + &mut self, + vids: &[ValueId], + ) -> Result, VMError> { + vids.iter().map(|vid| self.reg_load(*vid)).collect() + } +} diff --git a/src/backend/mir_interpreter/utils/mod.rs b/src/backend/mir_interpreter/utils/mod.rs index 9f58b442..9345ffd1 100644 --- a/src/backend/mir_interpreter/utils/mod.rs +++ b/src/backend/mir_interpreter/utils/mod.rs @@ -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::*;