Skip to content

Commit

Permalink
Merge pull request ethereum#3297 from ethereum/separate_expression_an…
Browse files Browse the repository at this point in the history
…d_statement

Separate expression and statement
  • Loading branch information
axic authored Jan 4, 2018
2 parents 14db10b + ca0d244 commit 2cdd789
Show file tree
Hide file tree
Showing 21 changed files with 202 additions and 86 deletions.
4 changes: 3 additions & 1 deletion libjulia/ASTDataForward.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ using If = solidity::assembly::If;
using Case = solidity::assembly::Case;
using Switch = solidity::assembly::Switch;
using ForLoop = solidity::assembly::ForLoop;
using ExpressionStatement = solidity::assembly::ExpressionStatement;
using Block = solidity::assembly::Block;

using TypedName = solidity::assembly::TypedName;

using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, If, Switch, ForLoop, Block>;
using Expression = boost::variant<FunctionalInstruction, FunctionCall, Identifier, Literal>;
using Statement = boost::variant<ExpressionStatement, Instruction, Label, StackAssignment, Assignment, VariableDeclaration, FunctionDefinition, If, Switch, ForLoop, Block>;

}
}
9 changes: 8 additions & 1 deletion libjulia/backends/evm/EVMCodeTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ void CodeTransform::operator()(StackAssignment const& _assignment)
checkStackHeight(&_assignment);
}

void CodeTransform::operator()(ExpressionStatement const& _statement)
{
m_assembly.setSourceLocation(_statement.location);
boost::apply_visitor(*this, _statement.expression);
checkStackHeight(&_statement);
}

void CodeTransform::operator()(Label const& _label)
{
m_assembly.setSourceLocation(_label.location);
Expand Down Expand Up @@ -460,7 +467,7 @@ AbstractAssembly::LabelID CodeTransform::functionEntryID(string const& _name, Sc
return m_context->functionEntryIDs[&_function];
}

void CodeTransform::visitExpression(Statement const& _expression)
void CodeTransform::visitExpression(Expression const& _expression)
{
int height = m_assembly.stackHeight();
boost::apply_visitor(*this, _expression);
Expand Down
3 changes: 2 additions & 1 deletion libjulia/backends/evm/EVMCodeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class CodeTransform: public boost::static_visitor<>
void operator()(Identifier const& _identifier);
void operator()(FunctionalInstruction const& _instr);
void operator()(FunctionCall const&);
void operator()(ExpressionStatement const& _statement);
void operator()(Label const& _label);
void operator()(StackAssignment const& _assignment);
void operator()(Assignment const& _assignment);
Expand All @@ -118,7 +119,7 @@ class CodeTransform: public boost::static_visitor<>
AbstractAssembly::LabelID labelID(solidity::assembly::Scope::Label const& _label);
AbstractAssembly::LabelID functionEntryID(std::string const& _name, solidity::assembly::Scope::Function const& _function);
/// Generates code for an expression that is supposed to return a single value.
void visitExpression(Statement const& _expression);
void visitExpression(Expression const& _expression);

void visitStatements(std::vector<Statement> const& _statements);

Expand Down
20 changes: 15 additions & 5 deletions libjulia/optimiser/ASTCopier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ Statement ASTCopier::operator()(Instruction const&)
return {};
}

Statement ASTCopier::operator()(ExpressionStatement const& _statement)
{
return ExpressionStatement{ _statement.location, translate(_statement.expression) };
}

Statement ASTCopier::operator()(VariableDeclaration const& _varDecl)
{
return VariableDeclaration{
Expand Down Expand Up @@ -67,7 +72,7 @@ Statement ASTCopier::operator()(Label const&)
return {};
}

Statement ASTCopier::operator()(FunctionCall const& _call)
Expression ASTCopier::operator()(FunctionCall const& _call)
{
return FunctionCall{
_call.location,
Expand All @@ -76,7 +81,7 @@ Statement ASTCopier::operator()(FunctionCall const& _call)
};
}

Statement ASTCopier::operator()(FunctionalInstruction const& _instruction)
Expression ASTCopier::operator()(FunctionalInstruction const& _instruction)
{
return FunctionalInstruction{
_instruction.location,
Expand All @@ -85,12 +90,12 @@ Statement ASTCopier::operator()(FunctionalInstruction const& _instruction)
};
}

Statement ASTCopier::operator()(Identifier const& _identifier)
Expression ASTCopier::operator()(Identifier const& _identifier)
{
return Identifier{_identifier.location, translateIdentifier(_identifier.name)};
}

Statement ASTCopier::operator()(Literal const& _literal)
Expression ASTCopier::operator()(Literal const& _literal)
{
return translate(_literal);
}
Expand Down Expand Up @@ -140,9 +145,14 @@ Statement ASTCopier::operator ()(Block const& _block)
return translate(_block);
}

Expression ASTCopier::translate(Expression const& _expression)
{
return _expression.apply_visitor(static_cast<ExpressionCopier&>(*this));
}

Statement ASTCopier::translate(Statement const& _statement)
{
return boost::apply_visitor(*this, _statement);
return _statement.apply_visitor(static_cast<StatementCopier&>(*this));
}

Block ASTCopier::translate(Block const& _block)
Expand Down
59 changes: 43 additions & 16 deletions libjulia/optimiser/ASTCopier.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,55 @@ namespace dev
namespace julia
{

class ExpressionCopier: public boost::static_visitor<Expression>
{
public:
virtual Expression operator()(Literal const& _literal) = 0;
virtual Expression operator()(Identifier const& _identifier) = 0;
virtual Expression operator()(FunctionalInstruction const& _instr) = 0;
virtual Expression operator()(FunctionCall const&) = 0;
};

class StatementCopier: public boost::static_visitor<Statement>
{
public:
virtual Statement operator()(ExpressionStatement const& _statement) = 0;
virtual Statement operator()(Instruction const& _instruction) = 0;
virtual Statement operator()(Label const& _label) = 0;
virtual Statement operator()(StackAssignment const& _assignment) = 0;
virtual Statement operator()(Assignment const& _assignment) = 0;
virtual Statement operator()(VariableDeclaration const& _varDecl) = 0;
virtual Statement operator()(If const& _if) = 0;
virtual Statement operator()(Switch const& _switch) = 0;
virtual Statement operator()(FunctionDefinition const&) = 0;
virtual Statement operator()(ForLoop const&) = 0;
virtual Statement operator()(Block const& _block) = 0;
};

/**
* Creates a copy of a iulia AST potentially replacing identifier names.
* Base class to be extended.
*/
class ASTCopier: public boost::static_visitor<Statement>
class ASTCopier: public ExpressionCopier, public StatementCopier
{
public:
Statement operator()(Literal const& _literal);
Statement operator()(Instruction const& _instruction);
Statement operator()(Identifier const& _identifier);
Statement operator()(FunctionalInstruction const& _instr);
Statement operator()(FunctionCall const&);
Statement operator()(Label const& _label);
Statement operator()(StackAssignment const& _assignment);
Statement operator()(Assignment const& _assignment);
Statement operator()(VariableDeclaration const& _varDecl);
Statement operator()(If const& _if);
Statement operator()(Switch const& _switch);
Statement operator()(FunctionDefinition const&);
Statement operator()(ForLoop const&);
Statement operator()(Block const& _block);

virtual Expression operator()(Literal const& _literal) override;
virtual Statement operator()(Instruction const& _instruction) override;
virtual Expression operator()(Identifier const& _identifier) override;
virtual Expression operator()(FunctionalInstruction const& _instr) override;
virtual Expression operator()(FunctionCall const&) override;
virtual Statement operator()(ExpressionStatement const& _statement) override;
virtual Statement operator()(Label const& _label) override;
virtual Statement operator()(StackAssignment const& _assignment) override;
virtual Statement operator()(Assignment const& _assignment) override;
virtual Statement operator()(VariableDeclaration const& _varDecl) override;
virtual Statement operator()(If const& _if) override;
virtual Statement operator()(Switch const& _switch) override;
virtual Statement operator()(FunctionDefinition const&) override;
virtual Statement operator()(ForLoop const&) override;
virtual Statement operator()(Block const& _block) override;

virtual Expression translate(Expression const& _expression);
virtual Statement translate(Statement const& _statement);

protected:
Expand Down
10 changes: 10 additions & 0 deletions libjulia/optimiser/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ void ASTWalker::operator()(FunctionCall const& _funCall)
walkVector(_funCall.arguments | boost::adaptors::reversed);
}

void ASTWalker::operator()(ExpressionStatement const& _statement)
{
boost::apply_visitor(*this, _statement.expression);
}

void ASTWalker::operator()(Assignment const& _assignment)
{
for (auto const& name: _assignment.variableNames)
Expand Down Expand Up @@ -100,6 +105,11 @@ void ASTModifier::operator()(FunctionCall& _funCall)
walkVector(_funCall.arguments | boost::adaptors::reversed);
}

void ASTModifier::operator()(ExpressionStatement& _statement)
{
boost::apply_visitor(*this, _statement.expression);
}

void ASTModifier::operator()(Assignment& _assignment)
{
for (auto& name: _assignment.variableNames)
Expand Down
6 changes: 6 additions & 0 deletions libjulia/optimiser/ASTWalker.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class ASTWalker: public boost::static_visitor<>
virtual void operator()(Identifier const&) {}
virtual void operator()(FunctionalInstruction const& _instr);
virtual void operator()(FunctionCall const& _funCall);
virtual void operator()(ExpressionStatement const& _statement);
virtual void operator()(Label const&) { solAssert(false, ""); }
virtual void operator()(StackAssignment const&) { solAssert(false, ""); }
virtual void operator()(Assignment const& _assignment);
Expand Down Expand Up @@ -77,6 +78,7 @@ class ASTModifier: public boost::static_visitor<>
virtual void operator()(Identifier&) {}
virtual void operator()(FunctionalInstruction& _instr);
virtual void operator()(FunctionCall& _funCall);
virtual void operator()(ExpressionStatement& _statement);
virtual void operator()(Label&) { solAssert(false, ""); }
virtual void operator()(StackAssignment&) { solAssert(false, ""); }
virtual void operator()(Assignment& _assignment);
Expand All @@ -98,6 +100,10 @@ class ASTModifier: public boost::static_visitor<>
{
boost::apply_visitor(*this, _st);
}
virtual void visit(Expression& _e)
{
boost::apply_visitor(*this, _e);
}
};

}
Expand Down
8 changes: 4 additions & 4 deletions libjulia/optimiser/Substitution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ using namespace std;
using namespace dev;
using namespace dev::julia;

Statement Substitution::translate(Statement const& _statement)
Expression Substitution::translate(Expression const& _expression)
{
if (_statement.type() == typeid(Identifier))
if (_expression.type() == typeid(Identifier))
{
string const& name = boost::get<Identifier>(_statement).name;
string const& name = boost::get<Identifier>(_expression).name;
if (m_substitutions.count(name))
// No recursive substitution
return ASTCopier().translate(*m_substitutions.at(name));
}
return ASTCopier::translate(_statement);
return ASTCopier::translate(_expression);
}
7 changes: 3 additions & 4 deletions libjulia/optimiser/Substitution.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,17 @@ namespace julia

/**
* Specific AST copier that replaces certain identifiers with expressions.
* Only works on ASTs that are expressions.
*/
class Substitution: public ASTCopier
{
public:
Substitution(std::map<std::string, Statement const*> const& _substitutions):
Substitution(std::map<std::string, Expression const*> const& _substitutions):
m_substitutions(_substitutions)
{}
virtual Statement translate(Statement const& _statement) override;
virtual Expression translate(Expression const& _expression) override;

private:
std::map<std::string, Statement const*> const& m_substitutions;
std::map<std::string, Expression const*> const& m_substitutions;
};

}
Expand Down
4 changes: 4 additions & 0 deletions libsolidity/analysis/ViewPureChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ class AssemblyViewPureChecker: public boost::static_visitor<void>
for (auto const& arg: _instr.arguments)
boost::apply_visitor(*this, arg);
}
void operator()(assembly::ExpressionStatement const& _expr)
{
boost::apply_visitor(*this, _expr.expression);
}
void operator()(assembly::StackAssignment const&) {}
void operator()(assembly::Assignment const& _assignment)
{
Expand Down
16 changes: 13 additions & 3 deletions libsolidity/inlineasm/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr)
return success;
}

bool AsmAnalyzer::operator()(assembly::ExpressionStatement const& _statement)
{
// size_t initialStackHeight = m_stackHeight;
bool success = boost::apply_visitor(*this, _statement.expression);
// if (!expectDeposit(0, initialStackHeight, _statement.location))
// success = false;
m_info.stackHeightInfo[&_statement] = m_stackHeight;
return success;
}

bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment)
{
solAssert(!m_julia, "");
Expand Down Expand Up @@ -407,13 +417,13 @@ bool AsmAnalyzer::operator()(Block const& _block)
return success;
}

bool AsmAnalyzer::expectExpression(Statement const& _statement)
bool AsmAnalyzer::expectExpression(Expression const& _expr)
{
bool success = true;
int const initialHeight = m_stackHeight;
if (!boost::apply_visitor(*this, _statement))
if (!boost::apply_visitor(*this, _expr))
success = false;
if (!expectDeposit(1, initialHeight, locationOf(_statement)))
if (!expectDeposit(1, initialHeight, locationOf(_expr)))
success = false;
return success;
}
Expand Down
3 changes: 2 additions & 1 deletion libsolidity/inlineasm/AsmAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class AsmAnalyzer: public boost::static_visitor<bool>
bool operator()(assembly::Identifier const&);
bool operator()(assembly::FunctionalInstruction const& _functionalInstruction);
bool operator()(assembly::Label const& _label);
bool operator()(assembly::ExpressionStatement const&);
bool operator()(assembly::StackAssignment const&);
bool operator()(assembly::Assignment const& _assignment);
bool operator()(assembly::VariableDeclaration const& _variableDeclaration);
Expand All @@ -77,7 +78,7 @@ class AsmAnalyzer: public boost::static_visitor<bool>

private:
/// Visits the statement and expects it to deposit one item onto the stack.
bool expectExpression(Statement const& _statement);
bool expectExpression(Expression const& _expr);
bool expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location);

/// Verifies that a variable to be assigned to exists and has the same size
Expand Down
16 changes: 9 additions & 7 deletions libsolidity/inlineasm/AsmData.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,25 @@ struct StackAssignment { SourceLocation location; Identifier variableName; };
/// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy
/// a single stack slot and expects a single expression on the right hand returning
/// the same amount of items as the number of variables.
struct Assignment { SourceLocation location; std::vector<Identifier> variableNames; std::shared_ptr<Statement> value; };
struct Assignment { SourceLocation location; std::vector<Identifier> variableNames; std::shared_ptr<Expression> value; };
/// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))"
struct FunctionalInstruction { SourceLocation location; solidity::Instruction instruction; std::vector<Statement> arguments; };
struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Statement> arguments; };
struct FunctionalInstruction { SourceLocation location; solidity::Instruction instruction; std::vector<Expression> arguments; };
struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Expression> arguments; };
/// Statement that contains only a single expression
struct ExpressionStatement { SourceLocation location; Expression expression; };
/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
struct VariableDeclaration { SourceLocation location; TypedNameList variables; std::shared_ptr<Statement> value; };
struct VariableDeclaration { SourceLocation location; TypedNameList variables; std::shared_ptr<Expression> value; };
/// Block that creates a scope (frees declared stack variables)
struct Block { SourceLocation location; std::vector<Statement> statements; };
/// Function definition ("function f(a, b) -> (d, e) { ... }")
struct FunctionDefinition { SourceLocation location; std::string name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
/// Conditional execution without "else" part.
struct If { SourceLocation location; std::shared_ptr<Statement> condition; Block body; };
struct If { SourceLocation location; std::shared_ptr<Expression> condition; Block body; };
/// Switch case or default case
struct Case { SourceLocation location; std::shared_ptr<Literal> value; Block body; };
/// Switch statement
struct Switch { SourceLocation location; std::shared_ptr<Statement> expression; std::vector<Case> cases; };
struct ForLoop { SourceLocation location; Block pre; std::shared_ptr<Statement> condition; Block post; Block body; };
struct Switch { SourceLocation location; std::shared_ptr<Expression> expression; std::vector<Case> cases; };
struct ForLoop { SourceLocation location; Block pre; std::shared_ptr<Expression> condition; Block post; Block body; };

struct LocationExtractor: boost::static_visitor<SourceLocation>
{
Expand Down
4 changes: 3 additions & 1 deletion libsolidity/inlineasm/AsmDataForward.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ struct If;
struct Switch;
struct Case;
struct ForLoop;
struct ExpressionStatement;
struct Block;

struct TypedName;

using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, If, Switch, ForLoop, Block>;
using Expression = boost::variant<FunctionalInstruction, FunctionCall, Identifier, Literal>;
using Statement = boost::variant<ExpressionStatement, Instruction, Label, StackAssignment, Assignment, VariableDeclaration, FunctionDefinition, If, Switch, ForLoop, Block>;

}
}
Expand Down
Loading

0 comments on commit 2cdd789

Please sign in to comment.