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,