diff options
author | Christian <c@ethdev.com> | 2014-11-25 21:43:23 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-11-26 22:35:25 +0800 |
commit | a2715c5f34cfa4050ba64b4a1467b9ca5821472b (patch) | |
tree | 699b649087db7c9b5c9eb000fb452d404af7c755 | |
parent | 6e6b85b58a478a7e2bc0f8bee976df97f9861b91 (diff) | |
download | dexon-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.cpp | 12 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 10 | ||||
-rw-r--r-- | Types.cpp | 41 | ||||
-rw-r--r-- | Types.h | 38 |
4 files changed, 72 insertions, 29 deletions
@@ -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; @@ -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 @@ -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; }; |