Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a40dcfe

Browse files
authored
Merge pull request argotorg#768 from roadriverrail/do_while_loops
Add support for do/while loops
2 parents 81118de + 4524ad0 commit a40dcfe

File tree

11 files changed

+92
-11
lines changed

11 files changed

+92
-11
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
### 0.4.5 (unreleased)
22

3+
Features:
4+
* Do-while loops: support for a C-style do{<block>}while(<expr>); control structure
5+
36
### 0.4.4 (2016-10-31)
47

58
Bugfixes:

docs/control-structures.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
Expressions and Control Structures
33
##################################
44

5-
.. index:: if, else, while, for, break, continue, return, switch, goto
5+
.. index:: if, else, while, do/while, for, break, continue, return, switch, goto
66

77
Control Structures
88
===================
99

1010
Most of the control structures from C or JavaScript are available in Solidity
1111
except for ``switch`` and ``goto``. So
12-
there is: ``if``, ``else``, ``while``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with
12+
there is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with
1313
the usual semantics known from C or JavaScript.
1414

1515
Parentheses can *not* be omitted for conditionals, but curly brances can be omitted

libsolidity/ast/AST.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,18 +1005,22 @@ class WhileStatement: public BreakableStatement
10051005
SourceLocation const& _location,
10061006
ASTPointer<ASTString> const& _docString,
10071007
ASTPointer<Expression> const& _condition,
1008-
ASTPointer<Statement> const& _body
1008+
ASTPointer<Statement> const& _body,
1009+
bool _isDoWhile
10091010
):
1010-
BreakableStatement(_location, _docString), m_condition(_condition), m_body(_body) {}
1011+
BreakableStatement(_location, _docString), m_condition(_condition), m_body(_body),
1012+
m_isDoWhile(_isDoWhile) {}
10111013
virtual void accept(ASTVisitor& _visitor) override;
10121014
virtual void accept(ASTConstVisitor& _visitor) const override;
10131015

10141016
Expression const& condition() const { return *m_condition; }
10151017
Statement const& body() const { return *m_body; }
1018+
bool isDoWhile() const { return m_isDoWhile; }
10161019

10171020
private:
10181021
ASTPointer<Expression> m_condition;
10191022
ASTPointer<Statement> m_body;
1023+
bool m_isDoWhile;
10201024
};
10211025

10221026
/**

libsolidity/ast/ASTJsonConverter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,11 @@ bool ASTJsonConverter::visit(IfStatement const& _node)
264264

265265
bool ASTJsonConverter::visit(WhileStatement const& _node)
266266
{
267-
addJsonNode(_node, "WhileStatement", {}, true);
267+
addJsonNode(
268+
_node,
269+
_node.isDoWhile() ? "DoWhileStatement" : "WhileStatement",
270+
{},
271+
true);
268272
return true;
269273
}
270274

libsolidity/ast/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ bool ASTPrinter::visit(IfStatement const& _node)
208208

209209
bool ASTPrinter::visit(WhileStatement const& _node)
210210
{
211-
writeLine("WhileStatement");
211+
writeLine(_node.isDoWhile() ? "DoWhileStatement" : "WhileStatement");
212212
printSourcePart(_node);
213213
return goDeeper();
214214
}

libsolidity/codegen/ContractCompiler.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,12 +611,25 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
611611
m_breakTags.push_back(loopEnd);
612612

613613
m_context << loopStart;
614-
compileExpression(_whileStatement.condition());
615-
m_context << Instruction::ISZERO;
616-
m_context.appendConditionalJumpTo(loopEnd);
614+
615+
// While loops have the condition prepended
616+
if (!_whileStatement.isDoWhile())
617+
{
618+
compileExpression(_whileStatement.condition());
619+
m_context << Instruction::ISZERO;
620+
m_context.appendConditionalJumpTo(loopEnd);
621+
}
617622

618623
_whileStatement.body().accept(*this);
619624

625+
// Do-while loops have the condition appended
626+
if (_whileStatement.isDoWhile())
627+
{
628+
compileExpression(_whileStatement.condition());
629+
m_context << Instruction::ISZERO;
630+
m_context.appendConditionalJumpTo(loopEnd);
631+
}
632+
620633
m_context.appendJumpTo(loopStart);
621634
m_context << loopEnd;
622635

libsolidity/formal/Why3Translator.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,16 @@ bool Why3Translator::visit(WhileStatement const& _node)
410410
{
411411
addSourceFromDocStrings(_node.annotation());
412412

413+
// Why3 does not appear to support do-while loops,
414+
// so we will simulate them by performing a while
415+
// loop with the body prepended once.
416+
417+
if (_node.isDoWhile())
418+
{
419+
visitIndentedUnlessBlock(_node.body());
420+
newLine();
421+
}
422+
413423
add("while ");
414424
_node.condition().accept(*this);
415425
newLine();

libsolidity/grammar.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ ArrayTypeName = TypeName StorageLocation? '[' Expression? ']'
4141
StorageLocation = 'memory' | 'storage'
4242

4343
Block = '{' Statement* '}'
44-
Statement = IfStatement | WhileStatement | ForStatement | Block |
44+
Statement = IfStatement | WhileStatement | DoWhileStatement | ForStatement | Block |
4545
( PlaceholderStatement | Continue | Break | Return |
4646
Throw | SimpleStatement ) ';'
4747

@@ -51,6 +51,7 @@ WhileStatement = 'while' '(' Expression ')' Statement
5151
PlaceholderStatement = '_'
5252
SimpleStatement = VariableDefinition | ExpressionStatement
5353
ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement
54+
DoWhileStatement = 'do' Statement 'while' '(' Expression ')' ';'
5455
Continue = 'continue'
5556
Break = 'break'
5657
Return = 'return' Expression?

libsolidity/parsing/Parser.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,8 @@ ASTPointer<Statement> Parser::parseStatement()
722722
return parseIfStatement(docString);
723723
case Token::While:
724724
return parseWhileStatement(docString);
725+
case Token::Do:
726+
return parseDoWhileStatement(docString);
725727
case Token::For:
726728
return parseForStatement(docString);
727729
case Token::LBrace:
@@ -816,9 +818,24 @@ ASTPointer<WhileStatement> Parser::parseWhileStatement(ASTPointer<ASTString> con
816818
expectToken(Token::RParen);
817819
ASTPointer<Statement> body = parseStatement();
818820
nodeFactory.setEndPositionFromNode(body);
819-
return nodeFactory.createNode<WhileStatement>(_docString, condition, body);
821+
return nodeFactory.createNode<WhileStatement>(_docString, condition, body, false);
820822
}
821823

824+
ASTPointer<WhileStatement> Parser::parseDoWhileStatement(ASTPointer<ASTString> const& _docString)
825+
{
826+
ASTNodeFactory nodeFactory(*this);
827+
expectToken(Token::Do);
828+
ASTPointer<Statement> body = parseStatement();
829+
expectToken(Token::While);
830+
expectToken(Token::LParen);
831+
ASTPointer<Expression> condition = parseExpression();
832+
expectToken(Token::RParen);
833+
nodeFactory.markEndPosition();
834+
expectToken(Token::Semicolon);
835+
return nodeFactory.createNode<WhileStatement>(_docString, condition, body, true);
836+
}
837+
838+
822839
ASTPointer<ForStatement> Parser::parseForStatement(ASTPointer<ASTString> const& _docString)
823840
{
824841
ASTNodeFactory nodeFactory(*this);

libsolidity/parsing/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class Parser: public ParserBase
8585
ASTPointer<InlineAssembly> parseInlineAssembly(ASTPointer<ASTString> const& _docString = {});
8686
ASTPointer<IfStatement> parseIfStatement(ASTPointer<ASTString> const& _docString);
8787
ASTPointer<WhileStatement> parseWhileStatement(ASTPointer<ASTString> const& _docString);
88+
ASTPointer<WhileStatement> parseDoWhileStatement(ASTPointer<ASTString> const& _docString);
8889
ASTPointer<ForStatement> parseForStatement(ASTPointer<ASTString> const& _docString);
8990
/// A "simple statement" can be a variable declaration statement or an expression statement.
9091
ASTPointer<Statement> parseSimpleStatement(ASTPointer<ASTString> const& _docString);

0 commit comments

Comments
 (0)