Parse for statement in assembly parser / printer

This commit is contained in:
Alex Beregszaszi
2017-06-16 10:56:21 +01:00
parent 54e97d1c34
commit 47925bc14e
13 changed files with 75 additions and 18 deletions
+5
View File
@@ -310,6 +310,11 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
return success;
}
bool AsmAnalyzer::operator()(assembly::ForLoop const&)
{
solAssert(false, "For loop not supported.");
}
bool AsmAnalyzer::operator()(Block const& _block)
{
bool success = true;
+3 -1
View File
@@ -51,7 +51,8 @@ struct StackAssignment;
struct FunctionDefinition;
struct FunctionCall;
struct Switch;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
struct ForLoop;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block, ForLoop>;
struct AsmAnalysisInfo;
@@ -83,6 +84,7 @@ public:
bool operator()(assembly::FunctionDefinition const& _functionDefinition);
bool operator()(assembly::FunctionCall const& _functionCall);
bool operator()(assembly::Switch const& _switch);
bool operator()(assembly::ForLoop const& _forLoop);
bool operator()(assembly::Block const& _block);
private:
+2 -1
View File
@@ -45,10 +45,11 @@ struct StackAssignment;
struct FunctionDefinition;
struct FunctionCall;
struct Switch;
struct ForLoop;
struct Scope;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, ForLoop, Block>;
struct AsmAnalysisInfo
{
+3 -1
View File
@@ -51,9 +51,10 @@ struct FunctionalInstruction;
struct FunctionDefinition;
struct FunctionCall;
struct Switch;
struct ForLoop;
struct Block;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, ForLoop, Block>;
/// Direct EVM instruction (except PUSHi and JUMPDEST)
struct Instruction { SourceLocation location; solidity::Instruction instruction; };
@@ -82,6 +83,7 @@ struct FunctionDefinition { SourceLocation location; std::string name; TypedName
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 LocationExtractor: boost::static_visitor<SourceLocation>
{
+16
View File
@@ -87,6 +87,8 @@ assembly::Statement Parser::parseStatement()
_switch.location.end = _switch.cases.back().body.location.end;
return _switch;
}
case Token::For:
return parseForLoop();
case Token::Assign:
{
if (m_julia)
@@ -171,6 +173,20 @@ assembly::Case Parser::parseCase()
return _case;
}
assembly::ForLoop Parser::parseForLoop()
{
ForLoop forLoop = createWithLocation<ForLoop>();
expectToken(Token::For);
forLoop.pre = parseBlock();
forLoop.condition = make_shared<Statement>(parseExpression());
if (forLoop.condition->type() == typeid(assembly::Instruction))
fatalParserError("Instructions are not supported as conditions for the for statement.");
forLoop.post = parseBlock();
forLoop.body = parseBlock();
forLoop.location.end = forLoop.body.location.end;
return forLoop;
}
assembly::Statement Parser::parseExpression()
{
Statement operation = parseElementaryOperation(true);
+1
View File
@@ -63,6 +63,7 @@ protected:
Block parseBlock();
Statement parseStatement();
Case parseCase();
ForLoop parseForLoop();
/// Parses a functional expression that has to push exactly one stack element
Statement parseExpression();
static std::map<std::string, dev::solidity::Instruction> const& instructions();
+13
View File
@@ -181,6 +181,19 @@ string AsmPrinter::operator()(Switch const& _switch)
return out;
}
string AsmPrinter::operator()(assembly::ForLoop const& _forLoop)
{
string out = "for ";
out += (*this)(_forLoop.pre);
out += "\n";
out += boost::apply_visitor(*this, *_forLoop.condition);
out += "\n";
out += (*this)(_forLoop.post);
out += "\n";
out += (*this)(_forLoop.body);
return out;
}
string AsmPrinter::operator()(Block const& _block)
{
if (_block.statements.empty())
+2
View File
@@ -41,6 +41,7 @@ struct VariableDeclaration;
struct FunctionDefinition;
struct FunctionCall;
struct Switch;
struct ForLoop;
struct Block;
class AsmPrinter: public boost::static_visitor<std::string>
@@ -59,6 +60,7 @@ public:
std::string operator()(assembly::FunctionDefinition const& _functionDefinition);
std::string operator()(assembly::FunctionCall const& _functionCall);
std::string operator()(assembly::Switch const& _switch);
std::string operator()(assembly::ForLoop const& _forLoop);
std::string operator()(assembly::Block const& _block);
private:
+5
View File
@@ -111,6 +111,11 @@ bool ScopeFiller::operator()(Switch const& _switch)
return success;
}
bool ScopeFiller::operator()(ForLoop const&)
{
solAssert(false, "For loop not supported.");
}
bool ScopeFiller::operator()(Block const& _block)
{
bool success = true;
+2
View File
@@ -47,6 +47,7 @@ struct StackAssignment;
struct FunctionDefinition;
struct FunctionCall;
struct Switch;
struct ForLoop;
struct Scope;
struct AsmAnalysisInfo;
@@ -71,6 +72,7 @@ public:
bool operator()(assembly::FunctionDefinition const& _functionDefinition);
bool operator()(assembly::FunctionCall const&) { return true; }
bool operator()(assembly::Switch const& _switch);
bool operator()(assembly::ForLoop const& _forLoop);
bool operator()(assembly::Block const& _block);
private: