aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.cpp5
-rw-r--r--libjulia/backends/evm/EVMCodeTransform.h16
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp5
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h4
-rw-r--r--libsolidity/inlineasm/AsmAnalysisInfo.h3
-rw-r--r--libsolidity/inlineasm/AsmData.h4
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp16
-rw-r--r--libsolidity/inlineasm/AsmParser.h1
-rw-r--r--libsolidity/inlineasm/AsmPrinter.cpp13
-rw-r--r--libsolidity/inlineasm/AsmPrinter.h2
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.cpp5
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.h2
-rw-r--r--test/libsolidity/InlineAssembly.cpp17
13 files changed, 75 insertions, 18 deletions
diff --git a/libjulia/backends/evm/EVMCodeTransform.cpp b/libjulia/backends/evm/EVMCodeTransform.cpp
index 7c14eb8b..00d0bde5 100644
--- a/libjulia/backends/evm/EVMCodeTransform.cpp
+++ b/libjulia/backends/evm/EVMCodeTransform.cpp
@@ -53,6 +53,11 @@ void CodeTransform::run(Block const& _block)
}
+void CodeTransform::operator()(ForLoop const&)
+{
+ solAssert(false, "For loop not removed during desugaring phase.");
+}
+
void CodeTransform::operator()(VariableDeclaration const& _varDecl)
{
solAssert(m_scope, "");
diff --git a/libjulia/backends/evm/EVMCodeTransform.h b/libjulia/backends/evm/EVMCodeTransform.h
index 202f5051..9814f0f5 100644
--- a/libjulia/backends/evm/EVMCodeTransform.h
+++ b/libjulia/backends/evm/EVMCodeTransform.h
@@ -32,21 +32,6 @@ namespace solidity
class ErrorReporter;
namespace assembly
{
-struct Literal;
-struct Block;
-struct Switch;
-struct Label;
-struct FunctionalInstruction;
-struct Assignment;
-struct VariableDeclaration;
-struct Instruction;
-struct Identifier;
-struct StackAssignment;
-struct FunctionDefinition;
-struct FunctionCall;
-
-using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
-
struct AsmAnalysisInfo;
}
}
@@ -115,6 +100,7 @@ public:
void operator()(solidity::assembly::VariableDeclaration const& _varDecl);
void operator()(solidity::assembly::Switch const& _switch);
void operator()(solidity::assembly::FunctionDefinition const&);
+ void operator()(solidity::assembly::ForLoop const&);
void operator()(solidity::assembly::Block const& _block);
private:
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 1a529118..68c940e7 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -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;
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h
index 2516722a..5cdf72b1 100644
--- a/libsolidity/inlineasm/AsmAnalysis.h
+++ b/libsolidity/inlineasm/AsmAnalysis.h
@@ -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:
diff --git a/libsolidity/inlineasm/AsmAnalysisInfo.h b/libsolidity/inlineasm/AsmAnalysisInfo.h
index 78c1fbe0..a75413a2 100644
--- a/libsolidity/inlineasm/AsmAnalysisInfo.h
+++ b/libsolidity/inlineasm/AsmAnalysisInfo.h
@@ -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
{
diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h
index 72afeef1..c2458bd7 100644
--- a/libsolidity/inlineasm/AsmData.h
+++ b/libsolidity/inlineasm/AsmData.h
@@ -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>
{
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index f9b073ba..d282a30d 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -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);
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index 5fafad23..45708afd 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -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();
diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp
index e282e5e8..0d06fedd 100644
--- a/libsolidity/inlineasm/AsmPrinter.cpp
+++ b/libsolidity/inlineasm/AsmPrinter.cpp
@@ -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())
diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libsolidity/inlineasm/AsmPrinter.h
index b0d7fc09..8808b058 100644
--- a/libsolidity/inlineasm/AsmPrinter.h
+++ b/libsolidity/inlineasm/AsmPrinter.h
@@ -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:
diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp
index 4d26dcf8..1aac902a 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.cpp
+++ b/libsolidity/inlineasm/AsmScopeFiller.cpp
@@ -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;
diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h
index 1166d50f..f04352c9 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.h
+++ b/libsolidity/inlineasm/AsmScopeFiller.h
@@ -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:
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index aae6dacd..a3339d47 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -291,6 +291,18 @@ BOOST_AUTO_TEST_CASE(switch_invalid_body)
CHECK_PARSE_ERROR("{ switch 42 case 1 mul case 2 {} default {} }", ParserError, "Expected token LBrace got 'Identifier'");
}
+BOOST_AUTO_TEST_CASE(for_statement)
+{
+ BOOST_CHECK(successParse("{ for {} 1 {} {} }"));
+ BOOST_CHECK(successParse("{ for { let i := 1 } le(i, 5) { i := add(i, 1) } {} }"));
+}
+
+BOOST_AUTO_TEST_CASE(for_invalid_expression)
+{
+ CHECK_PARSE_ERROR("{ for {} {} {} {} }", ParserError, "Literal, identifier or instruction expected.");
+ CHECK_PARSE_ERROR("{ 1 2 for {} mul {} {} }", ParserError, "Instructions are not supported as conditions for the for statement.");
+}
+
BOOST_AUTO_TEST_CASE(blocks)
{
BOOST_CHECK(successParse("{ let x := 7 { let y := 3 } { let z := 2 } }"));
@@ -409,6 +421,11 @@ BOOST_AUTO_TEST_CASE(print_switch)
parsePrintCompare("{\n switch 42\n case 1 {\n }\n case 2 {\n }\n default {\n }\n}");
}
+BOOST_AUTO_TEST_CASE(print_for)
+{
+ parsePrintCompare("{\n let ret := 5\n for {\n let i := 1\n }\n le(i, 15)\n {\n i := add(i, 1)\n }\n {\n ret := mul(ret, i)\n }\n}");
+}
+
BOOST_AUTO_TEST_CASE(function_definitions_multiple_args)
{
parsePrintCompare("{\n function f(a, d)\n {\n mstore(a, d)\n }\n function g(a, d) -> x, y\n {\n }\n}");