snarkvm_synthesizer_program/view/
parse.rs1use super::*;
17
18impl<N: Network> Parser for ViewCore<N> {
19 #[inline]
21 fn parse(string: &str) -> ParserResult<Self> {
22 let (string, _) = Sanitizer::parse(string)?;
24 let (string, _) = tag(Self::type_name())(string)?;
26 let (string, _) = Sanitizer::parse_whitespaces(string)?;
28 let (string, name) = Identifier::<N>::parse(string)?;
30 let (string, _) = Sanitizer::parse_whitespaces(string)?;
32 let (string, _) = tag(":")(string)?;
34
35 let (string, inputs) = many0(Input::parse)(string)?;
42 let (string, commands) = many0(Command::<N>::parse)(string)?;
43 let (string, outputs) = many0(Output::parse)(string)?;
44
45 map_res(take(0usize), move |_| {
46 let mut view = Self::new(name);
47 inputs.iter().cloned().try_for_each(|input| view.add_input(input))?;
48 commands.iter().cloned().try_for_each(|command| view.add_command(command))?;
49 outputs.iter().cloned().try_for_each(|output| view.add_output(output))?;
50 Ok::<_, Error>(view)
51 })(string)
52 }
53}
54
55impl<N: Network> FromStr for ViewCore<N> {
56 type Err = Error;
57
58 fn from_str(string: &str) -> Result<Self> {
59 match Self::parse(string) {
60 Ok((remainder, object)) => {
61 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
62 Ok(object)
63 }
64 Err(error) => bail!("Failed to parse string. {error}"),
65 }
66 }
67}
68
69impl<N: Network> Debug for ViewCore<N> {
70 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
71 Display::fmt(self, f)
72 }
73}
74
75impl<N: Network> Display for ViewCore<N> {
76 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
77 write!(f, "{} {}:", Self::type_name(), self.name)?;
78 self.inputs.iter().try_for_each(|input| write!(f, "\n {input}"))?;
79 self.commands.iter().try_for_each(|command| write!(f, "\n {command}"))?;
80 self.outputs.iter().try_for_each(|output| write!(f, "\n {output}"))
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use console::network::MainnetV0;
88
89 type CurrentNetwork = MainnetV0;
90
91 #[test]
92 fn test_view_parse() {
93 let view = ViewCore::<CurrentNetwork>::parse(
94 r"
95view foo:
96 input r0 as field.public;
97 input r1 as field.public;
98 add r0 r1 into r2;
99 output r2 as field.public;",
100 )
101 .unwrap()
102 .1;
103 assert_eq!("foo", view.name().to_string());
104 assert_eq!(2, view.inputs().len());
105 assert_eq!(1, view.commands().len());
106 assert_eq!(1, view.outputs().len());
107 }
108
109 #[test]
110 fn test_view_parse_no_inputs() {
111 let view = ViewCore::<CurrentNetwork>::parse(
112 r"
113view foo:
114 add 1u64 2u64 into r0;
115 output r0 as u64.public;",
116 )
117 .unwrap()
118 .1;
119 assert_eq!("foo", view.name().to_string());
120 assert_eq!(0, view.inputs().len());
121 assert_eq!(1, view.commands().len());
122 assert_eq!(1, view.outputs().len());
123 }
124
125 #[test]
126 fn test_view_display() {
127 let expected = r"view foo:
128 input r0 as field.public;
129 input r1 as field.public;
130 add r0 r1 into r2;
131 output r2 as field.public;";
132 let view = ViewCore::<CurrentNetwork>::parse(expected).unwrap().1;
133 assert_eq!(expected, format!("{view}"));
134 }
135
136 #[test]
137 fn test_view_parse_fails() {
138 assert!(
140 ViewCore::<CurrentNetwork>::from_str(
141 r"
142foo:
143 add 1u64 2u64 into r0;
144 output r0 as u64.public;"
145 )
146 .is_err()
147 );
148 assert!(
150 ViewCore::<CurrentNetwork>::from_str(
151 r"
152view foo
153 add 1u64 2u64 into r0;
154 output r0 as u64.public;"
155 )
156 .is_err()
157 );
158 assert!(
160 ViewCore::<CurrentNetwork>::from_str(
161 r"
162view foo:
163 input r0 as u64.public;
164 set r0 into balances[r0];
165 output r0 as u64.public;"
166 )
167 .is_err()
168 );
169 }
170
171 #[test]
172 fn test_view_parse_no_outputs_guard() {
173 let view = ViewCore::<CurrentNetwork>::parse(
176 r"
177view require_zero:
178 input r0 as u64.public;
179 assert.eq r0 0u64;",
180 )
181 .unwrap()
182 .1;
183 assert_eq!("require_zero", view.name().to_string());
184 assert_eq!(1, view.inputs().len());
185 assert_eq!(1, view.commands().len());
186 assert_eq!(0, view.outputs().len());
187 }
188
189 #[test]
190 fn test_view_parse_no_commands_passthrough() {
191 let view = ViewCore::<CurrentNetwork>::parse(
193 r"
194view identity:
195 input r0 as u64.public;
196 output r0 as u64.public;",
197 )
198 .unwrap()
199 .1;
200 assert_eq!("identity", view.name().to_string());
201 assert_eq!(1, view.inputs().len());
202 assert_eq!(0, view.commands().len());
203 assert_eq!(1, view.outputs().len());
204 }
205
206 #[test]
207 fn test_view_parse_fully_empty() {
208 let view = ViewCore::<CurrentNetwork>::parse(
210 r"
211view noop:",
212 )
213 .unwrap()
214 .1;
215 assert_eq!("noop", view.name().to_string());
216 assert_eq!(0, view.inputs().len());
217 assert_eq!(0, view.commands().len());
218 assert_eq!(0, view.outputs().len());
219 }
220}