Syntax changes for catching custom errors.

This commit is contained in:
chriseth
2021-02-02 16:14:44 +01:00
parent b3261d7b0f
commit edf3529db6
11 changed files with 179 additions and 70 deletions
+4 -3
View File
@@ -856,13 +856,14 @@ string Literal::getChecksummedAddress() const
TryCatchClause const* TryStatement::successClause() const
{
solAssert(m_clauses.size() > 0, "");
solAssert(m_clauses.front()->kind() == TryCatchClause::Kind::Success, "");
return m_clauses[0].get();
}
TryCatchClause const* TryStatement::panicClause() const
{
for (size_t i = 1; i < m_clauses.size(); ++i)
if (m_clauses[i]->errorName() == "Panic")
if (m_clauses[i]->kind() == TryCatchClause::Kind::Panic)
return m_clauses[i].get();
return nullptr;
}
@@ -870,7 +871,7 @@ TryCatchClause const* TryStatement::panicClause() const
TryCatchClause const* TryStatement::errorClause() const
{
for (size_t i = 1; i < m_clauses.size(); ++i)
if (m_clauses[i]->errorName() == "Error")
if (m_clauses[i]->kind() == TryCatchClause::Kind::Error)
return m_clauses[i].get();
return nullptr;
}
@@ -878,7 +879,7 @@ TryCatchClause const* TryStatement::errorClause() const
TryCatchClause const* TryStatement::fallbackClause() const
{
for (size_t i = 1; i < m_clauses.size(); ++i)
if (m_clauses[i]->errorName().empty())
if (m_clauses[i]->kind() == TryCatchClause::Kind::Fallback)
return m_clauses[i].get();
return nullptr;
}
+23 -4
View File
@@ -1503,29 +1503,46 @@ private:
class TryCatchClause: public ASTNode, public Scopable, public ScopeOpener
{
public:
enum Kind
{
Success,
Panic,
Error,
Fallback,
UserDefined
};
TryCatchClause(
int64_t _id,
SourceLocation const& _location,
ASTPointer<ASTString> _errorName,
Kind _kind,
ASTPointer<IdentifierPath> _errorName,
ASTPointer<ParameterList> _parameters,
ASTPointer<Block> _block
):
ASTNode(_id, _location),
m_kind(_kind),
m_errorName(std::move(_errorName)),
m_parameters(std::move(_parameters)),
m_block(std::move(_block))
{}
{
solAssert(!!m_errorName == (m_kind == Kind::UserDefined), "");
}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;
ASTString const& errorName() const { return *m_errorName; }
Kind kind() const { return m_kind; }
/// @returns the name of the error. Should only be called if catch kind is UserDefined.
IdentifierPath const& errorName() const { return *m_errorName; }
ParameterList const* parameters() const { return m_parameters.get(); }
Block const& block() const { return *m_block; }
TryCatchClauseAnnotation& annotation() const override;
private:
ASTPointer<ASTString> m_errorName;
Kind m_kind;
ASTPointer<IdentifierPath> m_errorName;
ASTPointer<ParameterList> m_parameters;
ASTPointer<Block> m_block;
};
@@ -1535,6 +1552,8 @@ private:
* Syntax:
* try <call> returns (uint x, uint y) {
* // success code
* } catch Custom(uint data) {
* // custom error handler
* } catch Panic(uint errorCode) {
* // panic
* } catch Error(string memory cause) {
+17 -1
View File
@@ -578,7 +578,10 @@ bool ASTJsonConverter::visit(IfStatement const& _node)
bool ASTJsonConverter::visit(TryCatchClause const& _node)
{
setJsonNode(_node, "TryCatchClause", {
make_pair("errorName", _node.errorName()),
make_pair("kind", catchClauseKind(_node.kind())),
make_pair("errorName", toJsonOrNull(
_node.kind() == TryCatchClause::Kind::UserDefined ? &_node.errorName() : nullptr
)),
make_pair("parameters", toJsonOrNull(_node.parameters())),
make_pair("block", toJson(_node.block()))
});
@@ -931,6 +934,19 @@ string ASTJsonConverter::functionCallKind(FunctionCallKind _kind)
}
}
string ASTJsonConverter::catchClauseKind(TryCatchClause::Kind _kind)
{
switch (_kind)
{
case TryCatchClause::Kind::Success: return "success";
case TryCatchClause::Kind::Panic: return "panic";
case TryCatchClause::Kind::Error: return "error";
case TryCatchClause::Kind::Fallback: return "fallback";
case TryCatchClause::Kind::UserDefined: return "userDefined";
}
solAssert(false, "Unknown kind of catch clause.");
}
string ASTJsonConverter::literalTokenKind(Token _token)
{
switch (_token)
+1
View File
@@ -153,6 +153,7 @@ private:
static std::string location(VariableDeclaration::Location _location);
static std::string contractKind(ContractKind _kind);
static std::string functionCallKind(FunctionCallKind _kind);
static std::string catchClauseKind(TryCatchClause::Kind _kind);
static std::string literalTokenKind(Token _token);
static std::string type(Expression const& _expression);
static std::string type(VariableDeclaration const& _varDecl);
+20 -1
View File
@@ -642,7 +642,8 @@ ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json::Value con
{
return createASTNode<TryCatchClause>(
_node,
memberAsASTString(_node, "errorName"),
tryCatchClauseKind(_node),
nullOrCast<IdentifierPath>(member(_node, "errorName")),
nullOrCast<ParameterList>(member(_node, "parameters")),
convertJsonToASTNode<Block>(member(_node, "block"))
);
@@ -959,6 +960,24 @@ bool ASTJsonImporter::memberAsBool(Json::Value const& _node, string const& _name
// =========== JSON to definition helpers =======================
TryCatchClause::Kind ASTJsonImporter::tryCatchClauseKind(Json::Value const& _node)
{
astAssert(!member(_node, "kind").isNull(), "");
if (_node["kind"].asString() == "success")
return TryCatchClause::Kind::Success;
else if (_node["kind"].asString() == "error")
return TryCatchClause::Kind::Error;
else if (_node["kind"].asString() == "panic")
return TryCatchClause::Kind::Panic;
else if (_node["kind"].asString() == "fallback")
return TryCatchClause::Kind::Fallback;
else if (_node["kind"].asString() == "userDefined")
return TryCatchClause::Kind::UserDefined;
else
astAssert(false, "Unknown try catch clause kind");
return {};
}
ContractKind ASTJsonImporter::contractKind(Json::Value const& _node)
{
ContractKind kind;
+1
View File
@@ -144,6 +144,7 @@ private:
Visibility visibility(Json::Value const& _node);
StateMutability stateMutability(Json::Value const& _node);
VariableDeclaration::Location location(Json::Value const& _node);
TryCatchClause::Kind tryCatchClauseKind(Json::Value const& _node);
ContractKind contractKind(Json::Value const& _node);
Token literalTokenKind(Json::Value const& _node);
Literal::SubDenomination subdenomination(Json::Value const& _node);
+4
View File
@@ -542,6 +542,8 @@ void TryCatchClause::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
{
if (m_errorName)
m_errorName->accept(_visitor);
if (m_parameters)
m_parameters->accept(_visitor);
m_block->accept(_visitor);
@@ -553,6 +555,8 @@ void TryCatchClause::accept(ASTConstVisitor& _visitor) const
{
if (_visitor.visit(*this))
{
if (m_errorName)
m_errorName->accept(_visitor);
if (m_parameters)
m_parameters->accept(_visitor);
m_block->accept(_visitor);