1use crate::{Opcode, Operand, Operation, RegistersCircuit, RegistersTrait, StackTrait};
17use console::{
18 network::prelude::*,
19 program::{Literal, LiteralType, PlaintextType, Register, RegisterType},
20};
21
22use core::marker::PhantomData;
23
24pub type UnaryLiteral<N, O> = Literals<N, O, 1>;
26pub type BinaryLiteral<N, O> = Literals<N, O, 2>;
28pub type TernaryLiteral<N, O> = Literals<N, O, 3>;
30
31#[derive(Clone, PartialEq, Eq, Hash)]
32pub struct Literals<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> {
33 operands: Vec<Operand<N>>,
35 destination: Register<N>,
37 _phantom: PhantomData<O>,
39}
40
41impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize>
42 Literals<N, O, NUM_OPERANDS>
43{
44 #[inline]
46 pub const fn opcode() -> Opcode {
47 O::OPCODE
48 }
49
50 #[inline]
52 pub fn operands(&self) -> &[Operand<N>] {
53 &self.operands
54 }
55
56 #[inline]
58 pub fn destinations(&self) -> Vec<Register<N>> {
59 vec![self.destination.clone()]
60 }
61
62 #[inline]
64 pub fn contains_external_struct(&self) -> bool {
65 false
66 }
67}
68
69impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize>
70 Literals<N, O, NUM_OPERANDS>
71{
72 pub fn evaluate(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
74 if self.operands.len() != NUM_OPERANDS {
76 bail!("Instruction '{}' expects {NUM_OPERANDS} operands, found {} operands", O::OPCODE, self.operands.len())
77 }
78
79 let inputs: Vec<_> =
81 self.operands.iter().map(|operand| registers.load_literal(stack, operand)).try_collect()?;
82 let input_types: Vec<_> =
84 inputs.iter().map(|input| RegisterType::Plaintext(PlaintextType::from(input.to_type()))).collect();
85
86 let inputs: [Literal<N>; NUM_OPERANDS] =
88 inputs.try_into().map_err(|_| anyhow!("Failed to prepare operands in evaluate"))?;
89
90 let output = O::evaluate(&inputs)?;
92
93 let output_type = RegisterType::Plaintext(PlaintextType::from(output.to_type()));
95
96 let expected_types = self.output_types(stack, &input_types)?;
98 ensure!(expected_types.len() == 1, "Expected 1 output type, found {}", expected_types.len());
100 ensure!(expected_types[0] == output_type, "Expected output type '{}', found {output_type}", expected_types[0]);
102
103 registers.store_literal(stack, &self.destination, output)
105 }
106
107 pub fn execute<A: circuit::Aleo<Network = N>>(
109 &self,
110 stack: &impl StackTrait<N>,
111 registers: &mut impl RegistersCircuit<N, A>,
112 ) -> Result<()> {
113 if self.operands.len() != NUM_OPERANDS {
115 bail!("Instruction '{}' expects {NUM_OPERANDS} operands, found {} operands", O::OPCODE, self.operands.len())
116 }
117
118 let inputs: Vec<_> =
120 self.operands.iter().map(|operand| registers.load_literal_circuit(stack, operand)).try_collect()?;
121 let input_types: Vec<_> =
123 inputs.iter().map(|input| RegisterType::Plaintext(PlaintextType::from(input.to_type()))).collect();
124
125 let output = O::execute(&inputs.try_into().map_err(|_| anyhow!("Failed to prepare operands in execute"))?)?;
127 let output_type = RegisterType::Plaintext(PlaintextType::from(output.to_type()));
129
130 let expected_types = self.output_types(stack, &input_types)?;
132 ensure!(expected_types.len() == 1, "Expected 1 output type, found {}", expected_types.len());
134 ensure!(expected_types[0] == output_type, "Expected output type '{}', found {output_type}", expected_types[0]);
136
137 registers.store_literal_circuit(stack, &self.destination, output)
139 }
140
141 #[inline]
143 pub fn finalize(&self, stack: &impl StackTrait<N>, registers: &mut impl RegistersTrait<N>) -> Result<()> {
144 self.evaluate(stack, registers)
145 }
146
147 pub fn output_types(
149 &self,
150 _stack: &impl StackTrait<N>,
151 input_types: &[RegisterType<N>],
152 ) -> Result<Vec<RegisterType<N>>> {
153 if input_types.len() != NUM_OPERANDS {
155 bail!("Instruction '{}' expects {NUM_OPERANDS} inputs, found {} inputs", O::OPCODE, input_types.len())
156 }
157 if self.operands.len() != NUM_OPERANDS {
159 bail!("Instruction '{}' expects {NUM_OPERANDS} operands, found {} operands", O::OPCODE, self.operands.len())
160 }
161
162 let input_types = input_types
164 .iter()
165 .map(|input_type| match input_type {
166 RegisterType::Plaintext(PlaintextType::Literal(literal_type)) => Ok(*literal_type),
167 RegisterType::Plaintext(PlaintextType::Struct(..))
168 | RegisterType::Plaintext(PlaintextType::ExternalStruct(..))
169 | RegisterType::Plaintext(PlaintextType::Array(..))
170 | RegisterType::Record(..)
171 | RegisterType::ExternalRecord(..)
172 | RegisterType::Future(..) => bail!("Expected literal type, found '{input_type}'"),
173 })
174 .collect::<Result<Vec<_>>>()?;
175
176 let output = O::output_type(&input_types.try_into().map_err(|_| anyhow!("Failed to prepare operand types"))?)?;
178
179 Ok(vec![RegisterType::Plaintext(PlaintextType::Literal(output))])
181 }
182}
183
184impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Parser
185 for Literals<N, O, NUM_OPERANDS>
186{
187 fn parse(string: &str) -> ParserResult<Self> {
189 let (string, _) = tag(*O::OPCODE)(string)?;
191 let (string, _) = Sanitizer::parse_whitespaces(string)?;
193
194 if NUM_OPERANDS > N::MAX_OPERANDS {
196 return map_res(fail, |_: ParserResult<Self>| {
197 Err(format!("The number of operands must be <= {}", N::MAX_OPERANDS))
198 })(string);
199 }
200
201 let mut operands = Vec::with_capacity(NUM_OPERANDS);
203 let mut string_tracker = string;
205 for _ in 0..NUM_OPERANDS {
207 let (string, operand) = Operand::parse(string_tracker)?;
209 let (string, _) = Sanitizer::parse_whitespaces(string)?;
211 operands.push(operand);
213 string_tracker = string;
215 }
216 let string = string_tracker;
218
219 let (string, _) = tag("into")(string)?;
221 let (string, _) = Sanitizer::parse_whitespaces(string)?;
223 let (string, destination) = Register::parse(string)?;
225
226 Ok((string, Self { operands, destination, _phantom: PhantomData }))
227 }
228}
229
230impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> FromStr
231 for Literals<N, O, NUM_OPERANDS>
232{
233 type Err = Error;
234
235 fn from_str(string: &str) -> Result<Self> {
237 match Self::parse(string) {
238 Ok((remainder, object)) => {
239 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
241 Ok(object)
243 }
244 Err(error) => bail!("Failed to parse string. {error}"),
245 }
246 }
247}
248
249impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Debug
250 for Literals<N, O, NUM_OPERANDS>
251{
252 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
254 Display::fmt(self, f)
255 }
256}
257
258impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Display
259 for Literals<N, O, NUM_OPERANDS>
260{
261 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
263 if NUM_OPERANDS > N::MAX_OPERANDS {
265 return Err(fmt::Error);
266 }
267 if self.operands.len() > NUM_OPERANDS {
269 return Err(fmt::Error);
270 }
271 write!(f, "{} ", O::OPCODE)?;
273 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
274 write!(f, "into {}", self.destination)
275 }
276}
277
278impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> FromBytes
279 for Literals<N, O, NUM_OPERANDS>
280{
281 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
283 if NUM_OPERANDS > N::MAX_OPERANDS {
285 return Err(error(format!("The number of operands must be <= {}", N::MAX_OPERANDS)));
286 }
287
288 let mut operands = Vec::with_capacity(NUM_OPERANDS);
290 for _ in 0..NUM_OPERANDS {
292 operands.push(Operand::read_le(&mut reader)?);
293 }
294
295 let destination = Register::read_le(&mut reader)?;
297 Ok(Self { operands, destination, _phantom: PhantomData })
299 }
300}
301
302impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> ToBytes
303 for Literals<N, O, NUM_OPERANDS>
304{
305 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
307 if NUM_OPERANDS > N::MAX_OPERANDS {
309 return Err(error(format!("The number of operands must be <= {}", N::MAX_OPERANDS)));
310 }
311 if self.operands.len() > NUM_OPERANDS {
313 return Err(error(format!("The number of operands must be {NUM_OPERANDS}")));
314 }
315 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
317 self.destination.write_le(&mut writer)
319 }
320}