mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
More general function types and references.
This commit is contained in:
parent
6e6b85b58a
commit
a2715c5f34
12
AST.cpp
12
AST.cpp
@ -467,19 +467,19 @@ void FunctionCall::checkTypeRequirements()
|
|||||||
//@todo would be nice to create a struct type from the arguments
|
//@todo would be nice to create a struct type from the arguments
|
||||||
// and then ask if that is implicitly convertible to the struct represented by the
|
// and then ask if that is implicitly convertible to the struct represented by the
|
||||||
// function parameters
|
// function parameters
|
||||||
FunctionDefinition const& fun = dynamic_cast<FunctionType const&>(*expressionType).getFunction();
|
FunctionType const& functionType = dynamic_cast<FunctionType const&>(*expressionType);
|
||||||
vector<ASTPointer<VariableDeclaration>> const& parameters = fun.getParameters();
|
TypePointers const& parameterTypes = functionType.getParameterTypes();
|
||||||
if (parameters.size() != m_arguments.size())
|
if (parameterTypes.size() != m_arguments.size())
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
|
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
|
||||||
for (size_t i = 0; i < m_arguments.size(); ++i)
|
for (size_t i = 0; i < m_arguments.size(); ++i)
|
||||||
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameters[i]->getType()))
|
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
|
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
|
||||||
// @todo actually the return type should be an anonymous struct,
|
// @todo actually the return type should be an anonymous struct,
|
||||||
// but we change it to the type of the first return value until we have structs
|
// but we change it to the type of the first return value until we have structs
|
||||||
if (fun.getReturnParameters().empty())
|
if (functionType.getReturnParameterTypes().empty())
|
||||||
m_type = make_shared<VoidType>();
|
m_type = make_shared<VoidType>();
|
||||||
else
|
else
|
||||||
m_type = fun.getReturnParameters().front()->getType();
|
m_type = functionType.getReturnParameterTypes().front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,16 +183,16 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
|
|
||||||
// Calling convention: Caller pushes return address and arguments
|
// Calling convention: Caller pushes return address and arguments
|
||||||
// Callee removes them and pushes return values
|
// Callee removes them and pushes return values
|
||||||
FunctionDefinition const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType()).getFunction();
|
FunctionType const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType());
|
||||||
|
|
||||||
eth::AssemblyItem returnLabel = m_context.pushNewTag();
|
eth::AssemblyItem returnLabel = m_context.pushNewTag();
|
||||||
std::vector<ASTPointer<Expression>> const& arguments = _functionCall.getArguments();
|
std::vector<ASTPointer<Expression>> const& arguments = _functionCall.getArguments();
|
||||||
if (asserts(arguments.size() == function.getParameters().size()))
|
if (asserts(arguments.size() == function.getParameterTypes().size()))
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
for (unsigned i = 0; i < arguments.size(); ++i)
|
for (unsigned i = 0; i < arguments.size(); ++i)
|
||||||
{
|
{
|
||||||
arguments[i]->accept(*this);
|
arguments[i]->accept(*this);
|
||||||
appendTypeConversion(*arguments[i]->getType(), *function.getParameters()[i]->getType());
|
appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i]);
|
||||||
}
|
}
|
||||||
_functionCall.getExpression().accept(*this);
|
_functionCall.getExpression().accept(*this);
|
||||||
|
|
||||||
@ -200,11 +200,11 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
m_context << returnLabel;
|
m_context << returnLabel;
|
||||||
|
|
||||||
// callee adds return parameters, but removes arguments and return label
|
// callee adds return parameters, but removes arguments and return label
|
||||||
m_context.adjustStackOffset(function.getReturnParameters().size() - arguments.size() - 1);
|
m_context.adjustStackOffset(function.getReturnParameterTypes().size() - arguments.size() - 1);
|
||||||
|
|
||||||
// @todo for now, the return value of a function is its first return value, so remove
|
// @todo for now, the return value of a function is its first return value, so remove
|
||||||
// all others
|
// all others
|
||||||
for (unsigned i = 1; i < function.getReturnParameters().size(); ++i)
|
for (unsigned i = 1; i < function.getReturnParameterTypes().size(); ++i)
|
||||||
m_context << eth::Instruction::POP;
|
m_context << eth::Instruction::POP;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
41
Types.cpp
41
Types.cpp
@ -189,7 +189,10 @@ u256 IntegerType::literalValue(Literal const& _literal) const
|
|||||||
return u256(value);
|
return u256(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MemberList IntegerType::AddressMemberList = MemberList({{"balance", std::make_shared<IntegerType const>(256)}});
|
const MemberList IntegerType::AddressMemberList =
|
||||||
|
MemberList({{"balance", make_shared<IntegerType const>(256)},
|
||||||
|
{"send", make_shared<FunctionType const>(TypePointers({make_shared<IntegerType const>(256)}),
|
||||||
|
TypePointers())}});
|
||||||
|
|
||||||
bool BoolType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
bool BoolType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
{
|
{
|
||||||
@ -299,17 +302,49 @@ u256 StructType::getStorageOffsetOfMember(string const& _name) const
|
|||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionType::FunctionType(FunctionDefinition const& _function)
|
||||||
|
{
|
||||||
|
TypePointers params;
|
||||||
|
TypePointers retParams;
|
||||||
|
params.reserve(_function.getParameters().size());
|
||||||
|
for (ASTPointer<VariableDeclaration> const& var: _function.getParameters())
|
||||||
|
params.push_back(var->getType());
|
||||||
|
retParams.reserve(_function.getReturnParameters().size());
|
||||||
|
for (ASTPointer<VariableDeclaration> const& var: _function.getReturnParameters())
|
||||||
|
retParams.push_back(var->getType());
|
||||||
|
swap(params, m_parameterTypes);
|
||||||
|
swap(retParams, m_returnParameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
bool FunctionType::operator==(Type const& _other) const
|
bool FunctionType::operator==(Type const& _other) const
|
||||||
{
|
{
|
||||||
if (_other.getCategory() != getCategory())
|
if (_other.getCategory() != getCategory())
|
||||||
return false;
|
return false;
|
||||||
FunctionType const& other = dynamic_cast<FunctionType const&>(_other);
|
FunctionType const& other = dynamic_cast<FunctionType const&>(_other);
|
||||||
return other.m_function == m_function;
|
|
||||||
|
if (m_parameterTypes.size() != other.m_parameterTypes.size() ||
|
||||||
|
m_returnParameterTypes.size() != other.m_returnParameterTypes.size())
|
||||||
|
return false;
|
||||||
|
auto typeCompare = [](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; };
|
||||||
|
|
||||||
|
if (!equal(m_parameterTypes.cbegin(), m_parameterTypes.cend(),
|
||||||
|
other.m_parameterTypes.cbegin(), typeCompare))
|
||||||
|
return false;
|
||||||
|
if (!equal(m_returnParameterTypes.cbegin(), m_returnParameterTypes.cend(),
|
||||||
|
other.m_returnParameterTypes.cbegin(), typeCompare))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string FunctionType::toString() const
|
string FunctionType::toString() const
|
||||||
{
|
{
|
||||||
return "function " + m_function.getName();
|
string name = "function (";
|
||||||
|
for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
|
||||||
|
name += (*it)->toString() + (it + 1 == m_parameterTypes.end() ? "" : ",");
|
||||||
|
name += ") returns (";
|
||||||
|
for (auto it = m_returnParameterTypes.begin(); it != m_returnParameterTypes.end(); ++it)
|
||||||
|
name += (*it)->toString() + (it + 1 == m_returnParameterTypes.end() ? "" : ",");
|
||||||
|
return name + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MappingType::operator==(Type const& _other) const
|
bool MappingType::operator==(Type const& _other) const
|
||||||
|
38
Types.h
38
Types.h
@ -39,6 +39,8 @@ namespace solidity
|
|||||||
// @todo realMxN, string<N>
|
// @todo realMxN, string<N>
|
||||||
|
|
||||||
class Type; // forward
|
class Type; // forward
|
||||||
|
using TypePointer = std::shared_ptr<Type const>;
|
||||||
|
using TypePointers = std::vector<TypePointer>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of members of a type.
|
* List of members of a type.
|
||||||
@ -46,7 +48,6 @@ class Type; // forward
|
|||||||
class MemberList
|
class MemberList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using TypePointer = std::shared_ptr<Type const>;
|
|
||||||
using MemberMap = std::map<std::string, TypePointer>;
|
using MemberMap = std::map<std::string, TypePointer>;
|
||||||
|
|
||||||
MemberList() {}
|
MemberList() {}
|
||||||
@ -54,7 +55,7 @@ public:
|
|||||||
TypePointer getMemberType(std::string const& _name) const
|
TypePointer getMemberType(std::string const& _name) const
|
||||||
{
|
{
|
||||||
auto it = m_memberTypes.find(_name);
|
auto it = m_memberTypes.find(_name);
|
||||||
return it != m_memberTypes.end() ? it->second : std::shared_ptr<Type const>();
|
return it != m_memberTypes.end() ? it->second : TypePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberMap::const_iterator begin() const { return m_memberTypes.begin(); }
|
MemberMap::const_iterator begin() const { return m_memberTypes.begin(); }
|
||||||
@ -82,6 +83,7 @@ public:
|
|||||||
static std::shared_ptr<Type> fromElementaryTypeName(Token::Value _typeToken);
|
static std::shared_ptr<Type> fromElementaryTypeName(Token::Value _typeToken);
|
||||||
static std::shared_ptr<Type> fromUserDefinedTypeName(UserDefinedTypeName const& _typeName);
|
static std::shared_ptr<Type> fromUserDefinedTypeName(UserDefinedTypeName const& _typeName);
|
||||||
static std::shared_ptr<Type> fromMapping(Mapping const& _typeName);
|
static std::shared_ptr<Type> fromMapping(Mapping const& _typeName);
|
||||||
|
static std::shared_ptr<Type> fromFunction(FunctionDefinition const& _function);
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||||
@ -117,7 +119,7 @@ public:
|
|||||||
/// Returns the list of all members of this type. Default implementation: no members.
|
/// Returns the list of all members of this type. Default implementation: no members.
|
||||||
virtual MemberList const& getMembers() const { return EmptyMemberList; }
|
virtual MemberList const& getMembers() const { return EmptyMemberList; }
|
||||||
/// Convenience method, returns the type of the given named member or an empty pointer if no such member exists.
|
/// Convenience method, returns the type of the given named member or an empty pointer if no such member exists.
|
||||||
std::shared_ptr<Type const> getMemberType(std::string const& _name) const { return getMembers().getMemberType(_name); }
|
TypePointer getMemberType(std::string const& _name) const { return getMembers().getMemberType(_name); }
|
||||||
|
|
||||||
virtual std::string toString() const = 0;
|
virtual std::string toString() const = 0;
|
||||||
virtual u256 literalValue(Literal const&) const
|
virtual u256 literalValue(Literal const&) const
|
||||||
@ -246,15 +248,20 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of a function, there is one distinct type per function definition.
|
* The type of a function, identified by its (return) parameter types.
|
||||||
|
* @todo the return parameters should also have names, i.e. return parameters should be a struct
|
||||||
|
* type.
|
||||||
*/
|
*/
|
||||||
class FunctionType: public Type
|
class FunctionType: public Type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Category getCategory() const override { return Category::FUNCTION; }
|
virtual Category getCategory() const override { return Category::FUNCTION; }
|
||||||
FunctionType(FunctionDefinition const& _function): m_function(_function) {}
|
explicit FunctionType(FunctionDefinition const& _function);
|
||||||
|
FunctionType(TypePointers const& _parameterTypes, TypePointers const& _returnParameterTypes):
|
||||||
|
m_parameterTypes(_parameterTypes), m_returnParameterTypes(_returnParameterTypes) {}
|
||||||
|
|
||||||
FunctionDefinition const& getFunction() const { return m_function; }
|
TypePointers const& getParameterTypes() const { return m_parameterTypes; }
|
||||||
|
TypePointers const& getReturnParameterTypes() const { return m_returnParameterTypes; }
|
||||||
|
|
||||||
virtual bool operator==(Type const& _other) const override;
|
virtual bool operator==(Type const& _other) const override;
|
||||||
virtual std::string toString() const override;
|
virtual std::string toString() const override;
|
||||||
@ -263,7 +270,8 @@ public:
|
|||||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FunctionDefinition const& m_function;
|
TypePointers m_parameterTypes;
|
||||||
|
TypePointers m_returnParameterTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -273,19 +281,19 @@ class MappingType: public Type
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Category getCategory() const override { return Category::MAPPING; }
|
virtual Category getCategory() const override { return Category::MAPPING; }
|
||||||
MappingType(std::shared_ptr<Type const> _keyType, std::shared_ptr<Type const> _valueType):
|
MappingType(TypePointer const& _keyType, TypePointer const& _valueType):
|
||||||
m_keyType(_keyType), m_valueType(_valueType) {}
|
m_keyType(_keyType), m_valueType(_valueType) {}
|
||||||
|
|
||||||
virtual bool operator==(Type const& _other) const override;
|
virtual bool operator==(Type const& _other) const override;
|
||||||
virtual std::string toString() const override;
|
virtual std::string toString() const override;
|
||||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||||
|
|
||||||
std::shared_ptr<Type const> getKeyType() const { return m_keyType; }
|
TypePointer getKeyType() const { return m_keyType; }
|
||||||
std::shared_ptr<Type const> getValueType() const { return m_valueType; }
|
TypePointer getValueType() const { return m_valueType; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Type const> m_keyType;
|
TypePointer m_keyType;
|
||||||
std::shared_ptr<Type const> m_valueType;
|
TypePointer m_valueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -312,9 +320,9 @@ class TypeType: public Type
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Category getCategory() const override { return Category::TYPE; }
|
virtual Category getCategory() const override { return Category::TYPE; }
|
||||||
TypeType(std::shared_ptr<Type const> const& _actualType): m_actualType(_actualType) {}
|
TypeType(TypePointer const& _actualType): m_actualType(_actualType) {}
|
||||||
|
|
||||||
std::shared_ptr<Type const> const& getActualType() const { return m_actualType; }
|
TypePointer const& getActualType() const { return m_actualType; }
|
||||||
|
|
||||||
virtual bool operator==(Type const& _other) const override;
|
virtual bool operator==(Type const& _other) const override;
|
||||||
virtual bool canBeStored() const override { return false; }
|
virtual bool canBeStored() const override { return false; }
|
||||||
@ -323,7 +331,7 @@ public:
|
|||||||
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
|
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Type const> m_actualType;
|
TypePointer m_actualType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user