Remove the legacy AST JSON output

This commit is contained in:
Alex Beregszaszi 2020-11-20 14:35:53 +00:00
parent 38f143c597
commit 3bce2a2294
8 changed files with 38 additions and 121 deletions

View File

@ -4,7 +4,9 @@ Breaking Changes:
* Assembler: The artificial ASSIGNIMMUTABLE opcode and the corresponding builtin in the "EVM with object access" dialect of Yul take the base offset of the code to modify as additional argument.
* Code Generator: All arithmetic is checked by default. These checks can be disabled using ``unchecked { ... }``.
* Code Generator: Cause a panic if a byte array in storage is accessed whose length is encoded incorrectly.
* Command Line Interface: Remove the legacy ``--ast-json`` option. Only the ``--ast-compact-json`` option is supported now.
* General: Remove global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``.
* Standard JSON: Remove the ``legacyAST`` option.
* Type Checker: Function call options can only be given once.
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.

View File

@ -327,7 +327,6 @@ Input Description
//
// File level (needs empty string as contract name):
// ast - AST of all source files
// legacyAST - legacy AST of all source files
//
// Contract level (needs the contract name or "*"):
// abi - ABI
@ -430,8 +429,6 @@ Output Description
"id": 1,
// The AST object
"ast": {},
// The legacy AST object
"legacyAST": {}
}
},
// This contains the contract-level outputs.

View File

@ -70,8 +70,7 @@ void addIfSet(std::vector<pair<string, Json::Value>>& _attributes, string const&
namespace solidity::frontend
{
ASTJsonConverter::ASTJsonConverter(bool _legacy, CompilerStack::State _stackState, map<string, unsigned> _sourceIndices):
m_legacy(_legacy),
ASTJsonConverter::ASTJsonConverter(CompilerStack::State _stackState, map<string, unsigned> _sourceIndices):
m_stackState(_stackState),
m_sourceIndices(std::move(_sourceIndices))
{
@ -100,60 +99,9 @@ void ASTJsonConverter::setJsonNode(
m_currentValue = Json::objectValue;
m_currentValue["id"] = nodeId(_node);
m_currentValue["src"] = sourceLocationToString(_node.location());
if (!m_legacy)
{
m_currentValue["nodeType"] = _nodeType;
for (auto& e: _attributes)
m_currentValue[e.first] = std::move(e.second);
}
else
{
m_currentValue["name"] = _nodeType;
Json::Value attrs(Json::objectValue);
if (
//these nodeTypes need to have a children-node even if it is empty
(_nodeType == "VariableDeclaration") ||
(_nodeType == "ParameterList") ||
(_nodeType == "Block") ||
(_nodeType == "InlineAssembly") ||
(_nodeType == "Throw")
)
m_currentValue["children"] = Json::arrayValue;
for (auto& e: _attributes)
{
if ((!e.second.isNull()) && (
(e.second.isObject() && e.second.isMember("name")) ||
(e.second.isArray() && e.second[0].isObject() && e.second[0].isMember("name")) ||
(e.first == "declarations") // (in the case (_,x)= ... there's a nullpointer at [0]
))
{
if (e.second.isObject())
{
if (!m_currentValue["children"].isArray())
m_currentValue["children"] = Json::arrayValue;
appendMove(m_currentValue["children"], std::move(e.second));
}
if (e.second.isArray())
for (auto& child: e.second)
if (!child.isNull())
{
if (!m_currentValue["children"].isArray())
m_currentValue["children"] = Json::arrayValue;
appendMove(m_currentValue["children"], std::move(child));
}
}
else
{
if (e.first == "typeDescriptions")
attrs["type"] = Json::Value(e.second["typeString"]);
else
attrs[e.first] = std::move(e.second);
}
}
if (!attrs.empty())
m_currentValue["attributes"] = std::move(attrs);
}
m_currentValue["nodeType"] = _nodeType;
for (auto& e: _attributes)
m_currentValue[e.first] = std::move(e.second);
}
size_t ASTJsonConverter::sourceIndexFromLocation(SourceLocation const& _location) const
@ -285,7 +233,7 @@ bool ASTJsonConverter::visit(ImportDirective const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair("file", _node.path()),
make_pair(m_legacy ? "SourceUnit" : "sourceUnit", idOrNull(_node.annotation().sourceUnit)),
make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
make_pair("scope", idOrNull(_node.scope()))
};
@ -442,8 +390,6 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
if (!_node.annotation().baseFunctions.empty())
attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
if (m_legacy)
attributes.emplace_back("isConstructor", _node.isConstructor());
setJsonNode(_node, "FunctionDefinition", std::move(attributes));
return false;
}
@ -586,9 +532,7 @@ bool ASTJsonConverter::visit(InlineAssembly const& _node)
externalReferencesJson.append(std::move(it.second));
setJsonNode(_node, "InlineAssembly", {
m_legacy ?
make_pair("operations", Json::Value(yul::AsmPrinter()(_node.operations()))) :
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
make_pair("externalReferences", std::move(externalReferencesJson)),
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
});
@ -794,14 +738,7 @@ bool ASTJsonConverter::visit(FunctionCall const& _node)
if (_node.annotation().kind.set())
{
FunctionCallKind nodeKind = *_node.annotation().kind;
if (m_legacy)
{
attributes.emplace_back("isStructConstructorCall", nodeKind == FunctionCallKind::StructConstructorCall);
attributes.emplace_back("type_conversion", nodeKind == FunctionCallKind::TypeConversion);
}
else
attributes.emplace_back("kind", functionCallKind(nodeKind));
attributes.emplace_back("kind", functionCallKind(nodeKind));
}
appendExpressionAttributes(attributes, _node.annotation());
@ -839,7 +776,7 @@ bool ASTJsonConverter::visit(NewExpression const& _node)
bool ASTJsonConverter::visit(MemberAccess const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair(m_legacy ? "member_name" : "memberName", _node.memberName()),
make_pair("memberName", _node.memberName()),
make_pair("expression", toJson(_node.expression())),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
};
@ -877,7 +814,7 @@ bool ASTJsonConverter::visit(Identifier const& _node)
for (auto const& dec: _node.annotation().overloadedDeclarations)
overloads.append(nodeId(*dec));
setJsonNode(_node, "Identifier", {
make_pair(m_legacy ? "value" : "name", _node.name()),
make_pair("name", _node.name()),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
make_pair("overloadedDeclarations", overloads),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
@ -889,7 +826,7 @@ bool ASTJsonConverter::visit(Identifier const& _node)
bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair(m_legacy ? "value" : "typeName", toJson(_node.type()))
make_pair("typeName", toJson(_node.type()))
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes));
@ -903,9 +840,9 @@ bool ASTJsonConverter::visit(Literal const& _node)
value = Json::nullValue;
Token subdenomination = Token(_node.subDenomination());
std::vector<pair<string, Json::Value>> attributes = {
make_pair(m_legacy ? "token" : "kind", literalTokenKind(_node.token())),
make_pair("kind", literalTokenKind(_node.token())),
make_pair("value", value),
make_pair(m_legacy ? "hexvalue" : "hexValue", util::toHex(util::asBytes(_node.value()))),
make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
make_pair(
"subdenomination",
subdenomination == Token::Illegal ?

View File

@ -51,11 +51,9 @@ class ASTJsonConverter: public ASTConstVisitor
{
public:
/// Create a converter to JSON for the given abstract syntax tree.
/// @a _legacy if true, use legacy format
/// @a _stackState state of the compiler stack to avoid outputting incomplete data
/// @a _sourceIndices is used to abbreviate source names in source locations.
explicit ASTJsonConverter(
bool _legacy,
CompilerStack::State _stackState,
std::map<std::string, unsigned> _sourceIndices = std::map<std::string, unsigned>()
);
@ -192,7 +190,6 @@ private:
_array.append(std::move(_value));
}
bool m_legacy = false; ///< if true, use legacy format
CompilerStack::State m_stackState = CompilerStack::State::Empty; ///< Used to only access information that already exists
bool m_inEvent = false; ///< whether we are currently inside an event or not
Json::Value m_currentValue;

View File

@ -1086,9 +1086,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
Json::Value sourceResult = Json::objectValue;
sourceResult["id"] = sourceIndex++;
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "ast", wildcardMatchesExperimental))
sourceResult["ast"] = ASTJsonConverter(false, compilerStack.state(), compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName));
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "legacyAST", wildcardMatchesExperimental))
sourceResult["legacyAST"] = ASTJsonConverter(true, compilerStack.state(), compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName));
sourceResult["ast"] = ASTJsonConverter(compilerStack.state(), compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName));
output["sources"][sourceName] = sourceResult;
}

View File

@ -1679,11 +1679,10 @@ void CommandLineInterface::handleCombinedJSON()
if (requests.count(g_strAst))
{
bool legacyFormat = !requests.count(g_strCompactJSON);
output[g_strSources] = Json::Value(Json::objectValue);
for (auto const& sourceCode: m_sourceCodes)
{
ASTJsonConverter converter(legacyFormat, m_compiler->state(), m_compiler->sourceIndices());
ASTJsonConverter converter(m_compiler->state(), m_compiler->sourceIndices());
output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue);
output[g_strSources][sourceCode.first]["AST"] = converter.toJson(m_compiler->ast(sourceCode.first));
}
@ -1698,45 +1697,34 @@ void CommandLineInterface::handleCombinedJSON()
sout() << json << endl;
}
void CommandLineInterface::handleAst(string const& _argStr)
void CommandLineInterface::handleAst()
{
string title;
if (!m_args.count(g_argAstCompactJson))
return;
if (_argStr == g_argAstJson)
title = "JSON AST:";
else if (_argStr == g_argAstCompactJson)
title = "JSON AST (compact format):";
else
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal argStr for AST"));
vector<ASTNode const*> asts;
for (auto const& sourceCode: m_sourceCodes)
asts.push_back(&m_compiler->ast(sourceCode.first));
// do we need AST output?
if (m_args.count(_argStr))
if (m_args.count(g_argOutputDir))
{
vector<ASTNode const*> asts;
for (auto const& sourceCode: m_sourceCodes)
asts.push_back(&m_compiler->ast(sourceCode.first));
bool legacyFormat = !m_args.count(g_argAstCompactJson);
if (m_args.count(g_argOutputDir))
{
for (auto const& sourceCode: m_sourceCodes)
{
stringstream data;
string postfix = "";
ASTJsonConverter(legacyFormat, m_compiler->state(), m_compiler->sourceIndices()).print(data, m_compiler->ast(sourceCode.first));
postfix += "_json";
boost::filesystem::path path(sourceCode.first);
createFile(path.filename().string() + postfix + ".ast", data.str());
}
stringstream data;
string postfix = "";
ASTJsonConverter(m_compiler->state(), m_compiler->sourceIndices()).print(data, m_compiler->ast(sourceCode.first));
postfix += "_json";
boost::filesystem::path path(sourceCode.first);
createFile(path.filename().string() + postfix + ".ast", data.str());
}
else
}
else
{
sout() << "JSON AST (compact format):" << endl << endl;
for (auto const& sourceCode: m_sourceCodes)
{
sout() << title << endl << endl;
for (auto const& sourceCode: m_sourceCodes)
{
sout() << endl << "======= " << sourceCode.first << " =======" << endl;
ASTJsonConverter(legacyFormat, m_compiler->state(), m_compiler->sourceIndices()).print(sout(), m_compiler->ast(sourceCode.first));
}
sout() << endl << "======= " << sourceCode.first << " =======" << endl;
ASTJsonConverter(m_compiler->state(), m_compiler->sourceIndices()).print(sout(), m_compiler->ast(sourceCode.first));
}
}
}
@ -2002,8 +1990,7 @@ void CommandLineInterface::outputCompilationResults()
handleCombinedJSON();
// do we need AST output?
handleAst(g_argAstJson);
handleAst(g_argAstCompactJson);
handleAst();
if (
!m_compiler->compilationSuccessful() &&

View File

@ -67,7 +67,7 @@ private:
void outputCompilationResults();
void handleCombinedJSON();
void handleAst(std::string const& _argStr);
void handleAst();
void handleBinary(std::string const& _contract);
void handleOpcode(std::string const& _contract);
void handleIR(std::string const& _contract);

View File

@ -68,7 +68,6 @@ private:
std::string m_expectationParseOnly;
std::string m_astFilename;
std::string m_astParseOnlyFilename;
std::string m_legacyAstFilename;
std::string m_result;
std::string m_resultLegacy;
std::string m_resultParseOnly;