Skip to content

Commit

Permalink
Add yul function definitions, some cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
camden-smallwood committed Jun 9, 2023
1 parent eee2537 commit b01c62e
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 9 deletions.
69 changes: 60 additions & 9 deletions solidity/src/ast/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,10 +662,10 @@ impl AstBuilder {

pub fn build_user_defined_value_type_definition(&mut self, input: &solang_parser::pt::TypeDefinition) -> UserDefinedValueTypeDefinition {
UserDefinedValueTypeDefinition {
underlying_type: todo!(),
name: todo!(),
name_location: todo!(),
canonical_name: todo!(),
underlying_type: self.build_type_name(&input.ty),
name: input.name.name.clone(),
name_location: Some(self.loc_to_src(&input.name.loc)),
canonical_name: None, // TODO
src: self.loc_to_src(&input.loc),
id: self.next_node_id(),
}
Expand Down Expand Up @@ -1534,6 +1534,30 @@ impl AstBuilder {
}
}

pub fn build_index_range_access(
&mut self,
loc: &solang_parser::pt::Loc,
array: &solang_parser::pt::Expression,
start: Option<&solang_parser::pt::Expression>,
end: Option<&solang_parser::pt::Expression>,
) -> IndexRangeAccess {
IndexRangeAccess {
base_expression: Box::new(self.build_expression(array)),
start_expression: start.as_ref().map(|x| Box::new(self.build_expression(x))),
end_expression: end.as_ref().map(|x| Box::new(self.build_expression(x))),
is_constant: false, // TODO
is_l_value: false, // TODO
is_pure: false, // TODO
l_value_requested: false, // TODO
type_descriptions: TypeDescriptions {
type_identifier: None, // TODO
type_string: None, // TODO
},
src: self.loc_to_src(loc),
id: self.next_node_id(),
}
}

pub fn build_expression(&mut self, input: &solang_parser::pt::Expression) -> Expression {
match input {
solang_parser::pt::Expression::PostIncrement(loc, x) => {
Expand All @@ -1552,7 +1576,9 @@ impl AstBuilder {
Expression::IndexAccess(self.build_index_access(loc, array, index.as_ref().unwrap()))
}

solang_parser::pt::Expression::ArraySlice(_, _, _, _) => todo!(),
solang_parser::pt::Expression::ArraySlice(loc, array, start, end) => {
Expression::IndexRangeAccess(self.build_index_range_access(loc, array, start.as_ref().map(|x| x.as_ref()), end.as_ref().map(|x| x.as_ref())))
}

solang_parser::pt::Expression::Parenthesis(_, expression) => {
self.build_expression(expression)
Expand Down Expand Up @@ -1862,11 +1888,23 @@ impl AstBuilder {
YulStatement::YulSwitch(self.build_yul_switch(switch))
}

solang_parser::pt::YulStatement::Leave(_) => todo!(),
solang_parser::pt::YulStatement::Break(_) => todo!(),
solang_parser::pt::YulStatement::Continue(_) => todo!(),
solang_parser::pt::YulStatement::Leave(_) => {
YulStatement::YulLeave
}

solang_parser::pt::YulStatement::Break(_) => {
YulStatement::YulBreak
}

solang_parser::pt::YulStatement::Continue(_) => {
YulStatement::YulContinue
}

solang_parser::pt::YulStatement::Block(_) => todo!(),
solang_parser::pt::YulStatement::FunctionDefinition(_) => todo!(),

solang_parser::pt::YulStatement::FunctionDefinition(function) => {
YulStatement::YulFunctionDefinition(self.build_yul_function_definition(function))
}

solang_parser::pt::YulStatement::FunctionCall(call) => {
YulStatement::YulExpressionStatement(YulExpressionStatement {
Expand Down Expand Up @@ -1949,6 +1987,19 @@ impl AstBuilder {
}
}

pub fn build_yul_function_definition(&mut self, function: &solang_parser::pt::YulFunctionDefinition) -> YulFunctionDefinition {
YulFunctionDefinition {
name: function.id.name.clone(),
parameters: function.params.iter()
.map(|param| self.build_yul_typed_name(param))
.collect(),
return_parameters: function.returns.iter()
.map(|param| self.build_yul_typed_name(param))
.collect(),
body: self.build_yul_block(&function.body),
}
}

pub fn build_yul_expression(&mut self, expression: &solang_parser::pt::YulExpression) -> YulExpression {
match expression {
solang_parser::pt::YulExpression::BoolLiteral(_, value, _) => YulExpression::YulLiteral(YulLiteral {
Expand Down
205 changes: 205 additions & 0 deletions solidity/src/ast/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,32 @@ pub struct YulExpressionStatementContext<'a, 'b, 'c> {
pub yul_expression_statement: &'a YulExpressionStatement,
}

pub struct YulFunctionDefinitionContext<'a, 'b, 'c> {
pub source_units: &'a [SourceUnit],
pub current_source_unit: &'a SourceUnit,
pub contract_definition: &'a ContractDefinition,
pub definition_node: &'a ContractDefinitionNode,
pub blocks: &'b mut Vec<&'a Block>,
pub statement: &'a Statement,
pub inline_assembly: &'a InlineAssembly,
pub yul_blocks: &'c mut Vec<&'a YulBlock>,
pub yul_statement: &'a YulStatement,
pub yul_function_definition: &'a YulFunctionDefinition,
}

pub struct YulTypedNameContext<'a, 'b, 'c> {
pub source_units: &'a [SourceUnit],
pub current_source_unit: &'a SourceUnit,
pub contract_definition: &'a ContractDefinition,
pub definition_node: &'a ContractDefinitionNode,
pub blocks: &'b mut Vec<&'a Block>,
pub statement: &'a Statement,
pub inline_assembly: &'a InlineAssembly,
pub yul_blocks: &'c mut Vec<&'a YulBlock>,
pub yul_statement: Option<&'a YulStatement>,
pub yul_typed_name: &'a YulTypedName,
}

pub struct YulExpressionContext<'a, 'b, 'c> {
pub source_units: &'a [SourceUnit],
pub current_source_unit: &'a SourceUnit,
Expand Down Expand Up @@ -337,6 +363,21 @@ pub trait AstVisitor {
fn visit_yul_expression_statement<'a, 'b, 'c>(&mut self, context: &mut YulExpressionStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_expression_statement<'a, 'b, 'c>(&mut self, context: &mut YulExpressionStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

fn visit_yul_function_definition<'a, 'b, 'c>(&mut self, context: &mut YulFunctionDefinitionContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_function_definition<'a, 'b, 'c>(&mut self, context: &mut YulFunctionDefinitionContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

fn visit_yul_leave<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_leave<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

fn visit_yul_break<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_break<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

fn visit_yul_continue<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_continue<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

fn visit_yul_typed_name<'a, 'b, 'c>(&mut self, context: &mut YulTypedNameContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_typed_name<'a, 'b, 'c>(&mut self, context: &mut YulTypedNameContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

fn visit_yul_expression<'a, 'b, 'c>(&mut self, context: &mut YulExpressionContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }
fn leave_yul_expression<'a, 'b, 'c>(&mut self, context: &mut YulExpressionContext<'a, 'b, 'c>) -> io::Result<()> { Ok(()) }

Expand Down Expand Up @@ -2306,6 +2347,39 @@ impl AstVisitor for AstVisitorData<'_> {
self.visit_yul_expression_statement(&mut context)?;
self.leave_yul_expression_statement(&mut context)?;
}

YulStatement::YulFunctionDefinition(yul_function_definition) => {
let mut context = YulFunctionDefinitionContext {
source_units: context.source_units,
current_source_unit: context.current_source_unit,
contract_definition: context.contract_definition,
definition_node: context.definition_node,
blocks: context.blocks,
statement: context.statement,
inline_assembly: context.inline_assembly,
yul_blocks: context.yul_blocks,
yul_statement: context.yul_statement,
yul_function_definition,
};

self.visit_yul_function_definition(&mut context)?;
self.leave_yul_function_definition(&mut context)?;
}

YulStatement::YulLeave => {
self.visit_yul_leave(context)?;
self.leave_yul_leave(context)?;
}

YulStatement::YulBreak => {
self.visit_yul_break(context)?;
self.leave_yul_break(context)?;
}

YulStatement::YulContinue => {
self.visit_yul_continue(context)?;
self.leave_yul_continue(context)?;
}
}

Ok(())
Expand Down Expand Up @@ -2624,6 +2698,22 @@ impl AstVisitor for AstVisitorData<'_> {
Ok(())
}

fn visit_yul_typed_name<'a, 'b, 'c>(&mut self, context: &mut YulTypedNameContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_typed_name(context)?;
}

Ok(())
}

fn leave_yul_typed_name<'a, 'b, 'c>(&mut self, context: &mut YulTypedNameContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.leave_yul_typed_name(context)?;
}

Ok(())
}

fn visit_yul_expression_statement<'a, 'b, 'c>(&mut self, context: &mut YulExpressionStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_expression_statement(context)?;
Expand Down Expand Up @@ -2656,6 +2746,121 @@ impl AstVisitor for AstVisitorData<'_> {
Ok(())
}

fn visit_yul_function_definition<'a, 'b, 'c>(&mut self, context: &mut YulFunctionDefinitionContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_function_definition(context)?;
}

for parameter in context.yul_function_definition.parameters.iter() {
let mut context = YulTypedNameContext {
source_units: context.source_units,
current_source_unit: context.current_source_unit,
contract_definition: context.contract_definition,
definition_node: context.definition_node,
blocks: context.blocks,
statement: context.statement,
inline_assembly: context.inline_assembly,
yul_blocks: context.yul_blocks,
yul_statement: Some(context.yul_statement),
yul_typed_name: parameter,
};

self.visit_yul_typed_name(&mut context)?;
self.leave_yul_typed_name(&mut context)?;
}

for parameter in context.yul_function_definition.return_parameters.iter() {
let mut context = YulTypedNameContext {
source_units: context.source_units,
current_source_unit: context.current_source_unit,
contract_definition: context.contract_definition,
definition_node: context.definition_node,
blocks: context.blocks,
statement: context.statement,
inline_assembly: context.inline_assembly,
yul_blocks: context.yul_blocks,
yul_statement: Some(context.yul_statement),
yul_typed_name: parameter,
};

self.visit_yul_typed_name(&mut context)?;
self.leave_yul_typed_name(&mut context)?;
}

let mut context = YulBlockContext {
source_units: context.source_units,
current_source_unit: context.current_source_unit,
contract_definition: context.contract_definition,
definition_node: context.definition_node,
blocks: context.blocks,
statement: context.statement,
inline_assembly: context.inline_assembly,
yul_blocks: context.yul_blocks,
yul_block: &context.yul_function_definition.body,
};

self.visit_yul_block(&mut context)?;
self.leave_yul_block(&mut context)?;

Ok(())
}

fn leave_yul_function_definition<'a, 'b, 'c>(&mut self, context: &mut YulFunctionDefinitionContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.leave_yul_function_definition(context)?;
}

Ok(())
}

fn visit_yul_leave<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_leave(context)?;
}

Ok(())
}

fn leave_yul_leave<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.leave_yul_leave(context)?;
}

Ok(())
}

fn visit_yul_break<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_break(context)?;
}

Ok(())
}

fn leave_yul_break<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.leave_yul_break(context)?;
}

Ok(())
}

fn visit_yul_continue<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_continue(context)?;
}

Ok(())
}

fn leave_yul_continue<'a, 'b, 'c>(&mut self, context: &mut YulStatementContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.leave_yul_continue(context)?;
}

Ok(())
}

fn visit_yul_expression<'a, 'b, 'c>(&mut self, context: &mut YulExpressionContext<'a, 'b, 'c>) -> io::Result<()> {
for visitor in self.visitors.iter_mut() {
visitor.visit_yul_expression(context)?;
Expand Down
17 changes: 17 additions & 0 deletions yul/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ pub enum YulStatement {
YulAssignment(YulAssignment),
YulVariableDeclaration(YulVariableDeclaration),
YulExpressionStatement(YulExpressionStatement),
YulFunctionDefinition(YulFunctionDefinition),
YulLeave,
YulBreak,
YulContinue,
}

impl<'de> Deserialize<'de> for YulStatement {
Expand All @@ -99,6 +103,10 @@ impl<'de> Deserialize<'de> for YulStatement {
"YulAssignment" => Ok(YulStatement::YulAssignment(serde_json::from_value(json).unwrap())),
"YulVariableDeclaration" => Ok(YulStatement::YulVariableDeclaration(serde_json::from_value(json).unwrap())),
"YulExpressionStatement" => Ok(YulStatement::YulExpressionStatement(serde_json::from_value(json).unwrap())),
"YulFunctionDefinition" => Ok(YulStatement::YulFunctionDefinition(serde_json::from_value(json).unwrap())),
"YulLeave" => Ok(YulStatement::YulLeave),
"YulBreak" => Ok(YulStatement::YulBreak),
"YulContinue" => Ok(YulStatement::YulContinue),
_ => panic!("Invalid yul statement node type: {node_type}"),
}
}
Expand Down Expand Up @@ -160,3 +168,12 @@ pub struct YulTypedName {
pub struct YulExpressionStatement {
pub expression: YulExpression,
}

#[derive(Clone, Debug, Deserialize, Eq, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct YulFunctionDefinition {
pub name: String,
pub parameters: Vec<YulTypedName>,
pub return_parameters: Vec<YulTypedName>,
pub body: YulBlock,
}

0 comments on commit b01c62e

Please sign in to comment.