This commit is contained in:
Pranav Gaddamadugu 2022-08-15 22:31:21 -07:00
parent f109241ee4
commit 8c8aacfbd8
3 changed files with 158 additions and 141 deletions

View File

@ -27,10 +27,10 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
/// Consumes an access expression, accumulating any statements that are generated. /// Consumes an access expression, accumulating any statements that are generated.
fn consume_access(&mut self, input: AccessExpression) -> Self::Output { fn consume_access(&mut self, input: AccessExpression) -> Self::Output {
let mut additional_output = Vec::new(); let (expr, mut statements) = match input {
let expr = Expression::Access(match input {
AccessExpression::AssociatedFunction(function) => { AccessExpression::AssociatedFunction(function) => {
let mut statements = Vec::new();
(
AccessExpression::AssociatedFunction(AssociatedFunction { AccessExpression::AssociatedFunction(AssociatedFunction {
ty: function.ty, ty: function.ty,
name: function.name, name: function.name,
@ -38,104 +38,105 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
.args .args
.into_iter() .into_iter()
.map(|arg| { .map(|arg| {
let (place, statement) = self.consume_expression(arg); let (arg, mut stmts) = self.consume_expression(arg);
additional_output.extend(statement); statements.append(&mut stmts);
place arg
}) })
.collect(), .collect(),
span: function.span, span: function.span,
}) }),
statements,
)
} }
AccessExpression::Member(member) => AccessExpression::Member(MemberAccess { AccessExpression::Member(member) => {
inner: { let (expr, statements) = self.consume_expression(*member.inner);
let (place, statement) = self.consume_expression(*member.inner); (
additional_output.extend(statement); AccessExpression::Member(MemberAccess {
Box::new(place) inner: Box::new(expr),
},
name: member.name, name: member.name,
span: member.span, span: member.span,
}), }),
AccessExpression::Tuple(tuple) => AccessExpression::Tuple(TupleAccess { statements,
tuple: { )
let (place, statement) = self.consume_expression(*tuple.tuple); }
additional_output.extend(statement); AccessExpression::Tuple(tuple) => {
Box::new(place) let (expr, statements) = self.consume_expression(*tuple.tuple);
}, (
AccessExpression::Tuple(TupleAccess {
tuple: Box::new(expr),
index: tuple.index, index: tuple.index,
span: tuple.span, span: tuple.span,
}), }),
expr => expr, statements,
}); )
let (place, statement) = self.simple_expr_assign_statement(expr); }
additional_output.push(statement); expr => (expr, Vec::new()),
};
let (place, statement) = self.unique_simple_assign_statement(Expression::Access(expr));
statements.push(statement);
(place, additional_output) (place, statements)
} }
/// Consumes a binary expression, accumulating any statements that are generated. /// Consumes a binary expression, accumulating any statements that are generated.
fn consume_binary(&mut self, input: BinaryExpression) -> Self::Output { fn consume_binary(&mut self, input: BinaryExpression) -> Self::Output {
let mut additional_output = Vec::new(); // Reconstruct the lhs of the binary expression.
let (left_expression, mut statements) = self.consume_expression(*input.left);
// Reconstruct the rhs of the binary expression.
let (right_expression, mut right_statements) = self.consume_expression(*input.right);
// Accumulate any statements produced.
statements.append(&mut right_statements);
let expr = Expression::Binary(BinaryExpression { // Construct and accumulate a unique assignment statement storing the result of the binary expression.
left: { let (place, statement) = self.unique_simple_assign_statement(Expression::Binary(BinaryExpression {
let (expression, statement) = self.consume_expression(*input.left); left: Box::new(left_expression),
additional_output.extend(statement); right: Box::new(right_expression),
Box::new(expression)
},
right: {
let (expression, statement) = self.consume_expression(*input.right);
additional_output.extend(statement);
Box::new(expression)
},
op: input.op, op: input.op,
span: input.span, span: input.span,
}); }));
let (place, statement) = self.simple_expr_assign_statement(expr); statements.push(statement);
additional_output.push(statement);
(place, additional_output) (place, statements)
} }
/// Consumes a call expression without visiting the function name, accumulating any statements that are generated. /// Consumes a call expression without visiting the function name, accumulating any statements that are generated.
fn consume_call(&mut self, input: CallExpression) -> Self::Output { fn consume_call(&mut self, input: CallExpression) -> Self::Output {
let mut additional_output = Vec::new(); let mut statements = Vec::new();
// Create a new assignment statement for the call expression. // Process the arguments, accumulating any statements produced.
let expr = Expression::Call(CallExpression { let arguments = input
// Note that we do not rename the function name.
function: input.function,
// Consume the arguments.
arguments: input
.arguments .arguments
.into_iter() .into_iter()
.map(|argument| { .map(|argument| {
let (argument, output) = self.consume_expression(argument); let (argument, mut stmts) = self.consume_expression(argument);
additional_output.extend(output); statements.append(&mut stmts);
argument argument
}) })
.collect(), .collect();
span: input.span,
});
let (place, statement) = self.simple_expr_assign_statement(expr);
additional_output.push(statement);
(place, additional_output) // Construct and accumulate a new assignment statement for the call expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Call(CallExpression {
// Note that we do not rename the function name.
function: input.function,
// Consume the arguments.
arguments,
span: input.span,
}));
statements.push(statement);
(place, statements)
} }
/// Consumes a circuit initialization expression with renamed variables, accumulating any statements that are generated. /// Consumes a circuit initialization expression with renamed variables, accumulating any statements that are generated.
fn consume_circuit_init(&mut self, input: CircuitExpression) -> Self::Output { fn consume_circuit_init(&mut self, input: CircuitExpression) -> Self::Output {
let mut additional_output = Vec::new(); let mut statements = Vec::new();
// Create a new assignment statement for the circuit init expression. // Process the members, accumulating any statements produced.
let expr = Expression::Circuit(CircuitExpression { let members = input
name: input.name,
span: input.span,
// Consume the circuit members.
members: input
.members .members
.into_iter() .into_iter()
.map(|arg| { .map(|arg| {
let (expression, output) = match &arg.expression.is_some() { let (expression, mut stmts) = match &arg.expression.is_some() {
// If the expression is None, then `arg` is a `CircuitVariableInitializer` of the form `<id>,`. // If the expression is None, then `arg` is a `CircuitVariableInitializer` of the form `<id>,`.
// In this case, we must consume the identifier and produce an initializer of the form `<id>: <renamed_id>`. // In this case, we must consume the identifier and produce an initializer of the form `<id>: <renamed_id>`.
false => self.consume_identifier(arg.identifier), false => self.consume_identifier(arg.identifier),
@ -144,7 +145,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
true => self.consume_expression(arg.expression.unwrap()), true => self.consume_expression(arg.expression.unwrap()),
}; };
// Add the output to the additional output. // Add the output to the additional output.
additional_output.extend(output); statements.append(&mut stmts);
// Return the new member. // Return the new member.
CircuitVariableInitializer { CircuitVariableInitializer {
@ -152,22 +153,29 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
expression: Some(expression), expression: Some(expression),
} }
}) })
.collect(), .collect();
});
let (place, statement) = self.simple_expr_assign_statement(expr);
additional_output.push(statement);
(place, additional_output) // Construct and accumulate a new assignment statement for the circuit init expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Circuit(CircuitExpression {
name: input.name,
span: input.span,
// Consume the circuit members.
members,
}));
statements.push(statement);
(place, statements)
} }
fn consume_err(&mut self, input: ErrExpression) -> Self::Output { /// `ErrExpressions` should not exist and thus do not need to be handled.
(Expression::Err(input), Default::default()) fn consume_err(&mut self, _input: ErrExpression) -> Self::Output {
unreachable!("`ErrExpression`s should not be in the AST at this phase of compilation.")
} }
/// Produces a new `Identifier` with a unique name. /// Produces a new `Identifier` with a unique name.
fn consume_identifier(&mut self, identifier: Identifier) -> Self::Output { fn consume_identifier(&mut self, identifier: Identifier) -> Self::Output {
let name = match self.is_lhs { let name = match self.is_lhs {
// If consumeing the left-hand side of a definition or assignment, a new unique name is introduced. // If consuming the left-hand side of a definition or assignment, a new unique name is introduced.
true => { true => {
let new_name = self.unique_symbol(identifier.name); let new_name = self.unique_symbol(identifier.name);
self.rename_table.update(identifier.name, new_name); self.rename_table.update(identifier.name, new_name);
@ -191,64 +199,74 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
) )
} }
/// Consumes and returns the literal without making any modifications.
fn consume_literal(&mut self, input: Literal) -> Self::Output { fn consume_literal(&mut self, input: Literal) -> Self::Output {
(Expression::Literal(input), Default::default()) (Expression::Literal(input), Default::default())
} }
/// Consumes a ternary expression, accumulating any statements that are generated. /// Consumes a ternary expression, accumulating any statements that are generated.
fn consume_ternary(&mut self, input: TernaryExpression) -> Self::Output { fn consume_ternary(&mut self, input: TernaryExpression) -> Self::Output {
let mut additional_output = Vec::new(); // Reconstruct the condition of the ternary expression.
let (cond_expr, mut statements) = self.consume_expression(*input.condition);
// Reconstruct the if-true case of the ternary expression.
let (if_true_expr, mut if_true_statements) = self.consume_expression(*input.if_true);
// Reconstruct the if-false case of the ternary expression.
let (if_false_expr, mut if_false_statements) = self.consume_expression(*input.if_false);
let expr = Expression::Ternary(TernaryExpression { // Accumulate any statements produced.
condition: Box::new(self.consume_expression(*input.condition).0), statements.append(&mut if_true_statements);
if_true: Box::new(self.consume_expression(*input.if_true).0), statements.append(&mut if_false_statements);
if_false: Box::new(self.consume_expression(*input.if_false).0),
// Construct and accumulate a unique assignment statement storing the result of the ternary expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Ternary(TernaryExpression {
condition: Box::new(cond_expr),
if_true: Box::new(if_true_expr),
if_false: Box::new(if_false_expr),
span: input.span, span: input.span,
}); }));
let (place, statement) = self.simple_expr_assign_statement(expr); statements.push(statement);
additional_output.push(statement);
(place, additional_output) (place, statements)
} }
/// Consumes a tuple expression, accumulating any statements that are generated /// Consumes a tuple expression, accumulating any statements that are generated
fn consume_tuple(&mut self, input: TupleExpression) -> Self::Output { fn consume_tuple(&mut self, input: TupleExpression) -> Self::Output {
let mut additional_output = Vec::new(); let mut statements = Vec::new();
let expr = Expression::Tuple(TupleExpression { // Process the elements, accumulating any statements produced.
elements: input let elements = input
.elements .elements
.into_iter() .into_iter()
.map(|element| { .map(|element| {
let (element, statements) = self.consume_expression(element); let (element, mut stmts) = self.consume_expression(element);
additional_output.extend(statements); statements.append(&mut stmts);
element element
}) })
.collect(), .collect();
span: input.span,
});
let (place, statement) = self.simple_expr_assign_statement(expr);
additional_output.push(statement);
(place, additional_output) // Construct and accumulate a new assignment statement for the tuple expression.
let (place, statement) = self.unique_simple_assign_statement(Expression::Tuple(TupleExpression {
elements,
span: input.span,
}));
statements.push(statement);
(place, statements)
} }
/// Consumes a unary expression, accumulating any statements that are generated. /// Consumes a unary expression, accumulating any statements that are generated.
fn consume_unary(&mut self, input: UnaryExpression) -> Self::Output { fn consume_unary(&mut self, input: UnaryExpression) -> Self::Output {
let mut additional_output = Vec::new(); // Reconstruct the operand of the unary expression.
let (receiver, mut statements) = self.consume_expression(*input.receiver);
let expr = Expression::Unary(UnaryExpression { // Construct and accumulate a new assignment statement for the unary expression.
receiver: { let (place, statement) = self.unique_simple_assign_statement(Expression::Unary(UnaryExpression {
let (expression, statement) = self.consume_expression(*input.receiver);
additional_output.extend(statement);
Box::new(expression)
},
op: input.op, op: input.op,
receiver: Box::new(receiver),
span: input.span, span: input.span,
}); }));
let (place, statement) = self.simple_expr_assign_statement(expr); statements.push(statement);
additional_output.push(statement);
(place, additional_output) (place, statements)
} }
} }

View File

@ -30,7 +30,6 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
/// Transforms a `ReturnStatement` into an empty `BlockStatement`, /// Transforms a `ReturnStatement` into an empty `BlockStatement`,
/// storing the expression and the associated guard in `self.early_returns`. /// storing the expression and the associated guard in `self.early_returns`.
///
/// Note that type checking guarantees that there is at most one `ReturnStatement` in a block. /// Note that type checking guarantees that there is at most one `ReturnStatement` in a block.
fn consume_return(&mut self, input: ReturnStatement) -> Self::Output { fn consume_return(&mut self, input: ReturnStatement) -> Self::Output {
// Construct the associated guard. // Construct the associated guard.

View File

@ -66,7 +66,7 @@ impl<'a> StaticSingleAssigner<'a> {
/// Constructs a simple assign statement for `expr` with a unique name. /// Constructs a simple assign statement for `expr` with a unique name.
/// For example, `expr` is transformed into `$var$0 = expr;`. /// For example, `expr` is transformed into `$var$0 = expr;`.
pub(crate) fn simple_expr_assign_statement(&mut self, expr: Expression) -> (Expression, Statement) { pub(crate) fn unique_simple_assign_statement(&mut self, expr: Expression) -> (Expression, Statement) {
// Create a new variable for the expression. // Create a new variable for the expression.
let place = Expression::Identifier(Identifier { let place = Expression::Identifier(Identifier {
name: self.unique_symbol("$var"), name: self.unique_symbol("$var"),