-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lowering pass and augmented assignments.
- Loading branch information
Showing
14 changed files
with
432 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,29 @@ | ||
use fe_analyzer::Context; | ||
|
||
use crate::lowering::mappers::functions; | ||
use fe_parser::ast as fe; | ||
use fe_parser::ast::ContractStmt; | ||
use fe_parser::node::Node; | ||
|
||
pub fn contract_def(context: &Context, stmt: Node<fe::ModuleStmt>) -> Node<fe::ModuleStmt> { | ||
if let fe::ModuleStmt::ContractDef { name, body } = stmt.kind { | ||
let lowered_body = body | ||
.into_iter() | ||
.map(|stmt| match stmt.kind { | ||
ContractStmt::ContractField { .. } => stmt, | ||
ContractStmt::EventDef { .. } => stmt, | ||
ContractStmt::FuncDef { .. } => functions::func_def(context, stmt), | ||
}) | ||
.collect(); | ||
|
||
return Node::new( | ||
fe::ModuleStmt::ContractDef { | ||
name, | ||
body: lowered_body, | ||
}, | ||
stmt.span, | ||
); | ||
} | ||
|
||
unreachable!() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,119 @@ | ||
use fe_analyzer::Context; | ||
use fe_parser::ast as fe; | ||
use fe_parser::node::Node; | ||
|
||
/// Builds a Yul expression from a Fe expression. | ||
pub fn expr(context: &Context, exp: Node<fe::Expr>) -> Node<fe::Expr> { | ||
let lowered_kind = match exp.kind { | ||
fe::Expr::Name(_) => exp.kind, | ||
fe::Expr::Num(_) => exp.kind, | ||
fe::Expr::Bool(_) => exp.kind, | ||
fe::Expr::Subscript { value, slices } => fe::Expr::Subscript { | ||
value: boxed_expr(context, value), | ||
slices: slices_index_expr(context, slices), | ||
}, | ||
fe::Expr::Attribute { value, attr } => fe::Expr::Attribute { | ||
value: boxed_expr(context, value), | ||
attr, | ||
}, | ||
fe::Expr::Ternary { | ||
if_expr, | ||
test, | ||
else_expr, | ||
} => fe::Expr::Ternary { | ||
if_expr: boxed_expr(context, if_expr), | ||
test: boxed_expr(context, test), | ||
else_expr: boxed_expr(context, else_expr), | ||
}, | ||
fe::Expr::BoolOperation { left, op, right } => fe::Expr::BoolOperation { | ||
left: boxed_expr(context, left), | ||
op, | ||
right: boxed_expr(context, right), | ||
}, | ||
fe::Expr::BinOperation { left, op, right } => fe::Expr::BinOperation { | ||
left: boxed_expr(context, left), | ||
op, | ||
right: boxed_expr(context, right), | ||
}, | ||
fe::Expr::UnaryOperation { op, operand } => fe::Expr::UnaryOperation { | ||
op, | ||
operand: boxed_expr(context, operand), | ||
}, | ||
fe::Expr::CompOperation { left, op, right } => fe::Expr::CompOperation { | ||
left: boxed_expr(context, left), | ||
op, | ||
right: boxed_expr(context, right), | ||
}, | ||
// TODO finish | ||
fe::Expr::Call { func, args } => fe::Expr::Call { | ||
func: boxed_expr(context, func), | ||
args: call_args(context, args), | ||
}, | ||
fe::Expr::List { .. } => unimplemented!(), | ||
fe::Expr::ListComp { .. } => unimplemented!(), | ||
fe::Expr::Tuple { .. } => unimplemented!(), | ||
fe::Expr::Str(_) => exp.kind, | ||
fe::Expr::Ellipsis => unimplemented!(), | ||
}; | ||
|
||
Node::new(lowered_kind, exp.span) | ||
} | ||
|
||
pub fn slices_index_expr( | ||
context: &Context, | ||
slices: Node<Vec<Node<fe::Slice>>>, | ||
) -> Node<Vec<Node<fe::Slice>>> { | ||
let first_slice = &slices.kind[0]; | ||
|
||
if let fe::Slice::Index(exp) = &first_slice.kind { | ||
return Node::new( | ||
vec![Node::new( | ||
fe::Slice::Index(Box::new(expr(context, *exp.to_owned()))), | ||
first_slice.span, | ||
)], | ||
slices.span, | ||
); | ||
} | ||
|
||
unreachable!() | ||
} | ||
|
||
pub fn optional_expr(context: &Context, exp: Option<Node<fe::Expr>>) -> Option<Node<fe::Expr>> { | ||
exp.map(|exp| expr(context, exp)) | ||
} | ||
|
||
#[allow(clippy::boxed_local)] | ||
pub fn boxed_expr(context: &Context, exp: Box<Node<fe::Expr>>) -> Box<Node<fe::Expr>> { | ||
Box::new(expr(context, *exp)) | ||
} | ||
|
||
pub fn multiple_exprs(context: &Context, exp: Vec<Node<fe::Expr>>) -> Vec<Node<fe::Expr>> { | ||
exp.into_iter().map(|exp| expr(context, exp)).collect() | ||
} | ||
|
||
fn call_args( | ||
context: &Context, | ||
args: Node<Vec<Node<fe::CallArg>>>, | ||
) -> Node<Vec<Node<fe::CallArg>>> { | ||
let lowered_args = args | ||
.kind | ||
.into_iter() | ||
.map(|arg| match arg.kind { | ||
fe::CallArg::Arg(inner_arg) => { | ||
Node::new(fe::CallArg::Arg(expr(context, inner_arg)), arg.span) | ||
} | ||
fe::CallArg::Kwarg(inner_arg) => { | ||
Node::new(fe::CallArg::Kwarg(kwarg(context, inner_arg)), arg.span) | ||
} | ||
}) | ||
.collect(); | ||
|
||
Node::new(lowered_args, args.span) | ||
} | ||
|
||
fn kwarg(context: &Context, kwarg: fe::Kwarg) -> fe::Kwarg { | ||
fe::Kwarg { | ||
name: kwarg.name, | ||
value: boxed_expr(context, kwarg.value), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,127 @@ | ||
use crate::lowering::mappers::expressions; | ||
use fe_analyzer::Context; | ||
use fe_parser::ast as fe; | ||
use fe_parser::node::Node; | ||
|
||
pub fn func_def(context: &Context, def: Node<fe::ContractStmt>) -> Node<fe::ContractStmt> { | ||
if let fe::ContractStmt::FuncDef { | ||
qual, | ||
name, | ||
args, | ||
return_type, | ||
body, | ||
} = def.kind | ||
{ | ||
let lowered_body = multiple_stmts(context, body); | ||
|
||
let lowered_kind = fe::ContractStmt::FuncDef { | ||
qual, | ||
name, | ||
args, | ||
return_type, | ||
body: lowered_body, | ||
}; | ||
|
||
return Node::new(lowered_kind, def.span); | ||
} | ||
|
||
unreachable!() | ||
} | ||
|
||
fn func_stmt(context: &Context, stmt: Node<fe::FuncStmt>) -> Vec<Node<fe::FuncStmt>> { | ||
let lowered_kinds = match stmt.kind { | ||
fe::FuncStmt::Return { value } => vec![fe::FuncStmt::Return { | ||
value: expressions::optional_expr(context, value), | ||
}], | ||
fe::FuncStmt::VarDecl { target, typ, value } => vec![fe::FuncStmt::VarDecl { | ||
target: expressions::expr(context, target), | ||
typ, | ||
value: expressions::optional_expr(context, value), | ||
}], | ||
fe::FuncStmt::Assign { targets, value } => vec![fe::FuncStmt::Assign { | ||
targets: expressions::multiple_exprs(context, targets), | ||
value: expressions::expr(context, value), | ||
}], | ||
fe::FuncStmt::Emit { value } => vec![fe::FuncStmt::Emit { | ||
value: expressions::expr(context, value), | ||
}], | ||
fe::FuncStmt::AugAssign { target, op, value } => aug_assign(context, target, op, value), | ||
fe::FuncStmt::For { | ||
target, | ||
iter, | ||
body, | ||
or_else, | ||
} => vec![fe::FuncStmt::For { | ||
target: expressions::expr(context, target), | ||
iter: expressions::expr(context, iter), | ||
body: multiple_stmts(context, body), | ||
or_else: multiple_stmts(context, or_else), | ||
}], | ||
fe::FuncStmt::While { | ||
test, | ||
body, | ||
or_else, | ||
} => vec![fe::FuncStmt::While { | ||
test: expressions::expr(context, test), | ||
body: multiple_stmts(context, body), | ||
or_else: multiple_stmts(context, or_else), | ||
}], | ||
fe::FuncStmt::If { | ||
test, | ||
body, | ||
or_else, | ||
} => vec![fe::FuncStmt::If { | ||
test: expressions::expr(context, test), | ||
body: multiple_stmts(context, body), | ||
or_else: multiple_stmts(context, or_else), | ||
}], | ||
fe::FuncStmt::Assert { test, msg } => vec![fe::FuncStmt::Assert { | ||
test: expressions::expr(context, test), | ||
msg: expressions::optional_expr(context, msg), | ||
}], | ||
fe::FuncStmt::Expr { value } => vec![fe::FuncStmt::Expr { | ||
value: expressions::expr(context, value), | ||
}], | ||
fe::FuncStmt::Pass => vec![fe::FuncStmt::Pass], | ||
fe::FuncStmt::Break => vec![fe::FuncStmt::Break], | ||
fe::FuncStmt::Continue => vec![fe::FuncStmt::Continue], | ||
fe::FuncStmt::Revert => vec![fe::FuncStmt::Revert], | ||
}; | ||
let span = stmt.span; | ||
|
||
lowered_kinds | ||
.into_iter() | ||
.map(|kind| Node::new(kind, span)) | ||
.collect() | ||
} | ||
|
||
fn multiple_stmts(context: &Context, stmts: Vec<Node<fe::FuncStmt>>) -> Vec<Node<fe::FuncStmt>> { | ||
stmts | ||
.into_iter() | ||
.map(|stmt| func_stmt(context, stmt)) | ||
.collect::<Vec<Vec<Node<fe::FuncStmt>>>>() | ||
.concat() | ||
} | ||
|
||
fn aug_assign( | ||
context: &Context, | ||
target: Node<fe::Expr>, | ||
op: Node<fe::BinOperator>, | ||
value: Node<fe::Expr>, | ||
) -> Vec<fe::FuncStmt> { | ||
let lowered_target = expressions::expr(context, target); | ||
let lowered_value = expressions::expr(context, value.clone()); | ||
|
||
let new_value_kind = fe::Expr::BinOperation { | ||
left: Box::new(lowered_target.clone().new_id()), | ||
op, | ||
right: Box::new(lowered_value), | ||
}; | ||
|
||
let new_value = Node::new(new_value_kind, value.span); | ||
|
||
return vec![fe::FuncStmt::Assign { | ||
targets: vec![lowered_target], | ||
value: new_value, | ||
}]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,20 @@ | ||
use fe_analyzer::Context; | ||
|
||
use crate::lowering::mappers::contracts; | ||
use fe_parser::ast as fe; | ||
|
||
pub fn module(context: &Context, module: fe::Module) -> fe::Module { | ||
let lowered_body = module | ||
.body | ||
.into_iter() | ||
.map(|stmt| match &stmt.kind { | ||
fe::ModuleStmt::TypeDef { .. } => stmt, | ||
fe::ModuleStmt::StructDef { .. } => stmt, | ||
fe::ModuleStmt::FromImport { .. } => stmt, | ||
fe::ModuleStmt::SimpleImport { .. } => stmt, | ||
fe::ModuleStmt::ContractDef { .. } => contracts::contract_def(context, stmt), | ||
}) | ||
.collect(); | ||
|
||
fe::Module { body: lowered_body } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.