Skip to content

Commit

Permalink
Ast-Import from standard-json
Browse files Browse the repository at this point in the history
  • Loading branch information
djudjuu authored and Marenz committed Jan 13, 2020
1 parent d577a76 commit aaf9349
Show file tree
Hide file tree
Showing 26 changed files with 2,073 additions and 143 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Language Features:

Compiler Features:
* General: Raise warning if runtime bytecode exceeds 24576 bytes (a limit introduced in Spurious Dragon).
* General: Support compiling starting from an imported AST. Among others, this can be used for mutation testing.
* Yul Optimizer: Apply penalty when trying to rematerialize into loops.

Bugfixes:
Expand Down
1 change: 1 addition & 0 deletions liblangutil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(sources
SemVerHandler.cpp
SemVerHandler.h
SourceLocation.h
SourceLocation.cpp
SourceReferenceExtractor.cpp
SourceReferenceExtractor.h
SourceReferenceFormatter.cpp
Expand Down
4 changes: 4 additions & 0 deletions liblangutil/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct CompilerError: virtual util::Exception {};
struct InternalCompilerError: virtual util::Exception {};
struct FatalError: virtual util::Exception {};
struct UnimplementedFeatureError: virtual util::Exception {};
struct InvalidAstError: virtual util::Exception {};

/// Assertion that throws an InternalCompilerError containing the given description if it is not met.
#define solAssert(CONDITION, DESCRIPTION) \
Expand All @@ -51,6 +52,9 @@ struct UnimplementedFeatureError: virtual util::Exception {};
#define solUnimplemented(DESCRIPTION) \
solUnimplementedAssert(false, DESCRIPTION)

#define astAssert(CONDITION, DESCRIPTION) \
assertThrow(CONDITION, ::solidity::langutil::InvalidAstError, DESCRIPTION)

class Error: virtual public util::Exception
{
public:
Expand Down
51 changes: 51 additions & 0 deletions liblangutil/SourceLocation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
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/>.
*/

#include <liblangutil/Exceptions.h>

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>

using namespace solidity;
namespace solidity::langutil
{

SourceLocation const parseSourceLocation(std::string const& _input, std::string const& _sourceName, size_t _maxIndex)
{
// Expected input: "start:length:sourceindex"
enum SrcElem : size_t { Start, Length, Index };

std::vector<std::string> pos;

boost::algorithm::split(pos, _input, boost::is_any_of(":"));

astAssert(
pos.size() == 3 &&
_maxIndex >= static_cast<size_t>(stoi(pos[Index])),
"'src'-field ill-formatted or src-index too high"
);

int start = stoi(pos[Start]);
int end = start + stoi(pos[Length]);

// ASSUMPTION: only the name of source is used from here on, the m_source of the CharStream-Object can be empty
std::shared_ptr<langutil::CharStream> source = std::make_shared<langutil::CharStream>("", _sourceName);

return SourceLocation{start, end, source};
}

}
54 changes: 26 additions & 28 deletions liblangutil/SourceLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
#pragma once

#include <libsolutil/Assertions.h>
#include <libsolutil/Common.h> // defines noexcept macro for MSVC
#include <libsolutil/Exceptions.h>

#include <liblangutil/CharStream.h>

#include <memory>
#include <string>
#include <ostream>
#include <tuple>

namespace solidity::langutil
{
Expand All @@ -46,9 +45,28 @@ struct SourceLocation
return source.get() == _other.source.get() && start == _other.start && end == _other.end;
}
bool operator!=(SourceLocation const& _other) const { return !operator==(_other); }
inline bool operator<(SourceLocation const& _other) const;
inline bool contains(SourceLocation const& _other) const;
inline bool intersects(SourceLocation const& _other) const;

inline bool operator<(SourceLocation const& _other) const
{
if (!source|| !_other.source)
return std::make_tuple(int(!!source), start, end) < std::make_tuple(int(!!_other.source), _other.start, _other.end);
else
return std::make_tuple(source->name(), start, end) < std::make_tuple(_other.source->name(), _other.start, _other.end);
}

inline bool contains(SourceLocation const& _other) const
{
if (isEmpty() || _other.isEmpty() || source.get() != _other.source.get())
return false;
return start <= _other.start && _other.end <= end;
}

inline bool intersects(SourceLocation const& _other) const
{
if (isEmpty() || _other.isEmpty() || source.get() != _other.source.get())
return false;
return _other.start < end && start < _other.end;
}

bool isEmpty() const { return start == -1 && end == -1; }

Expand Down Expand Up @@ -86,6 +104,8 @@ struct SourceLocation
std::shared_ptr<CharStream> source;
};

SourceLocation const parseSourceLocation(std::string const& _input, std::string const& _sourceName, size_t _maxIndex = -1);

/// Stream output for Location (used e.g. in boost exceptions).
inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location)
{
Expand All @@ -100,26 +120,4 @@ inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _locat
return _out;
}

bool SourceLocation::operator<(SourceLocation const& _other) const
{
if (!source|| !_other.source)
return std::make_tuple(int(!!source), start, end) < std::make_tuple(int(!!_other.source), _other.start, _other.end);
else
return std::make_tuple(source->name(), start, end) < std::make_tuple(_other.source->name(), _other.start, _other.end);
}

bool SourceLocation::contains(SourceLocation const& _other) const
{
if (isEmpty() || _other.isEmpty() || source.get() != _other.source.get())
return false;
return start <= _other.start && _other.end <= end;
}

bool SourceLocation::intersects(SourceLocation const& _other) const
{
if (isEmpty() || _other.isEmpty() || source.get() != _other.source.get())
return false;
return _other.start < end && start < _other.end;
}

}
4 changes: 4 additions & 0 deletions libsolidity/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ set(sources
ast/ASTAnnotations.h
ast/ASTEnums.h
ast/ASTForward.h
ast/AsmJsonImporter.cpp
ast/AsmJsonImporter.h
ast/ASTJsonConverter.cpp
ast/ASTJsonConverter.h
ast/ASTUtils.cpp
ast/ASTUtils.h
ast/ASTJsonImporter.cpp
ast/ASTJsonImporter.h
ast/ASTVisitor.h
ast/ExperimentalFeatures.h
ast/Types.cpp
Expand Down
40 changes: 37 additions & 3 deletions libsolidity/analysis/GlobalContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,44 @@ using namespace std;
namespace solidity::frontend
{

/// Magic variables get negative ids for easy differentiation
int magicVariableToID(std::string const& _name)
{
if (_name == "abi") return -1;
else if (_name == "addmod") return -2;
else if (_name == "assert") return -3;
else if (_name == "block") return -4;
else if (_name == "blockhash") return -5;
else if (_name == "ecrecover") return -6;
else if (_name == "gasleft") return -7;
else if (_name == "keccak256") return -8;
else if (_name == "log0") return -10;
else if (_name == "log1") return -11;
else if (_name == "log2") return -12;
else if (_name == "log3") return -13;
else if (_name == "log4") return -14;
else if (_name == "msg") return -15;
else if (_name == "mulmod") return -16;
else if (_name == "now") return -17;
else if (_name == "require") return -18;
else if (_name == "revert") return -19;
else if (_name == "ripemd160") return -20;
else if (_name == "selfdestruct") return -21;
else if (_name == "sha256") return -22;
else if (_name == "sha3") return -23;
else if (_name == "suicide") return -24;
else if (_name == "super") return -25;
else if (_name == "tx") return -26;
else if (_name == "type") return -27;
else if (_name == "this") return -28;
else
solAssert(false, "Unknown magic variable: \"" + _name + "\".");
}

inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariables()
{
static auto const magicVarDecl = [](string const& _name, Type const* _type) {
return make_shared<MagicVariableDeclaration>(_name, _type);
return make_shared<MagicVariableDeclaration>(magicVariableToID(_name), _name, _type);
};

return {
Expand Down Expand Up @@ -97,15 +131,15 @@ vector<Declaration const*> GlobalContext::declarations() const
MagicVariableDeclaration const* GlobalContext::currentThis() const
{
if (!m_thisPointer[m_currentContract])
m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>("this", TypeProvider::contract(*m_currentContract));
m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>(magicVariableToID("this"), "this", TypeProvider::contract(*m_currentContract));
return m_thisPointer[m_currentContract].get();

}

MagicVariableDeclaration const* GlobalContext::currentSuper() const
{
if (!m_superPointer[m_currentContract])
m_superPointer[m_currentContract] = make_shared<MagicVariableDeclaration>("super", TypeProvider::contract(*m_currentContract, true));
m_superPointer[m_currentContract] = make_shared<MagicVariableDeclaration>(magicVariableToID("super"), "super", TypeProvider::contract(*m_currentContract, true));
return m_superPointer[m_currentContract].get();
}

Expand Down
23 changes: 2 additions & 21 deletions libsolidity/ast/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,12 @@ using namespace std;
using namespace solidity;
using namespace solidity::frontend;

class IDDispenser
{
public:
static size_t next() { return ++instance(); }
static void reset() { instance() = 0; }
private:
static size_t& instance()
{
static IDDispenser dispenser;
return dispenser.id;
}
size_t id = 0;
};

ASTNode::ASTNode(SourceLocation const& _location):
m_id(IDDispenser::next()),
ASTNode::ASTNode(int64_t _id, SourceLocation const& _location):
m_id(_id),
m_location(_location)
{
}

void ASTNode::resetID()
{
IDDispenser::reset();
}

ASTAnnotation& ASTNode::annotation() const
{
if (!m_annotation)
Expand Down
Loading

0 comments on commit aaf9349

Please sign in to comment.