throw statement implementation

This commit is contained in:
LianaHus 2015-09-15 16:33:14 +02:00
parent 9d43f2c186
commit 279a36b6f8
14 changed files with 94 additions and 1 deletions

View File

@ -968,6 +968,18 @@ private:
ParameterList const* m_returnParameters;
};
/**
* @brief The Throw statement to throw that triggers a solidity exception(jump to ErrorTag)
*/
class Throw: public Statement
{
public:
Throw(SourceLocation const& _location): Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override{};
};
/**
* Definition of a variable as a statement inside a function. It requires a type name (which can
* also be "var") but the actual assignment can be missing.

View File

@ -64,6 +64,7 @@ class ForStatement;
class Continue;
class Break;
class Return;
class Throw;
class VariableDeclarationStatement;
class ExpressionStatement;
class Expression;

View File

@ -193,6 +193,12 @@ bool ASTJsonConverter::visit(Return const&)
return true;
}
bool ASTJsonConverter::visit(Throw const&)
{
addJsonNode("Throw", {}, true);;
return true;
}
bool ASTJsonConverter::visit(VariableDeclarationStatement const&)
{
addJsonNode("VariableDefinition", {}, true);
@ -364,6 +370,11 @@ void ASTJsonConverter::endVisit(Return const&)
goUp();
}
void ASTJsonConverter::endVisit(Throw const&)
{
goUp();
}
void ASTJsonConverter::endVisit(VariableDeclarationStatement const&)
{
goUp();

View File

@ -63,6 +63,7 @@ public:
bool visit(Continue const& _node) override;
bool visit(Break const& _node) override;
bool visit(Return const& _node) override;
bool visit(Throw const& _node) override;
bool visit(VariableDeclarationStatement const& _node) override;
bool visit(ExpressionStatement const& _node) override;
bool visit(Assignment const& _node) override;
@ -93,6 +94,7 @@ public:
void endVisit(Continue const&) override;
void endVisit(Break const&) override;
void endVisit(Return const&) override;
void endVisit(Throw const&) override;
void endVisit(VariableDeclarationStatement const&) override;
void endVisit(ExpressionStatement const&) override;
void endVisit(Assignment const&) override;

View File

@ -221,6 +221,13 @@ bool ASTPrinter::visit(Return const& _node)
return goDeeper();
}
bool ASTPrinter::visit(Throw const& _node)
{
writeLine("Throw");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(VariableDeclarationStatement const& _node)
{
writeLine("VariableDeclarationStatement");
@ -444,6 +451,11 @@ void ASTPrinter::endVisit(Return const&)
m_indentation--;
}
void ASTPrinter::endVisit(Throw const&)
{
m_indentation--;
}
void ASTPrinter::endVisit(VariableDeclarationStatement const&)
{
m_indentation--;

View File

@ -72,6 +72,7 @@ public:
bool visit(Continue const& _node) override;
bool visit(Break const& _node) override;
bool visit(Return const& _node) override;
bool visit(Throw const& _node) override;
bool visit(VariableDeclarationStatement const& _node) override;
bool visit(ExpressionStatement const& _node) override;
bool visit(Assignment const& _node) override;
@ -110,6 +111,7 @@ public:
void endVisit(Continue const&) override;
void endVisit(Break const&) override;
void endVisit(Return const&) override;
void endVisit(Throw const&) override;
void endVisit(VariableDeclarationStatement const&) override;
void endVisit(ExpressionStatement const&) override;
void endVisit(Assignment const&) override;

View File

@ -69,6 +69,7 @@ public:
virtual bool visit(Continue& _node) { return visitNode(_node); }
virtual bool visit(Break& _node) { return visitNode(_node); }
virtual bool visit(Return& _node) { return visitNode(_node); }
virtual bool visit(Throw& _node) { return visitNode(_node); }
virtual bool visit(VariableDeclarationStatement& _node) { return visitNode(_node); }
virtual bool visit(ExpressionStatement& _node) { return visitNode(_node); }
virtual bool visit(Assignment& _node) { return visitNode(_node); }
@ -108,6 +109,7 @@ public:
virtual void endVisit(Continue& _node) { endVisitNode(_node); }
virtual void endVisit(Break& _node) { endVisitNode(_node); }
virtual void endVisit(Return& _node) { endVisitNode(_node); }
virtual void endVisit(Throw& _node) { endVisitNode(_node); }
virtual void endVisit(VariableDeclarationStatement& _node) { endVisitNode(_node); }
virtual void endVisit(ExpressionStatement& _node) { endVisitNode(_node); }
virtual void endVisit(Assignment& _node) { endVisitNode(_node); }
@ -159,6 +161,7 @@ public:
virtual bool visit(Continue const& _node) { return visitNode(_node); }
virtual bool visit(Break const& _node) { return visitNode(_node); }
virtual bool visit(Return const& _node) { return visitNode(_node); }
virtual bool visit(Throw const& _node) { return visitNode(_node); }
virtual bool visit(VariableDeclarationStatement const& _node) { return visitNode(_node); }
virtual bool visit(ExpressionStatement const& _node) { return visitNode(_node); }
virtual bool visit(Assignment const& _node) { return visitNode(_node); }
@ -198,6 +201,7 @@ public:
virtual void endVisit(Continue const& _node) { endVisitNode(_node); }
virtual void endVisit(Break const& _node) { endVisitNode(_node); }
virtual void endVisit(Return const& _node) { endVisitNode(_node); }
virtual void endVisit(Throw const& _node) { endVisitNode(_node); }
virtual void endVisit(VariableDeclarationStatement const& _node) { endVisitNode(_node); }
virtual void endVisit(ExpressionStatement const& _node) { endVisitNode(_node); }
virtual void endVisit(Assignment const& _node) { endVisitNode(_node); }

View File

@ -491,6 +491,18 @@ void Return::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
void Throw::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
_visitor.endVisit(*this);
}
void Throw::accept(ASTConstVisitor& _visitor) const
{
if (_visitor.visit(*this))
_visitor.endVisit(*this);
}
void ExpressionStatement::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))

View File

@ -606,6 +606,13 @@ bool Compiler::visit(Return const& _return)
return false;
}
bool Compiler::visit(Throw const& _throw)
{
CompilerContext::LocationSetter locationSetter(m_context, _throw);
m_context.appendJumpTo(m_context.errorTag());
return false;
}
bool Compiler::visit(VariableDeclarationStatement const& _variableDeclarationStatement)
{
StackHeightChecker checker(m_context);

View File

@ -112,6 +112,7 @@ private:
virtual bool visit(Continue const& _continue) override;
virtual bool visit(Break const& _break) override;
virtual bool visit(Return const& _return) override;
virtual bool visit(Throw const& _throw) override;
virtual bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override;
virtual bool visit(ExpressionStatement const& _expressionStatement) override;
virtual bool visit(PlaceholderStatement const&) override;

View File

@ -622,6 +622,16 @@ ASTPointer<Statement> Parser::parseStatement()
statement = nodeFactory.createNode<Return>(expression);
break;
}
case Token::Throw:
{
ASTNodeFactory nodeFactory(*this);
ASTPointer<Expression> expression;
if (m_scanner->next() != Token::Semicolon)
BOOST_THROW_EXCEPTION(createParserError("Throw statement cannot have parameters."));
statement = nodeFactory.createNode<Throw>(/*expression*/);
break;
}
case Token::Identifier:
if (m_insideModifier && m_scanner->currentLiteral() == "_")
{

View File

@ -171,6 +171,7 @@ namespace solidity
K(Returns, "returns", 0) \
K(Storage, "storage", 0) \
K(Struct, "struct", 0) \
K(Throw, "throw", 0) \
K(Var, "var", 0) \
K(While, "while", 0) \
\
@ -316,7 +317,6 @@ namespace solidity
K(Of, "of", 0) \
K(Relocatable, "relocatable", 0) \
K(Switch, "switch", 0) \
K(Throw, "throw", 0) \
K(Try, "try", 0) \
K(Type, "type", 0) \
K(TypeOf, "typeof", 0) \

View File

@ -34,6 +34,7 @@ ForStatement = 'for' '(' (VardefOrExprStmt)? ';' (Expression)? ';' (ExpressionSt
Continue = 'continue' ';'
Break = 'break' ';'
Return = 'return' Expression? ';'
Throw = 'throw' Expression? ';'
VariableDefinition = VariableDeclaration ( = Expression )? ';'
Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | NewExpression | IndexAccess |

View File

@ -5265,6 +5265,24 @@ BOOST_AUTO_TEST_CASE(library_stray_values)
BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(42)));
}
BOOST_AUTO_TEST_CASE(simple_throw)
{
char const* sourceCode = R"(
contract Test {
function f(uint x) returns (uint) {
if (x > 10)
return x + 10;
else
throw;
return 2;
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256)", u256(11)) == encodeArgs(u256(21)));
BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs());
}
BOOST_AUTO_TEST_SUITE_END()
}