diff --git a/compiler/ast/src/functions/input/function_input.rs b/compiler/ast/src/functions/input/function_input.rs index 0da279d029..4aa10eec78 100644 --- a/compiler/ast/src/functions/input/function_input.rs +++ b/compiler/ast/src/functions/input/function_input.rs @@ -20,17 +20,32 @@ use leo_span::Span; use serde::{Deserialize, Serialize}; use std::fmt; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum ParamMode { + Const, + Private, + Public, +} + +impl fmt::Display for ParamMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use ParamMode::*; + + match self { + Const => write!(f, "const"), + Private => write!(f, "private"), + Public => write!(f, "public"), + } + } +} + /// A function parameter. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct FunctionInputVariable { /// The name the parameter is accessible as in the function's body. pub identifier: Identifier, /// Is it a const parameter? - pub const_: bool, - /// Is it a public parameter? - pub public: bool, - /// Is it a mutable parameter? - pub mutable: bool, + pub mode: ParamMode, /// What's the parameter's type? pub type_: Type, /// The parameters span from any annotations to its type. @@ -39,17 +54,7 @@ pub struct FunctionInputVariable { impl FunctionInputVariable { fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.public { - write!(f, "public ")?; - } else { - write!(f, "private ")?; - } - if self.const_ { - write!(f, "const ")?; - } - if self.mutable { - write!(f, "mut ")?; - } + write!(f, "{} ", self.mode)?; write!(f, "{}: ", self.identifier)?; write!(f, "{}", self.type_) } diff --git a/compiler/ast/src/input/definition.rs b/compiler/ast/src/input/definition.rs index 9090111b5e..6be63b04d3 100644 --- a/compiler/ast/src/input/definition.rs +++ b/compiler/ast/src/input/definition.rs @@ -15,14 +15,13 @@ // along with the Leo library. If not, see . use super::*; -use crate::{Expression, Identifier, Type}; +use crate::{Expression, Identifier, ParamMode, Type}; /// A single definition inside a section in a state or an input file. /// Definitions should be structured as: `: = ;` #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Definition { - pub const_: bool, - pub public: bool, + pub mode: ParamMode, pub type_: Type, pub name: Identifier, pub value: Expression, diff --git a/compiler/ast/src/reducer/reconstructing_reducer.rs b/compiler/ast/src/reducer/reconstructing_reducer.rs index 1af16ec488..d47053ad4e 100644 --- a/compiler/ast/src/reducer/reconstructing_reducer.rs +++ b/compiler/ast/src/reducer/reconstructing_reducer.rs @@ -274,9 +274,7 @@ pub trait ReconstructingReducer { ) -> Result { Ok(FunctionInputVariable { identifier, - const_: variable.const_, - mutable: variable.mutable, - public: variable.public, + mode: variable.mode, type_, span: variable.span.clone(), }) diff --git a/compiler/parser/src/parser/file.rs b/compiler/parser/src/parser/file.rs index 8fc836d74e..effb6b13a3 100644 --- a/compiler/parser/src/parser/file.rs +++ b/compiler/parser/src/parser/file.rs @@ -61,12 +61,23 @@ impl ParserContext<'_> { ) } + pub fn parse_function_parameter_mode(&mut self) -> Result { + let public = self.eat(Token::Public); + let const_ = self.eat(Token::Const); + + match (public, const_) { + (None, Some(_)) => Ok(ParamMode::Const), + (None, None) => Ok(ParamMode::Private), + (Some(_), None) => Ok(ParamMode::Public), + (Some(p), Some(c)) => Err(ParserError::inputs_multiple_variable_types_specified(&(p.span + c.span)).into()), + } + } + /// /// Returns a [`FunctionInput`] AST node if the next tokens represent a function parameter. /// pub fn parse_function_parameters(&mut self) -> Result { - let public = self.eat(Token::Public).is_some(); - let const_ = self.eat(Token::Const); + let mode = self.parse_function_parameter_mode()?; let mutable = self.eat(Token::Mut); let name = self.expect_ident()?; @@ -78,9 +89,7 @@ impl ParserContext<'_> { self.expect(Token::Colon)?; let type_ = self.parse_type()?.0; Ok(FunctionInput::Variable(FunctionInputVariable { - const_: const_.is_some(), - mutable: const_.is_none(), - public, + mode, type_, span: name.span.clone(), identifier: name, diff --git a/compiler/parser/src/parser/input.rs b/compiler/parser/src/parser/input.rs index 8750b7d3c3..2c0b68d6f8 100644 --- a/compiler/parser/src/parser/input.rs +++ b/compiler/parser/src/parser/input.rs @@ -67,8 +67,7 @@ impl ParserContext<'_> { /// ` : = ;` /// Returns [`Definition`]. pub fn parse_input_definition(&mut self) -> Result { - let public = self.eat(Token::Public).is_some(); - let const_ = self.eat(Token::Const).is_some(); + let mode = self.parse_function_parameter_mode()?; let name = self.expect_ident()?; self.expect(Token::Colon)?; @@ -78,8 +77,7 @@ impl ParserContext<'_> { self.expect(Token::Semicolon)?; Ok(Definition { - const_, - public, + mode, name, type_, value, diff --git a/leo/errors/src/parser/parser_errors.rs b/leo/errors/src/parser/parser_errors.rs index 9ce55319ca..217e305152 100644 --- a/leo/errors/src/parser/parser_errors.rs +++ b/leo/errors/src/parser/parser_errors.rs @@ -358,4 +358,12 @@ create_errors!( msg: format!("Found the char `{}`, but expected `{}`", found, expected), help: None, } + + /// For when a user specified more than a type on a parameter. + @formatted + inputs_multiple_variable_types_specified { + args: (), + msg: "A parameter cannot be both public and const.", + help: None, + } ); diff --git a/leo/span/src/symbol.rs b/leo/span/src/symbol.rs index 20d0b91200..095f0f83b6 100644 --- a/leo/span/src/symbol.rs +++ b/leo/span/src/symbol.rs @@ -131,7 +131,7 @@ symbols! { main, Mut: "mut", prelude, - Public: "public", + Public, Return: "return", Star: "*", std,