make it work for var x = f;

This commit is contained in:
Lu Guanqun 2015-03-05 23:02:35 -06:00
parent ddcfd441f3
commit 4033615464
4 changed files with 32 additions and 21 deletions

29
AST.cpp
View File

@ -674,15 +674,23 @@ void FunctionCall::checkTypeRequirements()
else if (OverloadedFunctionType const* overloadedTypes = dynamic_cast<OverloadedFunctionType const*>(expressionType)) else if (OverloadedFunctionType const* overloadedTypes = dynamic_cast<OverloadedFunctionType const*>(expressionType))
{ {
// this only applies to "x(3)" where x is assigned by "var x = f;" where f is an overloaded functions. // this only applies to "x(3)" where x is assigned by "var x = f;" where f is an overloaded functions.
overloadedTypes->m_identifier->overloadResolution(*this); auto identifier = dynamic_cast<Identifier*>(m_expression.get());
FunctionType const* functionType = dynamic_cast<FunctionType const*>(overloadedTypes->m_identifier->getType().get()); solAssert(identifier, "only applies to 'var x = f;'");
Declaration const* function = overloadedTypes->getIdentifier()->overloadResolution(*this);
if (!function)
BOOST_THROW_EXCEPTION(createTypeError("Can't resolve declarations"));
identifier->setReferencedDeclaration(*function);
identifier->checkTypeRequirements();
TypePointer type = identifier->getType();
FunctionType const* functionType = dynamic_cast<FunctionType const*>(type.get());
// @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 (functionType->getReturnParameterTypes().empty()) if (functionType->getReturnParameterTypes().empty())
m_type = make_shared<VoidType>(); m_type = make_shared<VoidType>();
else else
m_type = functionType->getReturnParameterTypes().front(); m_type = functionType->getReturnParameterTypes().front();
} }
else else
BOOST_THROW_EXCEPTION(createTypeError("Type is not callable.")); BOOST_THROW_EXCEPTION(createTypeError("Type is not callable."));
@ -781,7 +789,7 @@ void Identifier::checkTypeRequirementsWithFunctionCall(FunctionCall const& _func
solAssert(m_referencedDeclaration || !m_overloadedDeclarations.empty(), "Identifier not resolved."); solAssert(m_referencedDeclaration || !m_overloadedDeclarations.empty(), "Identifier not resolved.");
if (!m_referencedDeclaration) if (!m_referencedDeclaration)
overloadResolution(_functionCall); setReferencedDeclaration(*overloadResolution(_functionCall));
checkTypeRequirements(); checkTypeRequirements();
} }
@ -791,7 +799,7 @@ void Identifier::checkTypeRequirementsFromVariableDeclaration()
solAssert(m_referencedDeclaration || !m_overloadedDeclarations.empty(), "Identifier not resolved."); solAssert(m_referencedDeclaration || !m_overloadedDeclarations.empty(), "Identifier not resolved.");
if (!m_referencedDeclaration) if (!m_referencedDeclaration)
m_type = make_shared<OverloadedFunctionType>(m_overloadedDeclarations, this); m_type = make_shared<OverloadedFunctionType>(this);
else else
checkTypeRequirements(); checkTypeRequirements();
@ -808,13 +816,11 @@ void Identifier::checkTypeRequirements()
BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined.")); BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined."));
} }
void Identifier::overloadResolution(FunctionCall const& _functionCall) Declaration const* Identifier::overloadResolution(FunctionCall const& _functionCall)
{ {
solAssert(m_overloadedDeclarations.size() > 1, "FunctionIdentifier not resolved."); solAssert(m_overloadedDeclarations.size() > 1, "FunctionIdentifier not resolved.");
solAssert(!m_referencedDeclaration, "Referenced declaration should be null before overload resolution."); solAssert(!m_referencedDeclaration, "Referenced declaration should be null before overload resolution.");
bool resolved = false;
std::vector<ASTPointer<Expression const>> arguments = _functionCall.getArguments(); std::vector<ASTPointer<Expression const>> arguments = _functionCall.getArguments();
std::vector<ASTPointer<ASTString>> const& argumentNames = _functionCall.getNames(); std::vector<ASTPointer<ASTString>> const& argumentNames = _functionCall.getNames();
@ -844,7 +850,7 @@ void Identifier::overloadResolution(FunctionCall const& _functionCall)
{ {
return declaration->getScope() == possibles.front()->getScope(); return declaration->getScope() == possibles.front()->getScope();
})) }))
setReferencedDeclaration(*possibles.front()); return possibles.front();
else else
BOOST_THROW_EXCEPTION(createTypeError("Can't resolve identifier")); BOOST_THROW_EXCEPTION(createTypeError("Can't resolve identifier"));
} }
@ -852,6 +858,7 @@ void Identifier::overloadResolution(FunctionCall const& _functionCall)
// named arguments // named arguments
// TODO: don't support right now // TODO: don't support right now
BOOST_THROW_EXCEPTION(createTypeError("Named arguments with overloaded functions are not supported yet.")); BOOST_THROW_EXCEPTION(createTypeError("Named arguments with overloaded functions are not supported yet."));
return nullptr;
} }
void ElementaryTypeNameExpression::checkTypeRequirements() void ElementaryTypeNameExpression::checkTypeRequirements()

2
AST.h
View File

@ -1157,7 +1157,7 @@ public:
void checkTypeRequirementsWithFunctionCall(FunctionCall const& _functionCall); void checkTypeRequirementsWithFunctionCall(FunctionCall const& _functionCall);
void checkTypeRequirementsFromVariableDeclaration(); void checkTypeRequirementsFromVariableDeclaration();
void overloadResolution(FunctionCall const& _functionCall); Declaration const* overloadResolution(FunctionCall const& _functionCall);
private: private:
ASTPointer<ASTString> m_name; ASTPointer<ASTString> m_name;

View File

@ -822,11 +822,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
void ExpressionCompiler::endVisit(Identifier const& _identifier) void ExpressionCompiler::endVisit(Identifier const& _identifier)
{ {
Declaration const* declaration = _identifier.getReferencedDeclaration(); Declaration const* declaration = _identifier.getReferencedDeclaration();
if (declaration == nullptr) if (MagicVariableDeclaration const* magicVar = dynamic_cast<MagicVariableDeclaration const*>(declaration))
{
// no-op
}
else if (MagicVariableDeclaration const* magicVar = dynamic_cast<MagicVariableDeclaration const*>(declaration))
{ {
if (magicVar->getType()->getCategory() == Type::Category::Contract) if (magicVar->getType()->getCategory() == Type::Category::Contract)
// "this" or "super" // "this" or "super"
@ -849,6 +845,13 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
{ {
// no-op // no-op
} }
else if (declaration == nullptr && _identifier.getOverloadedDeclarations().size() > 1)
{
// var x = f;
declaration = *_identifier.getOverloadedDeclarations().begin();
FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration);
m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag();
}
else else
{ {
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context.")); BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));

View File

@ -527,13 +527,14 @@ private:
class OverloadedFunctionType: public Type class OverloadedFunctionType: public Type
{ {
public: public:
explicit OverloadedFunctionType(std::set<Declaration const*> const& _overloadedDeclarations, Identifier* _identifier): explicit OverloadedFunctionType(Identifier* _identifier): m_identifier(_identifier) {}
m_overloadedDeclarations(_overloadedDeclarations), m_identifier(_identifier) {}
virtual Category getCategory() const override { return Category::OverloadedFunctions; } virtual Category getCategory() const override { return Category::OverloadedFunctions; }
virtual std::string toString() const override { return "OverloadedFunctions"; } virtual std::string toString() const override { return "OverloadedFunctions"; }
// private: Identifier* getIdentifier() const { return m_identifier; }
std::set<Declaration const*> m_overloadedDeclarations;
private:
Identifier * m_identifier; Identifier * m_identifier;
}; };