ergotree_ir/mir/
upcast.rs1use super::expr::Expr;
4use super::expr::InvalidArgumentError;
5use crate::serialization::op_code::OpCode;
6use crate::serialization::sigma_byte_reader::SigmaByteRead;
7use crate::serialization::sigma_byte_writer::SigmaByteWrite;
8use crate::serialization::SigmaParsingError;
9use crate::serialization::SigmaSerializable;
10use crate::serialization::SigmaSerializeResult;
11use crate::types::stype::SType;
12
13use crate::has_opcode::HasStaticOpCode;
14
15#[derive(PartialEq, Eq, Debug, Clone)]
17pub struct Upcast {
18 pub input: Box<Expr>,
20 pub tpe: SType,
22}
23
24impl Upcast {
25 pub fn new(input: Expr, target_tpe: SType) -> Result<Self, InvalidArgumentError> {
27 if !target_tpe.is_numeric() {
28 return Err(InvalidArgumentError(format!(
29 "Upcast: expected target type to be numeric, got {:?}",
30 target_tpe
31 )));
32 }
33 let post_eval_tpe = input.post_eval_tpe();
34 if post_eval_tpe.is_numeric() {
35 Ok(Self {
36 input: input.into(),
37 tpe: target_tpe,
38 })
39 } else {
40 Err(InvalidArgumentError(format!(
41 "Upcast: expected input value type to be numeric, got {:?}",
42 post_eval_tpe
43 )))
44 }
45 }
46
47 pub fn tpe(&self) -> SType {
49 self.tpe.clone()
50 }
51}
52
53impl HasStaticOpCode for Upcast {
54 const OP_CODE: OpCode = OpCode::UPCAST;
55}
56
57impl SigmaSerializable for Upcast {
58 fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
59 self.input.sigma_serialize(w)?;
60 self.tpe.sigma_serialize(w)
61 }
62
63 fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
64 let input = Expr::sigma_parse(r)?.into();
65 let tpe = SType::sigma_parse(r)?;
66 Ok(Upcast { input, tpe })
67 }
68}
69
70#[cfg(feature = "arbitrary")]
71#[allow(clippy::unwrap_used)]
72mod arbitrary {
74 use crate::mir::expr::arbitrary::ArbExprParams;
75
76 use super::*;
77 use proptest::prelude::*;
78
79 impl Arbitrary for Upcast {
80 type Parameters = ();
81 type Strategy = BoxedStrategy<Self>;
82
83 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
84 any_with::<Expr>(ArbExprParams {
85 tpe: SType::SInt,
86 depth: 2,
87 })
88 .prop_map(|input| Upcast::new(input, SType::SLong).unwrap())
89 .boxed()
90 }
91 }
92}
93
94#[cfg(test)]
95#[cfg(feature = "arbitrary")]
96#[allow(clippy::panic)]
97pub mod proptests {
98
99 use super::*;
100 use crate::serialization::sigma_serialize_roundtrip;
101 use proptest::prelude::*;
102
103 proptest! {
104
105 #[test]
106 fn ser_roundtrip(v in any::<Upcast>()) {
107 let expr: Expr = v.into();
108 prop_assert_eq![sigma_serialize_roundtrip(&expr), expr];
109 }
110 }
111}