cairo_lang_casm/
operand.rs

1use core::fmt::Display;
2
3use cairo_lang_utils::bigint::BigIntAsHex;
4
5#[cfg(test)]
6#[path = "operand_test.rs"]
7mod test;
8
9#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
12#[cfg_attr(
13    feature = "parity-scale-codec",
14    derive(parity_scale_codec::Encode, parity_scale_codec::Decode)
15)]
16pub enum Register {
17    #[cfg_attr(feature = "parity-scale-codec", codec(index = 0))]
18    AP,
19    #[cfg_attr(feature = "parity-scale-codec", codec(index = 1))]
20    FP,
21}
22impl Display for Register {
23    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24        match self {
25            Register::AP => write!(f, "ap"),
26            Register::FP => write!(f, "fp"),
27        }
28    }
29}
30
31// Represents the rhs operand of an assert equal InstructionBody.
32#[derive(Clone, Debug, Eq, PartialEq)]
33#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
34#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
35#[cfg_attr(
36    feature = "parity-scale-codec",
37    derive(parity_scale_codec::Encode, parity_scale_codec::Decode)
38)]
39pub enum ResOperand {
40    #[cfg_attr(feature = "parity-scale-codec", codec(index = 0))]
41    Deref(CellRef),
42    #[cfg_attr(feature = "parity-scale-codec", codec(index = 1))]
43    DoubleDeref(CellRef, i16),
44    #[cfg_attr(feature = "parity-scale-codec", codec(index = 2))]
45    Immediate(BigIntAsHex),
46    #[cfg_attr(feature = "parity-scale-codec", codec(index = 3))]
47    BinOp(BinOpOperand),
48}
49impl Display for ResOperand {
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        match self {
52            ResOperand::Deref(operand) => write!(f, "{operand}"),
53            ResOperand::DoubleDeref(operand, offset) => write!(f, "[{operand} + {offset}]"),
54            ResOperand::Immediate(operand) => write!(f, "{}", operand.value),
55            ResOperand::BinOp(operand) => write!(f, "{operand}"),
56        }
57    }
58}
59impl From<DerefOrImmediate> for ResOperand {
60    fn from(x: DerefOrImmediate) -> Self {
61        match x {
62            DerefOrImmediate::Deref(deref) => ResOperand::Deref(deref),
63            DerefOrImmediate::Immediate(imm) => ResOperand::Immediate(imm),
64        }
65    }
66}
67
68impl<T: Into<BigIntAsHex>> From<T> for ResOperand {
69    fn from(imm: T) -> Self {
70        ResOperand::Immediate(imm.into())
71    }
72}
73
74/// Represents an operand of the form [reg + offset].
75#[derive(Copy, Clone, Debug, Eq, PartialEq)]
76#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
77#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
78#[cfg_attr(
79    feature = "parity-scale-codec",
80    derive(parity_scale_codec::Encode, parity_scale_codec::Decode)
81)]
82pub struct CellRef {
83    pub register: Register,
84    pub offset: i16,
85}
86impl Display for CellRef {
87    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88        write!(f, "[{} + {}]", self.register, self.offset)
89    }
90}
91
92/// Returns an AP DerefOperand with the given offset.
93pub fn ap_cell_ref(offset: i16) -> CellRef {
94    CellRef { register: Register::AP, offset }
95}
96
97#[derive(Clone, Debug, Eq, PartialEq)]
98#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
99#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
100#[cfg_attr(
101    feature = "parity-scale-codec",
102    derive(parity_scale_codec::Encode, parity_scale_codec::Decode)
103)]
104pub enum DerefOrImmediate {
105    #[cfg_attr(feature = "parity-scale-codec", codec(index = 0))]
106    Deref(CellRef),
107    #[cfg_attr(feature = "parity-scale-codec", codec(index = 1))]
108    Immediate(BigIntAsHex),
109}
110impl Display for DerefOrImmediate {
111    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
112        match self {
113            DerefOrImmediate::Deref(operand) => write!(f, "{operand}"),
114            DerefOrImmediate::Immediate(operand) => write!(f, "{}", operand.value),
115        }
116    }
117}
118impl<T: Into<BigIntAsHex>> From<T> for DerefOrImmediate {
119    fn from(x: T) -> Self {
120        DerefOrImmediate::Immediate(x.into())
121    }
122}
123impl From<CellRef> for DerefOrImmediate {
124    fn from(x: CellRef) -> Self {
125        DerefOrImmediate::Deref(x)
126    }
127}
128
129#[derive(Clone, Debug, Eq, PartialEq)]
130#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
131#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
132#[cfg_attr(
133    feature = "parity-scale-codec",
134    derive(parity_scale_codec::Encode, parity_scale_codec::Decode)
135)]
136pub enum Operation {
137    #[cfg_attr(feature = "parity-scale-codec", codec(index = 0))]
138    Add,
139    #[cfg_attr(feature = "parity-scale-codec", codec(index = 1))]
140    Mul,
141}
142impl Display for Operation {
143    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
144        match self {
145            Operation::Add => write!(f, "+"),
146            Operation::Mul => write!(f, "*"),
147        }
148    }
149}
150
151#[derive(Clone, Debug, Eq, PartialEq)]
152#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
153#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
154#[cfg_attr(
155    feature = "parity-scale-codec",
156    derive(parity_scale_codec::Encode, parity_scale_codec::Decode)
157)]
158pub struct BinOpOperand {
159    pub op: Operation,
160    pub a: CellRef,
161    pub b: DerefOrImmediate,
162}
163impl Display for BinOpOperand {
164    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
165        write!(f, "{} {} {}", self.a, self.op, self.b)
166    }
167}