Add finalize block to AST

This commit is contained in:
Pranav Gaddamadugu 2022-08-25 18:56:29 -07:00
parent 75307d1d4e
commit 5521e7f30b
14 changed files with 78 additions and 10 deletions

View File

@ -0,0 +1,45 @@
// 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 crate::{Block, FunctionInput, Node, Type};
use leo_span::Span;
use core::fmt;
use serde::{Deserialize, Serialize};
/// A finalize block.
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
pub struct Finalize {
/// The finalize block's input parameters.
pub input: Vec<FunctionInput>,
/// The finalize blocks's return type.
pub output: Type,
/// The body of the function.
pub block: Block,
/// The entire span of the finalize block.
pub span: Span,
}
impl fmt::Display for Finalize {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, " finalize")?;
let parameters = self.input.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
write!(f, "({}) -> {} {}", parameters, self.output, self.block)
}
}
crate::simple_node_impl!(Finalize);

View File

@ -17,6 +17,9 @@
pub mod annotation;
pub use annotation::*;
pub mod finalize;
pub use finalize::*;
pub mod function_input;
pub use function_input::*;
@ -24,7 +27,6 @@ use crate::{Block, Identifier, Node, Type};
use leo_span::{sym, Span, Symbol};
use serde::{Deserialize, Serialize};
use std::cell::Cell;
use std::fmt;
/// A function definition.
@ -38,11 +40,10 @@ pub struct Function {
pub input: Vec<FunctionInput>,
/// The function's required return type.
pub output: Type,
/// Any mapping to the core library.
/// Always `None` when initially parsed.
pub core_mapping: Cell<Option<Symbol>>,
/// The body of the function.
pub block: Block,
/// An optional finalize block
pub finalize: Option<Finalize>,
/// The entire span of the function definition.
pub span: Span,
}

View File

@ -22,6 +22,8 @@
#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
extern crate core;
pub mod access;
pub use self::access::*;

View File

@ -278,8 +278,13 @@ pub trait ProgramReconstructor: StatementReconstructor {
identifier: input.identifier,
input: input.input,
output: input.output,
core_mapping: input.core_mapping,
block: self.reconstruct_block(input.block),
finalize: input.finalize.map(|finalize| Finalize {
input: finalize.input,
output: finalize.output,
block: self.reconstruct_block(finalize.block),
span: finalize.span,
}),
span: input.span,
}
}

View File

@ -193,6 +193,9 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
fn visit_function(&mut self, input: &'a Function) {
self.visit_block(&input.block);
if let Some(finalize) = &input.finalize {
self.visit_block(&finalize.block);
}
}
fn visit_circuit(&mut self, _input: &'a Circuit) {}

View File

@ -43,6 +43,8 @@ pub enum Type {
String,
/// A static tuple of at least one type.
Tuple(Tuple),
/// The `unit` type.
Unit,
/// Placeholder for a type that could not be resolved or was not well-formed.
/// Will eventually lead to a compile error.
Err,
@ -61,7 +63,8 @@ impl Type {
| (Type::Field, Type::Field)
| (Type::Group, Type::Group)
| (Type::Scalar, Type::Scalar)
| (Type::String, Type::String) => true,
| (Type::String, Type::String)
| (Type::Unit, Type::Unit) => true,
(Type::Integer(left), Type::Integer(right)) => left.eq(right),
(Type::Mapping(left), Type::Mapping(right)) => {
left.key.eq_flat(&right.key) && left.value.eq_flat(&right.value)
@ -89,6 +92,7 @@ impl fmt::Display for Type {
Type::Scalar => write!(f, "scalar"),
Type::String => write!(f, "string"),
Type::Tuple(ref tuple) => write!(f, "{}", tuple),
Type::Unit => write!(f, "()"),
Type::Err => write!(f, "error"),
}
}

View File

@ -349,8 +349,8 @@ impl ParserContext<'_> {
input: inputs,
output,
span: start + block.span,
finalize: None,
block,
core_mapping: <_>::default(),
},
))
}

View File

@ -402,6 +402,7 @@ impl Token {
"else" => Token::Else,
"false" => Token::False,
"field" => Token::Field,
"finalize" => Token::Finalize,
"for" => Token::For,
"function" => Token::Function,
"group" => Token::Group,

View File

@ -88,6 +88,7 @@ mod tests {
else
false
field
finalize
for
function
group
@ -155,7 +156,7 @@ mod tests {
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address bool const else false field for function group i128 i64 i32 i16 i8 if in input let mut return scalar string test 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 bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut return scalar string test true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
/* test */ // "#
);
});

View File

@ -115,6 +115,7 @@ pub enum Token {
// Constant parameter
Constant,
Else,
Finalize,
For,
Function,
If,
@ -146,6 +147,7 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Else,
Token::False,
Token::Field,
Token::Finalize,
Token::For,
Token::Function,
Token::Group,
@ -192,6 +194,7 @@ impl Token {
Token::Else => sym::Else,
Token::False => sym::False,
Token::Field => sym::field,
Token::Finalize => sym::finalize,
Token::For => sym::For,
Token::Function => sym::function,
Token::Group => sym::group,
@ -312,6 +315,7 @@ impl fmt::Display for Token {
Const => write!(f, "const"),
Constant => write!(f, "constant"),
Else => write!(f, "else"),
Finalize => write!(f, "finalize"),
For => write!(f, "for"),
Function => write!(f, "function"),
If => write!(f, "if"),

View File

@ -43,6 +43,7 @@ impl<'a> CodeGenerator<'a> {
unreachable!("Tuple types are not supported at this phase of compilation")
}
Type::Err => unreachable!("Error types should not exist at this phase of compilation"),
Type::Unit => unreachable!("Unit types are not supported at this phase of compilation"),
}
}

View File

@ -38,8 +38,8 @@ impl ProgramReconstructor for Unroller<'_> {
identifier: function.identifier,
input: function.input,
output: function.output,
core_mapping: function.core_mapping,
block: self.reconstruct_block(function.block),
finalize: function.finalize,
span: function.span,
};

View File

@ -141,11 +141,11 @@ impl FunctionConsumer for StaticSingleAssigner<'_> {
identifier: function.identifier,
input: function.input,
output: function.output,
core_mapping: function.core_mapping,
block: Block {
span: Default::default(),
statements,
},
finalize: function.finalize,
span: function.span,
}
}

View File

@ -187,6 +187,7 @@ symbols! {
CoreFunction,
console,
Else: "else",
finalize,
For: "for",
function,
If: "if",