mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
AST for try and catch.
This commit is contained in:
parent
9ecd51c54d
commit
a66c354698
@ -448,12 +448,16 @@ bool VariableDeclaration::isLocalVariable() const
|
||||
dynamic_cast<FunctionTypeName const*>(s) ||
|
||||
dynamic_cast<CallableDeclaration const*>(s) ||
|
||||
dynamic_cast<Block const*>(s) ||
|
||||
dynamic_cast<TryCatchClause const*>(s) ||
|
||||
dynamic_cast<ForStatement const*>(s);
|
||||
}
|
||||
|
||||
bool VariableDeclaration::isCallableParameter() const
|
||||
{
|
||||
if (isReturnParameter())
|
||||
// TODO Adjust for catch params.
|
||||
// I think catch params should return true here.
|
||||
// some of the error strings would need to be adjusted.
|
||||
if (isReturnParameter() || dynamic_cast<TryCatchClause const*>(scope()))
|
||||
return true;
|
||||
|
||||
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
||||
@ -472,6 +476,7 @@ bool VariableDeclaration::isCallableParameter() const
|
||||
|
||||
bool VariableDeclaration::isLocalOrReturn() const
|
||||
{
|
||||
// TODO adjust for catch params
|
||||
return isReturnParameter() || (isLocalVariable() && !isCallableParameter());
|
||||
}
|
||||
|
||||
|
@ -553,7 +553,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter list, used as function parameter list and return list.
|
||||
* Parameter list, used as function parameter list, return list and for try and catch.
|
||||
* None of the parameters is allowed to contain mappings (not even recursively
|
||||
* inside structs).
|
||||
*/
|
||||
@ -1174,6 +1174,76 @@ private:
|
||||
ASTPointer<Statement> m_falseBody; ///< "else" part, optional
|
||||
};
|
||||
|
||||
/**
|
||||
* Clause of a try-catch block. Includes both the successful case and the
|
||||
* unsuccessful cases.
|
||||
* Names are only allowed for the unsuccessful cases.
|
||||
*/
|
||||
class TryCatchClause: public ASTNode, public Scopable
|
||||
{
|
||||
public:
|
||||
TryCatchClause(
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ASTString> const& _errorName,
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
ASTPointer<Block> const& _block
|
||||
):
|
||||
ASTNode(_location),
|
||||
m_errorName(_errorName),
|
||||
m_parameters(_parameters),
|
||||
m_block(_block)
|
||||
{}
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
ASTString const& errorName() const { return *m_errorName; }
|
||||
ParameterList const* parameters() const { return m_parameters.get(); }
|
||||
Block const& block() const { return *m_block; }
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_errorName;
|
||||
ASTPointer<ParameterList> m_parameters;
|
||||
ASTPointer<Block> m_block;
|
||||
};
|
||||
|
||||
/**
|
||||
* Try-statement with a variable number of catch statements.
|
||||
* Syntax:
|
||||
* try <call> returns (uint x, uint y) {
|
||||
* // success code
|
||||
* } catch Error(string memory cause) {
|
||||
* // error code, reason provided
|
||||
* } catch (bytes memory lowLevelData) {
|
||||
* // error code, no reason provided or non-matching error signature.
|
||||
* }
|
||||
*
|
||||
* The last statement given above can also be specified as
|
||||
* } catch () {
|
||||
*/
|
||||
class TryStatement: public Statement
|
||||
{
|
||||
public:
|
||||
TryStatement(
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ASTString> const& _docString,
|
||||
ASTPointer<Expression> const& _externalCall,
|
||||
std::vector<ASTPointer<TryCatchClause>> const& _clauses
|
||||
):
|
||||
Statement(_location, _docString),
|
||||
m_externalCall(_externalCall),
|
||||
m_clauses(_clauses)
|
||||
{}
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
Expression const& externalCall() const { return *m_externalCall; }
|
||||
std::vector<ASTPointer<TryCatchClause>> const& clauses() const { return m_clauses; }
|
||||
|
||||
private:
|
||||
ASTPointer<Expression> m_externalCall;
|
||||
std::vector<ASTPointer<TryCatchClause>> m_clauses;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statement in which a break statement is legal (abstract class).
|
||||
*/
|
||||
|
@ -218,6 +218,8 @@ enum class FunctionCallKind
|
||||
struct FunctionCallAnnotation: ExpressionAnnotation
|
||||
{
|
||||
FunctionCallKind kind = FunctionCallKind::Unset;
|
||||
/// If true, this is the external call of a try statement.
|
||||
bool tryCall = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -64,6 +64,8 @@ class Statement;
|
||||
class Block;
|
||||
class PlaceholderStatement;
|
||||
class IfStatement;
|
||||
class TryCatchClause;
|
||||
class TryStatement;
|
||||
class BreakableStatement;
|
||||
class WhileStatement;
|
||||
class ForStatement;
|
||||
|
@ -499,6 +499,25 @@ bool ASTJsonConverter::visit(IfStatement const& _node)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonConverter::visit(TryCatchClause const& _node)
|
||||
{
|
||||
setJsonNode(_node, "TryCatchClause", {
|
||||
make_pair("errorName", _node.errorName()),
|
||||
make_pair("parameters", toJsonOrNull(_node.parameters())),
|
||||
make_pair("block", toJson(_node.block()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonConverter::visit(TryStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "TryStatement", {
|
||||
make_pair("externalCall", toJson(_node.externalCall())),
|
||||
make_pair("clauses", toJson(_node.clauses()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonConverter::visit(WhileStatement const& _node)
|
||||
{
|
||||
setJsonNode(
|
||||
@ -647,7 +666,8 @@ bool ASTJsonConverter::visit(FunctionCall const& _node)
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("expression", toJson(_node.expression())),
|
||||
make_pair("names", std::move(names)),
|
||||
make_pair("arguments", toJson(_node.arguments()))
|
||||
make_pair("arguments", toJson(_node.arguments())),
|
||||
make_pair("tryCall", _node.annotation().tryCall)
|
||||
};
|
||||
if (m_legacy)
|
||||
{
|
||||
|
@ -93,6 +93,8 @@ public:
|
||||
bool visit(Block const& _node) override;
|
||||
bool visit(PlaceholderStatement const& _node) override;
|
||||
bool visit(IfStatement const& _node) override;
|
||||
bool visit(TryCatchClause const& _node) override;
|
||||
bool visit(TryStatement const& _node) override;
|
||||
bool visit(WhileStatement const& _node) override;
|
||||
bool visit(ForStatement const& _node) override;
|
||||
bool visit(Continue const& _node) override;
|
||||
|
@ -69,6 +69,8 @@ public:
|
||||
virtual bool visit(Block& _node) { return visitNode(_node); }
|
||||
virtual bool visit(PlaceholderStatement& _node) { return visitNode(_node); }
|
||||
virtual bool visit(IfStatement& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TryCatchClause& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TryStatement& _node) { return visitNode(_node); }
|
||||
virtual bool visit(WhileStatement& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ForStatement& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Continue& _node) { return visitNode(_node); }
|
||||
@ -117,6 +119,8 @@ public:
|
||||
virtual void endVisit(Block& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(PlaceholderStatement& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(IfStatement& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TryCatchClause& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TryStatement& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(WhileStatement& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ForStatement& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Continue& _node) { endVisitNode(_node); }
|
||||
@ -177,6 +181,8 @@ public:
|
||||
virtual bool visit(Block const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(PlaceholderStatement const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(IfStatement const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TryCatchClause const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TryStatement const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(WhileStatement const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ForStatement const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Continue const& _node) { return visitNode(_node); }
|
||||
@ -225,6 +231,8 @@ public:
|
||||
virtual void endVisit(Block const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(PlaceholderStatement const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(IfStatement const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TryCatchClause const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TryStatement const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(WhileStatement const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ForStatement const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Continue const& _node) { endVisitNode(_node); }
|
||||
|
@ -461,6 +461,48 @@ void IfStatement::accept(ASTConstVisitor& _visitor) const
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void TryCatchClause::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_parameters)
|
||||
m_parameters->accept(_visitor);
|
||||
m_block->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void TryCatchClause::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
if (m_parameters)
|
||||
m_parameters->accept(_visitor);
|
||||
m_block->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void TryStatement::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_externalCall->accept(_visitor);
|
||||
listAccept(m_clauses, _visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void TryStatement::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_externalCall->accept(_visitor);
|
||||
listAccept(m_clauses, _visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void WhileStatement::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
|
Loading…
Reference in New Issue
Block a user