Remove dynamic return types.

This commit is contained in:
chriseth 2015-06-22 18:05:13 +02:00
parent 2eabaa4716
commit 8639cf8e3d
3 changed files with 58 additions and 14 deletions

View File

@ -457,6 +457,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
strings(), strings(),
Location::Bare, Location::Bare,
false, false,
nullptr,
true, true,
true true
), ),
@ -1004,9 +1005,14 @@ void ExpressionCompiler::appendExternalFunctionCall(
_functionType.getReturnParameterTypes().empty() ? _functionType.getReturnParameterTypes().empty() ?
nullptr : nullptr :
_functionType.getReturnParameterTypes().front().get(); _functionType.getReturnParameterTypes().front().get();
unsigned retSize = firstReturnType ? firstReturnType->getCalldataEncodedSize() : 0; unsigned retSize = 0;
if (returnSuccessCondition) if (returnSuccessCondition)
retSize = 0; // return value actually is success condition retSize = 0; // return value actually is success condition
else if (firstReturnType)
{
retSize = firstReturnType->getCalldataEncodedSize();
solAssert(retSize > 0, "Unable to return dynamic type from external call.");
}
// Evaluate arguments. // Evaluate arguments.
TypePointers argumentTypes; TypePointers argumentTypes;
@ -1123,6 +1129,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
//@todo manually update free memory pointer if we accept returning memory-stored objects //@todo manually update free memory pointer if we accept returning memory-stored objects
utils().fetchFreeMemoryPointer(); utils().fetchFreeMemoryPointer();
utils().loadFromMemoryDynamic(*firstReturnType, false, true, false); utils().loadFromMemoryDynamic(*firstReturnType, false, true, false);
} }
} }

View File

@ -822,16 +822,16 @@ string ArrayType::toString(bool _short) const
TypePointer ArrayType::externalType() const TypePointer ArrayType::externalType() const
{ {
if (m_arrayKind != ArrayKind::Ordinary) if (m_arrayKind != ArrayKind::Ordinary)
return shared_from_this(); return this->copyForLocation(DataLocation::Memory, true);
if (!m_baseType->externalType()) if (!m_baseType->externalType())
return TypePointer(); return TypePointer();
if (m_baseType->getCategory() == Category::Array && m_baseType->isDynamicallySized()) if (m_baseType->getCategory() == Category::Array && m_baseType->isDynamicallySized())
return TypePointer(); return TypePointer();
if (isDynamicallySized()) if (isDynamicallySized())
return std::make_shared<ArrayType>(DataLocation::CallData, m_baseType->externalType()); return std::make_shared<ArrayType>(DataLocation::Memory, m_baseType->externalType());
else else
return std::make_shared<ArrayType>(DataLocation::CallData, m_baseType->externalType(), m_length); return std::make_shared<ArrayType>(DataLocation::Memory, m_baseType->externalType(), m_length);
} }
TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
@ -903,7 +903,7 @@ MemberList const& ContractType::getMembers() const
for (auto const& it: m_contract.getInterfaceFunctions()) for (auto const& it: m_contract.getInterfaceFunctions())
members.push_back(MemberList::Member( members.push_back(MemberList::Member(
it.second->getDeclaration().getName(), it.second->getDeclaration().getName(),
it.second, it.second->removeDynamicReturnTypes(),
&it.second->getDeclaration() &it.second->getDeclaration()
)); ));
m_members.reset(new MemberList(members)); m_members.reset(new MemberList(members));
@ -1084,7 +1084,11 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal
for (ASTPointer<VariableDeclaration> const& var: _function.getParameters()) for (ASTPointer<VariableDeclaration> const& var: _function.getParameters())
{ {
paramNames.push_back(var->getName()); paramNames.push_back(var->getName());
params.push_back(var->getType()); if (_isInternal)
params.push_back(var->getType());
else
params.push_back(var->getType()->externalType());
solAssert(!!params.back(), "Function argument type not valid in this context.");
} }
retParams.reserve(_function.getReturnParameters().size()); retParams.reserve(_function.getReturnParameters().size());
retParamNames.reserve(_function.getReturnParameters().size()); retParamNames.reserve(_function.getReturnParameters().size());
@ -1284,6 +1288,7 @@ MemberList const& FunctionType::getMembers() const
strings(), strings(),
Location::SetValue, Location::SetValue,
false, false,
nullptr,
m_gasSet, m_gasSet,
m_valueSet m_valueSet
) )
@ -1300,6 +1305,7 @@ MemberList const& FunctionType::getMembers() const
strings(), strings(),
Location::SetGas, Location::SetGas,
false, false,
nullptr,
m_gasSet, m_gasSet,
m_valueSet m_valueSet
) )
@ -1404,11 +1410,35 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con
m_returnParameterNames, m_returnParameterNames,
m_location, m_location,
m_arbitraryParameters, m_arbitraryParameters,
m_declaration,
m_gasSet || _setGas, m_gasSet || _setGas,
m_valueSet || _setValue m_valueSet || _setValue
); );
} }
FunctionTypePointer FunctionType::removeDynamicReturnTypes() const
{
//@todo make this more intelligent once we support destructuring assignments
TypePointers returnParameterTypes;
vector<string> returnParameterNames;
if (!m_returnParameterTypes.empty() && m_returnParameterTypes.front()->getCalldataEncodedSize() > 0)
{
returnParameterTypes.push_back(m_returnParameterTypes.front());
returnParameterNames.push_back(m_returnParameterNames.front());
}
return make_shared<FunctionType>(
m_parameterTypes,
returnParameterTypes,
m_parameterNames,
returnParameterNames,
m_location,
m_arbitraryParameters,
m_declaration,
m_gasSet,
m_valueSet
);
}
vector<string> const FunctionType::getParameterTypeNames() const vector<string> const FunctionType::getParameterTypeNames() const
{ {
vector<string> names; vector<string> names;

23
Types.h
View File

@ -669,17 +669,19 @@ public:
strings _returnParameterNames = strings(), strings _returnParameterNames = strings(),
Location _location = Location::Internal, Location _location = Location::Internal,
bool _arbitraryParameters = false, bool _arbitraryParameters = false,
Declaration const* _declaration = nullptr,
bool _gasSet = false, bool _gasSet = false,
bool _valueSet = false bool _valueSet = false
): ):
m_parameterTypes (_parameterTypes), m_parameterTypes(_parameterTypes),
m_returnParameterTypes (_returnParameterTypes), m_returnParameterTypes(_returnParameterTypes),
m_parameterNames (_parameterNames), m_parameterNames(_parameterNames),
m_returnParameterNames (_returnParameterNames), m_returnParameterNames(_returnParameterNames),
m_location (_location), m_location(_location),
m_arbitraryParameters (_arbitraryParameters), m_arbitraryParameters(_arbitraryParameters),
m_gasSet (_gasSet), m_gasSet(_gasSet),
m_valueSet (_valueSet) m_valueSet(_valueSet),
m_declaration(_declaration)
{} {}
TypePointers const& getParameterTypes() const { return m_parameterTypes; } TypePointers const& getParameterTypes() const { return m_parameterTypes; }
@ -733,6 +735,11 @@ public:
/// of the parameters to fals. /// of the parameters to fals.
TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const; TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const;
/// @returns a copy of this function type where all return parameters of dynamic size are removed.
/// This is needed if external functions are called internally, as they cannot return dynamic
/// values.
FunctionTypePointer removeDynamicReturnTypes() const;
private: private:
static TypePointers parseElementaryTypeVector(strings const& _types); static TypePointers parseElementaryTypeVector(strings const& _types);