ergotree_interpreter/eval/
extract_reg_as.rs1use std::convert::TryInto;
2
3use ergotree_ir::chain::ergo_box::ErgoBox;
4use ergotree_ir::mir::constant::TryExtractInto;
5use ergotree_ir::mir::extract_reg_as::ExtractRegisterAs;
6use ergotree_ir::mir::value::Value;
7use ergotree_ir::reference::Ref;
8
9use crate::eval::env::Env;
10use crate::eval::Context;
11use crate::eval::EvalError;
12use crate::eval::Evaluable;
13
14impl Evaluable for ExtractRegisterAs {
15 fn eval<'ctx>(
16 &self,
17 env: &mut Env<'ctx>,
18 ctx: &Context<'ctx>,
19 ) -> Result<Value<'ctx>, EvalError> {
20 let ir_box = self
21 .input
22 .eval(env, ctx)?
23 .try_extract_into::<Ref<'_, ErgoBox>>()?;
24 let id = self.register_id.try_into().map_err(|e| {
25 EvalError::RegisterIdOutOfBounds(format!(
26 "register index {} is out of bounds: {:?} ",
27 self.register_id, e
28 ))
29 })?;
30 let reg_val_opt = ir_box.get_register(id).map_err(|e| {
31 EvalError::NotFound(format!(
32 "Error getting the register id {id} with error {e:?}"
33 ))
34 })?;
35 Ok(Value::Opt(Box::new(reg_val_opt.map(|c| Value::from(c.v)))))
36 }
37}
38
39#[allow(clippy::unwrap_used)]
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use crate::eval::context::Context;
44 use crate::eval::tests::eval_out;
45 use ergotree_ir::mir::expr::Expr;
46 use ergotree_ir::mir::global_vars::GlobalVars;
47 use ergotree_ir::mir::option_get::OptionGet;
48 use ergotree_ir::mir::unary_op::OneArgOpTryBuild;
49 use ergotree_ir::types::stype::SType;
50 use sigma_test_util::force_any_val;
51
52 #[test]
53 fn eval_box_get_reg_r0() {
54 let get_reg_expr: Expr = ExtractRegisterAs::new(
55 GlobalVars::SelfBox.into(),
56 0,
57 SType::SOption(SType::SLong.into()),
58 )
59 .unwrap()
60 .into();
61 let option_get_expr: Expr = OptionGet::try_build(get_reg_expr).unwrap().into();
62 let ctx = force_any_val::<Context>();
63 let v = eval_out::<i64>(&option_get_expr, &ctx);
64 assert_eq!(v, ctx.self_box.value.as_i64());
65 }
66}