mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-11 04:49:15 +03:00
Parser support for transition keyword
This commit is contained in:
parent
62b16cfa51
commit
80d8880292
28
compiler/ast/src/functions/call_type.rs
Normal file
28
compiler/ast/src/functions/call_type.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2019-2022 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// An enum declaring how the function is invoked.
|
||||
/// A transition function is permitted the ability to manipulate records.
|
||||
/// A regular function is not permitted to manipulate records.
|
||||
/// An inline function is directly copied at the call site.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum CallType {
|
||||
Inline,
|
||||
Standard,
|
||||
Transition,
|
||||
}
|
@ -17,6 +17,9 @@
|
||||
pub mod annotation;
|
||||
pub use annotation::*;
|
||||
|
||||
pub mod call_type;
|
||||
pub use call_type::*;
|
||||
|
||||
pub mod external;
|
||||
pub use external::*;
|
||||
|
||||
@ -43,6 +46,8 @@ use std::fmt;
|
||||
pub struct Function {
|
||||
/// Annotations on the function.
|
||||
pub annotations: Vec<Annotation>,
|
||||
/// Is this function a transition, inlined, or a regular function?.
|
||||
pub call_type: CallType,
|
||||
/// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
|
||||
pub identifier: Identifier,
|
||||
/// The function's input parameters.
|
||||
@ -69,8 +74,10 @@ impl Eq for Function {}
|
||||
|
||||
impl Function {
|
||||
/// Initialize a new function.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
annotations: Vec<Annotation>,
|
||||
call_type: CallType,
|
||||
identifier: Identifier,
|
||||
input: Vec<Input>,
|
||||
output: Vec<Output>,
|
||||
@ -92,6 +99,7 @@ impl Function {
|
||||
|
||||
Function {
|
||||
annotations,
|
||||
call_type,
|
||||
identifier,
|
||||
input,
|
||||
output,
|
||||
@ -115,7 +123,12 @@ impl Function {
|
||||
/// Private formatting method used for optimizing [fmt::Debug] and [fmt::Display] implementations.
|
||||
///
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "function {}", self.identifier)?;
|
||||
match self.call_type {
|
||||
CallType::Inline => write!(f, "inline ")?,
|
||||
CallType::Standard => write!(f, "function ")?,
|
||||
CallType::Transition => write!(f, "transition ")?,
|
||||
}
|
||||
write!(f, "{}", self.identifier)?;
|
||||
|
||||
let parameters = self.input.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
|
||||
let returns = match self.output.len() {
|
||||
|
@ -341,6 +341,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
fn reconstruct_function(&mut self, input: Function) -> Function {
|
||||
Function {
|
||||
annotations: input.annotations,
|
||||
call_type: input.call_type,
|
||||
identifier: input.identifier,
|
||||
input: input.input,
|
||||
output: input.output,
|
||||
|
@ -177,7 +177,7 @@ impl<'a> ParserContext<'a> {
|
||||
}
|
||||
|
||||
/// Returns an unexpected error at the current token.
|
||||
fn unexpected<T>(&self, expected: impl Display) -> Result<T> {
|
||||
pub(super) fn unexpected<T>(&self, expected: impl Display) -> Result<T> {
|
||||
Err(ParserError::unexpected(&self.token.token, expected, self.token.span).into())
|
||||
}
|
||||
|
||||
|
@ -51,12 +51,8 @@ impl ParserContext<'_> {
|
||||
let (id, function) = self.parse_function()?;
|
||||
functions.insert(id, function);
|
||||
}
|
||||
Token::Const if self.peek_is_function() => {
|
||||
let (id, function) = self.parse_function()?;
|
||||
functions.insert(id, function);
|
||||
}
|
||||
Token::Identifier(sym::test) => return Err(ParserError::test_function(self.token.span).into()),
|
||||
Token::Function => {
|
||||
Token::Function | Token::Transition => {
|
||||
let (id, function) = self.parse_function()?;
|
||||
functions.insert(id, function);
|
||||
}
|
||||
@ -330,15 +326,6 @@ impl ParserContext<'_> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if the next token is Function or if it is a Const followed by Function.
|
||||
/// Returns `false` otherwise.
|
||||
fn peek_is_function(&self) -> bool {
|
||||
matches!(
|
||||
(&self.token.token, self.look_ahead(1, |t| &t.token)),
|
||||
(Token::Function, _) | (Token::Const, Token::Function)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns an [`Annotation`] AST node if the next tokens represent an annotation.
|
||||
fn parse_annotation(&mut self) -> Result<Annotation> {
|
||||
// Parse the `@` symbol and identifier.
|
||||
@ -364,8 +351,12 @@ impl ParserContext<'_> {
|
||||
while self.look_ahead(0, |t| &t.token) == &Token::At {
|
||||
annotations.push(self.parse_annotation()?)
|
||||
}
|
||||
// Parse `function IDENT`.
|
||||
let start = self.expect(&Token::Function)?;
|
||||
// Parse `<call_type> IDENT`, where `<call_type>` is `function` or `transition`.
|
||||
let (call_type, start) = match self.token.token {
|
||||
Token::Function => (CallType::Standard, self.expect(&Token::Function)?),
|
||||
Token::Transition => (CallType::Transition, self.expect(&Token::Transition)?),
|
||||
_ => self.unexpected("'function', 'transition'")?,
|
||||
};
|
||||
let name = self.expect_identifier()?;
|
||||
|
||||
// Parse parameters.
|
||||
@ -426,7 +417,7 @@ impl ParserContext<'_> {
|
||||
let span = start + block.span;
|
||||
Ok((
|
||||
name,
|
||||
Function::new(annotations, name, inputs, output, block, finalize, span),
|
||||
Function::new(annotations, call_type, name, inputs, output, block, finalize, span),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,7 @@ impl ProgramReconstructor for Flattener<'_> {
|
||||
|
||||
Function {
|
||||
annotations: function.annotations,
|
||||
call_type: function.call_type,
|
||||
identifier: function.identifier,
|
||||
input: function.input,
|
||||
output: function.output,
|
||||
|
@ -58,6 +58,7 @@ impl ProgramReconstructor for Unroller<'_> {
|
||||
// Reconstruct the function block.
|
||||
let reconstructed_function = Function {
|
||||
annotations: function.annotations,
|
||||
call_type: function.call_type,
|
||||
identifier: function.identifier,
|
||||
input: function.input,
|
||||
output: function.output,
|
||||
|
@ -72,6 +72,7 @@ impl FunctionConsumer for StaticSingleAssigner {
|
||||
|
||||
Function {
|
||||
annotations: function.annotations,
|
||||
call_type: function.call_type,
|
||||
identifier: function.identifier,
|
||||
input: function.input,
|
||||
output: function.output,
|
||||
|
Loading…
Reference in New Issue
Block a user