Consistent terminology for attached/bound functions

This commit is contained in:
wechman
2022-12-07 19:31:41 +01:00
committed by Kamil Śliwak
parent 1c8745c54a
commit 64a4f32bc2
42 changed files with 132 additions and 133 deletions
@@ -470,7 +470,7 @@ bool DeclarationTypeChecker::visit(UsingForDirective const& _usingFor)
m_errorReporter.typeError(
4167_error,
function->location(),
"Only file-level functions and library functions can be bound to a type in a \"using\" statement"
"Only file-level functions and library functions can be attached to a type in a \"using\" statement"
);
}
else
+1 -1
View File
@@ -427,7 +427,7 @@ bool SyntaxChecker::visit(UsingForDirective const& _usingFor)
m_errorReporter.syntaxError(
2854_error,
_usingFor.location(),
"Can only globally bind functions to specific types."
"Can only globally attach functions to specific types."
);
if (_usingFor.global() && m_currentContractKind)
m_errorReporter.syntaxError(
+5 -5
View File
@@ -3167,7 +3167,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
if (auto funType = dynamic_cast<FunctionType const*>(annotation.type))
{
solAssert(
!funType->bound() || exprType->isImplicitlyConvertibleTo(*funType->selfType()),
!funType->hasBoundFirstArgument() || exprType->isImplicitlyConvertibleTo(*funType->selfType()),
"Function \"" + memberName + "\" cannot be called on an object of type " +
exprType->humanReadableName() + " (expected " + funType->selfType()->humanReadableName() + ")."
);
@@ -3194,7 +3194,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
"Storage arrays with nested mappings do not support .push(<arg>)."
);
if (!funType->bound())
if (!funType->hasBoundFirstArgument())
if (auto typeType = dynamic_cast<TypeType const*>(exprType))
{
auto contractType = dynamic_cast<ContractType const*>(typeType->actualType());
@@ -3810,13 +3810,13 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
4731_error,
path->location(),
fmt::format(
"The function \"{}\" does not have any parameters, and therefore cannot be bound to the type \"{}\".",
"The function \"{}\" does not have any parameters, and therefore cannot be attached to the type \"{}\".",
joinHumanReadable(path->path(), "."),
normalizedType ? normalizedType->toString(true /* withoutDataLocation */) : "*"
)
);
FunctionType const* functionType = dynamic_cast<FunctionType const&>(*functionDefinition.type()).asBoundFunction();
FunctionType const* functionType = dynamic_cast<FunctionType const&>(*functionDefinition.type()).withBoundFirstArgument();
solAssert(functionType && functionType->selfType(), "");
BoolResult result = normalizedType->isImplicitlyConvertibleTo(
*TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->selfType())
@@ -3826,7 +3826,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
3100_error,
path->location(),
fmt::format(
"The function \"{}\" cannot be bound to the type \"{}\" because the type cannot "
"The function \"{}\" cannot be attached to the type \"{}\" because the type cannot "
"be implicitly converted to the first argument of the function (\"{}\"){}",
joinHumanReadable(path->path(), "."),
usingForType->toString(true /* withoutDataLocation */),
+2 -3
View File
@@ -644,10 +644,9 @@ private:
/**
* Using for directive:
*
* 1. `using LibraryName for T` attaches all functions from the library `LibraryName` to the type `T`
* 1. `using LibraryName for T` attaches all functions from the library `LibraryName` to the type `T`.
* 2. `using LibraryName for *` attaches to all types.
* 3. `using {f1, f2, ..., fn} for T` attaches the functions `f1`, `f2`, ...,
* `fn`, respectively to `T`.
* 3. `using {f1, f2, ..., fn} for T` attaches the functions `f1`, `f2`, ..., `fn`, respectively to `T`.
*
* For version 3, T has to be implicitly convertible to the first parameter type of
* all functions, and this is checked at the point of the using statement. For versions 1 and
+1 -1
View File
@@ -450,7 +450,7 @@ FunctionType const* TypeProvider::function(
)
{
// Can only use this constructor for "arbitraryParameters".
solAssert(!_options.valueSet && !_options.gasSet && !_options.saltSet && !_options.bound);
solAssert(!_options.valueSet && !_options.gasSet && !_options.saltSet && !_options.hasBoundFirstArgument);
return createAndGet<FunctionType>(
_parameterTypes,
_returnParameterTypes,
+30 -30
View File
@@ -305,7 +305,7 @@ MemberList const& Type::members(ASTNode const* _currentScope) const
"");
MemberList::MemberMap members = nativeMembers(_currentScope);
if (_currentScope)
members += boundFunctions(*this, *_currentScope);
members += attachedFunctions(*this, *_currentScope);
m_members[_currentScope] = make_unique<MemberList>(std::move(members));
}
return *m_members[_currentScope];
@@ -383,7 +383,7 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
}
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
MemberList::MemberMap Type::attachedFunctions(Type const& _type, ASTNode const& _scope)
{
MemberList::MemberMap members;
@@ -395,13 +395,13 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
Type const* functionType =
_function.libraryFunction() ? _function.typeViaContractName() : _function.type();
solAssert(functionType, "");
FunctionType const* asBoundFunction =
dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
solAssert(asBoundFunction, "");
FunctionType const* withBoundFirstArgument =
dynamic_cast<FunctionType const&>(*functionType).withBoundFirstArgument();
solAssert(withBoundFirstArgument, "");
if (_type.isImplicitlyConvertibleTo(*asBoundFunction->selfType()))
if (_type.isImplicitlyConvertibleTo(*withBoundFirstArgument->selfType()))
if (seenFunctions.insert(make_pair(*_name, &_function)).second)
members.emplace_back(&_function, asBoundFunction, *_name);
members.emplace_back(&_function, withBoundFirstArgument, *_name);
};
for (UsingForDirective const* ufd: usingForDirectivesForType(_type, _scope))
@@ -1879,21 +1879,21 @@ MemberList::MemberMap ArrayType::nativeMembers(ASTNode const*) const
strings{string()},
strings{string()},
FunctionType::Kind::ArrayPush
)->asBoundFunction());
)->withBoundFirstArgument());
members.emplace_back("push", TypeProvider::function(
TypePointers{thisAsPointer, baseType()},
TypePointers{},
strings{string(),string()},
strings{},
FunctionType::Kind::ArrayPush
)->asBoundFunction());
)->withBoundFirstArgument());
members.emplace_back("pop", TypeProvider::function(
TypePointers{thisAsPointer},
TypePointers{},
strings{string()},
strings{},
FunctionType::Kind::ArrayPop
)->asBoundFunction());
)->withBoundFirstArgument());
}
}
return members;
@@ -2952,7 +2952,7 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c
vector<string> FunctionType::parameterNames() const
{
if (!bound())
if (!hasBoundFirstArgument())
return m_parameterNames;
return vector<string>(m_parameterNames.cbegin() + 1, m_parameterNames.cend());
}
@@ -2981,7 +2981,7 @@ TypePointers FunctionType::returnParameterTypesWithoutDynamicTypes() const
TypePointers FunctionType::parameterTypes() const
{
if (!bound())
if (!hasBoundFirstArgument())
return m_parameterTypes;
return TypePointers(m_parameterTypes.cbegin() + 1, m_parameterTypes.cend());
}
@@ -3046,8 +3046,8 @@ string FunctionType::richIdentifier() const
id += "value";
if (saltSet())
id += "salt";
if (bound())
id += "bound_to" + identifierList(selfType());
if (hasBoundFirstArgument())
id += "attached_to" + identifierList(selfType());
return id;
}
@@ -3081,11 +3081,11 @@ BoolResult FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
FunctionType const& convertTo = dynamic_cast<FunctionType const&>(_convertTo);
// These two checks are duplicated in equalExcludingStateMutability, but are added here for error reporting.
if (convertTo.bound() != bound())
return BoolResult::err("Bound functions can not be converted to non-bound functions.");
if (convertTo.hasBoundFirstArgument() != hasBoundFirstArgument())
return BoolResult::err("Attached functions cannot be converted into unattached functions.");
if (convertTo.kind() != kind())
return BoolResult::err("Special functions can not be converted to function types.");
return BoolResult::err("Special functions cannot be converted to function types.");
if (!equalExcludingStateMutability(convertTo))
return false;
@@ -3122,10 +3122,10 @@ TypeResult FunctionType::binaryOperatorResult(Token _operator, Type const* _othe
else if (
kind() == Kind::External &&
sizeOnStack() == 2 &&
!bound() &&
!hasBoundFirstArgument() &&
other.kind() == Kind::External &&
other.sizeOnStack() == 2 &&
!other.bound()
!other.hasBoundFirstArgument()
)
return commonType(this, _other);
@@ -3210,7 +3210,7 @@ bool FunctionType::nameable() const
{
return
(m_kind == Kind::Internal || m_kind == Kind::External) &&
!bound() &&
!hasBoundFirstArgument() &&
!takesArbitraryParameters() &&
!gasSet() &&
!valueSet() &&
@@ -3249,7 +3249,7 @@ vector<tuple<string, Type const*>> FunctionType::makeStackItems() const
break;
case Kind::ArrayPush:
case Kind::ArrayPop:
solAssert(bound(), "");
solAssert(hasBoundFirstArgument(), "");
slots = {};
break;
default:
@@ -3262,7 +3262,7 @@ vector<tuple<string, Type const*>> FunctionType::makeStackItems() const
slots.emplace_back("value", TypeProvider::uint256());
if (saltSet())
slots.emplace_back("salt", TypeProvider::fixedBytes(32));
if (bound())
if (hasBoundFirstArgument())
slots.emplace_back("self", m_parameterTypes.front());
return slots;
}
@@ -3423,7 +3423,7 @@ TypeResult FunctionType::interfaceType(bool /*_inLibrary*/) const
Type const* FunctionType::mobileType() const
{
if (valueSet() || gasSet() || saltSet() || bound())
if (valueSet() || gasSet() || saltSet() || hasBoundFirstArgument())
return nullptr;
// return function without parameter names
@@ -3444,8 +3444,8 @@ bool FunctionType::canTakeArguments(
Type const* _selfType
) const
{
solAssert(!bound() || _selfType, "");
if (bound() && !_selfType->isImplicitlyConvertibleTo(*selfType()))
solAssert(!hasBoundFirstArgument() || _selfType, "");
if (hasBoundFirstArgument() && !_selfType->isImplicitlyConvertibleTo(*selfType()))
return false;
TypePointers paramTypes = parameterTypes();
std::vector<std::string> const paramNames = parameterNames();
@@ -3524,10 +3524,10 @@ bool FunctionType::equalExcludingStateMutability(FunctionType const& _other) con
if (gasSet() != _other.gasSet() || valueSet() != _other.valueSet() || saltSet() != _other.saltSet())
return false;
if (bound() != _other.bound())
if (hasBoundFirstArgument() != _other.hasBoundFirstArgument())
return false;
solAssert(!bound() || *selfType() == *_other.selfType(), "");
solAssert(!hasBoundFirstArgument() || *selfType() == *_other.selfType(), "");
return true;
}
@@ -3648,14 +3648,14 @@ Type const* FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bo
);
}
FunctionTypePointer FunctionType::asBoundFunction() const
FunctionTypePointer FunctionType::withBoundFirstArgument() const
{
solAssert(!m_parameterTypes.empty(), "");
solAssert(!gasSet(), "");
solAssert(!valueSet(), "");
solAssert(!saltSet(), "");
Options options = Options::fromFunctionType(*this);
options.bound = true;
options.hasBoundFirstArgument = true;
return TypeProvider::function(
m_parameterTypes,
m_returnParameterTypes,
@@ -3710,7 +3710,7 @@ FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary)
Type const* FunctionType::selfType() const
{
solAssert(bound(), "Function is not bound.");
solAssert(hasBoundFirstArgument(), "Function is not attached to a type.");
solAssert(m_parameterTypes.size() > 0, "Function has no self type.");
return m_parameterTypes.at(0);
}
+15 -15
View File
@@ -326,7 +326,7 @@ public:
/// given location.
virtual bool dataStoredIn(DataLocation) const { return false; }
/// Returns the list of all members of this type. Default implementation: no members apart from bound.
/// Returns the list of all members of this type. Default implementation: no members apart from attached functions.
/// @param _currentScope scope in which the members are accessed.
MemberList const& members(ASTNode const* _currentScope) const;
/// Convenience method, returns the type of the given named member or an empty pointer if no such member exists.
@@ -379,11 +379,11 @@ public:
private:
/// @returns a member list containing all members added to this type by `using for` directives.
static MemberList::MemberMap boundFunctions(Type const& _type, ASTNode const& _scope);
static MemberList::MemberMap attachedFunctions(Type const& _type, ASTNode const& _scope);
protected:
/// @returns the members native to this type depending on the given context. This function
/// is used (in conjunction with boundFunctions to fill m_members below.
/// is used (in conjunction with attachedFunctions to fill m_members below.
virtual MemberList::MemberMap nativeMembers(ASTNode const* /*_currentScope*/) const
{
return MemberList::MemberMap();
@@ -1272,7 +1272,7 @@ public:
bool saltSet = false;
/// true iff the function is called as arg1.fun(arg2, ..., argn).
/// This is achieved through the "using for" directive.
bool bound = false;
bool hasBoundFirstArgument = false;
static Options withArbitraryParameters()
{
@@ -1287,7 +1287,7 @@ public:
result.gasSet = _type.gasSet();
result.valueSet = _type.valueSet();
result.saltSet = _type.saltSet();
result.bound = _type.bound();
result.hasBoundFirstArgument = _type.hasBoundFirstArgument();
return result;
}
};
@@ -1322,7 +1322,7 @@ public:
)
{
// In this constructor, only the "arbitrary Parameters" option should be used.
solAssert(!bound() && !gasSet() && !valueSet() && !saltSet());
solAssert(!hasBoundFirstArgument() && !gasSet() && !valueSet() && !saltSet());
}
/// Detailed constructor, use with care.
@@ -1354,8 +1354,8 @@ public:
"Return parameter names list must match return parameter types list!"
);
solAssert(
!bound() || !m_parameterTypes.empty(),
"Attempted construction of bound function without self type"
!hasBoundFirstArgument() || !m_parameterTypes.empty(),
"Attempted construction of attached function without self type"
);
}
@@ -1372,7 +1372,7 @@ public:
/// storage pointers) are replaced by InaccessibleDynamicType instances.
TypePointers returnParameterTypesWithoutDynamicTypes() const;
std::vector<std::string> const& returnParameterNames() const { return m_returnParameterNames; }
/// @returns the "self" parameter type for a bound function
/// @returns the "self" parameter type for an attached function
Type const* selfType() const;
std::string richIdentifier() const override;
@@ -1406,8 +1406,8 @@ public:
/// @returns true if this function can take the given arguments (possibly
/// after implicit conversion).
/// @param _selfType if the function is bound, this has to be supplied and is the type of the
/// expression the function is called on.
/// @param _selfType if the function is attached as a member function, this has to be supplied
/// and is the type of the expression the function is called on.
bool canTakeArguments(
FuncCallArguments const& _arguments,
Type const* _selfType = nullptr
@@ -1471,20 +1471,20 @@ public:
bool gasSet() const { return m_options.gasSet; }
bool valueSet() const { return m_options.valueSet; }
bool saltSet() const { return m_options.saltSet; }
bool bound() const { return m_options.bound; }
bool hasBoundFirstArgument() const { return m_options.hasBoundFirstArgument; }
/// @returns a copy of this type, where gas or value are set manually. This will never set one
/// of the parameters to false.
Type const* copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const;
/// @returns a copy of this function type with the `bound` flag set to true.
/// @returns a copy of this function type with the `hasBoundFirstArgument` flag set to true.
/// Should only be called on library functions.
FunctionTypePointer asBoundFunction() const;
FunctionTypePointer withBoundFirstArgument() const;
/// @returns a copy of this function type where the location of reference types is changed
/// from CallData to Memory. This is the type that would be used when the function is
/// called externally, as opposed to the parameter types that are available inside the function body.
/// Also supports variants to be used for library or bound calls.
/// Also supports variants to be used for library or attached function calls.
/// @param _inLibrary if true, uses DelegateCall as location.
FunctionTypePointer asExternallyCallableFunction(bool _inLibrary) const;
+11 -11
View File
@@ -612,7 +612,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
else
{
FunctionType const& function = *functionType;
if (function.bound())
if (function.hasBoundFirstArgument())
solAssert(
function.kind() == FunctionType::Kind::DelegateCall ||
function.kind() == FunctionType::Kind::Internal ||
@@ -637,7 +637,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
bool shortcutTaken = false;
if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
{
solAssert(!function.bound(), "");
solAssert(!function.hasBoundFirstArgument(), "");
if (auto functionDef = dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration))
{
// Do not directly visit the identifier, because this way, we can avoid
@@ -657,7 +657,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes());
if (function.bound())
if (function.hasBoundFirstArgument())
{
// stack: arg2, ..., argn, label, arg1
unsigned depth = parameterSize + 1;
@@ -906,7 +906,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
argumentType &&
functionType->kind() == FunctionType::Kind::External &&
argumentType->kind() == FunctionType::Kind::External &&
!argumentType->bound(),
!argumentType->hasBoundFirstArgument(),
""
);
@@ -1029,7 +1029,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
}
case FunctionType::Kind::ArrayPush:
{
solAssert(function.bound(), "");
solAssert(function.hasBoundFirstArgument(), "");
_functionCall.expression().accept(*this);
if (function.parameterTypes().size() == 0)
@@ -1095,7 +1095,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::ArrayPop:
{
_functionCall.expression().accept(*this);
solAssert(function.bound(), "");
solAssert(function.hasBoundFirstArgument(), "");
solAssert(function.parameterTypes().empty(), "");
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
solAssert(arrayType && arrayType->dataStoredIn(DataLocation::Storage), "");
@@ -1476,10 +1476,10 @@ bool ExpressionCompiler::visit(NewExpression const&)
bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{
CompilerContext::LocationSetter locationSetter(m_context, _memberAccess);
// Check whether the member is a bound function.
// Check whether the member is an attached function.
ASTString const& member = _memberAccess.memberName();
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
if (funType->bound())
if (funType->hasBoundFirstArgument())
{
acceptAndConvert(_memberAccess.expression(), *funType->selfType(), true);
if (funType->kind() == FunctionType::Kind::Internal)
@@ -2570,14 +2570,14 @@ void ExpressionCompiler::appendExternalFunctionCall(
// function identifier [unless bare]
// contract address
unsigned selfSize = _functionType.bound() ? _functionType.selfType()->sizeOnStack() : 0;
unsigned selfSize = _functionType.hasBoundFirstArgument() ? _functionType.selfType()->sizeOnStack() : 0;
unsigned gasValueSize = (_functionType.gasSet() ? 1u : 0u) + (_functionType.valueSet() ? 1u : 0u);
unsigned contractStackPos = m_context.currentToBaseStackOffset(1 + gasValueSize + selfSize + (_functionType.isBareCall() ? 0 : 1));
unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize);
unsigned valueStackPos = m_context.currentToBaseStackOffset(1);
// move self object to top
if (_functionType.bound())
if (_functionType.hasBoundFirstArgument())
utils().moveToStackTop(gasValueSize, _functionType.selfType()->sizeOnStack());
auto funKind = _functionType.kind();
@@ -2605,7 +2605,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
// Evaluate arguments.
TypePointers argumentTypes;
TypePointers parameterTypes = _functionType.parameterTypes();
if (_functionType.bound())
if (_functionType.hasBoundFirstArgument())
{
argumentTypes.push_back(_functionType.selfType());
parameterTypes.insert(parameterTypes.begin(), _functionType.selfType());
+1 -1
View File
@@ -321,7 +321,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
_sourceType.isImplicitlyConvertibleTo(*m_dataType),
"function item stored but target is not implicitly convertible to source"
);
solAssert(!fun->bound(), "");
solAssert(!fun->hasBoundFirstArgument(), "");
if (fun->kind() == FunctionType::Kind::External)
{
solAssert(fun->sizeOnStack() == 2, "");
@@ -953,7 +953,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
solAssert(!functionType->takesArbitraryParameters());
vector<string> args;
if (functionType->bound())
if (functionType->hasBoundFirstArgument())
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
for (size_t i = 0; i < arguments.size(); ++i)
@@ -1024,7 +1024,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
solAssert(
IRVariable(arg).type() == *functionType &&
functionType->kind() == FunctionType::Kind::External &&
!functionType->bound(),
!functionType->hasBoundFirstArgument(),
""
);
define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::fixedBytes(32))) <<
@@ -1353,7 +1353,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
}
case FunctionType::Kind::ArrayPop:
{
solAssert(functionType->bound());
solAssert(functionType->hasBoundFirstArgument());
solAssert(functionType->parameterTypes().empty());
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(functionType->selfType());
solAssert(arrayType);
@@ -1557,7 +1557,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
solAssert(!_functionCall.annotation().tryCall);
solAssert(!functionType->valueSet());
solAssert(!functionType->gasSet());
solAssert(!functionType->bound());
solAssert(!functionType->hasBoundFirstArgument());
static map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = {
{FunctionType::Kind::ECRecover, std::make_tuple(1, 0)},
@@ -1623,7 +1623,7 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
setLocation(_options);
FunctionType const& previousType = dynamic_cast<FunctionType const&>(*_options.expression().annotation().type);
solUnimplementedAssert(!previousType.bound());
solUnimplementedAssert(!previousType.hasBoundFirstArgument());
// Copy over existing values.
for (auto const& item: previousType.stackItems())
@@ -1668,7 +1668,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
auto memberFunctionType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
Type::Category objectCategory = _memberAccess.expression().annotation().type->category();
if (memberFunctionType && memberFunctionType->bound())
if (memberFunctionType && memberFunctionType->hasBoundFirstArgument())
{
define(IRVariable(_memberAccess).part("self"), _memberAccess.expression());
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static);
@@ -2506,7 +2506,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
TypePointers parameterTypes = funType.parameterTypes();
TypePointers argumentTypes;
vector<string> argumentStrings;
if (funType.bound())
if (funType.hasBoundFirstArgument())
{
parameterTypes.insert(parameterTypes.begin(), funType.selfType());
argumentTypes.emplace_back(funType.selfType());
@@ -2655,7 +2655,7 @@ void IRGeneratorForStatements::appendBareCall(
{
FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression()));
solAssert(
!funType.bound() &&
!funType.hasBoundFirstArgument() &&
!funType.takesArbitraryParameters() &&
_arguments.size() == 1 &&
funType.parameterTypes().size() == 1, ""
+4 -4
View File
@@ -3120,12 +3120,12 @@ vector<smtutil::Expression> SMTEncoder::symbolicArguments(FunctionCall const& _f
vector<ASTPointer<Expression const>> arguments = _funCall.sortedArguments();
auto functionParams = funDef->parameters();
unsigned firstParam = 0;
if (funType->bound())
if (funType->hasBoundFirstArgument())
{
calledExpr = innermostTuple(*calledExpr);
auto const& boundFunction = dynamic_cast<MemberAccess const*>(calledExpr);
solAssert(boundFunction, "");
args.push_back(expr(boundFunction->expression(), functionParams.front()->type()));
auto const& attachedFunction = dynamic_cast<MemberAccess const*>(calledExpr);
solAssert(attachedFunction, "");
args.push_back(expr(attachedFunction->expression(), functionParams.front()->type()));
firstParam = 1;
}
+1 -1
View File
@@ -401,7 +401,7 @@ protected:
void createReturnedExpressions(FunctionCall const& _funCall, ContractDefinition const* _contextContract);
/// @returns the symbolic arguments for a function call,
/// taking into account bound functions and
/// taking into account attached functions and
/// type conversion.
std::vector<smtutil::Expression> symbolicArguments(FunctionCall const& _funCall, ContractDefinition const* _contextContract);