mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
WIP
This commit is contained in:
parent
7e5a6e9755
commit
d1a5283513
@ -147,10 +147,10 @@ impl ExpressionReconstructor for Flattener<'_> {
|
||||
(Expression::Identifier(first), Expression::Identifier(second))
|
||||
if self.structs.contains_key(&first.name) && self.structs.contains_key(&second.name) =>
|
||||
{
|
||||
let first_struct = self.symbol_table.lookup_struct(*self.structs.get(&first.name).unwrap()).unwrap();
|
||||
let second_struct = self.symbol_table.lookup_struct(*self.structs.get(&second.name).unwrap()).unwrap();
|
||||
let first_struct = self.structs.get(&first.name).unwrap().clone();
|
||||
let second_struct = self.structs.get(&second.name).unwrap();
|
||||
// Note that type checking guarantees that both expressions have the same same type. This is a sanity check.
|
||||
assert_eq!(first_struct, second_struct);
|
||||
assert_eq!(&first_struct, second_struct);
|
||||
|
||||
self.ternary_struct(first_struct, &input.condition, &first, &second)
|
||||
}
|
||||
|
@ -28,7 +28,9 @@ impl ProgramReconstructor for Flattener<'_> {
|
||||
self.structs = Default::default();
|
||||
for input in &finalize.input {
|
||||
if let Type::Identifier(struct_name) = input.type_() {
|
||||
self.structs.insert(input.identifier().name, struct_name.name);
|
||||
// Note that this unwrap is safe since type checking guarantees that the struct exists.
|
||||
let struct_ = self.symbol_table.lookup_struct(struct_name.name).unwrap().clone();
|
||||
self.structs.insert(input.identifier().name, struct_);
|
||||
}
|
||||
}
|
||||
// Flatten the finalize block.
|
||||
@ -55,7 +57,9 @@ impl ProgramReconstructor for Flattener<'_> {
|
||||
self.structs = Default::default();
|
||||
for input in &function.input {
|
||||
if let Type::Identifier(struct_name) = input.type_() {
|
||||
self.structs.insert(input.identifier().name, struct_name.name);
|
||||
// Note that this unwrap is safe since type checking guarantees that the struct exists.
|
||||
let struct_ = self.symbol_table.lookup_struct(struct_name.name).unwrap().clone();
|
||||
self.structs.insert(input.identifier().name, struct_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,9 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
|
||||
// If the output type is a struct, add it to `self.structs`.
|
||||
if let Type::Identifier(struct_name) = type_ {
|
||||
self.structs.insert(identifier.name, struct_name.name);
|
||||
// Note that this unwrap is safe since type checking guarantees that the struct exists.
|
||||
let struct_ = self.symbol_table.lookup_struct(struct_name.name).unwrap().clone();
|
||||
self.structs.insert(identifier.name, struct_);
|
||||
}
|
||||
|
||||
Expression::Identifier(identifier)
|
||||
@ -217,7 +219,9 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
type_ => {
|
||||
// If the function returns a struct, add it to `self.structs`.
|
||||
if let Type::Identifier(struct_name) = type_ {
|
||||
self.structs.insert(lhs_identifier.name, struct_name.name);
|
||||
// Note that this unwrap is safe since type checking guarantees that the struct exists.
|
||||
let struct_ = self.symbol_table.lookup_struct(struct_name.name).unwrap().clone();
|
||||
self.structs.insert(lhs_identifier.name, struct_);
|
||||
};
|
||||
(
|
||||
Statement::Assign(Box::new(AssignStatement {
|
||||
@ -266,7 +270,9 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
};
|
||||
// If the value type is a struct, add it to `self.structs`.
|
||||
if let Type::Identifier(struct_name) = value_type {
|
||||
self.structs.insert(lhs_identifier.name, struct_name.name);
|
||||
// Note that this unwrap is safe since type checking guarantees that the struct exists.
|
||||
let struct_ = self.symbol_table.lookup_struct(struct_name.name).unwrap().clone();
|
||||
self.structs.insert(lhs_identifier.name, struct_);
|
||||
}
|
||||
// Reconstruct the assignment.
|
||||
(
|
||||
@ -280,8 +286,7 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
)
|
||||
}
|
||||
(Expression::Identifier(identifier), expression) => {
|
||||
self.update_structs(&identifier, &expression);
|
||||
(self.assigner.simple_assign_statement(identifier, expression, self.node_builder.next_id()), statements)
|
||||
(self.simple_assign_statement(identifier, expression), statements)
|
||||
}
|
||||
// If the lhs is a tuple and the rhs is a function call, then return the reconstructed statement.
|
||||
(Expression::Tuple(tuple), Expression::Call(call)) => {
|
||||
@ -306,7 +311,9 @@ impl StatementReconstructor for Flattener<'_> {
|
||||
};
|
||||
// If the output type is a struct, add it to `self.structs`.
|
||||
if let Type::Identifier(struct_name) = type_ {
|
||||
self.structs.insert(identifier.name, struct_name.name);
|
||||
// Note that this unwrap is safe since type checking guarantees that the struct exists.
|
||||
let struct_ = self.symbol_table.lookup_struct(struct_name.name).unwrap().clone();
|
||||
self.structs.insert(identifier.name, struct_);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -57,7 +57,7 @@ pub struct Flattener<'a> {
|
||||
/// A struct used to construct (unique) assignment statements.
|
||||
pub(crate) assigner: &'a Assigner,
|
||||
/// The set of variables that are structs.
|
||||
pub(crate) structs: IndexMap<Symbol, Symbol>,
|
||||
pub(crate) structs: IndexMap<Symbol, Struct>,
|
||||
/// A stack of condition `Expression`s visited up to the current point in the AST.
|
||||
pub(crate) condition_stack: Vec<Expression>,
|
||||
/// A list containing tuples of guards and expressions associated `ReturnStatement`s.
|
||||
@ -167,41 +167,8 @@ impl<'a> Flattener<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up the name of the struct associated with an identifier or access expression, if it exists.
|
||||
pub(crate) fn lookup_struct_symbol(&self, expression: &Expression) -> Option<Symbol> {
|
||||
match expression {
|
||||
Expression::Identifier(identifier) => self.structs.get(&identifier.name).copied(),
|
||||
Expression::Access(AccessExpression::Member(access)) => {
|
||||
// The inner expression of an access expression is either an identifier or another access expression.
|
||||
let name = self.lookup_struct_symbol(&access.inner).unwrap();
|
||||
let struct_ = self.symbol_table.lookup_struct(name).unwrap();
|
||||
let Member { type_, .. } =
|
||||
struct_.members.iter().find(|member| member.name() == access.name.name).unwrap();
|
||||
match type_ {
|
||||
Type::Identifier(identifier) => Some(identifier.name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates `self.structs` for new assignment statements.
|
||||
/// Expects the left hand side of the assignment to be an identifier.
|
||||
pub(crate) fn update_structs(&mut self, lhs: &Identifier, rhs: &Expression) {
|
||||
match rhs {
|
||||
Expression::Struct(rhs) => {
|
||||
self.structs.insert(lhs.name, rhs.name.name);
|
||||
}
|
||||
// If the rhs of the assignment is an identifier that is a struct, add it to `self.structs`.
|
||||
Expression::Identifier(rhs) if self.structs.contains_key(&rhs.name) => {
|
||||
// Note that this unwrap is safe because we just checked that the key exists.
|
||||
self.structs.insert(lhs.name, *self.structs.get(&rhs.name).unwrap());
|
||||
}
|
||||
// Otherwise, do nothing.
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
/// Gets the type of the expression, if it's being tracked.
|
||||
pub(crate) fn get_type(&self, expression: &Expression) -> Option<Type> {}
|
||||
|
||||
/// A wrapper around `assigner.unique_simple_assign_statement` that updates `self.structs`.
|
||||
// TODO (@d0cd) Update to check for tuples and arrays
|
||||
@ -211,7 +178,7 @@ impl<'a> Flattener<'a> {
|
||||
// Construct the lhs of the assignment.
|
||||
let place = Identifier { name, span: Default::default(), id: self.node_builder.next_id() };
|
||||
// Construct the assignment statement.
|
||||
let statement = self.assigner.simple_assign_statement(place, expr, self.node_builder.next_id());
|
||||
let statement = self.simple_assign_statement(place, expr);
|
||||
|
||||
match &statement {
|
||||
Statement::Assign(assign) => {
|
||||
@ -222,10 +189,11 @@ impl<'a> Flattener<'a> {
|
||||
(place, statement)
|
||||
}
|
||||
|
||||
/// A wrapper around `assigner.simple_assign_statement` that updates `self.structs`.
|
||||
/// A wrapper around `assigner.simple_assign_statement` that tracks the type of the lhs.
|
||||
pub(crate) fn simple_assign_statement(&mut self, lhs: Identifier, rhs: Expression) -> Statement {
|
||||
self.update_structs(&lhs, &rhs);
|
||||
self.assigner.simple_assign_statement(lhs, rhs, self.node_builder.next_id())
|
||||
let statement = self.assigner.simple_assign_statement(lhs, rhs, self.node_builder.next_id());
|
||||
self.update_types(&statement);
|
||||
statement
|
||||
}
|
||||
|
||||
/// Folds a list of return statements into a single return statement and adds the produced statements to the block.
|
||||
@ -380,7 +348,7 @@ impl<'a> Flattener<'a> {
|
||||
|
||||
pub(crate) fn ternary_struct(
|
||||
&mut self,
|
||||
struct_: &Struct,
|
||||
struct_: Struct,
|
||||
condition: &Expression,
|
||||
first: &Identifier,
|
||||
second: &Identifier,
|
||||
@ -447,7 +415,7 @@ impl<'a> Flattener<'a> {
|
||||
let (identifier, statement) = self.unique_simple_assign_statement(expr);
|
||||
|
||||
// Mark the lhs of the assignment as a struct.
|
||||
self.structs.insert(identifier.name, struct_.identifier.name);
|
||||
self.structs.insert(identifier.name, struct_);
|
||||
|
||||
statements.push(statement);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user