/ synthesizer / program / src / finalize / 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  use crate::Command;
 18  
 19  impl<N: Network> Parser for FinalizeCore<N> {
 20      /// Parses a string into finalize.
 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 'finalize' 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 associated function name from the string.
 30          let (string, name) = Identifier::<N>::parse(string)?;
 31          // Parse the whitespace from the string.
 32          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 33          // Parse the colon ':' keyword from the string.
 34          let (string, _) = tag(":")(string)?;
 35  
 36          // Parse the inputs from the string.
 37          let (string, inputs) = many0(Input::parse)(string)?;
 38          // Parse the commands from the string.
 39          let (string, commands) = many1(Command::<N>::parse)(string)?;
 40  
 41          map_res(take(0usize), move |_| {
 42              // Initialize a new finalize.
 43              let mut finalize = Self::new(name);
 44              if let Err(error) = inputs.iter().cloned().try_for_each(|input| finalize.add_input(input)) {
 45                  eprintln!("{error}");
 46                  return Err(error);
 47              }
 48              if let Err(error) = commands.iter().cloned().try_for_each(|command| finalize.add_command(command)) {
 49                  eprintln!("{error}");
 50                  return Err(error);
 51              }
 52              Ok::<_, Error>(finalize)
 53          })(string)
 54      }
 55  }
 56  
 57  impl<N: Network> FromStr for FinalizeCore<N> {
 58      type Err = Error;
 59  
 60      /// Returns a finalize from a string literal.
 61      fn from_str(string: &str) -> Result<Self> {
 62          match Self::parse(string) {
 63              Ok((remainder, object)) => {
 64                  // Ensure the remainder is empty.
 65                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
 66                  // Return the object.
 67                  Ok(object)
 68              }
 69              Err(error) => bail!("Failed to parse string. {error}"),
 70          }
 71      }
 72  }
 73  
 74  impl<N: Network> Debug for FinalizeCore<N> {
 75      /// Prints the finalize as a string.
 76      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 77          Display::fmt(self, f)
 78      }
 79  }
 80  
 81  impl<N: Network> Display for FinalizeCore<N> {
 82      /// Prints the finalize as a string.
 83      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 84          // Write the finalize to a string.
 85          write!(f, "{} {}:", Self::type_name(), self.name)?;
 86          self.inputs.iter().try_for_each(|input| write!(f, "\n    {input}"))?;
 87          self.commands.iter().try_for_each(|command| write!(f, "\n    {command}"))
 88      }
 89  }
 90  
 91  #[cfg(test)]
 92  mod tests {
 93      use super::*;
 94      use crate::Finalize;
 95      use console::network::MainnetV0;
 96  
 97      type CurrentNetwork = MainnetV0;
 98  
 99      #[test]
100      fn test_finalize_parse() {
101          let finalize = Finalize::<CurrentNetwork>::parse(
102              r"
103  finalize foo:
104      input r0 as field.public;
105      input r1 as field.public;
106      add r0 r1 into r2;",
107          )
108          .unwrap()
109          .1;
110          assert_eq!("foo", finalize.name().to_string());
111          assert_eq!(2, finalize.inputs().len());
112          assert_eq!(1, finalize.commands().len());
113  
114          // Finalize with 0 inputs.
115          let finalize = Finalize::<CurrentNetwork>::parse(
116              r"
117  finalize foo:
118      add 1u32 2u32 into r0;",
119          )
120          .unwrap()
121          .1;
122          assert_eq!("foo", finalize.name().to_string());
123          assert_eq!(0, finalize.inputs().len());
124          assert_eq!(1, finalize.commands().len());
125      }
126  
127      #[test]
128      fn test_finalize_parse_cast() {
129          let finalize = Finalize::<CurrentNetwork>::parse(
130              r"
131  finalize foo:
132      input r0 as token.public;
133      cast r0.owner r0.token_amount into r1 as token;",
134          )
135          .unwrap()
136          .1;
137          assert_eq!("foo", finalize.name().to_string());
138          assert_eq!(1, finalize.inputs().len());
139          assert_eq!(1, finalize.commands().len());
140      }
141  
142      #[test]
143      fn test_finalize_display() {
144          let expected = r"finalize foo:
145      input r0 as field.public;
146      input r1 as field.public;
147      add r0 r1 into r2;";
148          let finalize = Finalize::<CurrentNetwork>::parse(expected).unwrap().1;
149          assert_eq!(expected, format!("{finalize}"),);
150      }
151  }