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(..)
173 | RegisterType::DynamicRecord
174 | RegisterType::DynamicFuture => bail!("Expected literal type, found '{input_type}'"),
175 })
176 .collect::<Result<Vec<_>>>()?;
177
178 let output = O::output_type(&input_types.try_into().map_err(|_| anyhow!("Failed to prepare operand types"))?)?;
180
181 Ok(vec![RegisterType::Plaintext(PlaintextType::Literal(output))])
183 }
184}
185
186impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Parser
187 for Literals<N, O, NUM_OPERANDS>
188{
189 fn parse(string: &str) -> ParserResult<Self> {
191 let (string, _) = tag(*O::OPCODE)(string)?;
193 let (string, _) = Sanitizer::parse_whitespaces(string)?;
195
196 if NUM_OPERANDS > N::MAX_OPERANDS {
198 return map_res(fail, |_: ParserResult<Self>| {
199 Err(format!("The number of operands must be <= {}", N::MAX_OPERANDS))
200 })(string);
201 }
202
203 let mut operands = Vec::with_capacity(NUM_OPERANDS);
205 let mut string_tracker = string;
207 for _ in 0..NUM_OPERANDS {
209 let (string, operand) = Operand::parse(string_tracker)?;
211 let (string, _) = Sanitizer::parse_whitespaces(string)?;
213 operands.push(operand);
215 string_tracker = string;
217 }
218 let string = string_tracker;
220
221 let (string, _) = tag("into")(string)?;
223 let (string, _) = Sanitizer::parse_whitespaces(string)?;
225 let (string, destination) = Register::parse(string)?;
227
228 Ok((string, Self { operands, destination, _phantom: PhantomData }))
229 }
230}
231
232impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> FromStr
233 for Literals<N, O, NUM_OPERANDS>
234{
235 type Err = Error;
236
237 fn from_str(string: &str) -> Result<Self> {
239 match Self::parse(string) {
240 Ok((remainder, object)) => {
241 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
243 Ok(object)
245 }
246 Err(error) => bail!("Failed to parse string. {error}"),
247 }
248 }
249}
250
251impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Debug
252 for Literals<N, O, NUM_OPERANDS>
253{
254 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
256 Display::fmt(self, f)
257 }
258}
259
260impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Display
261 for Literals<N, O, NUM_OPERANDS>
262{
263 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
265 if NUM_OPERANDS > N::MAX_OPERANDS {
267 return Err(fmt::Error);
268 }
269 if self.operands.len() > NUM_OPERANDS {
271 return Err(fmt::Error);
272 }
273 write!(f, "{} ", O::OPCODE)?;
275 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
276 write!(f, "into {}", self.destination)
277 }
278}
279
280impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> FromBytes
281 for Literals<N, O, NUM_OPERANDS>
282{
283 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
285 if NUM_OPERANDS > N::MAX_OPERANDS {
287 return Err(error(format!("The number of operands must be <= {}", N::MAX_OPERANDS)));
288 }
289
290 let mut operands = Vec::with_capacity(NUM_OPERANDS);
292 for _ in 0..NUM_OPERANDS {
294 operands.push(Operand::read_le(&mut reader)?);
295 }
296
297 let destination = Register::read_le(&mut reader)?;
299 Ok(Self { operands, destination, _phantom: PhantomData })
301 }
302}
303
304impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> ToBytes
305 for Literals<N, O, NUM_OPERANDS>
306{
307 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
309 if NUM_OPERANDS > N::MAX_OPERANDS {
311 return Err(error(format!("The number of operands must be <= {}", N::MAX_OPERANDS)));
312 }
313 if self.operands.len() > NUM_OPERANDS {
315 return Err(error(format!("The number of operands must be {NUM_OPERANDS}")));
316 }
317 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
319 self.destination.write_le(&mut writer)
321 }
322}