mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Provide dialect to Parser and InlineAssembly AST nodes.
This commit is contained in:
parent
fb2b3bb2b9
commit
9a00729ce7
@ -27,7 +27,6 @@
|
||||
#include <libyul/AsmAnalysis.h>
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/AsmData.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
|
||||
@ -707,7 +706,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
*_inlineAssembly.annotation().analysisInfo,
|
||||
m_errorReporter,
|
||||
Error::Type::SyntaxError,
|
||||
yul::EVMDialect::looseAssemblyForEVM(m_evmVersion),
|
||||
_inlineAssembly.dialect(),
|
||||
identifierAccess
|
||||
);
|
||||
if (!analyzer.analyze(_inlineAssembly.operations()))
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <libsolidity/analysis/ViewPureChecker.h>
|
||||
#include <libsolidity/ast/ExperimentalFeatures.h>
|
||||
#include <libyul/AsmData.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <libevmasm/SemanticInformation.h>
|
||||
#include <functional>
|
||||
@ -33,7 +34,11 @@ namespace
|
||||
class AssemblyViewPureChecker: public boost::static_visitor<void>
|
||||
{
|
||||
public:
|
||||
explicit AssemblyViewPureChecker(std::function<void(StateMutability, SourceLocation const&)> _reportMutability):
|
||||
explicit AssemblyViewPureChecker(
|
||||
yul::Dialect const& _dialect,
|
||||
std::function<void(StateMutability, SourceLocation const&)> _reportMutability
|
||||
):
|
||||
m_dialect(_dialect),
|
||||
m_reportMutability(_reportMutability) {}
|
||||
|
||||
void operator()(yul::Label const&) { }
|
||||
@ -69,6 +74,11 @@ public:
|
||||
}
|
||||
void operator()(yul::FunctionCall const& _funCall)
|
||||
{
|
||||
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
|
||||
if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
|
||||
if (fun->instruction)
|
||||
checkInstruction(_funCall.location, *fun->instruction);
|
||||
|
||||
for (auto const& arg: _funCall.arguments)
|
||||
boost::apply_visitor(*this, arg);
|
||||
}
|
||||
@ -107,7 +117,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(StateMutability, SourceLocation const&)> m_reportMutability;
|
||||
void checkInstruction(SourceLocation _location, dev::eth::Instruction _instruction)
|
||||
{
|
||||
if (eth::SemanticInformation::invalidInViewFunctions(_instruction))
|
||||
@ -117,6 +126,9 @@ private:
|
||||
else if (eth::SemanticInformation::invalidInPureFunctions(_instruction))
|
||||
m_reportMutability(StateMutability::View, _location);
|
||||
}
|
||||
|
||||
yul::Dialect const& m_dialect;
|
||||
std::function<void(StateMutability, SourceLocation const&)> m_reportMutability;
|
||||
};
|
||||
|
||||
}
|
||||
@ -223,6 +235,7 @@ void ViewPureChecker::endVisit(Identifier const& _identifier)
|
||||
void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
AssemblyViewPureChecker{
|
||||
_inlineAssembly.dialect(),
|
||||
[=](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); }
|
||||
}(_inlineAssembly.operations());
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ namespace yul
|
||||
{
|
||||
// Forward-declaration to <yul/AsmData.h>
|
||||
struct Block;
|
||||
struct Dialect;
|
||||
}
|
||||
|
||||
namespace dev
|
||||
@ -1049,17 +1050,20 @@ public:
|
||||
InlineAssembly(
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ASTString> const& _docString,
|
||||
yul::Dialect const& _dialect,
|
||||
std::shared_ptr<yul::Block> const& _operations
|
||||
):
|
||||
Statement(_location, _docString), m_operations(_operations) {}
|
||||
Statement(_location, _docString), m_dialect(_dialect), m_operations(_operations) {}
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
yul::Dialect const& dialect() const { return m_dialect; }
|
||||
yul::Block const& operations() const { return *m_operations; }
|
||||
|
||||
InlineAssemblyAnnotation& annotation() const override;
|
||||
|
||||
private:
|
||||
yul::Dialect const& m_dialect;
|
||||
std::shared_ptr<yul::Block> m_operations;
|
||||
};
|
||||
|
||||
|
@ -35,8 +35,9 @@
|
||||
|
||||
namespace yul
|
||||
{
|
||||
struct AsmAnalysisInfo;
|
||||
struct Identifier;
|
||||
struct AsmAnalysisInfo;
|
||||
struct Identifier;
|
||||
struct Dialect;
|
||||
}
|
||||
|
||||
namespace dev
|
||||
|
@ -217,7 +217,7 @@ bool CompilerStack::parse()
|
||||
string const& path = sourcesToParse[i];
|
||||
Source& source = m_sources[path];
|
||||
source.scanner->reset();
|
||||
source.ast = Parser(m_errorReporter).parse(source.scanner);
|
||||
source.ast = Parser(m_errorReporter, m_evmVersion).parse(source.scanner);
|
||||
if (!source.ast)
|
||||
solAssert(!Error::containsOnlyWarnings(m_errorReporter.errors()), "Parser returned null but did not report error.");
|
||||
else
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <liblangutil/Scanner.h>
|
||||
#include <liblangutil/SemVerHandler.h>
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
|
||||
@ -1039,21 +1040,22 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
|
||||
SourceLocation location{position(), -1, source()};
|
||||
|
||||
expectToken(Token::Assembly);
|
||||
yul::Dialect const& dialect = yul::EVMDialect::looseAssemblyForEVM(m_evmVersion);
|
||||
if (m_scanner->currentToken() == Token::StringLiteral)
|
||||
{
|
||||
if (m_scanner->currentLiteral() != "evmasm")
|
||||
fatalParserError("Only \"evmasm\" supported.");
|
||||
// This can be used in the future to set the dialect.
|
||||
m_scanner->next();
|
||||
}
|
||||
|
||||
// Using latest EVM Version for now, it will be run again later.
|
||||
yul::Parser asmParser(m_errorReporter, yul::EVMDialect::looseAssemblyForEVM(EVMVersion{}));
|
||||
yul::Parser asmParser(m_errorReporter, dialect);
|
||||
shared_ptr<yul::Block> block = asmParser.parse(m_scanner, true);
|
||||
if (block == nullptr)
|
||||
BOOST_THROW_EXCEPTION(FatalError());
|
||||
|
||||
location.end = block->location.end;
|
||||
return make_shared<InlineAssembly>(location, _docString, block);
|
||||
return make_shared<InlineAssembly>(location, _docString, dialect, block);
|
||||
}
|
||||
|
||||
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <liblangutil/ParserBase.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
namespace langutil
|
||||
{
|
||||
@ -38,7 +39,13 @@ namespace solidity
|
||||
class Parser: public langutil::ParserBase
|
||||
{
|
||||
public:
|
||||
explicit Parser(langutil::ErrorReporter& _errorReporter): ParserBase(_errorReporter) {}
|
||||
explicit Parser(
|
||||
langutil::ErrorReporter& _errorReporter,
|
||||
langutil::EVMVersion _evmVersion
|
||||
):
|
||||
ParserBase(_errorReporter),
|
||||
m_evmVersion(_evmVersion)
|
||||
{}
|
||||
|
||||
ASTPointer<SourceUnit> parse(std::shared_ptr<langutil::Scanner> const& _scanner);
|
||||
|
||||
@ -181,6 +188,7 @@ private:
|
||||
|
||||
/// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier.
|
||||
bool m_insideModifier = false;
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -90,19 +90,18 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
|
||||
return {name, f};
|
||||
}
|
||||
|
||||
map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess, bool _evmOpcodes)
|
||||
map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess)
|
||||
{
|
||||
map<YulString, BuiltinFunctionForEVM> builtins;
|
||||
if (_evmOpcodes)
|
||||
for (auto const& instr: Parser::instructions())
|
||||
if (
|
||||
!dev::eth::isDupInstruction(instr.second) &&
|
||||
!dev::eth::isSwapInstruction(instr.second) &&
|
||||
instr.second != eth::Instruction::JUMP &&
|
||||
instr.second != eth::Instruction::JUMPI &&
|
||||
_evmVersion.hasOpcode(instr.second)
|
||||
)
|
||||
builtins.emplace(createEVMFunction(instr.first, instr.second));
|
||||
for (auto const& instr: Parser::instructions())
|
||||
if (
|
||||
!dev::eth::isDupInstruction(instr.second) &&
|
||||
!dev::eth::isSwapInstruction(instr.second) &&
|
||||
instr.second != eth::Instruction::JUMP &&
|
||||
instr.second != eth::Instruction::JUMPI &&
|
||||
_evmVersion.hasOpcode(instr.second)
|
||||
)
|
||||
builtins.emplace(createEVMFunction(instr.first, instr.second));
|
||||
|
||||
if (_objectAccess)
|
||||
{
|
||||
@ -167,7 +166,7 @@ EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVer
|
||||
Dialect{_flavour},
|
||||
m_objectAccess(_objectAccess),
|
||||
m_evmVersion(_evmVersion),
|
||||
m_functions(createBuiltins(_evmVersion, _objectAccess, _flavour != AsmFlavour::Loose))
|
||||
m_functions(createBuiltins(_evmVersion, _objectAccess))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ eth::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
|
||||
{
|
||||
ErrorList errors;
|
||||
ErrorReporter errorReporter(errors);
|
||||
Parser parser(errorReporter);
|
||||
Parser parser(errorReporter, dev::test::Options::get().evmVersion());
|
||||
ASTPointer<SourceUnit> sourceUnit;
|
||||
BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(_sourceCode)));
|
||||
BOOST_CHECK(!!sourceUnit);
|
||||
|
@ -102,7 +102,9 @@ bytes compileFirstExpression(
|
||||
{
|
||||
ErrorList errors;
|
||||
ErrorReporter errorReporter(errors);
|
||||
sourceUnit = Parser(errorReporter).parse(make_shared<Scanner>(CharStream(_sourceCode, "")));
|
||||
sourceUnit = Parser(errorReporter, dev::test::Options::get().evmVersion()).parse(
|
||||
make_shared<Scanner>(CharStream(_sourceCode, ""))
|
||||
);
|
||||
if (!sourceUnit)
|
||||
return bytes();
|
||||
}
|
||||
|
@ -44,7 +44,10 @@ namespace
|
||||
ASTPointer<ContractDefinition> parseText(std::string const& _source, ErrorList& _errors)
|
||||
{
|
||||
ErrorReporter errorReporter(_errors);
|
||||
ASTPointer<SourceUnit> sourceUnit = Parser(errorReporter).parse(std::make_shared<Scanner>(CharStream(_source, "")));
|
||||
ASTPointer<SourceUnit> sourceUnit = Parser(
|
||||
errorReporter,
|
||||
dev::test::Options::get().evmVersion()
|
||||
).parse(std::make_shared<Scanner>(CharStream(_source, "")));
|
||||
if (!sourceUnit)
|
||||
return ASTPointer<ContractDefinition>();
|
||||
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
||||
|
Loading…
Reference in New Issue
Block a user