mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Minor changes after code review
This commit is contained in:
parent
70255f8776
commit
9e1ba093d5
@ -671,13 +671,13 @@ public:
|
|||||||
bool _global
|
bool _global
|
||||||
):
|
):
|
||||||
ASTNode(_id, _location),
|
ASTNode(_id, _location),
|
||||||
m_functions(std::move(_functions)),
|
m_functionsOrLibrary(std::move(_functions)),
|
||||||
m_operators(std::move(_operators)),
|
m_operators(std::move(_operators)),
|
||||||
m_usesBraces(_usesBraces),
|
m_usesBraces(_usesBraces),
|
||||||
m_typeName(std::move(_typeName)),
|
m_typeName(std::move(_typeName)),
|
||||||
m_global{_global}
|
m_global{_global}
|
||||||
{
|
{
|
||||||
solAssert(m_functions.size() == m_operators.size());
|
solAssert(m_functionsOrLibrary.size() == m_operators.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void accept(ASTVisitor& _visitor) override;
|
void accept(ASTVisitor& _visitor) override;
|
||||||
@ -687,19 +687,22 @@ public:
|
|||||||
TypeName const* typeName() const { return m_typeName.get(); }
|
TypeName const* typeName() const { return m_typeName.get(); }
|
||||||
|
|
||||||
/// @returns a list of functions or the single library.
|
/// @returns a list of functions or the single library.
|
||||||
std::vector<ASTPointer<IdentifierPath>> const& functionsOrLibrary() const { return m_functions; }
|
std::vector<ASTPointer<IdentifierPath>> const& functionsOrLibrary() const { return m_functionsOrLibrary; }
|
||||||
auto functionsAndOperators() const { return ranges::zip_view(m_functions, m_operators); }
|
auto functionsAndOperators() const { return ranges::zip_view(m_functionsOrLibrary, m_operators); }
|
||||||
bool usesBraces() const { return m_usesBraces; }
|
bool usesBraces() const { return m_usesBraces; }
|
||||||
bool global() const { return m_global; }
|
bool global() const { return m_global; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Either the single library or a list of functions.
|
/// Either the single library or a list of functions.
|
||||||
std::vector<ASTPointer<IdentifierPath>> m_functions;
|
std::vector<ASTPointer<IdentifierPath>> const m_functionsOrLibrary;
|
||||||
/// Operators, the functions are applied to.
|
/// Operators, the functions from @a m_functionsOrLibrary implement.
|
||||||
std::vector<std::optional<Token>> m_operators;
|
/// A token if the corresponding element in m_functionsOrLibrary
|
||||||
bool m_usesBraces;
|
/// defines an operator, nullptr otherwise.
|
||||||
ASTPointer<TypeName> m_typeName;
|
/// Note that this vector size must be equal to m_functionsOrLibrary size.
|
||||||
bool m_global = false;
|
std::vector<std::optional<Token>> const m_operators;
|
||||||
|
bool const m_usesBraces;
|
||||||
|
ASTPointer<TypeName> const m_typeName;
|
||||||
|
bool const m_global;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StructDefinition: public Declaration, public ScopeOpener
|
class StructDefinition: public Declaration, public ScopeOpener
|
||||||
|
@ -337,7 +337,7 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node)
|
|||||||
{
|
{
|
||||||
Json::Value functionNode;
|
Json::Value functionNode;
|
||||||
functionNode["function"] = toJson(*function);
|
functionNode["function"] = toJson(*function);
|
||||||
if (op)
|
if (op.has_value())
|
||||||
functionNode["operator"] = string(TokenTraits::toString(*op));
|
functionNode["operator"] = string(TokenTraits::toString(*op));
|
||||||
functionList.append(move(functionNode));
|
functionList.append(move(functionNode));
|
||||||
}
|
}
|
||||||
@ -828,8 +828,8 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node)
|
|||||||
make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
||||||
make_pair("subExpression", toJson(_node.subExpression()))
|
make_pair("subExpression", toJson(_node.subExpression()))
|
||||||
};
|
};
|
||||||
if (FunctionDefinition const* function = _node.annotation().userDefinedFunction)
|
if (FunctionDefinition const* referencedDeclaration = _node.annotation().userDefinedFunction)
|
||||||
attributes.emplace_back("function", nodeId(*function));
|
attributes.emplace_back("function", nodeId(*referencedDeclaration));
|
||||||
appendExpressionAttributes(attributes, _node.annotation());
|
appendExpressionAttributes(attributes, _node.annotation());
|
||||||
setJsonNode(_node, "UnaryOperation", std::move(attributes));
|
setJsonNode(_node, "UnaryOperation", std::move(attributes));
|
||||||
return false;
|
return false;
|
||||||
|
@ -194,7 +194,7 @@ void UsingForDirective::accept(ASTVisitor& _visitor)
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
listAccept(m_functions, _visitor);
|
listAccept(m_functionsOrLibrary, _visitor);
|
||||||
if (m_typeName)
|
if (m_typeName)
|
||||||
m_typeName->accept(_visitor);
|
m_typeName->accept(_visitor);
|
||||||
}
|
}
|
||||||
@ -205,7 +205,7 @@ void UsingForDirective::accept(ASTConstVisitor& _visitor) const
|
|||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
listAccept(m_functions, _visitor);
|
listAccept(m_functionsOrLibrary, _visitor);
|
||||||
if (m_typeName)
|
if (m_typeName)
|
||||||
m_typeName->accept(_visitor);
|
m_typeName->accept(_visitor);
|
||||||
}
|
}
|
||||||
|
@ -369,10 +369,9 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
|
|||||||
typeLocation = refType->location();
|
typeLocation = refType->location();
|
||||||
|
|
||||||
return usingForDirectives | ranges::views::filter([&](UsingForDirective const* _directive) -> bool {
|
return usingForDirectives | ranges::views::filter([&](UsingForDirective const* _directive) -> bool {
|
||||||
// Convert both types to pointers for comparison to see if the `using for`
|
// Convert both types to pointers for comparison to see if the `using for` directive applies.
|
||||||
// directive applies.
|
// Note that at this point we don't yet know if the functions are actually usable with the type.
|
||||||
// Further down, we check more detailed for each function if `_type` is
|
// `_type` may not be convertible to the function parameter type.
|
||||||
// convertible to the function parameter type.
|
|
||||||
return
|
return
|
||||||
!_directive->typeName() ||
|
!_directive->typeName() ||
|
||||||
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) ==
|
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) ==
|
||||||
@ -391,14 +390,14 @@ Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNod
|
|||||||
if (!typeDefinition())
|
if (!typeDefinition())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
set<FunctionDefinition const*> seenFunctions;
|
set<FunctionDefinition const*> matchingDefinitions;
|
||||||
for (UsingForDirective const* ufd: usingForDirectivesForType(*this, _scope))
|
for (UsingForDirective const* ufd: usingForDirectivesForType(*this, _scope))
|
||||||
for (auto const& [pathPointer, operator_]: ufd->functionsAndOperators())
|
for (auto const& [identifierPath, operator_]: ufd->functionsAndOperators())
|
||||||
{
|
{
|
||||||
if (operator_ != _token)
|
if (operator_ != _token)
|
||||||
continue;
|
continue;
|
||||||
FunctionDefinition const& function = dynamic_cast<FunctionDefinition const&>(
|
FunctionDefinition const& function = dynamic_cast<FunctionDefinition const&>(
|
||||||
*pathPointer->annotation().referencedDeclaration
|
*identifierPath->annotation().referencedDeclaration
|
||||||
);
|
);
|
||||||
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
|
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
|
||||||
function.libraryFunction() ? function.typeViaContractName() : function.type()
|
function.libraryFunction() ? function.typeViaContractName() : function.type()
|
||||||
@ -418,12 +417,12 @@ Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNod
|
|||||||
(!_unaryOperation && function.parameterList().parameters().size() == 2)
|
(!_unaryOperation && function.parameterList().parameters().size() == 2)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
seenFunctions.insert(&function);
|
matchingDefinitions.insert(&function);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seenFunctions.size() == 1)
|
if (matchingDefinitions.size() == 1)
|
||||||
return *seenFunctions.begin();
|
return *matchingDefinitions.begin();
|
||||||
else if (seenFunctions.size() == 0)
|
else if (matchingDefinitions.size() == 0)
|
||||||
return Result<FunctionDefinition const*>::err("No matching user-defined operator found.");
|
return Result<FunctionDefinition const*>::err("No matching user-defined operator found.");
|
||||||
else
|
else
|
||||||
return Result<FunctionDefinition const*>::err("Multiple user-defined functions provided for this operator.");
|
return Result<FunctionDefinition const*>::err("Multiple user-defined functions provided for this operator.");
|
||||||
@ -453,7 +452,9 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
|
|||||||
for (UsingForDirective const* ufd: usingForDirectivesForType(_type, _scope))
|
for (UsingForDirective const* ufd: usingForDirectivesForType(_type, _scope))
|
||||||
for (auto const& [pathPointer, operator_]: ufd->functionsAndOperators())
|
for (auto const& [pathPointer, operator_]: ufd->functionsAndOperators())
|
||||||
{
|
{
|
||||||
if (operator_)
|
if (operator_.has_value())
|
||||||
|
// Functions used to define operators are not bound to the type.
|
||||||
|
// I.e. `using {f} for T` allows `T x; x.f()` but `using {f as +} for T` does not.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
solAssert(pathPointer);
|
solAssert(pathPointer);
|
||||||
|
@ -79,8 +79,6 @@ contract C {
|
|||||||
function test_geq(int128 x) public pure returns (bool) { return w(x) >= w(2); }
|
function test_geq(int128 x) public pure returns (bool) { return w(x) >= w(2); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====
|
|
||||||
// compileViaYul: also
|
|
||||||
// ----
|
// ----
|
||||||
// test_bitor() -> 10
|
// test_bitor() -> 10
|
||||||
// test_bitand() -> 10
|
// test_bitand() -> 10
|
||||||
|
@ -18,7 +18,5 @@ contract C {
|
|||||||
return value + value * percentage;
|
return value + value * percentage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
|
||||||
// compileViaYul: also
|
|
||||||
// ----
|
// ----
|
||||||
// applyInterest(int128,int128): 500000000000000000000, 100000000000000000 -> 550000000000000000000
|
// applyInterest(int128,int128): 500000000000000000000, 100000000000000000 -> 550000000000000000000
|
||||||
|
@ -22,8 +22,6 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====
|
|
||||||
// compileViaYul: also
|
|
||||||
// ----
|
// ----
|
||||||
// f() -> 1
|
// f() -> 1
|
||||||
// g() -> 2
|
// g() -> 2
|
||||||
|
@ -36,8 +36,6 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====
|
|
||||||
// compileViaYul: also
|
|
||||||
// ----
|
// ----
|
||||||
// test1() -> 1
|
// test1() -> 1
|
||||||
// test2() -> 2
|
// test2() -> 2
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
==== Source: a.sol ====
|
==== Source: a.sol ====
|
||||||
pragma abicoder v2;
|
|
||||||
library L {
|
library L {
|
||||||
type Int is int128;
|
type Int is int128;
|
||||||
|
|
||||||
@ -8,21 +7,17 @@ library L {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
==== Source: b.sol ====
|
==== Source: b.sol ====
|
||||||
pragma abicoder v2;
|
|
||||||
import "a.sol" as a;
|
import "a.sol" as a;
|
||||||
==== Source: c.sol ====
|
==== Source: c.sol ====
|
||||||
pragma abicoder v2;
|
|
||||||
import "b.sol" as b;
|
import "b.sol" as b;
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
using {b.a.L.add as +} for b.a.L.Int;
|
using {b.a.L.add as +} for b.a.L.Int;
|
||||||
|
|
||||||
function f() pure public returns (b.a.L.Int) {
|
function f() pure public returns (b.a.L.Int) {
|
||||||
return b.a.L.Int.wrap(0) + b.a.L.Int.wrap(0);
|
return b.a.L.Int.wrap(0) + b.a.L.Int.wrap(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====
|
|
||||||
// compileViaYul: also
|
|
||||||
// ----
|
// ----
|
||||||
// f() -> 7
|
// f() -> 7
|
||||||
|
Loading…
Reference in New Issue
Block a user