/ synthesizer / program / src / closure / output / parse.rs
parse.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the deltavm 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 super::*;
 17  
 18  impl<N: Network> Parser for Output<N> {
 19      /// Parses a string into an output statement.
 20      /// The output statement is of the form `output {operand} as {register_type};`.
 21      #[inline]
 22      fn parse(string: &str) -> ParserResult<Self> {
 23          // Parse the whitespace and comments from the string.
 24          let (string, _) = Sanitizer::parse(string)?;
 25          // Parse the output keyword from the string.
 26          let (string, _) = tag(Self::type_name())(string)?;
 27          // Parse the whitespace from the string.
 28          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 29          // Parse the operand from the string.
 30          let (string, operand) = Operand::parse(string)?;
 31          // Parse the whitespace from the string.
 32          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 33          // Parse the "as" from the string.
 34          let (string, _) = tag("as")(string)?;
 35          // Parse the whitespace from the string.
 36          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 37          // Parse the register type from the string.
 38          let (string, register_type) = RegisterType::parse(string)?;
 39          // Parse the whitespace from the string.
 40          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 41          // Parse the semicolon from the string.
 42          let (string, _) = tag(";")(string)?;
 43          // Return the output statement.
 44          Ok((string, Self { operand, register_type }))
 45      }
 46  }
 47  
 48  impl<N: Network> FromStr for Output<N> {
 49      type Err = Error;
 50  
 51      /// Parses a string into an output statement.
 52      #[inline]
 53      fn from_str(string: &str) -> Result<Self> {
 54          match Self::parse(string) {
 55              Ok((remainder, object)) => {
 56                  // Ensure the remainder is empty.
 57                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
 58                  // Return the object.
 59                  Ok(object)
 60              }
 61              Err(error) => bail!("Failed to parse string. {error}"),
 62          }
 63      }
 64  }
 65  
 66  impl<N: Network> Debug for Output<N> {
 67      /// Prints the output as a string.
 68      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 69          Display::fmt(self, f)
 70      }
 71  }
 72  
 73  impl<N: Network> Display for Output<N> {
 74      /// Prints the output statement as a string.
 75      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 76          write!(
 77              f,
 78              "{type_} {operand} as {register_type};",
 79              type_ = Self::type_name(),
 80              operand = self.operand,
 81              register_type = self.register_type
 82          )
 83      }
 84  }
 85  
 86  #[cfg(test)]
 87  mod tests {
 88      use super::*;
 89      use console::{
 90          network::MainnetV0,
 91          program::{Literal, Register, U8},
 92      };
 93  
 94      type CurrentNetwork = MainnetV0;
 95  
 96      #[test]
 97      fn test_output_parse() -> Result<()> {
 98          // Register
 99          let output = Output::<CurrentNetwork>::parse("output r0 as field;").unwrap().1;
100          assert_eq!(output.operand(), &Operand::Register(Register::<CurrentNetwork>::Locator(0)));
101          assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("field")?);
102  
103          let output = Output::<CurrentNetwork>::parse("output 0u8 as u8;").unwrap().1;
104          assert_eq!(output.operand(), &Operand::Literal(Literal::<CurrentNetwork>::U8(U8::new(0))));
105          assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("u8")?);
106  
107          // Struct
108          let output = Output::<CurrentNetwork>::parse("output r1 as signature;").unwrap().1;
109          assert_eq!(output.operand(), &Operand::Register(Register::<CurrentNetwork>::Locator(1)));
110          assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("signature")?);
111  
112          // Record
113          let output = Output::<CurrentNetwork>::parse("output r2 as token.record;").unwrap().1;
114          assert_eq!(output.operand(), &Operand::Register(Register::<CurrentNetwork>::Locator(2)));
115          assert_eq!(output.register_type(), &RegisterType::<CurrentNetwork>::from_str("token.record")?);
116  
117          Ok(())
118      }
119  
120      #[test]
121      fn test_output_display() {
122          // Register
123          let output = Output::<CurrentNetwork>::parse("output r0 as field;").unwrap().1;
124          assert_eq!(format!("{output}"), "output r0 as field;");
125  
126          // Literal
127          let output = Output::<CurrentNetwork>::parse("output 0u8 as u8;").unwrap().1;
128          assert_eq!(format!("{output}"), "output 0u8 as u8;");
129  
130          // Struct
131          let output = Output::<CurrentNetwork>::parse("output r1 as signature;").unwrap().1;
132          assert_eq!(format!("{output}"), "output r1 as signature;");
133  
134          // Record
135          let output = Output::<CurrentNetwork>::parse("output r2 as token.record;").unwrap().1;
136          assert_eq!(format!("{output}"), "output r2 as token.record;");
137      }
138  }