aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/TypeChecker.cpp16
-rw-r--r--libsolidity/ast/AST.h9
-rw-r--r--libsolidity/ast/ASTAnnotations.h13
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp860
-rw-r--r--libsolidity/ast/ASTJsonConverter.h112
-rw-r--r--libsolidity/ast/Types.cpp2
-rw-r--r--libsolidity/codegen/CompilerContext.cpp16
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp36
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp6
-rw-r--r--libsolidity/formal/Why3Translator.cpp2
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp139
-rw-r--r--libsolidity/inlineasm/AsmScope.h4
-rw-r--r--libsolidity/inlineasm/AsmStack.h4
-rw-r--r--libsolidity/interface/StandardCompiler.cpp3
14 files changed, 677 insertions, 545 deletions
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/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 51dd9fd2..5c4f88c4 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -264,7 +264,7 @@ void CompilerContext::appendInlineAssembly(
assembly = &replacedAssembly;
}
- unsigned startStackHeight = stackHeight();
+ int startStackHeight = stackHeight();
assembly::ExternalIdentifierAccess identifierAccess;
identifierAccess.resolve = [&](
@@ -278,26 +278,26 @@ void CompilerContext::appendInlineAssembly(
identifierAccess.generateCode = [&](
assembly::Identifier const& _identifier,
assembly::IdentifierContext _context,
- eth::Assembly& _assembly
+ julia::AbstractAssembly& _assembly
)
{
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
solAssert(it != _localVariables.end(), "");
- unsigned stackDepth = _localVariables.end() - it;
- int stackDiff = _assembly.deposit() - startStackHeight + stackDepth;
+ int stackDepth = _localVariables.end() - it;
+ int stackDiff = _assembly.stackHeight() - startStackHeight + stackDepth;
if (_context == assembly::IdentifierContext::LValue)
stackDiff -= 1;
if (stackDiff < 1 || stackDiff > 16)
BOOST_THROW_EXCEPTION(
CompilerError() <<
- errinfo_comment("Stack too deep, try removing local variables.")
+ errinfo_comment("Stack too deep (" + to_string(stackDiff) + "), try removing local variables.")
);
if (_context == assembly::IdentifierContext::RValue)
- _assembly.append(dupInstruction(stackDiff));
+ _assembly.appendInstruction(dupInstruction(stackDiff));
else
{
- _assembly.append(swapInstruction(stackDiff));
- _assembly.append(Instruction::POP);
+ _assembly.appendInstruction(swapInstruction(stackDiff));
+ _assembly.appendInstruction(Instruction::POP);
}
};
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 34ef13c0..41940e1a 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -530,7 +530,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
return size_t(-1);
return ref->second.valueSize;
};
- identifierAccess.generateCode = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext _context, eth::Assembly& _assembly)
+ identifierAccess.generateCode = [&](assembly::Identifier const& _identifier, assembly::IdentifierContext _context, julia::AbstractAssembly& _assembly)
{
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), "");
@@ -538,21 +538,25 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
solAssert(!!decl, "");
if (_context == assembly::IdentifierContext::RValue)
{
- int const depositBefore = _assembly.deposit();
+ int const depositBefore = _assembly.stackHeight();
solAssert(!!decl->type(), "Type of declaration required but not yet determined.");
if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(decl))
{
solAssert(!ref->second.isOffset && !ref->second.isSlot, "");
functionDef = &m_context.resolveVirtualFunction(*functionDef);
- _assembly.append(m_context.functionEntryLabel(*functionDef).pushTag());
+ auto functionEntryLabel = m_context.functionEntryLabel(*functionDef).pushTag();
+ solAssert(functionEntryLabel.data() <= std::numeric_limits<size_t>::max(), "");
+ _assembly.appendLabelReference(size_t(functionEntryLabel.data()));
// If there is a runtime context, we have to merge both labels into the same
// stack slot in case we store it in storage.
if (CompilerContext* rtc = m_context.runtimeContext())
{
- _assembly.append(u256(1) << 32);
- _assembly.append(Instruction::MUL);
- _assembly.append(rtc->functionEntryLabel(*functionDef).toSubAssemblyTag(m_context.runtimeSub()));
- _assembly.append(Instruction::OR);
+ _assembly.appendConstant(u256(1) << 32);
+ _assembly.appendInstruction(Instruction::MUL);
+ auto runtimeEntryLabel = rtc->functionEntryLabel(*functionDef).toSubAssemblyTag(m_context.runtimeSub());
+ solAssert(runtimeEntryLabel.data() <= std::numeric_limits<size_t>::max(), "");
+ _assembly.appendLabelReference(size_t(runtimeEntryLabel.data()));
+ _assembly.appendInstruction(Instruction::OR);
}
}
else if (auto variable = dynamic_cast<VariableDeclaration const*>(decl))
@@ -570,7 +574,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
}
else if (m_context.isLocalVariable(decl))
{
- int stackDiff = _assembly.deposit() - m_context.baseStackOffsetOfVariable(*variable);
+ int stackDiff = _assembly.stackHeight() - m_context.baseStackOffsetOfVariable(*variable);
if (ref->second.isSlot || ref->second.isOffset)
{
solAssert(variable->type()->dataStoredIn(DataLocation::Storage), "");
@@ -587,7 +591,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
// only slot, offset is zero
if (ref->second.isOffset)
{
- _assembly.append(u256(0));
+ _assembly.appendConstant(u256(0));
return;
}
}
@@ -601,7 +605,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
errinfo_comment("Stack too deep, try removing local variables.")
);
solAssert(variable->type()->sizeOnStack() == 1, "");
- _assembly.append(dupInstruction(stackDiff));
+ _assembly.appendInstruction(dupInstruction(stackDiff));
}
else
solAssert(false, "");
@@ -610,11 +614,11 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{
solAssert(!ref->second.isOffset && !ref->second.isSlot, "");
solAssert(contract->isLibrary(), "");
- _assembly.appendLibraryAddress(contract->fullyQualifiedName());
+ _assembly.appendLinkerSymbol(contract->fullyQualifiedName());
}
else
solAssert(false, "Invalid declaration type.");
- solAssert(_assembly.deposit() - depositBefore == int(ref->second.valueSize), "");
+ solAssert(_assembly.stackHeight() - depositBefore == int(ref->second.valueSize), "");
}
else
{
@@ -626,15 +630,15 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
"Can only assign to stack variables in inline assembly."
);
solAssert(variable->type()->sizeOnStack() == 1, "");
- int stackDiff = _assembly.deposit() - m_context.baseStackOffsetOfVariable(*variable) - 1;
+ int stackDiff = _assembly.stackHeight() - m_context.baseStackOffsetOfVariable(*variable) - 1;
if (stackDiff > 16 || stackDiff < 1)
BOOST_THROW_EXCEPTION(
CompilerError() <<
errinfo_sourceLocation(_inlineAssembly.location()) <<
- errinfo_comment("Stack too deep, try removing local variables.")
+ errinfo_comment("Stack too deep(" + to_string(stackDiff) + "), try removing local variables.")
);
- _assembly.append(swapInstruction(stackDiff));
- _assembly.append(Instruction::POP);
+ _assembly.appendInstruction(swapInstruction(stackDiff));
+ _assembly.appendInstruction(Instruction::POP);
}
};
solAssert(_inlineAssembly.annotation().analysisInfo, "");
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/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index 44e12b3e..b8af9dc6 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -32,6 +32,8 @@
#include <libevmasm/SourceLocation.h>
#include <libevmasm/Instruction.h>
+#include <libjulia/backends/AbstractAssembly.h>
+
#include <libdevcore/CommonIO.h>
#include <boost/range/adaptor/reversed.hpp>
@@ -48,14 +50,53 @@ using namespace dev::solidity::assembly;
struct GeneratorState
{
- GeneratorState(ErrorList& _errors, AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly):
- errors(_errors), info(_analysisInfo), assembly(_assembly) {}
+ GeneratorState(ErrorList& _errors, AsmAnalysisInfo& _analysisInfo):
+ errors(_errors), info(_analysisInfo) {}
+
+ ErrorList& errors;
+ AsmAnalysisInfo info;
+};
- size_t newLabelId()
+class EthAssemblyAdapter: public julia::AbstractAssembly
+{
+public:
+ EthAssemblyAdapter(eth::Assembly& _assembly):
+ m_assembly(_assembly)
+ {
+ }
+ virtual void setSourceLocation(SourceLocation const& _location) override
+ {
+ m_assembly.setSourceLocation(_location);
+ }
+ virtual int stackHeight() const override { return m_assembly.deposit(); }
+ virtual void appendInstruction(solidity::Instruction _instruction) override
+ {
+ m_assembly.append(_instruction);
+ }
+ virtual void appendConstant(u256 const& _constant) override
+ {
+ m_assembly.append(_constant);
+ }
+ /// Append a label.
+ virtual void appendLabel(size_t _labelId) override
+ {
+ m_assembly.append(eth::AssemblyItem(eth::Tag, _labelId));
+ }
+ /// Append a label reference.
+ virtual void appendLabelReference(size_t _labelId) override
+ {
+ m_assembly.append(eth::AssemblyItem(eth::PushTag, _labelId));
+ }
+ virtual size_t newLabelId() override
+ {
+ return assemblyTagToIdentifier(m_assembly.newTag());
+ }
+ virtual void appendLinkerSymbol(std::string const& _linkerSymbol) override
{
- return assemblyTagToIdentifier(assembly.newTag());
+ m_assembly.appendLibraryAddress(_linkerSymbol);
}
+private:
size_t assemblyTagToIdentifier(eth::AssemblyItem const& _tag) const
{
u256 id = _tag.data();
@@ -63,9 +104,7 @@ struct GeneratorState
return size_t(id);
}
- ErrorList& errors;
- AsmAnalysisInfo info;
- eth::Assembly& assembly;
+ eth::Assembly& m_assembly;
};
class CodeTransform: public boost::static_visitor<>
@@ -76,81 +115,84 @@ public:
/// @param _identifierAccess used to resolve identifiers external to the inline assembly
explicit CodeTransform(
GeneratorState& _state,
+ julia::AbstractAssembly& _assembly,
assembly::Block const& _block,
assembly::ExternalIdentifierAccess const& _identifierAccess = assembly::ExternalIdentifierAccess()
- ): CodeTransform(_state, _block, _identifierAccess, _state.assembly.deposit())
+ ): CodeTransform(_state, _assembly, _block, _identifierAccess, _assembly.stackHeight())
{
}
private:
CodeTransform(
GeneratorState& _state,
+ julia::AbstractAssembly& _assembly,
assembly::Block const& _block,
assembly::ExternalIdentifierAccess const& _identifierAccess,
- int _initialDeposit
+ int _initialStackHeight
):
m_state(_state),
+ m_assembly(_assembly),
m_scope(*m_state.info.scopes.at(&_block)),
m_identifierAccess(_identifierAccess),
- m_initialDeposit(_initialDeposit)
+ m_initialStackHeight(_initialStackHeight)
{
- int blockStartDeposit = m_state.assembly.deposit();
+ int blockStartStackHeight = m_assembly.stackHeight();
std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this));
- m_state.assembly.setSourceLocation(_block.location);
+ m_assembly.setSourceLocation(_block.location);
// pop variables
for (auto const& identifier: m_scope.identifiers)
if (identifier.second.type() == typeid(Scope::Variable))
- m_state.assembly.append(solidity::Instruction::POP);
+ m_assembly.appendInstruction(solidity::Instruction::POP);
- int deposit = m_state.assembly.deposit() - blockStartDeposit;
+ int deposit = m_assembly.stackHeight() - blockStartStackHeight;
solAssert(deposit == 0, "Invalid stack height at end of block.");
}
public:
void operator()(assembly::Instruction const& _instruction)
{
- m_state.assembly.setSourceLocation(_instruction.location);
- m_state.assembly.append(_instruction.instruction);
+ m_assembly.setSourceLocation(_instruction.location);
+ m_assembly.appendInstruction(_instruction.instruction);
checkStackHeight(&_instruction);
}
void operator()(assembly::Literal const& _literal)
{
- m_state.assembly.setSourceLocation(_literal.location);
+ m_assembly.setSourceLocation(_literal.location);
if (_literal.kind == assembly::LiteralKind::Number)
- m_state.assembly.append(u256(_literal.value));
+ m_assembly.appendConstant(u256(_literal.value));
else if (_literal.kind == assembly::LiteralKind::Boolean)
{
if (_literal.value == "true")
- m_state.assembly.append(u256(1));
+ m_assembly.appendConstant(u256(1));
else
- m_state.assembly.append(u256(0));
+ m_assembly.appendConstant(u256(0));
}
else
{
solAssert(_literal.value.size() <= 32, "");
- m_state.assembly.append(u256(h256(_literal.value, h256::FromBinary, h256::AlignLeft)));
+ m_assembly.appendConstant(u256(h256(_literal.value, h256::FromBinary, h256::AlignLeft)));
}
checkStackHeight(&_literal);
}
void operator()(assembly::Identifier const& _identifier)
{
- m_state.assembly.setSourceLocation(_identifier.location);
+ m_assembly.setSourceLocation(_identifier.location);
// First search internals, then externals.
if (m_scope.lookup(_identifier.name, Scope::NonconstVisitor(
[=](Scope::Variable& _var)
{
if (int heightDiff = variableHeightDiff(_var, _identifier.location, false))
- m_state.assembly.append(solidity::dupInstruction(heightDiff));
+ m_assembly.appendInstruction(solidity::dupInstruction(heightDiff));
else
// Store something to balance the stack
- m_state.assembly.append(u256(0));
+ m_assembly.appendConstant(u256(0));
},
[=](Scope::Label& _label)
{
assignLabelIdIfUnset(_label);
- m_state.assembly.append(eth::AssemblyItem(eth::PushTag, _label.id));
+ m_assembly.appendLabelReference(*_label.id);
},
[=](Scope::Function&)
{
@@ -164,14 +206,14 @@ public:
m_identifierAccess.generateCode,
"Identifier not found and no external access available."
);
- m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_state.assembly);
+ m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_assembly);
checkStackHeight(&_identifier);
}
void operator()(FunctionalInstruction const& _instr)
{
for (auto it = _instr.arguments.rbegin(); it != _instr.arguments.rend(); ++it)
{
- int height = m_state.assembly.deposit();
+ int height = m_assembly.stackHeight();
boost::apply_visitor(*this, *it);
expectDeposit(1, height);
}
@@ -184,31 +226,31 @@ public:
}
void operator()(Label const& _label)
{
- m_state.assembly.setSourceLocation(_label.location);
+ m_assembly.setSourceLocation(_label.location);
solAssert(m_scope.identifiers.count(_label.name), "");
Scope::Label& label = boost::get<Scope::Label>(m_scope.identifiers.at(_label.name));
assignLabelIdIfUnset(label);
- m_state.assembly.append(eth::AssemblyItem(eth::Tag, label.id));
+ m_assembly.appendLabel(*label.id);
checkStackHeight(&_label);
}
void operator()(assembly::Assignment const& _assignment)
{
- m_state.assembly.setSourceLocation(_assignment.location);
+ m_assembly.setSourceLocation(_assignment.location);
generateAssignment(_assignment.variableName, _assignment.location);
checkStackHeight(&_assignment);
}
void operator()(FunctionalAssignment const& _assignment)
{
- int height = m_state.assembly.deposit();
+ int height = m_assembly.stackHeight();
boost::apply_visitor(*this, *_assignment.value);
expectDeposit(1, height);
- m_state.assembly.setSourceLocation(_assignment.location);
+ m_assembly.setSourceLocation(_assignment.location);
generateAssignment(_assignment.variableName, _assignment.location);
checkStackHeight(&_assignment);
}
void operator()(assembly::VariableDeclaration const& _varDecl)
{
- int height = m_state.assembly.deposit();
+ int height = m_assembly.stackHeight();
boost::apply_visitor(*this, *_varDecl.value);
expectDeposit(1, height);
auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(_varDecl.variable.name));
@@ -217,7 +259,7 @@ public:
}
void operator()(assembly::Block const& _block)
{
- CodeTransform(m_state, _block, m_identifierAccess, m_initialDeposit);
+ CodeTransform(m_state, m_assembly, _block, m_identifierAccess, m_initialStackHeight);
checkStackHeight(&_block);
}
void operator()(assembly::FunctionDefinition const&)
@@ -233,8 +275,8 @@ private:
{
Scope::Variable const& _var = boost::get<Scope::Variable>(*var);
if (int heightDiff = variableHeightDiff(_var, _location, true))
- m_state.assembly.append(solidity::swapInstruction(heightDiff - 1));
- m_state.assembly.append(solidity::Instruction::POP);
+ m_assembly.appendInstruction(solidity::swapInstruction(heightDiff - 1));
+ m_assembly.appendInstruction(solidity::Instruction::POP);
}
else
{
@@ -242,7 +284,7 @@ private:
m_identifierAccess.generateCode,
"Identifier not found and no external access available."
);
- m_identifierAccess.generateCode(_variableName, IdentifierContext::LValue, m_state.assembly);
+ m_identifierAccess.generateCode(_variableName, IdentifierContext::LValue, m_assembly);
}
}
@@ -251,7 +293,7 @@ private:
/// errors and the (positive) stack height difference otherwise.
int variableHeightDiff(Scope::Variable const& _var, SourceLocation const& _location, bool _forSwap)
{
- int heightDiff = m_state.assembly.deposit() - _var.stackHeight;
+ int heightDiff = m_assembly.stackHeight() - _var.stackHeight;
if (heightDiff <= (_forSwap ? 1 : 0) || heightDiff > (_forSwap ? 17 : 16))
{
//@TODO move this to analysis phase.
@@ -268,14 +310,14 @@ private:
void expectDeposit(int _deposit, int _oldHeight)
{
- solAssert(m_state.assembly.deposit() == _oldHeight + _deposit, "Invalid stack deposit.");
+ solAssert(m_assembly.stackHeight() == _oldHeight + _deposit, "Invalid stack deposit.");
}
void checkStackHeight(void const* _astElement)
{
solAssert(m_state.info.stackHeightInfo.count(_astElement), "Stack height for AST element not found.");
solAssert(
- m_state.info.stackHeightInfo.at(_astElement) == m_state.assembly.deposit() - m_initialDeposit,
+ m_state.info.stackHeightInfo.at(_astElement) == m_assembly.stackHeight() - m_initialStackHeight,
"Stack height mismatch between analysis and code generation phase."
);
}
@@ -283,15 +325,16 @@ private:
/// Assigns the label's id to a value taken from eth::Assembly if it has not yet been set.
void assignLabelIdIfUnset(Scope::Label& _label)
{
- if (_label.id == Scope::Label::unassignedLabelId)
- _label.id = m_state.newLabelId();
+ if (!_label.id)
+ _label.id.reset(m_assembly.newLabelId());
}
GeneratorState& m_state;
+ julia::AbstractAssembly& m_assembly;
Scope& m_scope;
ExternalIdentifierAccess m_identifierAccess;
- int const m_initialDeposit;
+ int const m_initialStackHeight;
};
eth::Assembly assembly::CodeGenerator::assemble(
@@ -301,8 +344,9 @@ eth::Assembly assembly::CodeGenerator::assemble(
)
{
eth::Assembly assembly;
- GeneratorState state(m_errors, _analysisInfo, assembly);
- CodeTransform(state, _parsedData, _identifierAccess);
+ GeneratorState state(m_errors, _analysisInfo);
+ EthAssemblyAdapter assemblyAdapter(assembly);
+ CodeTransform(state, assemblyAdapter, _parsedData, _identifierAccess);
return assembly;
}
@@ -313,6 +357,7 @@ void assembly::CodeGenerator::assemble(
ExternalIdentifierAccess const& _identifierAccess
)
{
- GeneratorState state(m_errors, _analysisInfo, _assembly);
- CodeTransform(state, _parsedData, _identifierAccess);
+ GeneratorState state(m_errors, _analysisInfo);
+ EthAssemblyAdapter assemblyAdapter(_assembly);
+ CodeTransform(state, assemblyAdapter, _parsedData, _identifierAccess);
}
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index dd45613d..70786dce 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -23,6 +23,7 @@
#include <libsolidity/interface/Exceptions.h>
#include <boost/variant.hpp>
+#include <boost/optional.hpp>
#include <functional>
#include <memory>
@@ -75,8 +76,7 @@ struct Scope
struct Label
{
- size_t id = unassignedLabelId;
- static const size_t unassignedLabelId = 0;
+ boost::optional<size_t> id;
};
struct Function
diff --git a/libsolidity/inlineasm/AsmStack.h b/libsolidity/inlineasm/AsmStack.h
index 77a7e02a..e223ccc9 100644
--- a/libsolidity/inlineasm/AsmStack.h
+++ b/libsolidity/inlineasm/AsmStack.h
@@ -24,6 +24,8 @@
#include <libsolidity/interface/Exceptions.h>
+#include <libjulia/backends/AbstractAssembly.h>
+
#include <string>
#include <functional>
@@ -51,7 +53,7 @@ struct ExternalIdentifierAccess
/// Resolve a an external reference given by the identifier in the given context.
/// @returns the size of the value (number of stack slots) or size_t(-1) if not found.
Resolver resolve;
- using CodeGenerator = std::function<void(assembly::Identifier const&, IdentifierContext, eth::Assembly&)>;
+ using CodeGenerator = std::function<void(assembly::Identifier const&, IdentifierContext, julia::AbstractAssembly&)>;
/// Generate code for retrieving the value (rvalue context) or storing the value (lvalue context)
/// of an identifier. The code should be appended to the assembly. In rvalue context, the value is supposed
/// to be put onto the stack, in lvalue context, the value is assumed to be at the top of the stack.
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;
}