Parsing of not fully implemented functions

- Adding the possibility of omitting a function body by simply ending a
  function definition with a semicolon

- Such a function is marked as not fully implemented and any contract
  that contains such a function is considered a not fully implemented contract
This commit is contained in:
Lefteris Karapetsas 2015-03-20 17:50:26 +01:00
parent 8f8e407306
commit 9d6d7ccab8
4 changed files with 89 additions and 39 deletions

View File

@ -311,8 +311,8 @@ void FunctionDefinition::checkTypeRequirements()
modifier->checkTypeRequirements(isConstructor() ?
dynamic_cast<ContractDefinition const&>(*getScope()).getBaseContracts() :
vector<ASTPointer<InheritanceSpecifier>>());
m_body->checkTypeRequirements();
if (m_body)
m_body->checkTypeRequirements();
}
string FunctionDefinition::getCanonicalSignature() const

85
AST.h
View File

@ -196,6 +196,21 @@ protected:
ASTPointer<ASTString> m_documentation;
};
/**
* Abstract class that is added to AST nodes that can be marked as not being fully implemented
*/
class ImplementationOptional
{
public:
explicit ImplementationOptional(bool _implemented): m_implemented(_implemented) {}
/// @return whether this node is fully implemented or not
bool isFullyImplemented() const { return m_implemented; }
protected:
bool m_implemented;
};
/// @}
/**
@ -203,20 +218,25 @@ protected:
* document order. It first visits all struct declarations, then all variable declarations and
* finally all function declarations.
*/
class ContractDefinition: public Declaration, public Documented
class ContractDefinition: public Declaration, public Documented, public ImplementationOptional
{
public:
ContractDefinition(SourceLocation const& _location,
ASTPointer<ASTString> const& _name,
ASTPointer<ASTString> const& _documentation,
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
std::vector<ASTPointer<EnumDefinition>> const& _definedEnums,
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
std::vector<ASTPointer<EventDefinition>> const& _events):
Declaration(_location, _name), Documented(_documentation),
ContractDefinition(
SourceLocation const& _location,
ASTPointer<ASTString> const& _name,
ASTPointer<ASTString> const& _documentation,
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
std::vector<ASTPointer<EnumDefinition>> const& _definedEnums,
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
std::vector<ASTPointer<EventDefinition>> const& _events,
bool _isFullyImplemented
):
Declaration(_location, _name),
Documented(_documentation),
ImplementationOptional(_isFullyImplemented),
m_baseContracts(_baseContracts),
m_definedStructs(_definedStructs),
m_definedEnums(_definedEnums),
@ -224,7 +244,7 @@ public:
m_definedFunctions(_definedFunctions),
m_functionModifiers(_functionModifiers),
m_events(_events)
{}
{}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
@ -378,25 +398,30 @@ private:
std::vector<ASTPointer<VariableDeclaration>> m_parameters;
};
class FunctionDefinition: public Declaration, public VariableScope, public Documented
class FunctionDefinition: public Declaration, public VariableScope, public Documented, public ImplementationOptional
{
public:
FunctionDefinition(SourceLocation const& _location, ASTPointer<ASTString> const& _name,
Declaration::Visibility _visibility, bool _isConstructor,
ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters,
bool _isDeclaredConst,
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body):
Declaration(_location, _name, _visibility), Documented(_documentation),
m_isConstructor(_isConstructor),
m_parameters(_parameters),
m_isDeclaredConst(_isDeclaredConst),
m_functionModifiers(_modifiers),
m_returnParameters(_returnParameters),
m_body(_body)
{}
FunctionDefinition(
SourceLocation const& _location,
ASTPointer<ASTString> const& _name,
Declaration::Visibility _visibility, bool _isConstructor,
ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters,
bool _isDeclaredConst,
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body
):
Declaration(_location, _name, _visibility),
Documented(_documentation),
ImplementationOptional(_body != nullptr),
m_isConstructor(_isConstructor),
m_parameters(_parameters),
m_isDeclaredConst(_isDeclaredConst),
m_functionModifiers(_modifiers),
m_returnParameters(_returnParameters),
m_body(_body)
{}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;

View File

@ -175,7 +175,8 @@ void FunctionDefinition::accept(ASTVisitor& _visitor)
if (m_returnParameters)
m_returnParameters->accept(_visitor);
listAccept(m_functionModifiers, _visitor);
m_body->accept(_visitor);
if (m_body)
m_body->accept(_visitor);
}
_visitor.endVisit(*this);
}
@ -188,7 +189,8 @@ void FunctionDefinition::accept(ASTConstVisitor& _visitor) const
if (m_returnParameters)
m_returnParameters->accept(_visitor);
listAccept(m_functionModifiers, _visitor);
m_body->accept(_visitor);
if (m_body)
m_body->accept(_visitor);
}
_visitor.endVisit(*this);
}

View File

@ -116,6 +116,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
{
ASTNodeFactory nodeFactory(*this);
ASTPointer<ASTString> docString;
bool contractFullyImplemented = true;
if (m_scanner->getCurrentCommentLiteral() != "")
docString = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
expectToken(Token::Contract);
@ -141,7 +142,12 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
if (currentToken == Token::RBrace)
break;
else if (currentToken == Token::Function)
functions.push_back(parseFunctionDefinition(name.get()));
{
ASTPointer<FunctionDefinition> func = parseFunctionDefinition(name.get());
functions.push_back(func);
if (!func->isFullyImplemented())
contractFullyImplemented = false;
}
else if (currentToken == Token::Struct)
structs.push_back(parseStructDefinition());
else if (currentToken == Token::Enum)
@ -164,8 +170,18 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
}
nodeFactory.markEndPosition();
expectToken(Token::RBrace);
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs, enums,
stateVariables, functions, modifiers, events);
return nodeFactory.createNode<ContractDefinition>(
name,
docString,
baseContracts,
structs,
enums,
stateVariables,
functions,
modifiers,
events,
contractFullyImplemented
);
}
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
@ -247,8 +263,15 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const*
}
else
returnParameters = createEmptyParameterList();
ASTPointer<Block> block = parseBlock();
nodeFactory.setEndPositionFromNode(block);
ASTPointer<Block> block = ASTPointer<Block>();
nodeFactory.markEndPosition();
if (m_scanner->getCurrentToken() != Token::Semicolon)
{
block = parseBlock();
nodeFactory.setEndPositionFromNode(block);
}
else
m_scanner->next(); // just consume the ';'
bool const c_isConstructor = (_contractName && *name == *_contractName);
return nodeFactory.createNode<FunctionDefinition>(name, visibility, c_isConstructor, docstring,
parameters, isDeclaredConst, modifiers,