mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
parsing ambiguous explicit future types. Ex: Future<u32, Future<u32>>
This commit is contained in:
parent
5903635fa3
commit
bf95c4966a
@ -41,6 +41,8 @@ pub(crate) struct ParserContext<'a> {
|
||||
pub(crate) disallow_struct_construction: bool,
|
||||
/// The name of the program being parsed.
|
||||
pub(crate) program_name: Option<Symbol>,
|
||||
/// Whether traversing an ambiguous Shr token.
|
||||
pub in_angle: bool,
|
||||
}
|
||||
|
||||
/// Dummy span used to appease borrow checker.
|
||||
@ -63,6 +65,7 @@ impl<'a> ParserContext<'a> {
|
||||
token,
|
||||
tokens,
|
||||
program_name: None,
|
||||
in_angle: false,
|
||||
};
|
||||
p.bump();
|
||||
p
|
||||
@ -248,6 +251,51 @@ impl<'a> ParserContext<'a> {
|
||||
self.parse_list(Delimiter::Bracket, Some(Token::Comma), f)
|
||||
}
|
||||
|
||||
/// Parse a list separated by `,` and delimited by angle brackets.
|
||||
/// Since the `>>` token is ambiguous, we need to create special state checks.
|
||||
pub (super) fn parse_angle_comma_list<T>(
|
||||
&mut self,
|
||||
sep: Option<Token>,
|
||||
mut f: impl FnMut(&mut Self) -> Result<Option<T>>,
|
||||
) -> Result<(Vec<T>, bool, Span)> {
|
||||
let (open, close) = Delimiter::AngleBracket.open_close_pair();
|
||||
let mut list = Vec::new();
|
||||
let mut trailing = false;
|
||||
|
||||
// Parse opening delimiter.
|
||||
let open_span = self.expect(&open)?;
|
||||
|
||||
while !self.check(&close) && !self.check(&Token::Shr){
|
||||
// Parse the element. We allow inner parser recovery through the `Option`.
|
||||
if let Some(elem) = f(self)? {
|
||||
list.push(elem);
|
||||
}
|
||||
// Parse the separator, if any.
|
||||
if sep.as_ref().filter(|sep| !self.eat(sep)).is_some() {
|
||||
trailing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
trailing = true;
|
||||
}
|
||||
|
||||
if self.token.token == Token::Shr {
|
||||
return if self.in_angle {
|
||||
self.in_angle = false;
|
||||
let end_span = self.expect(&Token::Shr)?;
|
||||
Ok((list, trailing, open_span + end_span))
|
||||
} else {
|
||||
self.in_angle = true;
|
||||
Ok((list, trailing, open_span + self.prev_token.span))
|
||||
};
|
||||
}
|
||||
|
||||
// Parse closing delimiter.
|
||||
let span = open_span + self.expect(&close)?;
|
||||
|
||||
Ok((list, trailing, span))
|
||||
}
|
||||
|
||||
/// Returns true if the current token is `(`.
|
||||
pub(super) fn peek_is_left_par(&self) -> bool {
|
||||
matches!(self.token.token, Token::LeftParen)
|
||||
|
@ -66,7 +66,6 @@ impl ParserContext<'_> {
|
||||
Token::Address => Type::Address,
|
||||
Token::Bool => Type::Boolean,
|
||||
Token::Field => Type::Field,
|
||||
Token::Future => Type::Future(Default::default()),
|
||||
Token::Group => Type::Group,
|
||||
Token::Scalar => Type::Scalar,
|
||||
Token::Signature => Type::Signature,
|
||||
@ -131,6 +130,23 @@ impl ParserContext<'_> {
|
||||
// Note: This is the only place where `Tuple` type is constructed in the parser.
|
||||
_ => Ok((Type::Tuple(TupleType::new(types.into_iter().map(|t| t.0).collect())), span)),
|
||||
}
|
||||
}
|
||||
else if self.token.token == Token::Future {
|
||||
// Parse the `Future` token.
|
||||
let span = self.expect(&Token::Future)?;
|
||||
// Parse the angle bracket list.
|
||||
if self.token.token == Token::Lt {
|
||||
let (types, _, full_span) = self.parse_angle_comma_list(Some(Token::Comma),|p| p.parse_type().map(Some))?;
|
||||
match types.len() {
|
||||
0 => return Err(ParserError::future_must_have_at_least_one_element(span).into()),
|
||||
// `Future<()>` corresponds to explicitly specifying a `Future` type with no inputs.
|
||||
1 if matches!(types.get(0).unwrap().0, Type::Unit) => return Ok((Type::Future(FutureType::new(vec![], None, true)), span + full_span)),
|
||||
_ => {},
|
||||
}
|
||||
Ok((Type::Future(FutureType::new(types.into_iter().map(|t| t.0).collect(), None, true)), span + full_span))
|
||||
} else {
|
||||
Ok((Type::Future(Default::default()), span))
|
||||
}
|
||||
} else {
|
||||
self.parse_primitive_type()
|
||||
}
|
||||
|
@ -342,4 +342,11 @@ create_messages!(
|
||||
msg: format!("Cannot create an external record. Records can only be created in the program that they are defined in."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
future_must_have_at_least_one_element {
|
||||
args: (),
|
||||
msg: "Future type must have at least one element.".to_string(),
|
||||
help: Some("Write `Future<()>` to explicitly type a future with no inputs.".to_string()),
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user