mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
fixes
This commit is contained in:
parent
c5464db066
commit
24c88795fe
@ -78,6 +78,7 @@ pub trait StatementConsumer {
|
||||
Statement::Block(stmt) => self.consume_block(stmt),
|
||||
Statement::Conditional(stmt) => self.consume_conditional(stmt),
|
||||
Statement::Console(stmt) => self.consume_console(stmt),
|
||||
Statement::Const(stmt) => self.consume_const(stmt),
|
||||
Statement::Definition(stmt) => self.consume_definition(stmt),
|
||||
Statement::Expression(stmt) => self.consume_expression_statement(stmt),
|
||||
Statement::Iteration(stmt) => self.consume_iteration(*stmt),
|
||||
@ -95,6 +96,8 @@ pub trait StatementConsumer {
|
||||
|
||||
fn consume_console(&mut self, input: ConsoleStatement) -> Self::Output;
|
||||
|
||||
fn consume_const(&mut self, input: ConstDeclaration) -> Self::Output;
|
||||
|
||||
fn consume_definition(&mut self, input: DefinitionStatement) -> Self::Output;
|
||||
|
||||
fn consume_expression_statement(&mut self, input: ExpressionStatement) -> Self::Output;
|
||||
|
@ -202,6 +202,7 @@ pub trait StatementReconstructor: ExpressionReconstructor {
|
||||
}
|
||||
Statement::Conditional(stmt) => self.reconstruct_conditional(stmt),
|
||||
Statement::Console(stmt) => self.reconstruct_console(stmt),
|
||||
Statement::Const(stmt) => self.reconstruct_const(stmt),
|
||||
Statement::Definition(stmt) => self.reconstruct_definition(stmt),
|
||||
Statement::Expression(stmt) => self.reconstruct_expression_statement(stmt),
|
||||
Statement::Iteration(stmt) => self.reconstruct_iteration(*stmt),
|
||||
@ -287,6 +288,19 @@ pub trait StatementReconstructor: ExpressionReconstructor {
|
||||
)
|
||||
}
|
||||
|
||||
fn reconstruct_const(&mut self, input: ConstDeclaration) -> (Statement, Self::AdditionalOutput) {
|
||||
(
|
||||
Statement::Const(ConstDeclaration {
|
||||
place: input.place,
|
||||
type_: input.type_,
|
||||
value: self.reconstruct_expression(input.value).0,
|
||||
span: input.span,
|
||||
id: input.id,
|
||||
}),
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
(
|
||||
Statement::Definition(DefinitionStatement {
|
||||
@ -368,7 +382,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
structs: input.structs.into_iter().map(|(i, c)| (i, self.reconstruct_struct(c))).collect(),
|
||||
mappings: input.mappings.into_iter().map(|(id, mapping)| (id, self.reconstruct_mapping(mapping))).collect(),
|
||||
functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(),
|
||||
consts: input.consts.into_iter().map(|(i, c)| (i, self.reconstruct_const(c))).collect(),
|
||||
consts: input.consts.into_iter().map(|(i, c)| (i, self.reconstruct_global_const(c))).collect(),
|
||||
span: input.span,
|
||||
}
|
||||
}
|
||||
@ -396,7 +410,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
}
|
||||
}
|
||||
|
||||
fn reconstruct_const(&mut self, input: DefinitionStatement) -> DefinitionStatement {
|
||||
fn reconstruct_global_const(&mut self, input: ConstDeclaration) -> ConstDeclaration {
|
||||
input
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
|
||||
Statement::Block(stmt) => self.visit_block(stmt),
|
||||
Statement::Conditional(stmt) => self.visit_conditional(stmt),
|
||||
Statement::Console(stmt) => self.visit_console(stmt),
|
||||
Statement::Const(stmt) => self.visit_const(stmt),
|
||||
Statement::Definition(stmt) => self.visit_definition(stmt),
|
||||
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
|
||||
Statement::Iteration(stmt) => self.visit_iteration(stmt),
|
||||
@ -177,6 +178,10 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, input: &'a ConstDeclaration) {
|
||||
self.visit_expression(&input.value, &Default::default());
|
||||
}
|
||||
|
||||
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
|
||||
self.visit_expression(&input.value, &Default::default());
|
||||
}
|
||||
@ -233,6 +238,4 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
|
||||
self.visit_block(&finalize.block);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, _input: &'a DefinitionStatement) {}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! A Leo program scope consists of struct, function, and mapping definitions.
|
||||
|
||||
use crate::{DefinitionStatement, Function, Mapping, ProgramId, Struct};
|
||||
use crate::{ConstDeclaration, Function, Mapping, ProgramId, Struct};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use leo_span::{Span, Symbol};
|
||||
@ -29,7 +29,7 @@ pub struct ProgramScope {
|
||||
/// The program id of the program scope.
|
||||
pub program_id: ProgramId,
|
||||
/// A map from const names to const definitions.
|
||||
pub consts: IndexMap<Symbol, DefinitionStatement>,
|
||||
pub consts: IndexMap<Symbol, ConstDeclaration>,
|
||||
/// A map from struct names to struct definitions.
|
||||
pub structs: IndexMap<Symbol, Struct>,
|
||||
/// A map from mapping names to mapping definitions.
|
||||
|
46
compiler/ast/src/statement/const_.rs
Normal file
46
compiler/ast/src/statement/const_.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2019-2023 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::{Expression, Identifier, Node, NodeID, Type};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// A constant declaration statement.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub struct ConstDeclaration {
|
||||
/// The place to assign to. As opposed to `DefinitionStatement`, this can only be an identifier
|
||||
pub place: Identifier,
|
||||
/// The type of the binding, if specified, or inferred otherwise.
|
||||
pub type_: Type,
|
||||
/// An initializer value for the binding.
|
||||
pub value: Expression,
|
||||
/// The span excluding the semicolon.
|
||||
pub span: Span,
|
||||
/// The ID of the node.
|
||||
pub id: NodeID,
|
||||
}
|
||||
|
||||
impl fmt::Display for ConstDeclaration {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.place)?;
|
||||
write!(f, ": {}", self.type_)?;
|
||||
write!(f, " = {};", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
crate::simple_node_impl!(ConstDeclaration);
|
@ -29,6 +29,9 @@ pub use conditional::*;
|
||||
pub mod console;
|
||||
pub use console::*;
|
||||
|
||||
pub mod const_;
|
||||
pub use const_::*;
|
||||
|
||||
pub mod definition;
|
||||
pub use definition::*;
|
||||
|
||||
@ -61,6 +64,8 @@ pub enum Statement {
|
||||
Conditional(ConditionalStatement),
|
||||
/// A console logging statement.
|
||||
Console(ConsoleStatement),
|
||||
/// A binding from identifier to constant value.
|
||||
Const(ConstDeclaration),
|
||||
/// A binding or set of bindings / variables to declare.
|
||||
Definition(DefinitionStatement),
|
||||
/// An expression statement
|
||||
@ -86,6 +91,7 @@ impl fmt::Display for Statement {
|
||||
Statement::Block(x) => x.fmt(f),
|
||||
Statement::Conditional(x) => x.fmt(f),
|
||||
Statement::Console(x) => x.fmt(f),
|
||||
Statement::Const(x) => x.fmt(f),
|
||||
Statement::Definition(x) => x.fmt(f),
|
||||
Statement::Expression(x) => x.fmt(f),
|
||||
Statement::Iteration(x) => x.fmt(f),
|
||||
@ -103,6 +109,7 @@ impl Node for Statement {
|
||||
Block(n) => n.span(),
|
||||
Conditional(n) => n.span(),
|
||||
Console(n) => n.span(),
|
||||
Const(n) => n.span(),
|
||||
Definition(n) => n.span(),
|
||||
Expression(n) => n.span(),
|
||||
Iteration(n) => n.span(),
|
||||
@ -118,6 +125,7 @@ impl Node for Statement {
|
||||
Block(n) => n.set_span(span),
|
||||
Conditional(n) => n.set_span(span),
|
||||
Console(n) => n.set_span(span),
|
||||
Const(n) => n.set_span(span),
|
||||
Definition(n) => n.set_span(span),
|
||||
Expression(n) => n.set_span(span),
|
||||
Iteration(n) => n.set_span(span),
|
||||
@ -133,6 +141,7 @@ impl Node for Statement {
|
||||
Block(n) => n.id(),
|
||||
Conditional(n) => n.id(),
|
||||
Console(n) => n.id(),
|
||||
Const(n) => n.id(),
|
||||
Definition(n) => n.id(),
|
||||
Expression(n) => n.id(),
|
||||
Iteration(n) => n.id(),
|
||||
@ -148,6 +157,7 @@ impl Node for Statement {
|
||||
Block(n) => n.set_id(id),
|
||||
Conditional(n) => n.set_id(id),
|
||||
Console(n) => n.set_id(id),
|
||||
Const(n) => n.set_id(id),
|
||||
Definition(n) => n.set_id(id),
|
||||
Expression(n) => n.set_id(id),
|
||||
Iteration(n) => n.set_id(id),
|
||||
|
@ -146,8 +146,8 @@ impl ParserContext<'_> {
|
||||
while self.has_next() {
|
||||
match &self.token.token {
|
||||
Token::Const => {
|
||||
let definition = self.parse_const_definition_statement()?;
|
||||
consts.insert(Symbol::intern(&definition.place.to_string()), definition);
|
||||
let declaration = self.parse_const_declaration_statement()?;
|
||||
consts.insert(Symbol::intern(&declaration.place.to_string()), declaration);
|
||||
}
|
||||
Token::Struct | Token::Record => {
|
||||
let (id, struct_) = self.parse_struct()?;
|
||||
|
@ -45,7 +45,7 @@ impl ParserContext<'_> {
|
||||
Token::For => Ok(Statement::Iteration(Box::new(self.parse_loop_statement()?))),
|
||||
Token::Assert | Token::AssertEq | Token::AssertNeq => Ok(self.parse_assert_statement()?),
|
||||
Token::Let => Ok(Statement::Definition(self.parse_definition_statement()?)),
|
||||
Token::Const => Ok(Statement::Definition(self.parse_const_definition_statement()?)),
|
||||
Token::Const => Ok(Statement::Const(self.parse_const_declaration_statement()?)),
|
||||
Token::LeftCurly => Ok(Statement::Block(self.parse_block()?)),
|
||||
Token::Console => Err(ParserError::console_statements_are_not_yet_supported(self.token.span).into()),
|
||||
Token::Finalize => Err(ParserError::finalize_statements_are_deprecated(self.token.span).into()),
|
||||
@ -315,34 +315,19 @@ impl ParserContext<'_> {
|
||||
Ok(ConsoleStatement { span: keyword + span, function, id: self.node_builder.next_id() })
|
||||
}
|
||||
|
||||
/// Returns a [`DefinitionStatement`] AST node if the next tokens represent a const definition statement.
|
||||
pub(super) fn parse_const_definition_statement(&mut self) -> Result<DefinitionStatement> {
|
||||
/// Returns a [`ConstDeclaration`] AST node if the next tokens represent a const declaration statement.
|
||||
pub(super) fn parse_const_declaration_statement(&mut self) -> Result<ConstDeclaration> {
|
||||
self.expect(&Token::Const)?;
|
||||
let decl_span = self.prev_token.span;
|
||||
let decl_type = match &self.prev_token.token {
|
||||
Token::Const => DeclarationType::Const,
|
||||
_ => unreachable!(
|
||||
"parse_const_definition_statement shouldn't produce this as have already ensured that first token was 'Const'"
|
||||
),
|
||||
};
|
||||
|
||||
// Parse variable name and type.
|
||||
let place = self.parse_expression()?;
|
||||
self.expect(&Token::Colon)?;
|
||||
let type_ = self.parse_type()?.0;
|
||||
let (place, type_, _) = self.parse_typed_ident()?;
|
||||
|
||||
self.expect(&Token::Assign)?;
|
||||
let value = self.parse_expression()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
|
||||
Ok(DefinitionStatement {
|
||||
span: decl_span + value.span(),
|
||||
declaration_type: decl_type,
|
||||
place,
|
||||
type_,
|
||||
value,
|
||||
id: self.node_builder.next_id(),
|
||||
})
|
||||
Ok(ConstDeclaration { span: decl_span + value.span(), place, type_, value, id: self.node_builder.next_id() })
|
||||
}
|
||||
|
||||
/// Returns a [`DefinitionStatement`] AST node if the next tokens represent a definition statement.
|
||||
|
@ -44,6 +44,9 @@ impl<'a> CodeGenerator<'a> {
|
||||
Statement::Block(stmt) => self.visit_block(stmt),
|
||||
Statement::Conditional(stmt) => self.visit_conditional(stmt),
|
||||
Statement::Console(stmt) => self.visit_console(stmt),
|
||||
Statement::Const(_) => {
|
||||
unreachable!("`ConstStatement`s should not be in the AST at this phase of compilation.")
|
||||
}
|
||||
Statement::Definition(stmt) => self.visit_definition(stmt),
|
||||
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
|
||||
Statement::Iteration(stmt) => self.visit_iteration(stmt),
|
||||
|
@ -17,7 +17,7 @@
|
||||
use indexmap::IndexMap;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use leo_ast::Literal;
|
||||
use leo_ast::Expression;
|
||||
use leo_errors::Result;
|
||||
use leo_span::Symbol;
|
||||
|
||||
@ -30,7 +30,7 @@ pub struct ConstantPropagationTable {
|
||||
pub(crate) parent: Option<Box<ConstantPropagationTable>>,
|
||||
/// The known constants in the current scope
|
||||
/// This field is populated as necessary.
|
||||
pub(crate) constants: IndexMap<Symbol, Literal>,
|
||||
pub(crate) constants: IndexMap<Symbol, Expression>,
|
||||
/// The index of the current scope.
|
||||
pub(crate) scope_index: usize,
|
||||
/// The sub-scopes of this scope.
|
||||
@ -47,8 +47,8 @@ impl ConstantPropagationTable {
|
||||
}
|
||||
|
||||
/// Inserts a constant into the constant propagation table.
|
||||
pub fn insert_constant(&mut self, symbol: Symbol, literal: Literal) -> Result<()> {
|
||||
self.constants.insert(symbol, literal);
|
||||
pub fn insert_constant(&mut self, symbol: Symbol, expr: Expression) -> Result<()> {
|
||||
self.constants.insert(symbol, expr);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ impl ConstantPropagationTable {
|
||||
}
|
||||
|
||||
/// Attempts to lookup a constant in the constant propagation table.
|
||||
pub fn lookup_constant(&self, symbol: Symbol) -> Option<&Literal> {
|
||||
pub fn lookup_constant(&self, symbol: Symbol) -> Option<&Expression> {
|
||||
if let Some(constant) = self.constants.get(&symbol) {
|
||||
Some(constant)
|
||||
} else if let Some(parent) = self.parent.as_ref() {
|
||||
|
@ -23,8 +23,8 @@ impl ExpressionReconstructor for Unroller<'_> {
|
||||
|
||||
fn reconstruct_identifier(&mut self, input: Identifier) -> (Expression, Self::AdditionalOutput) {
|
||||
// Substitute the identifier with the constant value if it is a constant.
|
||||
if let Some(literal) = self.constant_propagation_table.borrow().lookup_constant(input.name) {
|
||||
return (Expression::Literal(literal.clone()), Default::default());
|
||||
if let Some(expr) = self.constant_propagation_table.borrow().lookup_constant(input.name) {
|
||||
return (expr.clone(), Default::default());
|
||||
}
|
||||
(Expression::Identifier(input), Default::default())
|
||||
}
|
||||
|
@ -14,20 +14,23 @@
|
||||
// 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 leo_ast::{Expression::Literal, *};
|
||||
use leo_span::Symbol;
|
||||
use indexmap::IndexMap;
|
||||
use leo_ast::*;
|
||||
|
||||
use crate::Unroller;
|
||||
|
||||
impl ProgramReconstructor for Unroller<'_> {
|
||||
fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
|
||||
let new_consts = input.consts.into_iter().map(|(i, c)| (i, self.reconstruct_const(c))).collect();
|
||||
// Don't need to reconstructed consts, just need to add them to constant propagation table
|
||||
input.consts.into_iter().for_each(|(_, c)| {
|
||||
self.reconstruct_const(c);
|
||||
});
|
||||
ProgramScope {
|
||||
program_id: input.program_id,
|
||||
structs: input.structs,
|
||||
mappings: input.mappings,
|
||||
functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(),
|
||||
consts: new_consts,
|
||||
consts: IndexMap::new(),
|
||||
span: input.span,
|
||||
}
|
||||
}
|
||||
@ -83,56 +86,4 @@ impl ProgramReconstructor for Unroller<'_> {
|
||||
|
||||
reconstructed_function
|
||||
}
|
||||
|
||||
fn reconstruct_const(&mut self, input: DefinitionStatement) -> DefinitionStatement {
|
||||
// Reconstruct the RHS expression to allow for constant propagation
|
||||
let reconstructed_value_expression = self.reconstruct_expression(input.value.clone()).0;
|
||||
|
||||
// Helper function to add global constants to constant variable table
|
||||
let insert_variable = |symbol: Symbol, value: &Expression| {
|
||||
if let Literal(literal) = value {
|
||||
if let Err(err) = self.constant_propagation_table.borrow_mut().insert_constant(symbol, literal.clone())
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
} else {
|
||||
unreachable!("Type checking guarantees that the value of a constant is a literal.");
|
||||
}
|
||||
};
|
||||
|
||||
// No matter if doing multiple definitions in one line or not, insert all global constants into the constant propagation table
|
||||
match &input.place {
|
||||
Expression::Identifier(identifier) => {
|
||||
insert_variable(identifier.name, &reconstructed_value_expression);
|
||||
}
|
||||
Expression::Tuple(tuple_expression) => {
|
||||
let tuple_values: &Vec<Expression> = match &reconstructed_value_expression {
|
||||
Expression::Tuple(tuple_value_expression) => &tuple_value_expression.elements,
|
||||
_ => unreachable!(
|
||||
"Definition statement that defines tuple of variables must be assigned to tuple of values"
|
||||
),
|
||||
};
|
||||
|
||||
for (i, element) in tuple_expression.elements.iter().enumerate() {
|
||||
let identifier = match element {
|
||||
Expression::Identifier(identifier) => identifier,
|
||||
_ => unreachable!("All elements of a definition tuple must be identifiers"),
|
||||
};
|
||||
insert_variable(identifier.name, &tuple_values[i].clone());
|
||||
}
|
||||
}
|
||||
_ => unreachable!(
|
||||
"Type checking guarantees that the lhs of a `DefinitionStatement` is either an identifier or tuple."
|
||||
),
|
||||
}
|
||||
|
||||
DefinitionStatement {
|
||||
declaration_type: input.declaration_type,
|
||||
place: input.place,
|
||||
type_: input.type_,
|
||||
value: reconstructed_value_expression,
|
||||
span: input.span,
|
||||
id: input.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,26 +50,51 @@ impl StatementReconstructor for Unroller<'_> {
|
||||
(block, Default::default())
|
||||
}
|
||||
|
||||
fn reconstruct_const(&mut self, input: ConstDeclaration) -> (Statement, Self::AdditionalOutput) {
|
||||
// Reconstruct the RHS expression to allow for constant propagation
|
||||
let reconstructed_value_expression = self.reconstruct_expression(input.value.clone()).0;
|
||||
|
||||
// Add to constant propagation table. Since TC completed we know that the RHS is a literal or tuple of literals.
|
||||
if let Err(err) = self.constant_propagation_table.borrow_mut().insert_constant(input.place.name, input.value) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
|
||||
// Remove from symbol table
|
||||
if self.symbol_table.borrow().lookup_variable(input.place.name).is_some() {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().remove_variable_from_current_scope(input.place.name) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
Statement::Const(ConstDeclaration {
|
||||
place: input.place,
|
||||
type_: input.type_,
|
||||
value: reconstructed_value_expression,
|
||||
span: input.span,
|
||||
id: input.id,
|
||||
}),
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
// Helper function to add variables to symbol table
|
||||
let insert_variable = |symbol: Symbol, type_: Type, span: Span, declaration: VariableType| {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { type_, span, declaration })
|
||||
{
|
||||
let insert_variable = |symbol: Symbol, type_: Type, span: Span| {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol {
|
||||
type_,
|
||||
span,
|
||||
declaration: VariableType::Mut,
|
||||
}) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
};
|
||||
|
||||
let declaration =
|
||||
if input.declaration_type == DeclarationType::Const { VariableType::Const } else { VariableType::Mut };
|
||||
|
||||
// If we are unrolling a loop, then we need to repopulate the symbol table.
|
||||
// If we are not unrolling a loop, the we need to remove constants from the symbol table.
|
||||
// We always need to add constant variables to the constant variable table.
|
||||
if declaration == VariableType::Mut && self.is_unrolling {
|
||||
if self.is_unrolling {
|
||||
match &input.place {
|
||||
Expression::Identifier(identifier) => {
|
||||
insert_variable(identifier.name, input.type_.clone(), input.span, declaration);
|
||||
insert_variable(identifier.name, input.type_.clone(), input.span);
|
||||
}
|
||||
Expression::Tuple(tuple_expression) => {
|
||||
let tuple_type = match input.type_ {
|
||||
@ -83,15 +108,13 @@ impl StatementReconstructor for Unroller<'_> {
|
||||
Expression::Identifier(identifier) => identifier,
|
||||
_ => unreachable!("Type checking guarantees that if the lhs is a tuple, all of its elements are identifiers.")
|
||||
};
|
||||
insert_variable(identifier.name, input.type_.clone(), input.span, declaration);
|
||||
insert_variable(identifier.name, input.type_.clone(), input.span);
|
||||
});
|
||||
}
|
||||
_ => unreachable!(
|
||||
"Type checking guarantees that the lhs of a `DefinitionStatement` is either an identifier or tuple."
|
||||
),
|
||||
}
|
||||
} else if declaration == VariableType::Const {
|
||||
return (Statement::Definition(self.reconstruct_const(input.clone())), true);
|
||||
}
|
||||
|
||||
// Reconstruct the expression and return
|
||||
@ -104,7 +127,7 @@ impl StatementReconstructor for Unroller<'_> {
|
||||
span: input.span,
|
||||
id: input.id,
|
||||
}),
|
||||
false,
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use leo_ast::{
|
||||
Block,
|
||||
Expression,
|
||||
IntegerType,
|
||||
IterationStatement,
|
||||
Literal,
|
||||
@ -240,12 +241,24 @@ impl<'a> Unroller<'a> {
|
||||
// Add the loop variable as a constant for the current scope
|
||||
self.constant_propagation_table
|
||||
.borrow_mut()
|
||||
.insert_constant(input.variable.name, value)
|
||||
.insert_constant(input.variable.name, Expression::Literal(value.clone()))
|
||||
.expect("Failed to insert constant into CPT");
|
||||
|
||||
// Reconstruct the statements in the loop body.
|
||||
let statements: Vec<_> =
|
||||
input.block.statements.clone().into_iter().map(|s| self.reconstruct_statement(s).0).collect();
|
||||
let statements: Vec<_> = input
|
||||
.block
|
||||
.statements
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter_map(|s| {
|
||||
let (reconstructed_statement, additional_output) = self.reconstruct_statement(s);
|
||||
if additional_output {
|
||||
None // Exclude this statement from the block since it is a constant variable definition
|
||||
} else {
|
||||
Some(reconstructed_statement)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let block = Statement::Block(Block { statements, span: input.block.span, id: input.block.id });
|
||||
|
||||
|
@ -26,6 +26,7 @@ use leo_ast::{
|
||||
CallExpression,
|
||||
ConditionalStatement,
|
||||
ConsoleStatement,
|
||||
ConstDeclaration,
|
||||
DefinitionStatement,
|
||||
Expression,
|
||||
ExpressionConsumer,
|
||||
@ -214,6 +215,10 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
unreachable!("Parsing guarantees that console statements are not present in the program.")
|
||||
}
|
||||
|
||||
fn consume_const(&mut self, _: ConstDeclaration) -> Self::Output {
|
||||
unreachable!("Loop unrolling pass removes all constant declaration statements in the program.")
|
||||
}
|
||||
|
||||
/// Consumes the `DefinitionStatement` into an `AssignStatement`, renaming the left-hand-side as appropriate.
|
||||
fn consume_definition(&mut self, definition: DefinitionStatement) -> Self::Output {
|
||||
// First consume the right-hand-side of the definition.
|
||||
|
@ -54,7 +54,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
||||
// Typecheck each const definition, and append to symbol table.
|
||||
input.consts.values().for_each(|c| self.visit_definition(c));
|
||||
input.consts.values().for_each(|c| self.visit_const(c));
|
||||
|
||||
// Typecheck each struct definition.
|
||||
input.structs.values().for_each(|function| self.visit_struct(function));
|
||||
|
@ -35,6 +35,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
Statement::Block(stmt) => self.visit_block(stmt),
|
||||
Statement::Conditional(stmt) => self.visit_conditional(stmt),
|
||||
Statement::Console(stmt) => self.visit_console(stmt),
|
||||
Statement::Const(stmt) => self.visit_const(stmt),
|
||||
Statement::Definition(stmt) => self.visit_definition(stmt),
|
||||
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
|
||||
Statement::Iteration(stmt) => self.visit_iteration(stmt),
|
||||
@ -150,10 +151,57 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
unreachable!("Parsing guarantees that console statements are not present in the AST.");
|
||||
}
|
||||
|
||||
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
|
||||
let declaration =
|
||||
if input.declaration_type == DeclarationType::Const { VariableType::Const } else { VariableType::Mut };
|
||||
fn visit_const(&mut self, input: &'a ConstDeclaration) {
|
||||
// Check that the type of the definition is not a unit type, singleton tuple type, or nested tuple type.
|
||||
match &input.type_ {
|
||||
// If the type is an empty tuple, return an error.
|
||||
Type::Unit => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.span)),
|
||||
// If the type is a singleton tuple, return an error.
|
||||
Type::Tuple(tuple) => match tuple.len() {
|
||||
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
|
||||
_ => {
|
||||
if tuple.iter().any(|type_| matches!(type_, Type::Tuple(_))) {
|
||||
self.emit_err(TypeCheckerError::nested_tuple_type(input.span))
|
||||
}
|
||||
}
|
||||
},
|
||||
Type::Mapping(_) | Type::Err => unreachable!(
|
||||
"Parsing guarantees that `mapping` and `err` types are not present at this location in the AST."
|
||||
),
|
||||
// Otherwise, the type is valid.
|
||||
_ => (), // Do nothing
|
||||
}
|
||||
|
||||
// Enforce that Constant variables have literal expressions on right-hand side
|
||||
match &input.value {
|
||||
Expression::Literal(_) => (),
|
||||
Expression::Tuple(tuple_expression) => match tuple_expression.elements.len() {
|
||||
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
|
||||
_ => {
|
||||
if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) {
|
||||
self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(
|
||||
input.span,
|
||||
))
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())),
|
||||
}
|
||||
|
||||
// Check the expression on the right-hand side.
|
||||
self.visit_expression(&input.value, &Some(input.type_.clone()));
|
||||
|
||||
// Add constants to symbol table so that any references to them in later statements will pass TC
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(input.place.name, VariableSymbol {
|
||||
type_: input.type_.clone(),
|
||||
span: input.place.span,
|
||||
declaration: VariableType::Const,
|
||||
}) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
|
||||
// Check that the type of the definition is defined.
|
||||
self.assert_type_is_defined(&input.type_, input.span);
|
||||
|
||||
@ -177,35 +225,17 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
_ => (), // Do nothing
|
||||
}
|
||||
|
||||
// Enforce additional constraint that constant definitions can only be literals or tuples of literals. This will be removed after constant folding.
|
||||
if input.declaration_type == DeclarationType::Const {
|
||||
// Enforce that Constant variables have literal expressions on right-hand side
|
||||
match &input.value {
|
||||
Expression::Literal(_) => (),
|
||||
Expression::Tuple(tuple_expression) => match tuple_expression.elements.len() {
|
||||
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
|
||||
_ => {
|
||||
if tuple_expression.elements.iter().any(|expr| !matches!(expr, Expression::Literal(_))) {
|
||||
self.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(
|
||||
input.span,
|
||||
))
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => self
|
||||
.emit_err(TypeCheckerError::const_declaration_must_be_literal_or_tuple_of_literals(input.span())),
|
||||
}
|
||||
}
|
||||
|
||||
// Check the expression on the right-hand side.
|
||||
self.visit_expression(&input.value, &Some(input.type_.clone()));
|
||||
|
||||
// TODO: Dedup with unrolling pass.
|
||||
// Helper to insert the variables into the symbol table.
|
||||
let insert_variable = |symbol: Symbol, type_: Type, span: Span, declaration: VariableType| {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { type_, span, declaration })
|
||||
{
|
||||
let insert_variable = |symbol: Symbol, type_: Type, span: Span| {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol {
|
||||
type_,
|
||||
span,
|
||||
declaration: VariableType::Mut,
|
||||
}) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
};
|
||||
@ -213,7 +243,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// Insert the variables in the into the symbol table.
|
||||
match &input.place {
|
||||
Expression::Identifier(identifier) => {
|
||||
insert_variable(identifier.name, input.type_.clone(), identifier.span, declaration)
|
||||
insert_variable(identifier.name, input.type_.clone(), identifier.span)
|
||||
}
|
||||
Expression::Tuple(tuple_expression) => {
|
||||
let tuple_type = match &input.type_ {
|
||||
@ -222,6 +252,14 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
"Type checking guarantees that if the lhs is a tuple, its associated type is also a tuple."
|
||||
),
|
||||
};
|
||||
if tuple_expression.elements.len() != tuple_type.len() {
|
||||
return self.emit_err(TypeCheckerError::incorrect_num_tuple_elements(
|
||||
tuple_expression.elements.len(),
|
||||
tuple_type.len(),
|
||||
input.place.span(),
|
||||
));
|
||||
}
|
||||
|
||||
tuple_expression.elements.iter().zip_eq(tuple_type.0.iter()).for_each(|(expression, type_)| {
|
||||
let identifier = match expression {
|
||||
Expression::Identifier(identifier) => identifier,
|
||||
@ -231,7 +269,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
));
|
||||
}
|
||||
};
|
||||
insert_variable(identifier.name, type_.clone(), identifier.span, declaration)
|
||||
insert_variable(identifier.name, type_.clone(), identifier.span)
|
||||
});
|
||||
}
|
||||
_ => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.place.span())),
|
||||
|
@ -49,10 +49,14 @@ The errors for the `leo-compiler` crate. Its error codes will range from 6_000-6
|
||||
|
||||
The errors for the `leo-imports` crate. Its error codes will range from 4_000-4_999 and be prefixed with the characters `IMP`.
|
||||
|
||||
## Input
|
||||
### Input
|
||||
|
||||
The errors for the `leo-ast` crate. Its error codes will range from 8_000-8_999 and be prefixed with the characters `INP`.
|
||||
|
||||
### Loop Unrolling
|
||||
|
||||
The errors for loop unrolling in the `leo-passes` crate. Its error codes will range from 9_000-9_999 and be prefixed with the characters `LUN`.
|
||||
|
||||
### Package
|
||||
|
||||
The errors for the `leo-package` crate. Its error codes will range from 5_000-5_999 and be prefixed with the characters `PAK`.
|
||||
|
@ -18,9 +18,9 @@ use crate::create_messages;
|
||||
use std::fmt::Debug;
|
||||
|
||||
create_messages!(
|
||||
/// AstError enum that represents all the errors for the `leo-ast` crate.
|
||||
/// LoopUnrollerError enum that represents all the errors for the loop unrolling errors in the `leo-loop_unroller` crate.
|
||||
LoopUnrollerError,
|
||||
code_mask: 8000i32,
|
||||
code_mask: 9000i32,
|
||||
code_prefix: "LUN",
|
||||
|
||||
@formatted
|
||||
|
@ -14,7 +14,6 @@
|
||||
// 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::loop_unroller::LoopUnrollerError;
|
||||
/// Contains the ASG error definitions.
|
||||
use crate::LeoMessageCode;
|
||||
|
||||
@ -38,6 +37,9 @@ pub use self::flattener::*;
|
||||
pub mod input;
|
||||
pub use self::input::*;
|
||||
|
||||
pub mod loop_unroller;
|
||||
pub use self::loop_unroller::*;
|
||||
|
||||
/// Contains the Package error definitions.
|
||||
pub mod package;
|
||||
pub use self::package::*;
|
||||
@ -46,7 +48,6 @@ pub use self::package::*;
|
||||
pub mod parser;
|
||||
pub use self::parser::*;
|
||||
|
||||
pub mod loop_unroller;
|
||||
/// Contains the Type Checker error definitions.
|
||||
pub mod type_checker;
|
||||
|
||||
|
@ -671,4 +671,17 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
incorrect_num_tuple_elements {
|
||||
args: (identifiers: impl Display, types: impl Display),
|
||||
msg: format!("Expected a tuple with {types} elements, found one with {identifiers} elements"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
const_declaration_can_only_have_one_binding {
|
||||
args: (),
|
||||
msg: format!("A constant declaration statement can only bind a single value"),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: af2effe11f5047f1accaca1df1d8456dbb355969e1e843ba37eda44257570551
|
||||
type_checked_symbol_table: 61642b3cd24a2f6303c7abf5dac2821ed2f739f5d009f448b7eef2693fbfb0eb
|
||||
unrolled_symbol_table: 751fa39b0cb4c55b0bd8ac36ef03aefc90829cb4f06ed664b5915b16dbaaaa70
|
||||
initial_ast: 8147cde7c4f4b40f45e67afc32bb4f1c28e994968b52b4d2c7f40fa9b9ef3d0c
|
||||
unrolled_ast: d0850814c6ead0d76661bf37b45212d2edbb6b47d38a006d43e5cba4fcc779f1
|
||||
ssa_ast: b02e95a4c70b6d2fe4b9ba66d742d6001acf85fee058f0f065525265b5ee9c2b
|
||||
flattened_ast: 7d8d33926bf19f4e5e00d9611b77284ce467483bb35192e7f4f9c7ae295c559b
|
||||
inlined_ast: 7d8d33926bf19f4e5e00d9611b77284ce467483bb35192e7f4f9c7ae295c559b
|
||||
dce_ast: 419b58124f548bd498b1cb0dda20f13505372d86cc2d405e9e97cca9327a3bd9
|
||||
bytecode: acfb8fc365ba153cf8598a04dad8ff4ac65b9df6c6356cb077fcf9dafbead7e9
|
||||
warnings: ""
|
@ -4,12 +4,12 @@ expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 77b127880b95652f948bc184d24fb51eb368cc2ccb022093cd27c2fbc03bb70e
|
||||
type_checked_symbol_table: be1bdc9825b662e2070dabbd8e16d24d51ed989e91e385f9ebf27e11dc12b902
|
||||
unrolled_symbol_table: be1bdc9825b662e2070dabbd8e16d24d51ed989e91e385f9ebf27e11dc12b902
|
||||
initial_ast: 0ab8753999f0db720682d3600df3575fcb8da517f539ee23844406eef6cdf0d0
|
||||
unrolled_ast: 3f0b5beb875ff9de3b98978d7136c946f450f32b0c7bab7ac47257a9c8d4a7ea
|
||||
ssa_ast: 2fd2a759cd7ab2242c9f7b97bc1241ab81bd26d6e1f35a308792edff76226e8f
|
||||
flattened_ast: f6ea27693b4afa98e03b9201a01ba174c999395159b952bd2057291224a363f2
|
||||
inlined_ast: f6ea27693b4afa98e03b9201a01ba174c999395159b952bd2057291224a363f2
|
||||
dce_ast: f6ea27693b4afa98e03b9201a01ba174c999395159b952bd2057291224a363f2
|
||||
unrolled_symbol_table: 435f5b6da45d68cf00a82aca5b9bd6e326c5d7d2252811db0e96afd1de00a727
|
||||
initial_ast: f7f9f8362006d7a5e3659df72b883a2f21bc5ee43381ccbd023b32de23c5f833
|
||||
unrolled_ast: 6ec80c2610eb0231078e39c207e6fef0346325d175c821c4e16d8aa96becedec
|
||||
ssa_ast: bb89e164033dca2cb1b61d21c2e012bf72ce6d832c94de647a94f3a0ddf579e6
|
||||
flattened_ast: 40c0e11be11bed1d1214f8b9a1dba9a34a86070eb9ffbc92827185ceaa458f08
|
||||
inlined_ast: 40c0e11be11bed1d1214f8b9a1dba9a34a86070eb9ffbc92827185ceaa458f08
|
||||
dce_ast: 40c0e11be11bed1d1214f8b9a1dba9a34a86070eb9ffbc92827185ceaa458f08
|
||||
bytecode: 88de5519495f51852482cfc5ab129cde77b8d2b53fd2eebfd66472c6fe0cdafe
|
||||
warnings: ""
|
||||
|
@ -4,12 +4,12 @@ expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: d1eed24f01e5256fec3b444fd3a38b7e25756c5fb20010872884a34d54ef888c
|
||||
type_checked_symbol_table: 89c060252a9e229b91f2ac52e5e3823e04400f3e060ead04999aa4911f42c731
|
||||
unrolled_symbol_table: 26537147843c8e9daeda6a7af59b2b4bca86c6f067b08a4f4c3a7b7ffe30e59a
|
||||
initial_ast: 1b2029fc1b5100e84675a87052375b38af1da27315d22daf1ccf49f17c5e5cf9
|
||||
unrolled_ast: 6c9e5266587d4b90c0ea7522edcc4c3a6b00f6cfaadb91c59daba698b2da5b91
|
||||
ssa_ast: a69548faa4852b092997ff059e4bbeb2161caada00423171ff0c98a167891165
|
||||
flattened_ast: c67bdab30e2af4d0130fc11772176f267e1a7144488fab3ae7bcd33136b3ee47
|
||||
inlined_ast: c67bdab30e2af4d0130fc11772176f267e1a7144488fab3ae7bcd33136b3ee47
|
||||
dce_ast: c67bdab30e2af4d0130fc11772176f267e1a7144488fab3ae7bcd33136b3ee47
|
||||
unrolled_symbol_table: c00e0818651bd9e2c068becdf3819b8d46238e0cfad46c87791efa9c97c6f9de
|
||||
initial_ast: 310ef81cd18a675700a7c5d315978a5aeddfcb5220d7cb3ebb2c22cdefc72c27
|
||||
unrolled_ast: 7e5cc7fedc616597a85fa4a5b46cc5432b93cf2d1f76f615f72d0a287f17232a
|
||||
ssa_ast: a789faf5dde9e018665a22e2aa96674ca424dfdc6abc954c099113d7136e7e02
|
||||
flattened_ast: 6d1021575d55836a866f7b99e87fed633869521e08d97f3d25fdfc2e7e60648d
|
||||
inlined_ast: 6d1021575d55836a866f7b99e87fed633869521e08d97f3d25fdfc2e7e60648d
|
||||
dce_ast: 6d1021575d55836a866f7b99e87fed633869521e08d97f3d25fdfc2e7e60648d
|
||||
bytecode: a6350aaded46f7047061f7e68a8ae41eb8aa0d29f02560257ecdc582a6c684f9
|
||||
warnings: ""
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ELUN0378000]: The loop range must be increasing.\n --> compiler-test:6:26\n |\n 6 | const STOP: u8 = 0u8;\n | ^^^\n"
|
||||
- "Error [ELUN0379000]: The loop range must be increasing.\n --> compiler-test:6:26\n |\n 6 | const STOP: u8 = 0u8;\n | ^^^\n"
|
||||
|
@ -4,12 +4,12 @@ expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: c6a4e40ae8f466c3ff6bf5d356d6ba89684438f88015e8ea23ff43eadb662b49
|
||||
type_checked_symbol_table: 0b88104308fe0b9e390a59a4359d6245170347557911b21ba04cd1d9124da14d
|
||||
unrolled_symbol_table: 0f5bcb03574cbdb2a6a0f335693d8bc0bca4926ce259fa0e0acc09baba07bcdd
|
||||
initial_ast: 0418d21afa3636a1e9b0c4440bb1b06633c7674a0157ffb2b1b26b478147fee8
|
||||
unrolled_ast: e07e1eab58e31a09d2b4464a0644fe3b4189aeb4d4418963ecdb9c0fdb8a25cc
|
||||
ssa_ast: b5306dfc16a75fa20fa0c8c8c8df27de7c9cc76399f8245e7baa4998e77d4b5a
|
||||
flattened_ast: 88e816cddb1f37e20dbf4c53e4c12095a8b6374af790d5210b431c0787607f73
|
||||
inlined_ast: 88e816cddb1f37e20dbf4c53e4c12095a8b6374af790d5210b431c0787607f73
|
||||
dce_ast: e01c208549e62b4372dcbfd2c24fb4c3bba4e7cb20e7e0a47acf67dd9dda5c63
|
||||
unrolled_symbol_table: af56532f8dd6c6ca6f5fc8af3667202298898a54fe2f871a7874684a712f141d
|
||||
initial_ast: 542dc099a401102c60c971fc4c4a97dc5a885e9b949b647ffd12fa418b82ede0
|
||||
unrolled_ast: 6cee219515c51e5b250b0e1905eaeeb27b2d6de0690055bc9e2a8fbb50f5330a
|
||||
ssa_ast: cd15cc9451d67fd9489a4de0ad5debd70f410ca9b8608bacd408948ee1d79e18
|
||||
flattened_ast: a9cb531c3f1a8f3ae4d192d5c630fb0e92800ce2b974017835c90658969cda46
|
||||
inlined_ast: a9cb531c3f1a8f3ae4d192d5c630fb0e92800ce2b974017835c90658969cda46
|
||||
dce_ast: a9cb531c3f1a8f3ae4d192d5c630fb0e92800ce2b974017835c90658969cda46
|
||||
bytecode: d9595550f8a3d55b350b4f46059fb01bf63308aa4b4416594c2eb20231f6483a
|
||||
warnings: ""
|
||||
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: d698a6988e2f4caf3321c2a5b0c0228721f13930b072f738e97747b7d3ade0de
|
||||
type_checked_symbol_table: 88168597bb3de8d73a3ada9b63c026594d716c75f2deb4b7d20abd2758d6b4d3
|
||||
unrolled_symbol_table: 88168597bb3de8d73a3ada9b63c026594d716c75f2deb4b7d20abd2758d6b4d3
|
||||
initial_ast: f24907cd9e0f0b5f3fce4efb5eeea7945ec22c4780a31df6870816eb9480632f
|
||||
unrolled_ast: 764e6b1b9204c5d98a6ccb9354fbee08aac7cc83647c5ebcd2e9c2880daa2544
|
||||
ssa_ast: 764e6b1b9204c5d98a6ccb9354fbee08aac7cc83647c5ebcd2e9c2880daa2544
|
||||
flattened_ast: 96c6bdf5200642b65e8f6e83228dc0a01c493c13d3b4d9686829b2efca7451fb
|
||||
inlined_ast: 96c6bdf5200642b65e8f6e83228dc0a01c493c13d3b4d9686829b2efca7451fb
|
||||
dce_ast: 96c6bdf5200642b65e8f6e83228dc0a01c493c13d3b4d9686829b2efca7451fb
|
||||
bytecode: 91d9f12af3f91ba9332bdf7303424e4369e14db4b713c13f43afc72a55cfcd4a
|
||||
warnings: ""
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372080]: The value of a const declaration must be a literal\n --> compiler-test:4:5\n |\n 4 | const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nError [ETYC0372058]: A tuple expression cannot contain another tuple expression.\n --> compiler-test:4:43\n |\n 4 | const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));\n | ^^^^^^^^^\nError [ETYC0372023]: Tuples must be explicitly typed in Leo\n --> compiler-test:4:43\n |\n 4 | const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));\n | ^^^^^^^^^\n |\n = The function definition must match the function return statement\n"
|
||||
- "Error [EPAR0370009]: unexpected string: expected 'identifier', found '('\n --> compiler-test:4:11\n |\n 4 | const (HELLO,GOODBYE): (u8,u8) = (1u8, 1u8);\n | ^"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EAST0372009]: variable `HELLO` shadowed by\n --> compiler-test:5:11\n |\n 5 | const HELLO: u8 = 0u8;\n | ^^^^^\n"
|
||||
- "Error [EPAR0370009]: unexpected string: expected 'identifier', found '('\n --> compiler-test:4:11\n |\n 4 | const (HELLO,GOODBYE): (u8,u8) = (0u8,0u8);\n | ^"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ELUN0378000]: The loop range must be increasing.\n --> compiler-test:7:28\n |\n 7 | for i: i8 in 10i8..5i8 {\n | ^^^\n"
|
||||
- "Error [ELUN0379000]: The loop range must be increasing.\n --> compiler-test:7:28\n |\n 7 | for i: i8 in 10i8..5i8 {\n | ^^^\n"
|
||||
|
@ -4,13 +4,13 @@ expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 4194c6207c716b52d30529becd081afc9b7313e8e1ce400cc65c33fac50fab31
|
||||
type_checked_symbol_table: 51dec1877b8da96c81929eabd624019ae50c181362703756b68d94d002cb2f56
|
||||
unrolled_symbol_table: f62721c061790b66cf66c0dbac8f85ca582bb420e6b315e081e7894bb81e8cdf
|
||||
initial_ast: 40297565663ad5f424bb0ac5a571ea56a99043ce11acc018df07cbbcc2df2994
|
||||
unrolled_ast: d00d781141ee230a9b6602ed35a264bde7f84cc3ea904e7aa83ea3edd877e723
|
||||
ssa_ast: 5455c22f4e05610c0bd8c2a7ac0d15d8aab1f8ae6cc23fcdb3cc75e75e16519d
|
||||
flattened_ast: 84a675cf8525bd7a82dabe9fb1542926b34e611fcf4a51e82528cd855b18b5c8
|
||||
inlined_ast: 84a675cf8525bd7a82dabe9fb1542926b34e611fcf4a51e82528cd855b18b5c8
|
||||
dce_ast: 84a675cf8525bd7a82dabe9fb1542926b34e611fcf4a51e82528cd855b18b5c8
|
||||
unrolled_symbol_table: 0b6340ef766a4154f31b5fa00d9bebe8478a8e3c81f091b8433e870ad7213b25
|
||||
initial_ast: bc84c92328b456b2a88fadd3998ae180078447418a1adacbc9495f3d9177a38a
|
||||
unrolled_ast: e9972535de2da936d1db8f65497b529ceedc0a691ea34a9e407447c84311332f
|
||||
ssa_ast: 5a9e0d139821e42ea9cdb3a75c9b9ccdd10e4368490f2c5a1edca0e3d41913d5
|
||||
flattened_ast: 99f8c4ca373d413eba9db8b8949bdf493e6a201298578c22608de3bc8f4abcbf
|
||||
inlined_ast: 99f8c4ca373d413eba9db8b8949bdf493e6a201298578c22608de3bc8f4abcbf
|
||||
dce_ast: 99f8c4ca373d413eba9db8b8949bdf493e6a201298578c22608de3bc8f4abcbf
|
||||
bytecode: 6f468335c2ba73721aece1b1018fff421437eee9d52956368d33822d46e8c012
|
||||
warnings: ""
|
||||
results:
|
||||
|
17
tests/tests/compiler/constants/const_tuple_declaration.leo
Normal file
17
tests/tests/compiler/constants/const_tuple_declaration.leo
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
|
||||
const B: (u8,u32) = (1u8,1u32);
|
||||
transition foo() -> u32 {
|
||||
for i: u32 in 0u32..1u32 {
|
||||
let d:(u8,u32) = B;
|
||||
const A:u32 = 1u32;
|
||||
let c:u32 = A;
|
||||
}
|
||||
return 1u32;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
const START: u32 = 0u32;
|
||||
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
const (HELLO,GOODBYE): (u8,u8) = (1u8, 1u8);
|
||||
transition foo(a: u8, b: u8, flag: bool) -> u8 {
|
||||
return GOODBYE;
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ expectation: Fail
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
const (GOODBYE,HELLO): (u8,u8) = (0u8,(1u8,1u8));
|
||||
const (HELLO,GOODBYE): (u8,u8) = (1u8, 1u8);
|
||||
transition foo(a: u8, b: u8, flag: bool) -> u8 {
|
||||
return GOODBYE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user