impl tuple parsing

This commit is contained in:
collin 2022-07-09 12:39:50 -07:00
parent 296c62a280
commit 9e422599a0
7 changed files with 36 additions and 17 deletions

View File

@ -320,8 +320,8 @@ impl ParserContext<'_> {
})) }))
} }
/// Parses a tuple of expressions. /// Parses a tuple of `Expression` AST nodes.
fn parse_expr_tuple(&mut self) -> Result<(Vec<Expression>, bool, Span)> { pub(crate) fn parse_expr_tuple(&mut self) -> Result<(Vec<Expression>, bool, Span)> {
self.parse_paren_comma_list(|p| p.parse_expression().map(Some)) self.parse_paren_comma_list(|p| p.parse_expression().map(Some))
} }
@ -384,7 +384,10 @@ impl ParserContext<'_> {
if !trailing && tuple.len() == 1 { if !trailing && tuple.len() == 1 {
Ok(tuple.swap_remove(0)) Ok(tuple.swap_remove(0))
} else { } else {
Err(ParserError::unexpected("A tuple expression.", "A valid expression.", span).into()) Ok(Expression::Tuple(TupleExpression {
elements: tuple,
span
}))
} }
} }

View File

@ -107,7 +107,7 @@ impl ParserContext<'_> {
fn parse_member(&mut self) -> Result<(Identifier, Type)> { fn parse_member(&mut self) -> Result<(Identifier, Type)> {
let name = self.expect_ident()?; let name = self.expect_ident()?;
self.expect(&Token::Colon)?; self.expect(&Token::Colon)?;
let type_ = self.parse_all_types()?.0; let type_ = self.parse_single_type()?.0;
Ok((name, type_)) Ok((name, type_))
} }
@ -201,7 +201,7 @@ impl ParserContext<'_> {
let name = self.expect_ident()?; let name = self.expect_ident()?;
self.expect(&Token::Colon)?; self.expect(&Token::Colon)?;
let type_ = self.parse_all_types()?.0; let type_ = self.parse_single_type()?.0;
Ok(FunctionInput::Variable(FunctionInputVariable::new( Ok(FunctionInput::Variable(FunctionInputVariable::new(
name, mode, type_, name.span, name, mode, type_, name.span,
))) )))
@ -229,7 +229,7 @@ impl ParserContext<'_> {
// Parse return type. // Parse return type.
self.expect(&Token::Arrow)?; self.expect(&Token::Arrow)?;
self.disallow_circuit_construction = true; self.disallow_circuit_construction = true;
let output = self.parse_all_types()?.0; let output = self.parse_any_type()?.0;
self.disallow_circuit_construction = false; self.disallow_circuit_construction = false;
// Parse the function body. // Parse the function body.

View File

@ -103,7 +103,7 @@ impl ParserContext<'_> {
let start_span = self.expect(&Token::For)?; let start_span = self.expect(&Token::For)?;
let ident = self.expect_ident()?; let ident = self.expect_ident()?;
self.expect(&Token::Colon)?; self.expect(&Token::Colon)?;
let type_ = self.parse_all_types()?; let type_ = self.parse_single_type()?;
self.expect(&Token::In)?; self.expect(&Token::In)?;
// Parse iteration range. // Parse iteration range.
@ -222,7 +222,7 @@ impl ParserContext<'_> {
}; };
self.expect(&Token::Colon)?; self.expect(&Token::Colon)?;
let type_ = self.parse_all_types()?; let type_ = self.parse_single_type()?;
self.expect(&Token::Assign)?; self.expect(&Token::Assign)?;
let expr = self.parse_expression()?; let expr = self.parse_expression()?;

View File

@ -74,7 +74,7 @@ impl ParserContext<'_> {
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type. /// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type.
/// Also returns the span of the parsed token. /// Also returns the span of the parsed token.
pub fn parse_all_types(&mut self) -> Result<(Type, Span)> { pub fn parse_single_type(&mut self) -> Result<(Type, Span)> {
Ok(if let Some(ident) = self.eat_identifier() { Ok(if let Some(ident) = self.eat_identifier() {
let span = ident.span; let span = ident.span;
(Type::Identifier(ident), span) (Type::Identifier(ident), span)
@ -82,4 +82,21 @@ impl ParserContext<'_> {
self.parse_non_ident_types()? self.parse_non_ident_types()?
}) })
} }
/// Returns a [`(Type, Span)`] where `Type` is a `Type::Tuple` AST node.
pub fn parse_tuple_type(&mut self) -> Result<(Type, Span)> { // todo: catch and return error for nested tuple type.
let (types, _, span) = self.parse_paren_comma_list(|p| p.parse_single_type().map(Some))?;
let elements = types.into_iter().map(|(type_, _)| type_).collect::<Vec<_>>();
Ok((Tuple::new(elements, span)?, span))
}
/// Returns a [`(Type, Span)`] where `Type` is a tuple or single type.
pub fn parse_any_type(&mut self) -> Result<(Type, Span)> {
if self.peek_is_left_par() {
self.parse_tuple_type()
} else {
self.parse_single_type()
}
}
} }

View File

@ -26,7 +26,7 @@ function mint(r0: address, r1: u64) -> Token {
// The `transfer` function sends the specified number of tokens // The `transfer` function sends the specified number of tokens
// to the receiver from the provided token record. // to the receiver from the provided token record.
function transfer(r0: Token, r1: Receiver) -> Token { function transfer(r0: Token, r1: Receiver) -> (Token, Token) {
// Checks the given token record has sufficient balance. // Checks the given token record has sufficient balance.
// This `sub` operation is safe, and the proof will fail // This `sub` operation is safe, and the proof will fail
// if an overflow occurs. The output register `r2` holds // if an overflow occurs. The output register `r2` holds
@ -41,8 +41,7 @@ function transfer(r0: Token, r1: Receiver) -> Token {
// with the change amount for the sender. // with the change amount for the sender.
let r4: Token = mint(r0.owner, r0.amount); let r4: Token = mint(r0.owner, r0.amount);
// return (r3, r4); return (r3, r4);
return r3;
} }
function main() -> u8 { function main() -> u8 {

View File

@ -131,19 +131,19 @@ create_messages!(
help: None, help: None,
} }
/// For when a user tries to define a tuple dimension of 1. /// For when a user tries to define an empty tuple.
@formatted @formatted
empty_tuple { empty_tuple {
args: (), args: (),
msg: "Tuples of 0 elements are not allowed.", msg: "Tuples of zero elements are not allowed.",
help: None, help: None,
} }
/// For when a user tries to define a tuple dimension of 1. /// For when a user tries to define a tuple dimension of one.
@formatted @formatted
one_element_tuple { one_element_tuple {
args: (), args: (),
msg: "Tuples of 1 element are not allowed.", msg: "Tuples of one element are not allowed.",
help: Some("Try defining a single type by removing the parenthesis `( )`".to_string()), help: Some("Try defining a single type by removing the parenthesis `( )`".to_string()),
} }

View File

@ -275,7 +275,7 @@ create_messages!(
@formatted @formatted
incorrect_tuple_length { incorrect_tuple_length {
args: (expected: impl Display, actual: impl Display), args: (expected: impl Display, actual: impl Display),
msg: format!("Expected a tuple of length `{expected}` got `{actual}`"), msg: format!("Expected a tuple of length `{expected}` found length `{actual}`"),
help: None, help: None,
} }