aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-11-25 21:43:23 +0800
committerChristian <c@ethdev.com>2014-11-26 22:35:25 +0800
commita2715c5f34cfa4050ba64b4a1467b9ca5821472b (patch)
tree699b649087db7c9b5c9eb000fb452d404af7c755
parent6e6b85b58a478a7e2bc0f8bee976df97f9861b91 (diff)
downloaddexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.tar
dexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.tar.gz
dexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.tar.bz2
dexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.tar.lz
dexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.tar.xz
dexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.tar.zst
dexon-solidity-a2715c5f34cfa4050ba64b4a1467b9ca5821472b.zip
More general function types and references.
-rw-r--r--AST.cpp12
-rw-r--r--ExpressionCompiler.cpp10
-rw-r--r--Types.cpp41
-rw-r--r--Types.h38
4 files changed, 72 insertions, 29 deletions
diff --git a/AST.cpp b/AST.cpp
index 168a095c..5c07ec80 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -467,19 +467,19 @@ void FunctionCall::checkTypeRequirements()
//@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
// function parameters
- FunctionDefinition const& fun = dynamic_cast<FunctionType const&>(*expressionType).getFunction();
- vector<ASTPointer<VariableDeclaration>> const& parameters = fun.getParameters();
- if (parameters.size() != m_arguments.size())
+ FunctionType const& functionType = dynamic_cast<FunctionType const&>(*expressionType);
+ TypePointers const& parameterTypes = functionType.getParameterTypes();
+ if (parameterTypes.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
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."));
// @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
- if (fun.getReturnParameters().empty())
+ if (functionType.getReturnParameterTypes().empty())
m_type = make_shared<VoidType>();
else
- m_type = fun.getReturnParameters().front()->getType();
+ m_type = functionType.getReturnParameterTypes().front();
}
}
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index de8bc1d2..9e396874 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -183,16 +183,16 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
// Calling convention: Caller pushes return address and arguments
// 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();
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());
for (unsigned i = 0; i < arguments.size(); ++i)
{
arguments[i]->accept(*this);
- appendTypeConversion(*arguments[i]->getType(), *function.getParameters()[i]->getType());
+ appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i]);
}
_functionCall.getExpression().accept(*this);
@@ -200,11 +200,11 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
m_context << returnLabel;
// 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
// 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;
}
return false;
diff --git a/Types.cpp b/Types.cpp
index 616c9183..a6b18b10 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -189,7 +189,10 @@ u256 IntegerType::literalValue(Literal const& _literal) const
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
{
@@ -299,17 +302,49 @@ u256 StructType::getStorageOffsetOfMember(string const& _name) const
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
{
if (_other.getCategory() != getCategory())
return false;
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
{
- 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
diff --git a/Types.h b/Types.h
index 2dd4af64..17d9053b 100644
--- a/Types.h
+++ b/Types.h
@@ -39,6 +39,8 @@ namespace solidity
// @todo realMxN, string<N>
class Type; // forward
+using TypePointer = std::shared_ptr<Type const>;
+using TypePointers = std::vector<TypePointer>;
/**
* List of members of a type.
@@ -46,7 +48,6 @@ class Type; // forward
class MemberList
{
public:
- using TypePointer = std::shared_ptr<Type const>;
using MemberMap = std::map<std::string, TypePointer>;
MemberList() {}
@@ -54,7 +55,7 @@ public:
TypePointer getMemberType(std::string const& _name) const
{
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(); }
@@ -82,6 +83,7 @@ public:
static std::shared_ptr<Type> fromElementaryTypeName(Token::Value _typeToken);
static std::shared_ptr<Type> fromUserDefinedTypeName(UserDefinedTypeName 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
@@ -117,7 +119,7 @@ public:
/// Returns the list of all members of this type. Default implementation: no members.
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.
- 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 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
{
public:
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 std::string toString() const override;
@@ -263,7 +270,8 @@ public:
virtual bool canLiveOutsideStorage() const override { return false; }
private:
- FunctionDefinition const& m_function;
+ TypePointers m_parameterTypes;
+ TypePointers m_returnParameterTypes;
};
/**
@@ -273,19 +281,19 @@ class MappingType: public Type
{
public:
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) {}
virtual bool operator==(Type const& _other) const override;
virtual std::string toString() const override;
virtual bool canLiveOutsideStorage() const override { return false; }
- std::shared_ptr<Type const> getKeyType() const { return m_keyType; }
- std::shared_ptr<Type const> getValueType() const { return m_valueType; }
+ TypePointer getKeyType() const { return m_keyType; }
+ TypePointer getValueType() const { return m_valueType; }
private:
- std::shared_ptr<Type const> m_keyType;
- std::shared_ptr<Type const> m_valueType;
+ TypePointer m_keyType;
+ TypePointer m_valueType;
};
/**
@@ -312,9 +320,9 @@ class TypeType: public Type
{
public:
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 canBeStored() const override { return false; }
@@ -323,7 +331,7 @@ public:
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
private:
- std::shared_ptr<Type const> m_actualType;
+ TypePointer m_actualType;
};