Struct leo_passes::flattening::flattener::Flattener

source ·
pub struct Flattener<'a> {
    pub(crate) symbol_table: &'a SymbolTable,
    pub(crate) type_table: &'a TypeTable,
    pub(crate) node_builder: &'a NodeBuilder,
    pub(crate) assigner: &'a Assigner,
    pub(crate) condition_stack: Vec<Expression>,
    pub(crate) returns: Vec<(Option<Expression>, ReturnStatement)>,
    pub(crate) program: Option<Symbol>,
    pub(crate) is_async: bool,
}

Fields§

§symbol_table: &'a SymbolTable

The symbol table associated with the program.

§type_table: &'a TypeTable

A mapping between node IDs and their types.

§node_builder: &'a NodeBuilder

A counter used to generate unique node IDs.

§assigner: &'a Assigner

A struct used to construct (unique) assignment statements.

§condition_stack: Vec<Expression>

A stack of condition Expressions visited up to the current point in the AST.

§returns: Vec<(Option<Expression>, ReturnStatement)>

A list containing tuples of guards and expressions associated ReturnStatements. A guard is an expression that evaluates to true on the execution path of the ReturnStatement. Note that returns are inserted in the order they are encountered during a pre-order traversal of the AST. Note that type checking guarantees that there is at most one return in a basic block.

§program: Option<Symbol>

The program name.

§is_async: bool

Whether the function is an async function.

Implementations§

source§

impl<'a> Flattener<'a>

source

pub(crate) fn new( symbol_table: &'a SymbolTable, type_table: &'a TypeTable, node_builder: &'a NodeBuilder, assigner: &'a Assigner, ) -> Self

source

pub(crate) fn clear_early_returns( &mut self, ) -> Vec<(Option<Expression>, ReturnStatement)>

Clears the state associated with ReturnStatements, returning the ones that were previously stored.

source

pub(crate) fn construct_guard(&mut self) -> Option<Expression>

Constructs a guard from the current state of the condition stack.

source

pub(crate) fn fold_guards( &mut self, prefix: &str, guards: Vec<(Option<Expression>, Expression)>, ) -> (Expression, Vec<Statement>)

Fold guards and expressions into a single expression. Note that this function assumes that at least one guard is present.

source

pub(crate) fn unique_simple_assign_statement( &mut self, expr: Expression, ) -> (Identifier, Statement)

A wrapper around assigner.unique_simple_assign_statement that updates self.structs.

source

pub(crate) fn simple_assign_statement( &mut self, lhs: Identifier, rhs: Expression, ) -> Statement

A wrapper around assigner.simple_assign_statement that tracks the type of the lhs.

source

pub(crate) fn fold_returns( &mut self, block: &mut Block, returns: Vec<(Option<Expression>, ReturnStatement)>, )

Folds a list of return statements into a single return statement and adds the produced statements to the block.

source

pub(crate) fn ternary_array( &mut self, array: &ArrayType, condition: &Expression, first: &Identifier, second: &Identifier, ) -> (Expression, Vec<Statement>)

source

pub(crate) fn ternary_struct( &mut self, struct_: &Composite, condition: &Expression, first: &Identifier, second: &Identifier, ) -> (Expression, Vec<Statement>)

source

pub(crate) fn ternary_tuple( &mut self, tuple_type: &TupleType, condition: &Expression, first: &Identifier, second: &Identifier, ) -> (Expression, Vec<Statement>)

Trait Implementations§

source§

impl ExpressionReconstructor for Flattener<'_>

source§

fn reconstruct_struct_init( &mut self, input: StructExpression, ) -> (Expression, Self::AdditionalOutput)

Reconstructs a struct init expression, flattening any tuples in the expression.

source§

fn reconstruct_ternary( &mut self, input: TernaryExpression, ) -> (Expression, Self::AdditionalOutput)

Reconstructs ternary expressions over arrays, structs, and tuples, accumulating any statements that are generated. This is necessary because Aleo instructions does not support ternary expressions over composite data types. For example, the ternary expression cond ? (a, b) : (c, d) is flattened into the following:

let var$0 = cond ? a : c;
let var$1 = cond ? b : d;
(var$0, var$1)

For structs, the ternary expression cond ? a : b, where a and b are both structs Foo { bar: u8, baz: u8 }, is flattened into the following:

let var$0 = cond ? a.bar : b.bar;
let var$1 = cond ? a.baz : b.baz;
let var$2 = Foo { bar: var$0, baz: var$1 };
var$2
§

type AdditionalOutput = Vec<Statement>

source§

fn reconstruct_expression( &mut self, input: Expression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_access( &mut self, input: AccessExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_array_access( &mut self, input: ArrayAccess, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_associated_constant( &mut self, input: AssociatedConstant, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_associated_function( &mut self, input: AssociatedFunction, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_member_access( &mut self, input: MemberAccess, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_tuple_access( &mut self, input: TupleAccess, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_array( &mut self, input: ArrayExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_binary( &mut self, input: BinaryExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_call( &mut self, input: CallExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_cast( &mut self, input: CastExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_err( &mut self, _input: ErrExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_identifier( &mut self, input: Identifier, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_literal( &mut self, input: Literal, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_locator( &mut self, input: LocatorExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_tuple( &mut self, input: TupleExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_unary( &mut self, input: UnaryExpression, ) -> (Expression, Self::AdditionalOutput)

source§

fn reconstruct_unit( &mut self, input: UnitExpression, ) -> (Expression, Self::AdditionalOutput)

source§

impl<'a> Pass for Flattener<'a>

§

type Input = (Ast, &'a SymbolTable, &'a TypeTable, &'a NodeBuilder, &'a Assigner)

§

type Output = Result<Ast, LeoError>

source§

fn do_pass((ast, st, tt, node_builder, assigner): Self::Input) -> Self::Output

Runs the compiler pass.
source§

impl ProgramReconstructor for Flattener<'_>

source§

fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope

Flattens a program scope.

source§

fn reconstruct_function(&mut self, function: Function) -> Function

Flattens a function’s body

source§

fn reconstruct_program(&mut self, input: Program) -> Program

source§

fn reconstruct_stub(&mut self, input: Stub) -> Stub

source§

fn reconstruct_function_stub(&mut self, input: FunctionStub) -> FunctionStub

source§

fn reconstruct_struct(&mut self, input: Composite) -> Composite

source§

fn reconstruct_import(&mut self, input: Program) -> Program

source§

fn reconstruct_mapping(&mut self, input: Mapping) -> Mapping

source§

impl StatementReconstructor for Flattener<'_>

source§

fn reconstruct_assert( &mut self, input: AssertStatement, ) -> (Statement, Self::AdditionalOutput)

Rewrites an assert statement into a flattened form. Assert statements at the top level only have their arguments flattened. Assert statements inside a conditional statement are flattened to such that the check is conditional on the execution path being valid. For example, the following snippet:

if condition1 {
   if condition2 {
       assert(foo);
   }
}

is flattened to:

assert(!(condition1 && condition2) || foo);

which is equivalent to the logical formula (condition1 /\ condition2) ==> foo.

source§

fn reconstruct_assign( &mut self, assign: AssignStatement, ) -> (Statement, Self::AdditionalOutput)

Flattens an assign statement, if necessary. Marks variables as structs as necessary. Note that new statements are only produced if the right hand side is a ternary expression over structs. Otherwise, the statement is returned as is.

source§

fn reconstruct_block(&mut self, block: Block) -> (Block, Self::AdditionalOutput)

Flattens the statements inside a basic block. The resulting block does not contain any conditional statements.

source§

fn reconstruct_conditional( &mut self, conditional: ConditionalStatement, ) -> (Statement, Self::AdditionalOutput)

Flatten a conditional statement into a list of statements.

source§

fn reconstruct_return( &mut self, input: ReturnStatement, ) -> (Statement, Self::AdditionalOutput)

Transforms a return statement into an empty block statement. Stores the arguments to the return statement, which are later folded into a single return statement at the end of the function.

source§

fn reconstruct_console( &mut self, _: ConsoleStatement, ) -> (Statement, Self::AdditionalOutput)

source§

fn reconstruct_definition( &mut self, _definition: DefinitionStatement, ) -> (Statement, Self::AdditionalOutput)

source§

fn reconstruct_iteration( &mut self, _input: IterationStatement, ) -> (Statement, Self::AdditionalOutput)

source§

fn reconstruct_statement( &mut self, input: Statement, ) -> (Statement, Self::AdditionalOutput)

source§

fn reconstruct_const( &mut self, input: ConstDeclaration, ) -> (Statement, Self::AdditionalOutput)

source§

fn reconstruct_expression_statement( &mut self, input: ExpressionStatement, ) -> (Statement, Self::AdditionalOutput)

Auto Trait Implementations§

§

impl<'a> Freeze for Flattener<'a>

§

impl<'a> !RefUnwindSafe for Flattener<'a>

§

impl<'a> !Send for Flattener<'a>

§

impl<'a> !Sync for Flattener<'a>

§

impl<'a> Unpin for Flattener<'a>

§

impl<'a> !UnwindSafe for Flattener<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more