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