Add support for expression statements in compiler passes

This commit is contained in:
d0cd 2022-10-21 18:31:48 -07:00
parent a7795b72db
commit 40ff47882f
5 changed files with 48 additions and 4 deletions

View File

@ -276,6 +276,7 @@ impl<'a> CodeGenerator<'a> {
}
}
// TODO: Fix to allow zero or multiple outputs.
fn visit_call(&mut self, input: &'a CallExpression) -> (String, String) {
let mut call_instruction = match &input.external {
Some(external) => format!(" call {external}.aleo/{} ", input.function),

View File

@ -18,8 +18,8 @@ use crate::CodeGenerator;
use leo_ast::{
AssignStatement, Block, ConditionalStatement, ConsoleFunction, ConsoleStatement, DecrementStatement,
DefinitionStatement, Expression, FinalizeStatement, IncrementStatement, IterationStatement, Mode, Output,
ReturnStatement, Statement,
DefinitionStatement, Expression, ExpressionStatement, FinalizeStatement, IncrementStatement, IterationStatement,
Mode, Output, ReturnStatement, Statement,
};
use itertools::Itertools;
@ -34,6 +34,7 @@ impl<'a> CodeGenerator<'a> {
Statement::Console(stmt) => self.visit_console(stmt),
Statement::Decrement(stmt) => self.visit_decrement(stmt),
Statement::Definition(stmt) => self.visit_definition(stmt),
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
Statement::Finalize(stmt) => self.visit_finalize(stmt),
Statement::Increment(stmt) => self.visit_increment(stmt),
Statement::Iteration(stmt) => self.visit_iteration(stmt),
@ -110,6 +111,13 @@ impl<'a> CodeGenerator<'a> {
unreachable!("DefinitionStatement's should not exist in SSA form.")
}
fn visit_expression_statement(&mut self, input: &'a ExpressionStatement) -> String {
match input.expression {
Expression::Call(_) => self.visit_expression(&input.expression).1,
_ => unreachable!("ExpressionStatement's can only contain CallExpression's."),
}
}
fn visit_increment(&mut self, input: &'a IncrementStatement) -> String {
let (index, mut instructions) = self.visit_expression(&input.index);
let (amount, amount_instructions) = self.visit_expression(&input.amount);

View File

@ -18,8 +18,8 @@ use crate::{RenameTable, StaticSingleAssigner};
use leo_ast::{
AssignStatement, Block, ConditionalStatement, ConsoleFunction, ConsoleStatement, DecrementStatement,
DefinitionStatement, Expression, ExpressionConsumer, FinalizeStatement, Identifier, IncrementStatement,
IterationStatement, ReturnStatement, Statement, StatementConsumer, TernaryExpression,
DefinitionStatement, Expression, ExpressionConsumer, ExpressionStatement, FinalizeStatement, Identifier,
IncrementStatement, IterationStatement, ReturnStatement, Statement, StatementConsumer, TernaryExpression,
};
use leo_span::Symbol;
@ -234,6 +234,20 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
statements
}
/// Consumes the expressions associated with `ExpressionStatement`, returning the simplified `ExpressionStatement`.
fn consume_expression_statement(&mut self, input: ExpressionStatement) -> Self::Output {
// Process the expression associated with the `ExpressionStatement`.
let (expression, mut statements) = self.consume_expression(input.expression);
// Add the `ExpressionStatement` to the list of produced statements.
statements.push(Statement::Expression(ExpressionStatement {
expression,
span: input.span,
}));
statements
}
/// Consumes the expressions associated with the `FinalizeStatement`, returning the simplified `FinalizeStatement`.
fn consume_finalize(&mut self, input: FinalizeStatement) -> Self::Output {
let mut statements = Vec::new();

View File

@ -34,6 +34,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
Statement::Console(stmt) => self.visit_console(stmt),
Statement::Decrement(stmt) => self.visit_decrement(stmt),
Statement::Definition(stmt) => self.visit_definition(stmt),
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
Statement::Finalize(stmt) => self.visit_finalize(stmt),
Statement::Increment(stmt) => self.visit_increment(stmt),
Statement::Iteration(stmt) => self.visit_iteration(stmt),
@ -224,6 +225,19 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
}
}
fn visit_expression_statement(&mut self, input: &'a ExpressionStatement) {
// Expression statements can only be function calls.
if !matches!(input.expression, Expression::Call(_)) {
self.emit_err(TypeCheckerError::expression_statement_must_be_function_call(
input.span(),
));
} else {
// Check the expression.
// TODO: Should the output type be restricted to unit types?
self.visit_expression(&input.expression, &None);
}
}
fn visit_finalize(&mut self, input: &'a FinalizeStatement) {
if self.is_finalize {
self.emit_err(TypeCheckerError::finalize_in_finalize(input.span()));

View File

@ -512,4 +512,11 @@ create_messages!(
msg: format!("A finalize statement cannot contain tuple expressions."),
help: None,
}
@formatted
expression_statement_must_be_function_call {
args: (),
msg: format!("An expression statement must be a function call."),
help: None,
}
);