1use crate::{
17 Opcode,
18 Operand,
19 Operation,
20 traits::{RegistersLoad, RegistersLoadCircuit, RegistersStore, RegistersStoreCircuit, StackMatches, StackProgram},
21};
22use console::{
23 network::prelude::*,
24 program::{Literal, LiteralType, PlaintextType, Register, RegisterType},
25};
26
27use core::marker::PhantomData;
28
29pub type UnaryLiteral<N, O> = Literals<N, O, 1>;
31pub type BinaryLiteral<N, O> = Literals<N, O, 2>;
33pub type TernaryLiteral<N, O> = Literals<N, O, 3>;
35
36#[derive(Clone, PartialEq, Eq, Hash)]
37pub struct Literals<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> {
38 operands: Vec<Operand<N>>,
40 destination: Register<N>,
42 _phantom: PhantomData<O>,
44}
45
46impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize>
47 Literals<N, O, NUM_OPERANDS>
48{
49 #[inline]
51 pub const fn opcode() -> Opcode {
52 O::OPCODE
53 }
54
55 #[inline]
57 pub fn operands(&self) -> &[Operand<N>] {
58 &self.operands
59 }
60
61 #[inline]
63 pub fn destinations(&self) -> Vec<Register<N>> {
64 vec![self.destination.clone()]
65 }
66}
67
68impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize>
69 Literals<N, O, NUM_OPERANDS>
70{
71 #[inline]
73 pub fn evaluate(
74 &self,
75 stack: &(impl StackMatches<N> + StackProgram<N>),
76 registers: &mut (impl RegistersLoad<N> + RegistersStore<N>),
77 ) -> Result<()> {
78 if self.operands.len() != NUM_OPERANDS {
80 bail!("Instruction '{}' expects {NUM_OPERANDS} operands, found {} operands", O::OPCODE, self.operands.len())
81 }
82
83 let inputs: Vec<_> =
85 self.operands.iter().map(|operand| registers.load_literal(stack, operand)).try_collect()?;
86 let input_types: Vec<_> =
88 inputs.iter().map(|input| RegisterType::Plaintext(PlaintextType::from(input.to_type()))).collect();
89
90 let inputs: [Literal<N>; NUM_OPERANDS] =
92 inputs.try_into().map_err(|_| anyhow!("Failed to prepare operands in evaluate"))?;
93
94 let output = O::evaluate(&inputs)?;
96
97 let output_type = RegisterType::Plaintext(PlaintextType::from(output.to_type()));
99
100 let expected_types = self.output_types(stack, &input_types)?;
102 ensure!(expected_types.len() == 1, "Expected 1 output type, found {}", expected_types.len());
104 ensure!(expected_types[0] == output_type, "Expected output type '{}', found {output_type}", expected_types[0]);
106
107 registers.store_literal(stack, &self.destination, output)
109 }
110
111 #[inline]
113 pub fn execute<A: circuit::Aleo<Network = N>>(
114 &self,
115 stack: &(impl StackMatches<N> + StackProgram<N>),
116 registers: &mut (impl RegistersLoadCircuit<N, A> + RegistersStoreCircuit<N, A>),
117 ) -> Result<()> {
118 if self.operands.len() != NUM_OPERANDS {
120 bail!("Instruction '{}' expects {NUM_OPERANDS} operands, found {} operands", O::OPCODE, self.operands.len())
121 }
122
123 let inputs: Vec<_> =
125 self.operands.iter().map(|operand| registers.load_literal_circuit(stack, operand)).try_collect()?;
126 let input_types: Vec<_> =
128 inputs.iter().map(|input| RegisterType::Plaintext(PlaintextType::from(input.to_type()))).collect();
129
130 let output = O::execute(&inputs.try_into().map_err(|_| anyhow!("Failed to prepare operands in execute"))?)?;
132 let output_type = RegisterType::Plaintext(PlaintextType::from(output.to_type()));
134
135 let expected_types = self.output_types(stack, &input_types)?;
137 ensure!(expected_types.len() == 1, "Expected 1 output type, found {}", expected_types.len());
139 ensure!(expected_types[0] == output_type, "Expected output type '{}', found {output_type}", expected_types[0]);
141
142 registers.store_literal_circuit(stack, &self.destination, output)
144 }
145
146 #[inline]
148 pub fn finalize(
149 &self,
150 stack: &(impl StackMatches<N> + StackProgram<N>),
151 registers: &mut (impl RegistersLoad<N> + RegistersStore<N>),
152 ) -> Result<()> {
153 self.evaluate(stack, registers)
154 }
155
156 #[inline]
158 pub fn output_types(
159 &self,
160 _stack: &impl StackProgram<N>,
161 input_types: &[RegisterType<N>],
162 ) -> Result<Vec<RegisterType<N>>> {
163 if input_types.len() != NUM_OPERANDS {
165 bail!("Instruction '{}' expects {NUM_OPERANDS} inputs, found {} inputs", O::OPCODE, input_types.len())
166 }
167 if self.operands.len() != NUM_OPERANDS {
169 bail!("Instruction '{}' expects {NUM_OPERANDS} operands, found {} operands", O::OPCODE, self.operands.len())
170 }
171
172 let input_types = input_types
174 .iter()
175 .map(|input_type| match input_type {
176 RegisterType::Plaintext(PlaintextType::Literal(literal_type)) => Ok(*literal_type),
177 RegisterType::Plaintext(PlaintextType::Struct(..))
178 | RegisterType::Plaintext(PlaintextType::Array(..))
179 | RegisterType::Record(..)
180 | RegisterType::ExternalRecord(..)
181 | RegisterType::Future(..) => bail!("Expected literal type, found '{input_type}'"),
182 })
183 .collect::<Result<Vec<_>>>()?;
184
185 let output = O::output_type(&input_types.try_into().map_err(|_| anyhow!("Failed to prepare operand types"))?)?;
187
188 Ok(vec![RegisterType::Plaintext(PlaintextType::Literal(output))])
190 }
191}
192
193impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Parser
194 for Literals<N, O, NUM_OPERANDS>
195{
196 #[inline]
198 fn parse(string: &str) -> ParserResult<Self> {
199 let (string, _) = tag(*O::OPCODE)(string)?;
201 let (string, _) = Sanitizer::parse_whitespaces(string)?;
203
204 if NUM_OPERANDS > N::MAX_OPERANDS {
206 return map_res(fail, |_: ParserResult<Self>| {
207 Err(format!("The number of operands must be <= {}", N::MAX_OPERANDS))
208 })(string);
209 }
210
211 let mut operands = Vec::with_capacity(NUM_OPERANDS);
213 let mut string_tracker = string;
215 for _ in 0..NUM_OPERANDS {
217 let (string, operand) = Operand::parse(string_tracker)?;
219 let (string, _) = Sanitizer::parse_whitespaces(string)?;
221 operands.push(operand);
223 string_tracker = string;
225 }
226 let string = string_tracker;
228
229 let (string, _) = tag("into")(string)?;
231 let (string, _) = Sanitizer::parse_whitespaces(string)?;
233 let (string, destination) = Register::parse(string)?;
235
236 Ok((string, Self { operands, destination, _phantom: PhantomData }))
237 }
238}
239
240impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> FromStr
241 for Literals<N, O, NUM_OPERANDS>
242{
243 type Err = Error;
244
245 #[inline]
247 fn from_str(string: &str) -> Result<Self> {
248 match Self::parse(string) {
249 Ok((remainder, object)) => {
250 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
252 Ok(object)
254 }
255 Err(error) => bail!("Failed to parse string. {error}"),
256 }
257 }
258}
259
260impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Debug
261 for Literals<N, O, NUM_OPERANDS>
262{
263 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
265 Display::fmt(self, f)
266 }
267}
268
269impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> Display
270 for Literals<N, O, NUM_OPERANDS>
271{
272 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
274 if NUM_OPERANDS > N::MAX_OPERANDS {
276 return Err(fmt::Error);
277 }
278 if self.operands.len() > NUM_OPERANDS {
280 return Err(fmt::Error);
281 }
282 write!(f, "{} ", O::OPCODE)?;
284 self.operands.iter().try_for_each(|operand| write!(f, "{operand} "))?;
285 write!(f, "into {}", self.destination)
286 }
287}
288
289impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> FromBytes
290 for Literals<N, O, NUM_OPERANDS>
291{
292 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
294 if NUM_OPERANDS > N::MAX_OPERANDS {
296 return Err(error(format!("The number of operands must be <= {}", N::MAX_OPERANDS)));
297 }
298
299 let mut operands = Vec::with_capacity(NUM_OPERANDS);
301 for _ in 0..NUM_OPERANDS {
303 operands.push(Operand::read_le(&mut reader)?);
304 }
305
306 let destination = Register::read_le(&mut reader)?;
308 Ok(Self { operands, destination, _phantom: PhantomData })
310 }
311}
312
313impl<N: Network, O: Operation<N, Literal<N>, LiteralType, NUM_OPERANDS>, const NUM_OPERANDS: usize> ToBytes
314 for Literals<N, O, NUM_OPERANDS>
315{
316 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
318 if NUM_OPERANDS > N::MAX_OPERANDS {
320 return Err(error(format!("The number of operands must be <= {}", N::MAX_OPERANDS)));
321 }
322 if self.operands.len() > NUM_OPERANDS {
324 return Err(error(format!("The number of operands must be {NUM_OPERANDS}")));
325 }
326 self.operands.iter().try_for_each(|operand| operand.write_le(&mut writer))?;
328 self.destination.write_le(&mut writer)
330 }
331}