mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
WIP-Friday
This commit is contained in:
parent
8df6b50a78
commit
cca832e56a
@ -53,6 +53,8 @@ set(sources
|
||||
ast/ASTJsonImporter.h
|
||||
ast/ASTVisitor.h
|
||||
ast/ExperimentalFeatures.h
|
||||
ast/JsonInterfaceImporter.cpp
|
||||
ast/JsonInterfaceImporter.h
|
||||
ast/Types.cpp
|
||||
ast/Types.h
|
||||
ast/TypeProvider.cpp
|
||||
|
@ -231,6 +231,12 @@ vector<pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition:
|
||||
});
|
||||
}
|
||||
|
||||
TypePointer ImportedContractDefinition::type() const
|
||||
{
|
||||
return {};
|
||||
// TODO: Think about whether this type needs to be specified or returning {} is sufficient.
|
||||
}
|
||||
|
||||
TypePointer ContractDefinition::type() const
|
||||
{
|
||||
return TypeProvider::typeType(TypeProvider::contract(*this));
|
||||
|
@ -454,7 +454,12 @@ protected:
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* TODO: docstring
|
||||
* Definition of an imported interface declaration.
|
||||
*
|
||||
* This is not the actually imported interface but the reference to it.
|
||||
* It will be resolved by CompilerStack to add any missing interface definitions
|
||||
* by looking for any ImportedContractDefinition in the ASTs and append them - embeded into
|
||||
* SourceUnit's - to its collection of sources.
|
||||
*/
|
||||
class ImportedContractDefinition: public Declaration // TODO(needed?), public StructurallyDocumented
|
||||
{
|
||||
@ -471,6 +476,7 @@ public:
|
||||
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
TypePointer type() const override;
|
||||
|
||||
ASTPointer<ASTString> const& path() const noexcept { return m_path; }
|
||||
|
||||
|
@ -50,7 +50,23 @@ public:
|
||||
|
||||
ASTPointer<ContractDefinition> jsonToContract(Json::Value const& _sourceList);
|
||||
|
||||
ASTPointer<ContractDefinition> jsonToInterface(
|
||||
int64_t _nodeId,
|
||||
langutil::SourceLocation const& _location,
|
||||
std::string const& _name,
|
||||
Json::Value const& _source
|
||||
);
|
||||
|
||||
private:
|
||||
ASTPointer<ASTNode> createInterfaceMember(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
);
|
||||
|
||||
ASTPointer<ParameterList> createInterfaceParameters(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _array
|
||||
);
|
||||
|
||||
// =========== general creation functions ==============
|
||||
|
||||
|
198
libsolidity/ast/JsonInterfaceImporter.cpp
Normal file
198
libsolidity/ast/JsonInterfaceImporter.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#include <libsolidity/ast/JsonInterfaceImporter.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
ASTPointer<SourceUnit> JsonInterfaceImporter::importInterfaceAsSourceUnit(
|
||||
langutil::SourceLocation const& _location,
|
||||
std::optional<std::string> const& _license,
|
||||
std::string const& _name,
|
||||
Json::Value const& _source
|
||||
)
|
||||
{
|
||||
auto interface = importInterface(_location, _name, _source);
|
||||
return make_shared<SourceUnit>(
|
||||
m_nextId++,
|
||||
_location,
|
||||
_license,
|
||||
vector<ASTPointer<ASTNode>>{ interface }
|
||||
);
|
||||
}
|
||||
|
||||
ASTPointer<ASTNode> JsonInterfaceImporter::importInterface(
|
||||
langutil::SourceLocation const& _location,
|
||||
string const& _name,
|
||||
Json::Value const& _source
|
||||
)
|
||||
{
|
||||
// TODO: contractInheritanceDefinition
|
||||
// TODO: "anything in ContractDefintion that returns a vector of FunctionDefinitons needs to be refactored to return a base class of FunctionDefiniton such that the imported interface can also return something that is not directly a FunctionDefinition"
|
||||
|
||||
vector<ASTPointer<ASTNode>> members;
|
||||
for (auto const& jsonMember: _source)
|
||||
if (auto member = createMember(_location, jsonMember); member != nullptr)
|
||||
members.push_back(member);
|
||||
|
||||
return make_shared<ContractDefinition>(
|
||||
m_nextId++,
|
||||
_location,
|
||||
make_shared<ASTString>(_name),
|
||||
ASTPointer<StructuredDocumentation>{},
|
||||
vector<ASTPointer<InheritanceSpecifier>>{}, // TODO: see contractInheritanceDefinition
|
||||
members,
|
||||
ContractKind::Interface,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
ASTPointer<ASTNode> JsonInterfaceImporter::createMember(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
)
|
||||
{
|
||||
if (_node["type"] == "function")
|
||||
return createFunction(_location, _node);
|
||||
else if (_node["type"] == "event")
|
||||
return createEvent(_location, _node);
|
||||
else
|
||||
{
|
||||
// TODO: report error of invalid type. Use m_errorReporter for that.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ASTPointer<ASTNode> JsonInterfaceImporter::createFunction(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
)
|
||||
{
|
||||
auto const mutability = stateMutability(_node["stateMutability"]);
|
||||
auto const name = _node["name"].asString();
|
||||
auto const inputs = createParameters(_location, false, _node["inputs"]);
|
||||
auto const outputs = createParameters(_location, false, _node["outputs"]);
|
||||
auto const kind = Token::Function;
|
||||
|
||||
return createASTNode<FunctionDefinition>(
|
||||
_location,
|
||||
make_shared<ASTString>(name),
|
||||
Visibility::Default,
|
||||
mutability,
|
||||
kind,
|
||||
true, // interface functions are always virtual
|
||||
nullptr, // overrides
|
||||
nullptr, // documentation
|
||||
inputs,
|
||||
vector<ASTPointer<ModifierInvocation>>{},
|
||||
outputs,
|
||||
nullptr // no body
|
||||
);
|
||||
}
|
||||
|
||||
ASTPointer<ASTNode> JsonInterfaceImporter::createEvent(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
)
|
||||
{
|
||||
bool const anonymous = _node["anonymous"].asBool();
|
||||
auto inputs = createParameters(_location, true, _node["inputs"]);
|
||||
auto const name = _node["name"].asString();
|
||||
|
||||
return createASTNode<EventDefinition>(
|
||||
_location,
|
||||
make_shared<ASTString>(name),
|
||||
ASTPointer<StructuredDocumentation>{},
|
||||
inputs,
|
||||
anonymous
|
||||
);
|
||||
}
|
||||
|
||||
ASTPointer<ParameterList> JsonInterfaceImporter::createParameters(
|
||||
langutil::SourceLocation const& _location,
|
||||
bool _indexed,
|
||||
Json::Value const& _node
|
||||
)
|
||||
{
|
||||
vector<ASTPointer<VariableDeclaration>> parameters;
|
||||
|
||||
for (auto& param: _node)
|
||||
parameters.push_back(createParameter(_location, _indexed, param));
|
||||
|
||||
return createASTNode<ParameterList>(_location, parameters);
|
||||
}
|
||||
|
||||
ASTPointer<VariableDeclaration> JsonInterfaceImporter::createParameter(
|
||||
langutil::SourceLocation const& _location,
|
||||
bool _indexed,
|
||||
Json::Value const& _node
|
||||
)
|
||||
{
|
||||
// "indexed" (only when event)
|
||||
auto const parameterName = _node["name"].asString();
|
||||
auto const typeName = _node["type"].asString();
|
||||
ASTPointer<TypeName> type = {}; // TODO (get me from typeName)
|
||||
|
||||
return createASTNode<VariableDeclaration>(
|
||||
_location,
|
||||
type,
|
||||
make_shared<ASTString>(parameterName),
|
||||
ASTPointer<Expression>{}, // value
|
||||
Visibility::Default,
|
||||
ASTPointer<StructuredDocumentation>{}, // documentation
|
||||
false, // isStateVariable
|
||||
_indexed,
|
||||
VariableDeclaration::Mutability::Mutable,
|
||||
ASTPointer<OverrideSpecifier>{}
|
||||
);
|
||||
// TODO
|
||||
// return createASTNode<VariableDeclaration>(
|
||||
// _location,
|
||||
// nullOrCast<TypeName>(member(_node, "typeName")),
|
||||
// make_shared<ASTString>(member(_node, "name").asString()),
|
||||
// nullOrCast<Expression>(member(_node, "value")),
|
||||
// visibility(_node),
|
||||
// _node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
|
||||
// memberAsBool(_node, "stateVariable"),
|
||||
// _node.isMember("indexed") ? memberAsBool(_node, "indexed") : false,
|
||||
// mutability,
|
||||
// _node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
|
||||
// location(_node)
|
||||
// );
|
||||
}
|
||||
|
||||
StateMutability JsonInterfaceImporter::stateMutability(Json::Value const& _node) const
|
||||
{
|
||||
// TODO: see that we can avoid duplication with ASTJsonImporter
|
||||
astAssert(member(_node, "stateMutability").isString(), "StateMutability' expected to be string.");
|
||||
string const mutabilityStr = member(_node, "stateMutability").asString();
|
||||
|
||||
if (mutabilityStr == "pure")
|
||||
return StateMutability::Pure;
|
||||
else if (mutabilityStr == "view")
|
||||
return StateMutability::View;
|
||||
else if (mutabilityStr == "nonpayable")
|
||||
return StateMutability::NonPayable;
|
||||
else if (mutabilityStr == "payable")
|
||||
return StateMutability::Payable;
|
||||
else
|
||||
astAssert(false, "Unknown stateMutability");
|
||||
}
|
||||
|
||||
Json::Value JsonInterfaceImporter::member(Json::Value const& _node, string const& _name) const
|
||||
{
|
||||
// TODO: see that we can avoid duplication with ASTJsonImporter
|
||||
astAssert(_node.isMember(_name), "Node '" + _node["nodeType"].asString() + "' (id " + _node["id"].asString() + ") is missing field '" + _name + "'.");
|
||||
return _node[_name];
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
ASTPointer<T> JsonInterfaceImporter::createASTNode(
|
||||
langutil::SourceLocation const& _location,
|
||||
Args&&... _args
|
||||
)
|
||||
{
|
||||
return make_shared<T>(m_nextId++, _location, forward<Args>(_args)...);
|
||||
}
|
||||
|
||||
} // end namespace
|
93
libsolidity/ast/JsonInterfaceImporter.h
Normal file
93
libsolidity/ast/JsonInterfaceImporter.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
|
||||
#include <json/json.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
class JsonInterfaceImporter
|
||||
{
|
||||
public:
|
||||
JsonInterfaceImporter(int64_t _nextId):
|
||||
m_nextId{ _nextId }
|
||||
{}
|
||||
|
||||
ASTPointer<SourceUnit> importInterfaceAsSourceUnit(
|
||||
langutil::SourceLocation const& _location,
|
||||
std::optional<std::string> const& _licenseString,
|
||||
std::string const& _name,
|
||||
Json::Value const& _source
|
||||
);
|
||||
|
||||
ASTPointer<ASTNode> importInterface(
|
||||
langutil::SourceLocation const& _location,
|
||||
std::string const& _name,
|
||||
Json::Value const& _source
|
||||
);
|
||||
|
||||
private:
|
||||
ASTPointer<ASTNode> createMember(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
);
|
||||
|
||||
ASTPointer<ASTNode> createFunction(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
);
|
||||
|
||||
ASTPointer<ASTNode> createEvent(
|
||||
langutil::SourceLocation const& _location,
|
||||
Json::Value const& _node
|
||||
);
|
||||
|
||||
ASTPointer<ParameterList> createParameters(
|
||||
langutil::SourceLocation const& _location,
|
||||
bool _indexed,
|
||||
Json::Value const& _node
|
||||
);
|
||||
|
||||
ASTPointer<VariableDeclaration> createParameter(
|
||||
langutil::SourceLocation const& _location,
|
||||
bool _indexed,
|
||||
Json::Value const& _node
|
||||
);
|
||||
|
||||
private: // helper functions (TODO: that could be shared with ASTJsonImporter)
|
||||
StateMutability stateMutability(Json::Value const& _node) const;
|
||||
|
||||
Json::Value member(Json::Value const& _node, std::string const& _name) const;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
ASTPointer<T> createASTNode(
|
||||
langutil::SourceLocation const& _location,
|
||||
Args&&... _args
|
||||
);
|
||||
|
||||
private:
|
||||
int64_t m_nextId;
|
||||
};
|
||||
|
||||
} // end namespace
|
@ -41,6 +41,7 @@
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/ast/ASTJsonImporter.h>
|
||||
#include <libsolidity/ast/JsonInterfaceImporter.h>
|
||||
#include <libsolidity/codegen/Compiler.h>
|
||||
#include <libsolidity/formal/ModelChecker.h>
|
||||
#include <libsolidity/interface/ABI.h>
|
||||
@ -276,7 +277,9 @@ bool CompilerStack::parse()
|
||||
|
||||
void CompilerStack::loadMissingInterfaces(int64_t _baseNodeID)
|
||||
{
|
||||
JsonInterfaceImporter interfaceImporter{_baseNodeID};
|
||||
vector<ASTPointer<SourceUnit>> importedSources;
|
||||
|
||||
for (auto const& sourcePair: m_sources)
|
||||
{
|
||||
ASTPointer<SourceUnit> const& source = sourcePair.second.ast;
|
||||
@ -297,15 +300,17 @@ void CompilerStack::loadMissingInterfaces(int64_t _baseNodeID)
|
||||
string const& jsonString = result.responseOrErrorMessage;
|
||||
Json::Value json;
|
||||
util::jsonParseStrict(jsonString, json, nullptr);
|
||||
ASTPointer<ContractDefinition> jsonContract = ASTJsonImporter{m_evmVersion}.jsonToContract(json);
|
||||
|
||||
auto importedSource = make_shared<SourceUnit>(
|
||||
_baseNodeID++,
|
||||
SourceLocation{},
|
||||
source->licenseString(),
|
||||
vector<ASTPointer<ASTNode>>{ jsonContract }
|
||||
);
|
||||
importedSources.push_back(importedSource);
|
||||
ASTPointer<SourceUnit> importedSource =
|
||||
interfaceImporter.importInterfaceAsSourceUnit(
|
||||
importedContract->location(),
|
||||
source->licenseString(),
|
||||
importedContract->name(),
|
||||
json
|
||||
);
|
||||
|
||||
if (importedSource != nullptr)
|
||||
importedSources.push_back(importedSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -292,7 +292,7 @@ std::pair<ContractKind, bool> Parser::parseContractKind()
|
||||
return std::make_pair(kind, abstract);
|
||||
}
|
||||
|
||||
ASTPointer<ContractDefinition> Parser::parseInterfaceDefinition()
|
||||
ASTPointer<ASTNode> Parser::parseInterfaceDefinition()
|
||||
{
|
||||
// interfaceDefinition
|
||||
// : 'interface' identifier 'from' StringLiteralFragment
|
||||
|
@ -91,7 +91,7 @@ private:
|
||||
std::pair<ContractKind, bool> parseContractKind();
|
||||
ASTPointer<ContractDefinition> parseContractDefinition();
|
||||
std::vector<ASTPointer<InheritanceSpecifier>> parseContractInheritanceList();
|
||||
ASTPointer<ContractDefinition> parseInterfaceDefinition();
|
||||
ASTPointer<ASTNode> parseInterfaceDefinition();
|
||||
std::vector<ASTPointer<ASTNode>> parseContractBody();
|
||||
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
|
||||
Visibility parseVisibilitySpecifier();
|
||||
|
@ -0,0 +1,7 @@
|
||||
interface I from "interface_imported_I.json";
|
||||
|
||||
contract C {
|
||||
function f() public pure {
|
||||
}
|
||||
}
|
||||
// ----
|
142
test/libsolidity/syntaxTests/parsing/interface_imported_I.json
Normal file
142
test/libsolidity/syntaxTests/parsing/interface_imported_I.json
Normal file
@ -0,0 +1,142 @@
|
||||
[
|
||||
{
|
||||
"state_mutability": "view",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"state_mutability": "view",
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "supply",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"state_mutability": "payable",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"state_mutability": "view",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "balance",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"state_mutability": "payable",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue
Block a user