diff options
author | chriseth <chris@ethereum.org> | 2017-05-22 20:33:46 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-22 20:33:46 +0800 |
commit | 8eead553aff1ec30c3d1b15ae9b2929b887ede49 (patch) | |
tree | a9eba765277360c579ee89ee78d9606c17cb9ffa | |
parent | e3af064098edae79aa3bbfb2a96b43fa3479269d (diff) | |
parent | e82df073d15237455b1e53e35ef544aea72a69f9 (diff) | |
download | dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.gz dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.bz2 dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.lz dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.xz dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.tar.zst dexon-solidity-8eead553aff1ec30c3d1b15ae9b2929b887ede49.zip |
Merge pull request #1810 from ethereum/compactJson
Compact format for AST-Json.
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 16 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 9 | ||||
-rw-r--r-- | libsolidity/ast/ASTAnnotations.h | 13 | ||||
-rw-r--r-- | libsolidity/ast/ASTJsonConverter.cpp | 860 | ||||
-rw-r--r-- | libsolidity/ast/ASTJsonConverter.h | 112 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 2 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 6 | ||||
-rw-r--r-- | libsolidity/formal/Why3Translator.cpp | 2 | ||||
-rw-r--r-- | libsolidity/interface/StandardCompiler.cpp | 3 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 10 | ||||
-rw-r--r-- | solc/jsonCompiler.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/ASTJSON.cpp | 24 | ||||
-rw-r--r-- | test/libsolidity/JSONCompiler.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/StandardCompiler.cpp | 6 |
15 files changed, 579 insertions, 495 deletions
diff --git a/Changelog.md b/Changelog.md index be5c18c5..650d75d8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,5 @@ ### 0.4.12 (unreleased) + * AST: export all attributes to Json format ### 0.4.11 (2017-05-03) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 38cdc1f8..8161a3a1 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1238,13 +1238,17 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) if (auto const* typeType = dynamic_cast<TypeType const*>(expressionType.get())) { - _functionCall.annotation().isStructConstructorCall = (typeType->actualType()->category() == Type::Category::Struct); - _functionCall.annotation().isTypeConversion = !_functionCall.annotation().isStructConstructorCall; + if (typeType->actualType()->category() == Type::Category::Struct) + _functionCall.annotation().kind = FunctionCallKind::StructConstructorCall; + else + _functionCall.annotation().kind = FunctionCallKind::TypeConversion; + } else - _functionCall.annotation().isStructConstructorCall = _functionCall.annotation().isTypeConversion = false; + _functionCall.annotation().kind = FunctionCallKind::FunctionCall; + solAssert(_functionCall.annotation().kind != FunctionCallKind::Unset, ""); - if (_functionCall.annotation().isTypeConversion) + if (_functionCall.annotation().kind == FunctionCallKind::TypeConversion) { TypeType const& t = dynamic_cast<TypeType const&>(*expressionType); TypePointer resultType = t.actualType(); @@ -1274,7 +1278,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) /// For error message: Struct members that were removed during conversion to memory. set<string> membersRemovedForStructConstructor; - if (_functionCall.annotation().isStructConstructorCall) + if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall) { TypeType const& t = dynamic_cast<TypeType const&>(*expressionType); auto const& structType = dynamic_cast<StructType const&>(*t.actualType()); @@ -1312,7 +1316,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) toString(parameterTypes.size()) + "."; // Extend error message in case we try to construct a struct with mapping member. - if (_functionCall.annotation().isStructConstructorCall && !membersRemovedForStructConstructor.empty()) + if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall && !membersRemovedForStructConstructor.empty()) { msg += " Members that have to be skipped in memory:"; for (auto const& member: membersRemovedForStructConstructor) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 02234ffc..71b81a69 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -583,8 +583,7 @@ public: bool isPayable() const { return m_isPayable; } std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; } std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); } - Block const& body() const { return *m_body; } - + Block const& body() const { solAssert(m_body, ""); return *m_body; } virtual bool isVisibleInContract() const override { return Declaration::isVisibleInContract() && !isConstructor() && !name().empty(); @@ -1314,7 +1313,7 @@ private: /** * Tuple, parenthesized expression, or bracketed expression. - * Examples: (1, 2), (x,), (x), (), [1, 2], + * Examples: (1, 2), (x,), (x), (), [1, 2], * Individual components might be empty shared pointers (as in the second example). * The respective types in lvalue context are: 2-tuple, 2-tuple (with wildcard), type of x, 0-tuple * Not in lvalue context: 2-tuple, _1_-tuple, type of x, 0-tuple. @@ -1327,8 +1326,8 @@ public: std::vector<ASTPointer<Expression>> const& _components, bool _isArray ): - Expression(_location), - m_components(_components), + Expression(_location), + m_components(_components), m_isArray(_isArray) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index a7d89248..45a6dd1a 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -200,12 +200,17 @@ struct BinaryOperationAnnotation: ExpressionAnnotation TypePointer commonType; }; +enum class FunctionCallKind +{ + Unset, + FunctionCall, + TypeConversion, + StructConstructorCall +}; + struct FunctionCallAnnotation: ExpressionAnnotation { - /// Whether this is an explicit type conversion. - bool isTypeConversion = false; - /// Whether this is a struct constructor call. - bool isStructConstructorCall = false; + FunctionCallKind kind = FunctionCallKind::Unset; }; } diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 9ea23687..40c552a3 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -25,6 +25,8 @@ #include <libdevcore/UTF8.h> #include <libsolidity/ast/AST.h> #include <libsolidity/interface/Exceptions.h> +#include <libsolidity/inlineasm/AsmData.h> +#include <libsolidity/inlineasm/AsmPrinter.h> using namespace std; @@ -33,49 +35,86 @@ namespace dev namespace solidity { -void ASTJsonConverter::addJsonNode( +ASTJsonConverter::ASTJsonConverter(bool _legacy, map<string, unsigned> _sourceIndices): + m_legacy(_legacy), + m_sourceIndices(_sourceIndices) +{ +} + + +void ASTJsonConverter::setJsonNode( ASTNode const& _node, string const& _nodeName, - initializer_list<pair<string const, Json::Value const>> _attributes, - bool _hasChildren = false + initializer_list<pair<string, Json::Value>>&& _attributes ) { - ASTJsonConverter::addJsonNode( + ASTJsonConverter::setJsonNode( _node, _nodeName, - std::vector<pair<string const, Json::Value const>>(_attributes), - _hasChildren + std::vector<pair<string, Json::Value>>(std::move(_attributes)) ); } - -void ASTJsonConverter::addJsonNode( + +void ASTJsonConverter::setJsonNode( ASTNode const& _node, - string const& _nodeName, - std::vector<pair<string const, Json::Value const>> const& _attributes, - bool _hasChildren = false + string const& _nodeType, + std::vector<pair<string, Json::Value>>&& _attributes ) { - Json::Value node; - - node["id"] = Json::UInt64(_node.id()); - node["src"] = sourceLocationToString(_node.location()); - node["name"] = _nodeName; - if (_attributes.size() != 0) + m_currentValue = Json::objectValue; + m_currentValue["id"] = nodeId(_node); + m_currentValue["src"] = sourceLocationToString(_node.location()); + if (!m_legacy) { - Json::Value attrs; + m_currentValue["nodeType"] = _nodeType; for (auto& e: _attributes) - attrs[e.first] = e.second; - node["attributes"] = attrs; + m_currentValue[e.first] = std::move(e.second); } - - m_jsonNodePtrs.top()->append(node); - - if (_hasChildren) + else { - Json::Value& addedNode = (*m_jsonNodePtrs.top())[m_jsonNodePtrs.top()->size() - 1]; - Json::Value children(Json::arrayValue); - addedNode["children"] = children; - m_jsonNodePtrs.push(&addedNode["children"]); + 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") + ) + { + Json::Value children(Json::arrayValue); + m_currentValue["children"] = children; + } + + 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()) + m_currentValue["children"].append(std::move(e.second)); + if (e.second.isArray()) + for (auto& child: e.second) + if (!child.isNull()) + m_currentValue["children"].append(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); } } @@ -90,34 +129,89 @@ string ASTJsonConverter::sourceLocationToString(SourceLocation const& _location) return std::to_string(_location.start) + ":" + std::to_string(length) + ":" + std::to_string(sourceIndex); } -ASTJsonConverter::ASTJsonConverter( - ASTNode const& _ast, - map<string, unsigned> _sourceIndices -): m_ast(&_ast), m_sourceIndices(_sourceIndices) +string ASTJsonConverter::namePathToString(std::vector<ASTString> const& _namePath) const { + return boost::algorithm::join(_namePath, "."); } -void ASTJsonConverter::print(ostream& _stream) +Json::Value ASTJsonConverter::typePointerToJson(TypePointer _tp) { - process(); - _stream << m_astJson; + Json::Value typeDescriptions(Json::objectValue); + typeDescriptions["typeString"] = _tp ? Json::Value(_tp->toString()) : Json::nullValue; + typeDescriptions["typeIdentifier"] = _tp ? Json::Value(_tp->identifier()) : Json::nullValue; + return typeDescriptions; + +} +Json::Value ASTJsonConverter::typePointerToJson(std::shared_ptr<std::vector<TypePointer>> _tps) +{ + if (_tps) + { + Json::Value arguments(Json::arrayValue); + for (auto const& tp: *_tps) + arguments.append(typePointerToJson(tp)); + return arguments; + } + else + return Json::nullValue; } -Json::Value const& ASTJsonConverter::json() +void ASTJsonConverter::appendExpressionAttributes( + std::vector<pair<string, Json::Value>>& _attributes, + ExpressionAnnotation const& _annotation +) { - process(); - return m_astJson; + std::vector<pair<string, Json::Value>> exprAttributes = { + make_pair("typeDescriptions", typePointerToJson(_annotation.type)), + make_pair("isConstant", _annotation.isConstant), + make_pair("isPure", _annotation.isPure), + make_pair("isLValue", _annotation.isLValue), + make_pair("lValueRequested", _annotation.lValueRequested), + make_pair("argumentTypes", typePointerToJson(_annotation.argumentTypes)) + }; + _attributes += exprAttributes; } -bool ASTJsonConverter::visit(SourceUnit const&) +Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<assembly::Identifier const* ,InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) { - Json::Value children(Json::arrayValue); + Json::Value tuple(Json::objectValue); + tuple["src"] = sourceLocationToString(_info.first->location); + tuple["declaration"] = idOrNull(_info.second.declaration); + tuple["isSlot"] = Json::Value(_info.second.isSlot); + tuple["isOffset"] = Json::Value(_info.second.isOffset); + tuple["valueSize"] = _info.second.valueSize; + return tuple; +} - m_astJson["name"] = "SourceUnit"; - m_astJson["children"] = children; - m_jsonNodePtrs.push(&m_astJson["children"]); +void ASTJsonConverter::print(ostream& _stream, ASTNode const& _node) +{ + _stream << toJson(_node); +} - return true; +Json::Value ASTJsonConverter::toJson(ASTNode const& _node) +{ + _node.accept(*this); + return std::move(m_currentValue); +} + +bool ASTJsonConverter::visit(SourceUnit const& _node) +{ + Json::Value exportedSymbols = Json::objectValue; + for (auto const& sym: _node.annotation().exportedSymbols) + { + exportedSymbols[sym.first] = Json::arrayValue; + for (Declaration const* overload: sym.second) + exportedSymbols[sym.first].append(nodeId(*overload)); + } + setJsonNode( + _node, + "SourceUnit", + { + make_pair("absolutePath", _node.annotation().path), + make_pair("exportedSymbols", move(exportedSymbols)), + make_pair("nodes", toJson(_node.nodes())) + } + ); + return false; } bool ASTJsonConverter::visit(PragmaDirective const& _node) @@ -125,313 +219,487 @@ bool ASTJsonConverter::visit(PragmaDirective const& _node) Json::Value literals(Json::arrayValue); for (auto const& literal: _node.literals()) literals.append(literal); - addJsonNode(_node, "PragmaDirective", { make_pair("literals", literals) }); - return true; + setJsonNode( _node, "PragmaDirective", { + make_pair("literals", std::move(literals)) + }); + return false; } bool ASTJsonConverter::visit(ImportDirective const& _node) { - addJsonNode(_node, "ImportDirective", { make_pair("file", _node.path())}); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("file", _node.path()), + make_pair("absolutePath", _node.annotation().absolutePath), + make_pair(m_legacy ? "SourceUnit" : "sourceUnit", nodeId(*_node.annotation().sourceUnit)), + make_pair("scope", idOrNull(_node.scope())) + }; + attributes.push_back(make_pair("unitAlias", _node.name())); + Json::Value symbolAliases(Json::arrayValue); + for (auto const& symbolAlias: _node.symbolAliases()) + { + Json::Value tuple(Json::objectValue); + solAssert(symbolAlias.first, ""); + tuple["foreign"] = nodeId(*symbolAlias.first); + tuple["local"] = symbolAlias.second ? Json::Value(*symbolAlias.second) : Json::nullValue; + symbolAliases.append(tuple); + } + attributes.push_back(make_pair("symbolAliases", std::move(symbolAliases))); + setJsonNode(_node, "ImportDirective", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(ContractDefinition const& _node) { - Json::Value linearizedBaseContracts(Json::arrayValue); - for (auto const& baseContract: _node.annotation().linearizedBaseContracts) - linearizedBaseContracts.append(Json::UInt64(baseContract->id())); - addJsonNode(_node, "ContractDefinition", { + setJsonNode(_node, "ContractDefinition", { make_pair("name", _node.name()), - make_pair("isLibrary", _node.isLibrary()), + make_pair("contractKind", contractKind(_node.contractKind())), make_pair("fullyImplemented", _node.annotation().isFullyImplemented), - make_pair("linearizedBaseContracts", linearizedBaseContracts), - }, true); - return true; + make_pair("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts)), + make_pair("baseContracts", toJson(_node.baseContracts())), + make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies)), + make_pair("nodes", toJson(_node.subNodes())), + make_pair("scope", idOrNull(_node.scope())) + }); + return false; } bool ASTJsonConverter::visit(InheritanceSpecifier const& _node) { - addJsonNode(_node, "InheritanceSpecifier", {}, true); - return true; + setJsonNode(_node, "InheritanceSpecifier", { + make_pair("baseName", toJson(_node.name())), + make_pair("arguments", toJson(_node.arguments())) + }); + return false; } bool ASTJsonConverter::visit(UsingForDirective const& _node) { - addJsonNode(_node, "UsingForDirective", {}, true); - return true; + setJsonNode(_node, "UsingForDirective", { + make_pair("libraryName", toJson(_node.libraryName())), + make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue) + }); + return false; } bool ASTJsonConverter::visit(StructDefinition const& _node) { - addJsonNode(_node, "StructDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "StructDefinition", { + make_pair("name", _node.name()), + make_pair("visibility", visibility(_node.visibility())), + make_pair("canonicalName", _node.annotation().canonicalName), + make_pair("members", toJson(_node.members())), + make_pair("scope", idOrNull(_node.scope())) + }); + return false; } bool ASTJsonConverter::visit(EnumDefinition const& _node) { - addJsonNode(_node, "EnumDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "EnumDefinition", { + make_pair("name", _node.name()), + make_pair("canonicalName", _node.annotation().canonicalName), + make_pair("members", toJson(_node.members())) + }); + return false; } bool ASTJsonConverter::visit(EnumValue const& _node) { - addJsonNode(_node, "EnumValue", { make_pair("name", _node.name()) }); - return true; + setJsonNode(_node, "EnumValue", { + make_pair("name", _node.name()) + }); + return false; } bool ASTJsonConverter::visit(ParameterList const& _node) { - addJsonNode(_node, "ParameterList", {}, true); - return true; + setJsonNode(_node, "ParameterList", { + make_pair("parameters", toJson(_node.parameters())) + }); + return false; } bool ASTJsonConverter::visit(FunctionDefinition const& _node) { - addJsonNode(_node, "FunctionDefinition", { + std::vector<pair<string, Json::Value>> attributes = { make_pair("name", _node.name()), - make_pair("constant", _node.isDeclaredConst()), + make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.isDeclaredConst()), make_pair("payable", _node.isPayable()), - make_pair("visibility", visibility(_node.visibility())) - }, true); - return true; + make_pair("visibility", visibility(_node.visibility())), + make_pair("parameters", toJson(_node.parameterList())), + make_pair("isConstructor", _node.isConstructor()), + make_pair("returnParameters", toJson(*_node.returnParameterList())), + make_pair("modifiers", toJson(_node.modifiers())), + make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue), + make_pair("implemented", _node.isImplemented()), + make_pair("scope", idOrNull(_node.scope())) + }; + setJsonNode(_node, "FunctionDefinition", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(VariableDeclaration const& _node) { - std::vector<pair<string const, Json::Value const>> attributes = { + std::vector<pair<string, Json::Value>> attributes = { make_pair("name", _node.name()), - make_pair("type", type(_node)), + make_pair("typeName", toJsonOrNull(_node.typeName())), make_pair("constant", _node.isConstant()), + make_pair("stateVariable", _node.isStateVariable()), make_pair("storageLocation", location(_node.referenceLocation())), - make_pair("visibility", visibility(_node.visibility())) - }; + make_pair("visibility", visibility(_node.visibility())), + make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue), + make_pair("scope", idOrNull(_node.scope())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }; if (m_inEvent) attributes.push_back(make_pair("indexed", _node.isIndexed())); - addJsonNode(_node, "VariableDeclaration", attributes, true); - return true; - + setJsonNode(_node, "VariableDeclaration", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(ModifierDefinition const& _node) { - addJsonNode(_node, "ModifierDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "ModifierDefinition", { + make_pair("name", _node.name()), + make_pair("visibility", visibility(_node.visibility())), + make_pair("parameters", toJson(_node.parameterList())), + make_pair("body", toJson(_node.body())) + }); + return false; } bool ASTJsonConverter::visit(ModifierInvocation const& _node) { - addJsonNode(_node, "ModifierInvocation", {}, true); - return true; + setJsonNode(_node, "ModifierInvocation", { + make_pair("modifierName", toJson(*_node.name())), + make_pair("arguments", toJson(_node.arguments())) + }); + return false; } bool ASTJsonConverter::visit(TypeName const&) { - return true; + solAssert(false, "AST node of abstract type used."); + return false; } bool ASTJsonConverter::visit(EventDefinition const& _node) { m_inEvent = true; - addJsonNode(_node, "EventDefinition", { make_pair("name", _node.name()) }, true); - return true; + setJsonNode(_node, "EventDefinition", { + make_pair("name", _node.name()), + make_pair("parameters", toJson(_node.parameterList())), + make_pair("anonymous", _node.isAnonymous()) + }); + return false; } bool ASTJsonConverter::visit(ElementaryTypeName const& _node) { - addJsonNode(_node, "ElementaryTypeName", { make_pair("name", _node.typeName().toString()) }); - return true; + setJsonNode(_node, "ElementaryTypeName", { + make_pair("name", _node.typeName().toString()), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(UserDefinedTypeName const& _node) { - addJsonNode(_node, "UserDefinedTypeName", { - make_pair("name", boost::algorithm::join(_node.namePath(), ".")) + setJsonNode(_node, "UserDefinedTypeName", { + make_pair("name", namePathToString(_node.namePath())), + make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), + make_pair("contractScope", idOrNull(_node.annotation().contractScope)), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) }); - return true; + return false; } bool ASTJsonConverter::visit(FunctionTypeName const& _node) { - addJsonNode(_node, "FunctionTypeName", { + setJsonNode(_node, "FunctionTypeName", { make_pair("payable", _node.isPayable()), make_pair("visibility", visibility(_node.visibility())), - make_pair("constant", _node.isDeclaredConst()) - }, true); - return true; + make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.isDeclaredConst()), + make_pair("parameterTypes", toJson(_node.parameterTypes())), + make_pair("returnParameterTypes", toJson(_node.returnParameterTypes())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(Mapping const& _node) { - addJsonNode(_node, "Mapping", {}, true); - return true; + setJsonNode(_node, "Mapping", { + make_pair("keyType", toJson(_node.keyType())), + make_pair("valueType", toJson(_node.valueType())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(ArrayTypeName const& _node) { - addJsonNode(_node, "ArrayTypeName", {}, true); - return true; + setJsonNode(_node, "ArrayTypeName", { + make_pair("baseType", toJson(_node.baseType())), + make_pair("length", toJsonOrNull(_node.length())), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)) + }); + return false; } bool ASTJsonConverter::visit(InlineAssembly const& _node) { - addJsonNode(_node, "InlineAssembly", {}, true); - return true; + Json::Value externalReferences(Json::arrayValue); + for (auto const& it : _node.annotation().externalReferences) + { + if (it.first) + { + Json::Value tuple(Json::objectValue); + tuple[it.first->name] = inlineAssemblyIdentifierToJson(it); + externalReferences.append(tuple); + } + } + setJsonNode(_node, "InlineAssembly", { + make_pair("operations", Json::Value(assembly::AsmPrinter()(_node.operations()))), + make_pair("externalReferences", std::move(externalReferences)) + }); + return false; } bool ASTJsonConverter::visit(Block const& _node) { - addJsonNode(_node, "Block", {}, true); - return true; + setJsonNode(_node, "Block", { + make_pair("statements", toJson(_node.statements())) + }); + return false; } bool ASTJsonConverter::visit(PlaceholderStatement const& _node) { - addJsonNode(_node, "PlaceholderStatement", {}); - return true; + setJsonNode(_node, "PlaceholderStatement", {}); + return false; } bool ASTJsonConverter::visit(IfStatement const& _node) { - addJsonNode(_node, "IfStatement", {}, true); - return true; + setJsonNode(_node, "IfStatement", { + make_pair("condition", toJson(_node.condition())), + make_pair("trueBody", toJson(_node.trueStatement())), + make_pair("falseBody", toJsonOrNull(_node.falseStatement())) + }); + return false; } bool ASTJsonConverter::visit(WhileStatement const& _node) { - addJsonNode( + setJsonNode( _node, _node.isDoWhile() ? "DoWhileStatement" : "WhileStatement", - {}, - true); - return true; + { + make_pair("condition", toJson(_node.condition())), + make_pair("body", toJson(_node.body())) + } + ); + return false; } bool ASTJsonConverter::visit(ForStatement const& _node) { - addJsonNode(_node, "ForStatement", {}, true); - return true; + setJsonNode(_node, "ForStatement", { + make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())), + make_pair("condition", toJsonOrNull(_node.condition())), + make_pair("loopExpression", toJsonOrNull(_node.loopExpression())), + make_pair("body", toJson(_node.body())) + }); + return false; } bool ASTJsonConverter::visit(Continue const& _node) { - addJsonNode(_node, "Continue", {}); - return true; + setJsonNode(_node, "Continue", {}); + return false; } bool ASTJsonConverter::visit(Break const& _node) { - addJsonNode(_node, "Break", {}); - return true; + setJsonNode(_node, "Break", {}); + return false; } bool ASTJsonConverter::visit(Return const& _node) { - addJsonNode(_node, "Return", {}, true);; - return true; + setJsonNode(_node, "Return", { + make_pair("expression", toJsonOrNull(_node.expression())), + make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters)) + }); + return false; } bool ASTJsonConverter::visit(Throw const& _node) { - addJsonNode(_node, "Throw", {}, true);; - return true; + setJsonNode(_node, "Throw", {});; + return false; } bool ASTJsonConverter::visit(VariableDeclarationStatement const& _node) { - addJsonNode(_node, "VariableDeclarationStatement", {}, true); - return true; + Json::Value varDecs(Json::arrayValue); + for (auto const& v: _node.annotation().assignments) + varDecs.append(idOrNull(v)); + setJsonNode(_node, "VariableDeclarationStatement", { + make_pair("assignments", std::move(varDecs)), + make_pair("declarations", toJson(_node.declarations())), + make_pair("initialValue", toJsonOrNull(_node.initialValue())) + }); + return false; } bool ASTJsonConverter::visit(ExpressionStatement const& _node) { - addJsonNode(_node, "ExpressionStatement", {}, true); - return true; + setJsonNode(_node, "ExpressionStatement", { + make_pair("expression", toJson(_node.expression())) + }); + return false; } bool ASTJsonConverter::visit(Conditional const& _node) { - addJsonNode(_node, "Conditional", {}, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("condition", toJson(_node.condition())), + make_pair("trueExpression", toJson(_node.trueExpression())), + make_pair("falseExpression", toJson(_node.falseExpression())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "Conditional", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(Assignment const& _node) { - addJsonNode(_node, "Assignment", - { make_pair("operator", Token::toString(_node.assignmentOperator())), - make_pair("type", type(_node)) }, - true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("operator", Token::toString(_node.assignmentOperator())), + make_pair("leftHandSide", toJson(_node.leftHandSide())), + make_pair("rightHandSide", toJson(_node.rightHandSide())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode( _node, "Assignment", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(TupleExpression const& _node) { - addJsonNode(_node, "TupleExpression",{}, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("isInlineArray", Json::Value(_node.isInlineArray())), + make_pair("components", toJson(_node.components())), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "TupleExpression", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(UnaryOperation const& _node) { - addJsonNode(_node, "UnaryOperation", - { make_pair("prefix", _node.isPrefixOperation()), - make_pair("operator", Token::toString(_node.getOperator())), - make_pair("type", type(_node)) }, - true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("prefix", _node.isPrefixOperation()), + make_pair("operator", Token::toString(_node.getOperator())), + make_pair("subExpression", toJson(_node.subExpression())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "UnaryOperation", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(BinaryOperation const& _node) { - addJsonNode(_node, "BinaryOperation", { + std::vector<pair<string, Json::Value>> attributes = { make_pair("operator", Token::toString(_node.getOperator())), - make_pair("type", type(_node)) - }, true); - return true; + make_pair("leftExpression", toJson(_node.leftExpression())), + make_pair("rightExpression", toJson(_node.rightExpression())), + make_pair("commonType", typePointerToJson(_node.annotation().commonType)), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "BinaryOperation", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(FunctionCall const& _node) { - addJsonNode(_node, "FunctionCall", { - make_pair("type_conversion", _node.annotation().isTypeConversion), - make_pair("type", type(_node)) - }, true); - return true; + Json::Value names(Json::arrayValue); + for (auto const& name: _node.names()) + names.append(Json::Value(*name)); + std::vector<pair<string, Json::Value>> attributes = { + make_pair("expression", toJson(_node.expression())), + make_pair("names", std::move(names)), + make_pair("arguments", toJson(_node.arguments())) + }; + if (m_legacy) + { + attributes.push_back(make_pair("isStructConstructorCall", _node.annotation().kind == FunctionCallKind::StructConstructorCall)); + attributes.push_back(make_pair("type_conversion", _node.annotation().kind == FunctionCallKind::TypeConversion)); + } + else + attributes.push_back(make_pair("kind", functionCallKind(_node.annotation().kind))); + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "FunctionCall", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(NewExpression const& _node) { - addJsonNode(_node, "NewExpression", { make_pair("type", type(_node)) }, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("typeName", toJson(_node.typeName())) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "NewExpression", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(MemberAccess const& _node) { - addJsonNode(_node, "MemberAccess", { - make_pair("member_name", _node.memberName()), - make_pair("type", type(_node)) - }, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair(m_legacy ? "member_name" : "memberName", _node.memberName()), + make_pair("expression", toJson(_node.expression())), + make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "MemberAccess", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(IndexAccess const& _node) { - addJsonNode(_node, "IndexAccess", { make_pair("type", type(_node)) }, true); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair("baseExpression", toJson(_node.baseExpression())), + make_pair("indexExpression", toJsonOrNull(_node.indexExpression())), + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "IndexAccess", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(Identifier const& _node) { - addJsonNode(_node, "Identifier", - { make_pair("value", _node.name()), make_pair("type", type(_node)) }); - return true; + Json::Value overloads(Json::arrayValue); + for (auto const& dec: _node.annotation().overloadedDeclarations) + overloads.append(nodeId(*dec)); + setJsonNode(_node, "Identifier", { + make_pair(m_legacy ? "value" : "name", _node.name()), + make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)), + make_pair("overloadedDeclarations", overloads), + make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)), + make_pair("argumentTypes", typePointerToJson(_node.annotation().argumentTypes)) + }); + return false; } bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node) { - addJsonNode(_node, "ElementaryTypeNameExpression", { - make_pair("value", _node.typeName().toString()), - make_pair("type", type(_node)) - }); - return true; + std::vector<pair<string, Json::Value>> attributes = { + make_pair(m_legacy ? "value" : "typeName", _node.typeName().toString()) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes)); + return false; } bool ASTJsonConverter::visit(Literal const& _node) @@ -441,240 +709,26 @@ bool ASTJsonConverter::visit(Literal const& _node) if (!dev::validateUTF8(_node.value())) value = Json::nullValue; Token::Value subdenomination = Token::Value(_node.subDenomination()); - addJsonNode(_node, "Literal", { + std::vector<pair<string, Json::Value>> attributes = { make_pair("token", tokenString ? tokenString : Json::Value()), make_pair("value", value), - make_pair("hexvalue", toHex(_node.value())), + make_pair(m_legacy ? "hexvalue" : "hexValue", toHex(_node.value())), make_pair( "subdenomination", subdenomination == Token::Illegal ? Json::nullValue : Json::Value{Token::toString(subdenomination)} - ), - make_pair("type", type(_node)) - }); - return true; -} - -void ASTJsonConverter::endVisit(SourceUnit const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(PragmaDirective const&) -{ -} - -void ASTJsonConverter::endVisit(ImportDirective const&) -{ -} - -void ASTJsonConverter::endVisit(ContractDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(InheritanceSpecifier const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(UsingForDirective const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(StructDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(EnumDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(EnumValue const&) -{ -} - -void ASTJsonConverter::endVisit(ParameterList const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(FunctionDefinition const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(VariableDeclaration const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ModifierDefinition const&) -{ - goUp(); + ) + }; + appendExpressionAttributes(attributes, _node.annotation()); + setJsonNode(_node, "Literal", std::move(attributes)); + return false; } -void ASTJsonConverter::endVisit(ModifierInvocation const&) -{ - goUp(); -} void ASTJsonConverter::endVisit(EventDefinition const&) { m_inEvent = false; - goUp(); -} - -void ASTJsonConverter::endVisit(TypeName const&) -{ -} - -void ASTJsonConverter::endVisit(ElementaryTypeName const&) -{ -} - -void ASTJsonConverter::endVisit(UserDefinedTypeName const&) -{ -} - -void ASTJsonConverter::endVisit(FunctionTypeName const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Mapping const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ArrayTypeName const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(InlineAssembly const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Block const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(PlaceholderStatement const&) -{ -} - -void ASTJsonConverter::endVisit(IfStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(WhileStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ForStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Continue const&) -{ -} - -void ASTJsonConverter::endVisit(Break const&) -{ -} - -void ASTJsonConverter::endVisit(Return const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Throw const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(VariableDeclarationStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(ExpressionStatement const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Conditional const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Assignment const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(TupleExpression const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(UnaryOperation const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(BinaryOperation const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(FunctionCall const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(NewExpression const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(MemberAccess const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(IndexAccess const&) -{ - goUp(); -} - -void ASTJsonConverter::endVisit(Identifier const&) -{ -} - -void ASTJsonConverter::endVisit(ElementaryTypeNameExpression const&) -{ -} - -void ASTJsonConverter::endVisit(Literal const&) -{ -} - -void ASTJsonConverter::process() -{ - if (!processed) - m_ast->accept(*this); - processed = true; } string ASTJsonConverter::visibility(Declaration::Visibility const& _visibility) @@ -709,6 +763,36 @@ string ASTJsonConverter::location(VariableDeclaration::Location _location) } } +string ASTJsonConverter::contractKind(ContractDefinition::ContractKind _kind) +{ + switch (_kind) + { + case ContractDefinition::ContractKind::Interface: + return "interface"; + case ContractDefinition::ContractKind::Contract: + return "contract"; + case ContractDefinition::ContractKind::Library: + return "library"; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of contract.")); + } +} + +string ASTJsonConverter::functionCallKind(FunctionCallKind _kind) +{ + switch (_kind) + { + case FunctionCallKind::FunctionCall: + return "functionCall"; + case FunctionCallKind::TypeConversion: + return "typeConversion"; + case FunctionCallKind::StructConstructorCall: + return "structConstructorCall"; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of function call .")); + } +} + string ASTJsonConverter::type(Expression const& _expression) { return _expression.annotation().type ? _expression.annotation().type->toString() : "Unknown"; diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index bd5e6560..5ee40536 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -42,15 +42,23 @@ class ASTJsonConverter: public ASTConstVisitor { public: /// Create a converter to JSON for the given abstract syntax tree. + /// @a _legacy if true, use legacy format /// @a _sourceIndices is used to abbreviate source names in source locations. explicit ASTJsonConverter( - ASTNode const& _ast, + bool _legacy, std::map<std::string, unsigned> _sourceIndices = std::map<std::string, unsigned>() ); /// Output the json representation of the AST to _stream. - void print(std::ostream& _stream); - Json::Value const& json(); - + void print(std::ostream& _stream, ASTNode const& _node); + Json::Value toJson(ASTNode const& _node); + template <class T> + Json::Value toJson(std::vector<ASTPointer<T>> const& _nodes) + { + Json::Value ret(Json::arrayValue); + for (auto const& n: _nodes) + ret.append(n ? toJson(*n) : Json::nullValue); + return ret; + } bool visit(SourceUnit const& _node) override; bool visit(PragmaDirective const& _node) override; bool visit(ImportDirective const& _node) override; @@ -97,82 +105,60 @@ public: bool visit(ElementaryTypeNameExpression const& _node) override; bool visit(Literal const& _node) override; - void endVisit(SourceUnit const&) override; - void endVisit(PragmaDirective const&) override; - void endVisit(ImportDirective const&) override; - void endVisit(ContractDefinition const&) override; - void endVisit(InheritanceSpecifier const&) override; - void endVisit(UsingForDirective const&) override; - void endVisit(StructDefinition const&) override; - void endVisit(EnumDefinition const&) override; - void endVisit(EnumValue const&) override; - void endVisit(ParameterList const&) override; - void endVisit(FunctionDefinition const&) override; - void endVisit(VariableDeclaration const&) override; - void endVisit(ModifierDefinition const&) override; - void endVisit(ModifierInvocation const&) override; void endVisit(EventDefinition const&) override; - void endVisit(TypeName const&) override; - void endVisit(ElementaryTypeName const&) override; - void endVisit(UserDefinedTypeName const&) override; - void endVisit(FunctionTypeName const&) override; - void endVisit(Mapping const&) override; - void endVisit(ArrayTypeName const&) override; - void endVisit(InlineAssembly const&) override; - void endVisit(Block const&) override; - void endVisit(PlaceholderStatement const&) override; - void endVisit(IfStatement const&) override; - void endVisit(WhileStatement const&) override; - void endVisit(ForStatement const&) override; - void endVisit(Continue const&) override; - void endVisit(Break const&) override; - void endVisit(Return const&) override; - void endVisit(Throw const&) override; - void endVisit(VariableDeclarationStatement const&) override; - void endVisit(ExpressionStatement const&) override; - void endVisit(Conditional const&) override; - void endVisit(Assignment const&) override; - void endVisit(TupleExpression const&) override; - void endVisit(UnaryOperation const&) override; - void endVisit(BinaryOperation const&) override; - void endVisit(FunctionCall const&) override; - void endVisit(NewExpression const&) override; - void endVisit(MemberAccess const&) override; - void endVisit(IndexAccess const&) override; - void endVisit(Identifier const&) override; - void endVisit(ElementaryTypeNameExpression const&) override; - void endVisit(Literal const&) override; private: - void process(); - void addJsonNode( + void setJsonNode( ASTNode const& _node, std::string const& _nodeName, - std::initializer_list<std::pair<std::string const, Json::Value const>> _attributes, - bool _hasChildren + std::initializer_list<std::pair<std::string, Json::Value>>&& _attributes ); - void addJsonNode( + void setJsonNode( ASTNode const& _node, std::string const& _nodeName, - std::vector<std::pair<std::string const, Json::Value const>> const& _attributes, - bool _hasChildren + std::vector<std::pair<std::string, Json::Value>>&& _attributes ); std::string sourceLocationToString(SourceLocation const& _location) const; + std::string namePathToString(std::vector<ASTString> const& _namePath) const; + Json::Value idOrNull(ASTNode const* _pt) + { + return _pt ? Json::Value(nodeId(*_pt)) : Json::nullValue; + } + Json::Value toJsonOrNull(ASTNode const* _node) + { + return _node ? toJson(*_node) : Json::nullValue; + } + Json::Value inlineAssemblyIdentifierToJson(std::pair<assembly::Identifier const* , InlineAssemblyAnnotation::ExternalIdentifierInfo> _info); std::string visibility(Declaration::Visibility const& _visibility); std::string location(VariableDeclaration::Location _location); + std::string contractKind(ContractDefinition::ContractKind _kind); + std::string functionCallKind(FunctionCallKind _kind); std::string type(Expression const& _expression); std::string type(VariableDeclaration const& _varDecl); - inline void goUp() + int nodeId(ASTNode const& _node) { - solAssert(!m_jsonNodePtrs.empty(), "Uneven json nodes stack. Internal error."); - m_jsonNodePtrs.pop(); + return _node.id(); } - + template<class Container> + Json::Value getContainerIds(Container const& container) + { + Json::Value tmp(Json::arrayValue); + for (auto const& element: container) + { + solAssert(element, ""); + tmp.append(nodeId(*element)); + } + return tmp; + } + Json::Value typePointerToJson(TypePointer _tp); + Json::Value typePointerToJson(std::shared_ptr<std::vector<TypePointer>> _tps); + void appendExpressionAttributes( + std::vector<std::pair<std::string, Json::Value>> &_attributes, + ExpressionAnnotation const& _annotation + ); + bool m_legacy = false; ///< if true, use legacy format bool m_inEvent = false; ///< whether we are currently inside an event or not - bool processed = false; - Json::Value m_astJson; - std::stack<Json::Value*> m_jsonNodePtrs; - ASTNode const* m_ast; + Json::Value m_currentValue; std::map<std::string, unsigned> m_sourceIndices; }; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 41ee6498..cfee041e 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2183,6 +2183,8 @@ string FunctionType::identifier() const case Kind::ArrayPush: id += "arraypush"; break; case Kind::ByteArrayPush: id += "bytearraypush"; break; case Kind::ObjectCreation: id += "objectcreation"; break; + case Kind::Assert: id += "assert"; break; + case Kind::Require: id += "require";break; default: solAssert(false, "Unknown function location."); break; } if (isConstant()) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index f018b311..0aa82ea8 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -434,7 +434,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { CompilerContext::LocationSetter locationSetter(m_context, _functionCall); - if (_functionCall.annotation().isTypeConversion) + if (_functionCall.annotation().kind == FunctionCallKind::TypeConversion) { solAssert(_functionCall.arguments().size() == 1, ""); solAssert(_functionCall.names().empty(), ""); @@ -445,7 +445,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } FunctionTypePointer functionType; - if (_functionCall.annotation().isStructConstructorCall) + if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall) { auto const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type); auto const& structType = dynamic_cast<StructType const&>(*type.actualType()); @@ -476,7 +476,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) solAssert(found, ""); } - if (_functionCall.annotation().isStructConstructorCall) + if (_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall) { TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type); auto const& structType = dynamic_cast<StructType const&>(*type.actualType()); diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp index b6f17907..77d3c217 100644 --- a/libsolidity/formal/Why3Translator.cpp +++ b/libsolidity/formal/Why3Translator.cpp @@ -582,7 +582,7 @@ bool Why3Translator::visit(BinaryOperation const& _binaryOperation) bool Why3Translator::visit(FunctionCall const& _node) { - if (_node.annotation().isTypeConversion || _node.annotation().isStructConstructorCall) + if (_node.annotation().kind == FunctionCallKind::TypeConversion || _node.annotation().kind == FunctionCallKind::StructConstructorCall) { error(_node, "Only ordinary function calls supported."); return true; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 503be57b..d5dbaa46 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -377,7 +377,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) { Json::Value sourceResult = Json::objectValue; sourceResult["id"] = sourceIndex++; - sourceResult["legacyAST"] = ASTJsonConverter(m_compilerStack.ast(source), m_compilerStack.sourceIndices()).json(); + sourceResult["ast"] = ASTJsonConverter(false, m_compilerStack.sourceIndices()).toJson(m_compilerStack.ast(source)); + sourceResult["legacyAST"] = ASTJsonConverter(true, m_compilerStack.sourceIndices()).toJson(m_compilerStack.ast(source)); output["sources"][source] = sourceResult; } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index d5a60b50..e55e3e7e 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -838,9 +838,9 @@ void CommandLineInterface::handleCombinedJSON() output[g_strSources] = Json::Value(Json::objectValue); for (auto const& sourceCode: m_sourceCodes) { - ASTJsonConverter converter(m_compiler->ast(sourceCode.first), m_compiler->sourceIndices()); + ASTJsonConverter converter(true, m_compiler->sourceIndices()); output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue); - output[g_strSources][sourceCode.first]["AST"] = converter.json(); + output[g_strSources][sourceCode.first]["AST"] = converter.toJson(m_compiler->ast(sourceCode.first)); } } cout << dev::jsonCompactPrint(output) << endl; @@ -883,8 +883,7 @@ void CommandLineInterface::handleAst(string const& _argStr) } else { - ASTJsonConverter converter(m_compiler->ast(sourceCode.first)); - converter.print(data); + ASTJsonConverter(true).print(data, m_compiler->ast(sourceCode.first)); postfix += "_json"; } boost::filesystem::path path(sourceCode.first); @@ -908,8 +907,7 @@ void CommandLineInterface::handleAst(string const& _argStr) } else { - ASTJsonConverter converter(m_compiler->ast(sourceCode.first)); - converter.print(cout); + ASTJsonConverter(true).print(cout, m_compiler->ast(sourceCode.first)); } } } diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 92a102b6..7f99324e 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -245,7 +245,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback output["sourceList"].append(source); output["sources"] = Json::Value(Json::objectValue); for (auto const& source: compiler.sourceNames()) - output["sources"][source]["AST"] = ASTJsonConverter(compiler.ast(source), compiler.sourceIndices()).json(); + output["sources"][source]["AST"] = ASTJsonConverter(true, compiler.sourceIndices()).toJson(compiler.ast(source)); } catch (...) { diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp index d23815b4..8a790347 100644 --- a/test/libsolidity/ASTJSON.cpp +++ b/test/libsolidity/ASTJSON.cpp @@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); } @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(source_location) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition"); BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition"); @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(inheritance_specifier) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2"); BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier"); BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1"); @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(using_for_directive) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value usingFor = astJson["children"][1]["children"][0]; BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective"); BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1"); @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(enum_value) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value enumDefinition = astJson["children"][0]["children"][0]; BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue"); BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A"); @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(modifier_definition) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value modifier = astJson["children"][0]["children"][0]; BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition"); BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M"); @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(modifier_invocation) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value modifier = astJson["children"][0]["children"][1]["children"][2]; BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation"); BOOST_CHECK_EQUAL(modifier["src"], "52:4:1"); @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(event_definition) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value event = astJson["children"][0]["children"][0]; BOOST_CHECK_EQUAL(event["name"], "EventDefinition"); BOOST_CHECK_EQUAL(event["attributes"]["name"], "E"); @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(array_type_name) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value array = astJson["children"][0]["children"][0]["children"][0]; BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName"); BOOST_CHECK_EQUAL(array["src"], "13:6:1"); @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(placeholder_statement) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0]; BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement"); BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1"); @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(non_utf8) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1]; BOOST_CHECK_EQUAL(literal["name"], "Literal"); BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff"); @@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(function_type) c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json(); + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); Json::Value fun = astJson["children"][0]["children"][0]; BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition"); Json::Value argument = fun["children"][0]["children"][0]; diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp index 46c718d7..6aec59ab 100644 --- a/test/libsolidity/JSONCompiler.cpp +++ b/test/libsolidity/JSONCompiler.cpp @@ -90,10 +90,12 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(result["sources"]["fileA"].isObject()); BOOST_CHECK(result["sources"]["fileA"]["AST"].isObject()); BOOST_CHECK(dev::jsonCompactPrint(result["sources"]["fileA"]["AST"]) == - "{\"children\":[{\"attributes\":{\"fullyImplemented\":true,\"isLibrary\":false,\"linearizedBaseContracts\":[1]," - "\"name\":\"A\"},\"children\":[],\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"name\":\"SourceUnit\"}"); + "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}}," + "\"children\":[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null]," + "\"contractKind\":\"contract\",\"fullyImplemented\":true,\"linearizedBaseContracts\":[1]," + "\"name\":\"A\",\"nodes\":[null],\"scope\":2},\"id\":1,\"name\":\"ContractDefinition\"," + "\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}"); } - BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index ec2f69d9..050ca500 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -215,8 +215,10 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(result["sources"]["fileA"].isObject()); BOOST_CHECK(result["sources"]["fileA"]["legacyAST"].isObject()); BOOST_CHECK(dev::jsonCompactPrint(result["sources"]["fileA"]["legacyAST"]) == - "{\"children\":[{\"attributes\":{\"fullyImplemented\":true,\"isLibrary\":false,\"linearizedBaseContracts\":[1]," - "\"name\":\"A\"},\"children\":[],\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"name\":\"SourceUnit\"}"); + "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}},\"children\":" + "[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null],\"contractKind\":\"contract\"," + "\"fullyImplemented\":true,\"linearizedBaseContracts\":[1],\"name\":\"A\",\"nodes\":[null],\"scope\":2}," + "\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}"); } BOOST_AUTO_TEST_SUITE_END() |