/ synthesizer / program / src / logic / command / await_.rs
await_.rs
  1  // Copyright (c) 2025 ADnet Contributors
  2  // This file is part of the AlphaVM library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use crate::{Opcode, Operand};
 17  use console::{network::prelude::*, program::Register};
 18  
 19  /// An await command, e.g. `await r0;`.
 20  /// Awaits the result of an asynchronous call (a future).
 21  /// Note that asynchronous calls currently do not return a value.
 22  #[derive(Clone, PartialEq, Eq, Hash)]
 23  pub struct Await<N: Network> {
 24      /// The operands.
 25      /// Note: Byte and string parsing guarantees that this is a single register operand.
 26      operands: [Operand<N>; 1],
 27  }
 28  
 29  impl<N: Network> Await<N> {
 30      /// Returns the opcode.
 31      #[inline]
 32      pub const fn opcode() -> Opcode {
 33          Opcode::Command("await")
 34      }
 35  
 36      /// Returns the operands in the command.
 37      #[inline]
 38      pub fn operands(&self) -> &[Operand<N>] {
 39          &self.operands
 40      }
 41  
 42      /// Returns the register containing the future.
 43      #[inline]
 44      pub fn register(&self) -> &Register<N> {
 45          // Note: This byte and string parsing guarantees that the operand is a single register.
 46          let Operand::Register(register) = &self.operands[0] else {
 47              unreachable!("The operands of an await command must be a single register.")
 48          };
 49          // Return the register.
 50          register
 51      }
 52  }
 53  
 54  impl<N: Network> Parser for Await<N> {
 55      /// Parses a string into an operation.
 56      #[inline]
 57      fn parse(string: &str) -> ParserResult<Self> {
 58          // Parse the whitespace and comments from the string.
 59          let (string, _) = Sanitizer::parse(string)?;
 60          // Parse the opcode from the string.
 61          let (string, _) = tag(*Self::opcode())(string)?;
 62          // Parse the whitespace from the string.
 63          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 64          // Parse the register from the string.
 65          let (string, register) = Register::parse(string)?;
 66          // Parse the whitespace from the string.
 67          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 68          // Parse the ';' from the string.
 69          let (string, _) = tag(";")(string)?;
 70  
 71          Ok((string, Self { operands: [Operand::Register(register)] }))
 72      }
 73  }
 74  
 75  impl<N: Network> FromStr for Await<N> {
 76      type Err = Error;
 77  
 78      /// Parses a string into the command.
 79      #[inline]
 80      fn from_str(string: &str) -> Result<Self> {
 81          match Self::parse(string) {
 82              Ok((remainder, object)) => {
 83                  // Ensure the remainder is empty.
 84                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
 85                  // Return the object.
 86                  Ok(object)
 87              }
 88              Err(error) => bail!("Failed to parse string. {error}"),
 89          }
 90      }
 91  }
 92  
 93  impl<N: Network> Debug for Await<N> {
 94      /// Prints the command as a string.
 95      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 96          Display::fmt(self, f)
 97      }
 98  }
 99  
100  impl<N: Network> Display for Await<N> {
101      /// Prints the command to a string.
102      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
103          // Print the command.
104          write!(f, "await {};", self.register())
105      }
106  }
107  
108  impl<N: Network> FromBytes for Await<N> {
109      /// Reads the command from a buffer.
110      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
111          // Read the register.
112          let register = Register::read_le(&mut reader)?;
113  
114          Ok(Self { operands: [Operand::Register(register)] })
115      }
116  }
117  
118  impl<N: Network> ToBytes for Await<N> {
119      /// Writes the operation to a buffer.
120      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
121          // Write the register.
122          self.register().write_le(&mut writer)?;
123          Ok(())
124      }
125  }
126  
127  #[cfg(test)]
128  mod tests {
129      use super::*;
130      use console::{network::MainnetV0, program::Register};
131  
132      type CurrentNetwork = MainnetV0;
133  
134      #[test]
135      fn test_parse() {
136          let (string, await_) = Await::<CurrentNetwork>::parse("await r1;").unwrap();
137          assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
138          assert_eq!(await_.register(), &Register::Locator(1));
139      }
140  }