This commit is contained in:
Pranav Gaddamadugu 2022-10-07 19:59:10 -07:00 committed by d0cd
parent 605f675ff6
commit 6ae2d9727b
7 changed files with 38 additions and 40 deletions

View File

@ -17,7 +17,10 @@
use crate::Flattener;
use itertools::Itertools;
use leo_ast::{HEAD, AccessExpression, Expression, ExpressionReconstructor, Member, MemberAccess, Statement, StructExpression, StructVariableInitializer, TernaryExpression, TupleExpression, AssociatedFunction, Circuit, CircuitExpression, CircuitMember, CircuitVariableInitializer, c06fba2d5, WIP, Struct};
use leo_ast::{
AccessExpression, AssociatedFunction, Expression, ExpressionReconstructor, Member, MemberAccess, Statement, Struct,
StructExpression, StructVariableInitializer, TernaryExpression, TupleExpression,
};
// TODO: Clean up logic. To be done in a follow-up PR (feat/tuples)
@ -70,7 +73,7 @@ impl ExpressionReconstructor for Flattener<'_> {
}
/// Reconstructs a struct init expression, flattening any tuples in the expression.
fn reconstruct_struct_init(&mut self, input: CircuitExpression) -> (Expression, Self::AdditionalOutput) {
fn reconstruct_struct_init(&mut self, input: StructExpression) -> (Expression, Self::AdditionalOutput) {
let mut statements = Vec::new();
let mut flattened_expressions = Vec::with_capacity(input.members.len());

View File

@ -17,8 +17,8 @@
use crate::Flattener;
use leo_ast::{
Circuit, CircuitMember, Finalize, FinalizeStatement, Function, Identifier, ProgramReconstructor, Statement,
StatementReconstructor, Type,
Finalize, FinalizeStatement, Function, Identifier, Member, ProgramReconstructor, Statement, StatementReconstructor,
Struct, Type,
};
use leo_span::Symbol;
@ -124,36 +124,36 @@ impl ProgramReconstructor for Flattener<'_> {
}
}
/// Flattens the circuit definitions in the program, flattening any tuples in the definitions.
/// For example, the follow circuit definitions:
/// Flattens the struct definitions in the program, flattening any tuples in the definitions.
/// For example, the follow struct definitions:
/// ```leo
/// circuit Bar {
/// struct Bar {
/// a: u8,
/// b: (u16, u32),
/// }
///
/// circuit Foo {
/// struct Foo {
/// c: u8,
/// d: (Bar, (Bar, Bar)),
/// }
/// ```
/// are flattened in the following way.
/// ```leo
/// circuit Bar {
/// struct Bar {
/// a_0: u8,
/// b_0: u16,
/// b_1: u32,
/// }
///
/// circuit Foo {
/// struct Foo {
/// c_0: u8,
/// d_0: Bar,
/// d_1_0: Bar,
/// d_1_1: Bar,
/// }
fn reconstruct_circuit(&mut self, input: Circuit) -> Circuit {
// Helper to rename and flatten a circuit member.
fn rename_member(identifier: Identifier, type_: Type, index: usize) -> Vec<CircuitMember> {
fn reconstruct_struct(&mut self, input: Struct) -> Struct {
// Helper to rename and flatten a struct member.
fn rename_member(identifier: Identifier, type_: Type, index: usize) -> Vec<Member> {
// Construct the new name for the identifier.
let identifier = Identifier::new(Symbol::intern(&format!("{}_{}", identifier.name, index)));
match type_ {
@ -166,7 +166,7 @@ impl ProgramReconstructor for Flattener<'_> {
members
}
// Otherwise, rename the member and return it as a singleton list.
type_ => vec![CircuitMember::CircuitVariable(identifier, type_)],
type_ => vec![Member { identifier, type_ }],
}
}
@ -176,22 +176,22 @@ impl ProgramReconstructor for Flattener<'_> {
.members
.into_iter()
.enumerate()
.for_each(|(i, CircuitMember::CircuitVariable(identifier, type_))| {
.for_each(|(i, Member { identifier, type_ })| {
members.extend(rename_member(identifier, type_, i));
});
// Construct the flattened circuit.
let circuit = Circuit {
// Construct the flattened struct.
let struct_ = Struct {
identifier: input.identifier,
members,
is_record: input.is_record,
span: input.span,
};
// Add the flattened circuit to the circuit map.
self.flattened_structs.insert(circuit.identifier.name, circuit.clone());
// Add the flattened struct to the struct map.
self.flattened_structs.insert(struct_.identifier.name, struct_.clone());
// Return the flattened circuit.
circuit
// Return the flattened struct.
struct_
}
}

View File

@ -17,9 +17,9 @@
use crate::Flattener;
use leo_ast::{
AssignStatement, Block, ConditionalStatement, DefinitionStatement, Expression, ExpressionReconstructor,
FinalizeStatement, IterationStatement, Node, ReturnStatement, Statement, StatementReconstructor, UnaryExpression,
UnaryOperation,
AssignStatement, BinaryExpression, BinaryOperation, Block, ConditionalStatement, ConsoleFunction, ConsoleStatement,
DefinitionStatement, Expression, ExpressionReconstructor, FinalizeStatement, IterationStatement, Node,
ReturnStatement, Statement, StatementReconstructor, UnaryExpression, UnaryOperation,
};
impl StatementReconstructor for Flattener<'_> {

View File

@ -17,8 +17,8 @@
use crate::{Assigner, SymbolTable};
use leo_ast::{
AccessExpression, BinaryExpression, BinaryOperation, Block, Circuit, CircuitMember, Expression,
ExpressionReconstructor, Identifier, ReturnStatement, Statement, TernaryExpression, Type,
AccessExpression, BinaryExpression, BinaryOperation, Block, Expression, ExpressionReconstructor, Identifier,
Member, ReturnStatement, Statement, Struct, TernaryExpression, Type,
};
use leo_span::Symbol;
@ -44,7 +44,7 @@ pub struct Flattener<'a> {
/// Note that type checking guarantees that there is at most one finalize in a basic block.
pub(crate) finalizes: Vec<Vec<(Option<Expression>, Expression)>>,
/// A mapping between struct names and flattened struct declarations.
pub(crate) flattened_structs: IndexMap<Symbol, Circuit>,
pub(crate) flattened_structs: IndexMap<Symbol, Struct>,
/// A mapping between variables and flattened tuple expressions.
pub(crate) tuples: IndexMap<Symbol, Vec<Expression>>,
}

View File

@ -172,7 +172,6 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
})
.collect();
// Reorder the members to match that of the struct definition.
// Lookup the struct definition.

View File

@ -50,7 +50,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
Expression::Access(access) => self.visit_access(access, additional),
Expression::Binary(binary) => self.visit_binary(binary, additional),
Expression::Call(call) => self.visit_call(call, additional),
Expression::Circuit(circuit) => self.visit_circuit_init(circuit, additional),
Expression::Struct(struct_) => self.visit_struct_init(struct_, additional),
Expression::Err(err) => self.visit_err(err, additional),
Expression::Identifier(identifier) => self.visit_identifier(identifier, additional),
Expression::Literal(literal) => self.visit_literal(literal, additional),

View File

@ -30,17 +30,13 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_struct(&mut self, input: &'a Struct) {
// Check for conflicting struct/record member names.
let mut used = HashSet::new();
if !input
.members
.iter()
.all(|Member { identifier, type_} | {
// TODO: Better spans.
// Check that the member types are valid.
self.assert_type_is_defined(type_, ident.span);
self.assert_valid_declaration_or_parameter_type(type_, ident.span);
used.insert(ident.name)
})
{
if !input.members.iter().all(|Member { identifier, type_ }| {
// TODO: Better spans.
// Check that the member types are valid.
self.assert_type_is_defined(type_, identifier.span);
self.assert_valid_declaration_or_parameter_type(type_, identifier.span);
used.insert(identifier.name)
}) {
self.emit_err(if input.is_record {
TypeCheckerError::duplicate_record_variable(input.name(), input.span())
} else {