Skip to main content

snarkvm_synthesizer_program/logic/command/
position.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM 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
16use crate::Opcode;
17use console::{network::prelude::*, program::Identifier};
18
19/// A position command, e.g. `position exit`.
20/// Indicates a position to which the program can branch to.
21#[derive(Clone, PartialEq, Eq, Hash)]
22pub struct Position<N: Network> {
23    /// The name to reference when branching to this position.
24    name: Identifier<N>,
25}
26
27impl<N: Network> Position<N> {
28    /// Returns the opcode.
29    #[inline]
30    pub const fn opcode() -> Opcode {
31        Opcode::Command("position")
32    }
33
34    /// Returns the name.
35    #[inline]
36    pub fn name(&self) -> &Identifier<N> {
37        &self.name
38    }
39
40    /// Returns whether this command refers to an external struct.
41    #[inline]
42    pub fn contains_external_struct(&self) -> bool {
43        false
44    }
45}
46
47impl<N: Network> Position<N> {
48    /// Finalizes the command.
49    /// Note that `Position` is a no-op.
50    #[inline]
51    pub fn finalize(&self) -> Result<()> {
52        Ok(())
53    }
54}
55
56impl<N: Network> Parser for Position<N> {
57    /// Parses a string into a command.
58    #[inline]
59    fn parse(string: &str) -> ParserResult<Self> {
60        // Parse the whitespace and comments from the string.
61        let (string, _) = Sanitizer::parse(string)?;
62        // Parse the opcode from the string.
63        let (string, _) = tag(*Self::opcode())(string)?;
64        // Parse the whitespace from the string.
65        let (string, _) = Sanitizer::parse_whitespaces(string)?;
66
67        // Parse the name from the string.
68        let (string, name) = Identifier::parse(string)?;
69
70        // Parse the whitespace from the string.
71        let (string, _) = Sanitizer::parse_whitespaces(string)?;
72        // Parse the ";" from the string.
73        let (string, _) = tag(";")(string)?;
74
75        Ok((string, Self { name }))
76    }
77}
78
79impl<N: Network> FromStr for Position<N> {
80    type Err = Error;
81
82    /// Parses a string into the command.
83    #[inline]
84    fn from_str(string: &str) -> Result<Self> {
85        match Self::parse(string) {
86            Ok((remainder, object)) => {
87                // Ensure the remainder is empty.
88                ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
89                // Return the object.
90                Ok(object)
91            }
92            Err(error) => bail!("Failed to parse string. {error}"),
93        }
94    }
95}
96
97impl<N: Network> Debug for Position<N> {
98    /// Prints the command as a string.
99    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
100        Display::fmt(self, f)
101    }
102}
103
104impl<N: Network> Display for Position<N> {
105    /// Prints the command to a string.
106    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
107        // Print the command.
108        write!(f, "{} ", Self::opcode())?;
109        // Print the name.
110        write!(f, "{};", self.name)
111    }
112}
113
114impl<N: Network> FromBytes for Position<N> {
115    /// Reads the command from a buffer.
116    fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
117        // Read the name.
118        let name = Identifier::read_le(&mut reader)?;
119        // Return the command.
120        Ok(Self { name })
121    }
122}
123
124impl<N: Network> ToBytes for Position<N> {
125    /// Writes the command to a buffer.
126    fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
127        // Write the name.
128        self.name.write_le(&mut writer)
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135    use console::network::MainnetV0;
136
137    type CurrentNetwork = MainnetV0;
138
139    #[test]
140    fn test_parse() {
141        let (string, position) = Position::<CurrentNetwork>::parse("position exit;").unwrap();
142        assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
143        assert_eq!(position.name, Identifier::from_str("exit").unwrap());
144    }
145}