Support private mode in parser and passes

This commit is contained in:
d0cd 2022-11-12 09:53:20 -08:00
parent 1b95340edc
commit b16926449c
8 changed files with 40 additions and 22 deletions

View File

@ -279,7 +279,7 @@ impl ParserContext<'_> {
/// Returns a [`ParamMode`] AST node if the next tokens represent a function parameter mode.
pub(super) fn parse_mode(&mut self) -> Result<Mode> {
// TODO: Allow explicit "private" mode.
let private = self.eat(&Token::Private).then_some(self.prev_token.span);
let public = self.eat(&Token::Public).then_some(self.prev_token.span);
let constant = self.eat(&Token::Constant).then_some(self.prev_token.span);
let const_ = self.eat(&Token::Const).then_some(self.prev_token.span);
@ -288,16 +288,21 @@ impl ParserContext<'_> {
self.emit_warning(ParserWarning::const_parameter_or_input(span));
}
match (public, constant, const_) {
(None, Some(_), None) => Ok(Mode::Const),
(None, None, Some(_)) => Ok(Mode::Const),
(None, None, None) => Ok(Mode::None),
(Some(_), None, None) => Ok(Mode::Public),
(Some(m1), Some(m2), None) | (Some(m1), None, Some(m2)) | (None, Some(m1), Some(m2)) => {
Err(ParserError::inputs_multiple_variable_types_specified(m1 + m2).into())
}
(Some(m1), Some(m2), Some(m3)) => {
Err(ParserError::inputs_multiple_variable_types_specified(m1 + m2 + m3).into())
match (private, public, constant, const_) {
(None, None, None, None) => Ok(Mode::None),
(Some(_), None, None, None) => Ok(Mode::Private),
(None, Some(_), None, None) => Ok(Mode::Public),
(None, None, Some(_), None) => Ok(Mode::Const),
(None, None, None, Some(_)) => Ok(Mode::Const),
_ => {
let mut spans = [private, public, constant, const_].into_iter().flatten();
// There must exist at least one mode, since the none case is handled above.
let starting_span = spans.next().unwrap();
// Sum the spans.
let summed_span = spans.fold(starting_span, |span, next| span + next);
// Emit an error.
Err(ParserError::inputs_multiple_variable_modes_specified(summed_span).into())
}
}
}

View File

@ -420,6 +420,7 @@ impl Token {
"let" => Token::Let,
"leo" => Token::Leo,
"mapping" => Token::Mapping,
"private" => Token::Private,
"program" => Token::Program,
"public" => Token::Public,
"record" => Token::Record,

View File

@ -103,7 +103,9 @@ mod tests {
input
let
mut
private
program
public
return
scalar
self
@ -161,7 +163,7 @@ mod tests {
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address async bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut program return scalar self string struct test transition true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address async bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut private program public return scalar self string struct test transition true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
/* test */ // "#
);
});

View File

@ -126,6 +126,7 @@ pub enum Token {
Increment,
Let,
Mapping,
Private,
Program,
// For public inputs.
Public,
@ -171,6 +172,7 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Increment,
Token::Let,
Token::Mapping,
Token::Private,
Token::Program,
Token::Public,
Token::Record,
@ -224,8 +226,9 @@ impl Token {
Token::Let => sym::Let,
Token::Leo => sym::leo,
Token::Mapping => sym::mapping,
Token::Private => sym::private,
Token::Program => sym::program,
Token::Public => sym::Public,
Token::Public => sym::public,
Token::Record => sym::record,
Token::Return => sym::Return,
Token::Scalar => sym::scalar,
@ -345,6 +348,7 @@ impl fmt::Display for Token {
Increment => write!(f, "increment"),
Let => write!(f, "let"),
Mapping => write!(f, "mapping"),
Private => write!(f, "private"),
Program => write!(f, "program"),
Public => write!(f, "public"),
Return => write!(f, "return"),

View File

@ -143,7 +143,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
true if input_var.mode() == Mode::Const => self.emit_err(
TypeCheckerError::transition_function_inputs_cannot_be_const(input_var.span()),
),
// If the function is not a program function, then check that the parameters do not have an associated mode.
// If the function is not a transition function, then check that the parameters do not have an associated mode.
false if input_var.mode() != Mode::None => self.emit_err(
TypeCheckerError::regular_function_inputs_cannot_have_modes(input_var.span()),
),
@ -253,8 +253,8 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
self.assert_type_is_valid(output_type.span(), &output_type.type_());
// Check that the mode of the output is valid.
if output_type.mode() == Mode::Const {
self.emit_err(TypeCheckerError::finalize_input_mode_must_be_public(output_type.span()));
if output_type.mode() == Mode::Const || output_type.mode() == Mode::Private {
self.emit_err(TypeCheckerError::finalize_output_mode_must_be_public(output_type.span()));
}
});

View File

@ -206,7 +206,6 @@ symbols! {
mapping,
Mut: "mut",
prelude,
Public,
Return: "return",
SelfLower: "self",
SelfUpper: "Self",

View File

@ -183,12 +183,12 @@ create_messages!(
help: None,
}
/// For when a user specified more than a type on a parameter.
/// For when a user specified more than one mode on a parameter.
@formatted
inputs_multiple_variable_types_specified {
inputs_multiple_variable_modes_specified {
args: (),
msg: "A parameter cannot be both public and const.",
help: None,
msg: "A parameter cannot have multiple modes.",
help: Some("Consider using either `constant`, `public`, `private`, or none at all.".to_string()),
}
/// For when the lexer encountered a bidi override character

View File

@ -314,7 +314,14 @@ create_messages!(
finalize_input_mode_must_be_public {
args: (),
msg: format!("An input to a finalize block must be public."),
help: Some("Add a `public` modifier to the input variable declaration or remove the visibility modifier entirely.".to_string()),
help: Some("Use a `public` modifier to the input variable declaration or remove the visibility modifier entirely.".to_string()),
}
@formatted
finalize_output_mode_must_be_public {
args: (),
msg: format!("An output from a finalize block must be public."),
help: Some("Use a `public` modifier to the output variable declaration or remove the visibility modifier entirely.".to_string()),
}
@formatted