aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-06-19 17:53:22 +0800
committerGitHub <noreply@github.com>2017-06-19 17:53:22 +0800
commit0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf (patch)
tree49cfc2be091c868bdc5865a9d718ea33b1a1269e /libsolidity
parente0b9589e5a5b961541aefe783045b93fac347773 (diff)
parentc5339037e9c1d25c95093f905ebe443a38d419f0 (diff)
downloaddexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.gz
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.bz2
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.lz
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.xz
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.zst
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.zip
Merge pull request #2225 from ethereum/julia-for
Implement for statement in assembly parser / printer / code generator
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp31
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h17
-rw-r--r--libsolidity/inlineasm/AsmAnalysisInfo.h17
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp2
-rw-r--r--libsolidity/inlineasm/AsmData.h23
-rw-r--r--libsolidity/inlineasm/AsmDataForward.h52
-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.h15
-rw-r--r--libsolidity/inlineasm/AsmScope.cpp9
-rw-r--r--libsolidity/inlineasm/AsmScope.h2
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.cpp20
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.h16
-rw-r--r--libsolidity/interface/AssemblyStack.cpp2
15 files changed, 159 insertions, 77 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 1a529118..2891ec95 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -310,6 +310,33 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
return success;
}
+bool AsmAnalyzer::operator()(assembly::ForLoop const& _for)
+{
+ Scope* originalScope = m_currentScope;
+
+ bool success = true;
+ if (!(*this)(_for.pre))
+ success = false;
+ // The block was closed already, but we re-open it again and stuff the
+ // condition, the body and the post part inside.
+ m_stackHeight += scope(&_for.pre).numberOfVariables();
+ m_currentScope = &scope(&_for.pre);
+
+ if (!expectExpression(*_for.condition))
+ success = false;
+ m_stackHeight--;
+ if (!(*this)(_for.body))
+ success = false;
+ if (!(*this)(_for.post))
+ success = false;
+
+ m_stackHeight -= scope(&_for.pre).numberOfVariables();
+ m_info.stackHeightInfo[&_for] = m_stackHeight;
+ m_currentScope = originalScope;
+
+ return success;
+}
+
bool AsmAnalyzer::operator()(Block const& _block)
{
bool success = true;
@@ -322,9 +349,7 @@ bool AsmAnalyzer::operator()(Block const& _block)
if (!boost::apply_visitor(*this, s))
success = false;
- for (auto const& identifier: scope(&_block).identifiers)
- if (identifier.second.type() == typeid(Scope::Variable))
- --m_stackHeight;
+ m_stackHeight -= scope(&_block).numberOfVariables();
int const stackDiff = m_stackHeight - initialStackHeight;
if (stackDiff != 0)
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h
index 2516722a..76d2eba1 100644
--- a/libsolidity/inlineasm/AsmAnalysis.h
+++ b/libsolidity/inlineasm/AsmAnalysis.h
@@ -26,6 +26,8 @@
#include <libjulia/backends/evm/AbstractAssembly.h>
+#include <libsolidity/inlineasm/AsmDataForward.h>
+
#include <boost/variant.hpp>
#include <functional>
@@ -39,20 +41,6 @@ class ErrorReporter;
namespace assembly
{
-struct Literal;
-struct Block;
-struct Label;
-struct FunctionalInstruction;
-struct Assignment;
-struct VariableDeclaration;
-struct Instruction;
-struct Identifier;
-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 AsmAnalysisInfo;
/**
@@ -83,6 +71,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..bd3b28c4 100644
--- a/libsolidity/inlineasm/AsmAnalysisInfo.h
+++ b/libsolidity/inlineasm/AsmAnalysisInfo.h
@@ -20,6 +20,8 @@
#pragma once
+#include <libsolidity/inlineasm/AsmDataForward.h>
+
#include <boost/variant.hpp>
#include <map>
@@ -33,23 +35,8 @@ namespace solidity
namespace assembly
{
-struct Literal;
-struct Block;
-struct Label;
-struct FunctionalInstruction;
-struct Assignment;
-struct VariableDeclaration;
-struct Instruction;
-struct Identifier;
-struct StackAssignment;
-struct FunctionDefinition;
-struct FunctionCall;
-struct Switch;
-
struct Scope;
-using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
-
struct AsmAnalysisInfo
{
using StackHeightInfo = std::map<void const*, int>;
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index 27750453..3c7c62c6 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -141,5 +141,5 @@ void assembly::CodeGenerator::assemble(
)
{
EthAssemblyAdapter assemblyAdapter(_assembly);
- julia::CodeTransform(assemblyAdapter, _analysisInfo, false, _identifierAccess).run(_parsedData);
+ julia::CodeTransform(assemblyAdapter, _analysisInfo, false, _identifierAccess)(_parsedData);
}
diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h
index 72afeef1..db5840bc 100644
--- a/libsolidity/inlineasm/AsmData.h
+++ b/libsolidity/inlineasm/AsmData.h
@@ -22,10 +22,13 @@
#pragma once
-#include <boost/variant.hpp>
+#include <libsolidity/inlineasm/AsmDataForward.h>
+
#include <libevmasm/Instruction.h>
#include <libevmasm/SourceLocation.h>
+#include <boost/variant.hpp>
+
namespace dev
{
namespace solidity
@@ -38,23 +41,6 @@ using Type = std::string;
struct TypedName { SourceLocation location; std::string name; Type type; };
using TypedNameList = std::vector<TypedName>;
-/// What follows are the AST nodes for assembly.
-
-struct Instruction;
-struct Literal;
-struct Label;
-struct StackAssignment;
-struct Identifier;
-struct Assignment;
-struct VariableDeclaration;
-struct FunctionalInstruction;
-struct FunctionDefinition;
-struct FunctionCall;
-struct Switch;
-struct Block;
-
-using Statement = boost::variant<Instruction, Literal, Label, StackAssignment, Identifier, Assignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Switch, Block>;
-
/// Direct EVM instruction (except PUSHi and JUMPDEST)
struct Instruction { SourceLocation location; solidity::Instruction instruction; };
/// Literal number or string (up to 32 bytes)
@@ -82,6 +68,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/AsmDataForward.h b/libsolidity/inlineasm/AsmDataForward.h
new file mode 100644
index 00000000..4ead7ff5
--- /dev/null
+++ b/libsolidity/inlineasm/AsmDataForward.h
@@ -0,0 +1,52 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2016
+ * Forward declaration of classes for inline assembly / JULIA AST
+ */
+
+#pragma once
+
+#include <boost/variant.hpp>
+
+namespace dev
+{
+namespace solidity
+{
+namespace assembly
+{
+
+struct Instruction;
+struct Literal;
+struct Label;
+struct StackAssignment;
+struct Identifier;
+struct Assignment;
+struct VariableDeclaration;
+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, ForLoop, Block>;
+
+}
+}
+}
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..f57dddc8 100644
--- a/libsolidity/inlineasm/AsmPrinter.h
+++ b/libsolidity/inlineasm/AsmPrinter.h
@@ -22,6 +22,8 @@
#pragma once
+#include <libsolidity/inlineasm/AsmDataForward.h>
+
#include <boost/variant.hpp>
namespace dev
@@ -30,18 +32,6 @@ namespace solidity
{
namespace assembly
{
-struct Instruction;
-struct Literal;
-struct Identifier;
-struct FunctionalInstruction;
-struct Label;
-struct StackAssignment;
-struct Assignment;
-struct VariableDeclaration;
-struct FunctionDefinition;
-struct FunctionCall;
-struct Switch;
-struct Block;
class AsmPrinter: public boost::static_visitor<std::string>
{
@@ -59,6 +49,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/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp
index 1db5ca41..315d5953 100644
--- a/libsolidity/inlineasm/AsmScope.cpp
+++ b/libsolidity/inlineasm/AsmScope.cpp
@@ -80,6 +80,15 @@ bool Scope::exists(string const& _name)
return false;
}
+size_t Scope::numberOfVariables() const
+{
+ size_t count = 0;
+ for (auto const& identifier: identifiers)
+ if (identifier.second.type() == typeid(Scope::Variable))
+ count++;
+ return count;
+}
+
bool Scope::insideFunction() const
{
for (Scope const* s = this; s; s = s->superScope)
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index de9119e0..cc240565 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -109,6 +109,8 @@ struct Scope
/// across function and assembly boundaries).
bool exists(std::string const& _name);
+ /// @returns the number of variables directly registered inside the scope.
+ size_t numberOfVariables() const;
/// @returns true if this scope is inside a function.
bool insideFunction() const;
diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp
index 4d26dcf8..3bef9cec 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.cpp
+++ b/libsolidity/inlineasm/AsmScopeFiller.cpp
@@ -111,6 +111,26 @@ bool ScopeFiller::operator()(Switch const& _switch)
return success;
}
+bool ScopeFiller::operator()(ForLoop const& _forLoop)
+{
+ Scope* originalScope = m_currentScope;
+
+ bool success = true;
+ if (!(*this)(_forLoop.pre))
+ success = false;
+ m_currentScope = &scope(&_forLoop.pre);
+ if (!boost::apply_visitor(*this, *_forLoop.condition))
+ success = false;
+ if (!(*this)(_forLoop.body))
+ success = false;
+ if (!(*this)(_forLoop.post))
+ success = false;
+
+ m_currentScope = originalScope;
+
+ return success;
+}
+
bool ScopeFiller::operator()(Block const& _block)
{
bool success = true;
diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h
index 1166d50f..80c03d2c 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.h
+++ b/libsolidity/inlineasm/AsmScopeFiller.h
@@ -20,6 +20,8 @@
#pragma once
+#include <libsolidity/inlineasm/AsmDataForward.h>
+
#include <boost/variant.hpp>
#include <functional>
@@ -35,19 +37,6 @@ namespace assembly
{
struct TypedName;
-struct Literal;
-struct Block;
-struct Label;
-struct FunctionalInstruction;
-struct Assignment;
-struct VariableDeclaration;
-struct Instruction;
-struct Identifier;
-struct StackAssignment;
-struct FunctionDefinition;
-struct FunctionCall;
-struct Switch;
-
struct Scope;
struct AsmAnalysisInfo;
@@ -71,6 +60,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/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp
index 7dc1edc7..2d85895e 100644
--- a/libsolidity/interface/AssemblyStack.cpp
+++ b/libsolidity/interface/AssemblyStack.cpp
@@ -100,7 +100,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
{
MachineAssemblyObject object;
julia::EVMAssembly assembly(true);
- julia::CodeTransform(assembly, *m_analysisInfo, true).run(*m_parserResult);
+ julia::CodeTransform(assembly, *m_analysisInfo, true)(*m_parserResult);
object.bytecode = make_shared<eth::LinkerObject>(assembly.finalize());
/// TOOD: fill out text representation
return object;