Line data Source code
1 : /* valadostatement.vala
2 : *
3 : * Copyright (C) 2006-2009 Jürg Billeter
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2.1 of the License, or (at your option) any later version.
9 :
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 :
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 : using GLib;
24 :
25 : /**
26 : * Represents a do iteration statement in the source code.
27 : */
28 10 : public class Vala.DoStatement : Loop, Statement {
29 : /**
30 : * Creates a new do statement.
31 : *
32 : * @param condition loop condition
33 : * @param body loop body
34 : * @param source_reference reference to source code
35 : * @return newly created do statement
36 : */
37 27 : public DoStatement (Expression condition, Block body, SourceReference? source_reference = null) {
38 9 : base (condition, body, source_reference);
39 : }
40 :
41 9 : public override void accept (CodeVisitor visitor) {
42 9 : visitor.visit_do_statement (this);
43 : }
44 :
45 9 : public override void accept_children (CodeVisitor visitor) {
46 9 : body.accept (visitor);
47 :
48 9 : condition.accept (visitor);
49 :
50 9 : visitor.visit_end_full_expression (condition);
51 : }
52 :
53 9 : public override bool check (CodeContext context) {
54 9 : if (checked) {
55 0 : return !error;
56 : }
57 :
58 9 : checked = true;
59 :
60 : // convert to simple loop
61 :
62 : // do not generate variable and if block if condition is always true
63 9 : if (condition.is_always_true ()) {
64 3 : var loop = new LoopStatement (body, source_reference);
65 :
66 3 : unowned Block parent_block = (Block) parent_node;
67 3 : parent_block.replace_statement (this, loop);
68 :
69 3 : if (!loop.check (context)) {
70 0 : error = true;
71 : }
72 :
73 3 : return !error;
74 : }
75 :
76 6 : var block = new Block (source_reference);
77 :
78 6 : var first_local = new LocalVariable (context.analyzer.bool_type.copy (), get_temp_name (), new BooleanLiteral (true, source_reference), source_reference);
79 6 : block.add_statement (new DeclarationStatement (first_local, source_reference));
80 :
81 6 : var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
82 6 : var true_block = new Block (condition.source_reference);
83 6 : true_block.add_statement (new BreakStatement (condition.source_reference));
84 6 : var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
85 :
86 6 : var condition_block = new Block (condition.source_reference);
87 6 : condition_block.add_statement (if_stmt);
88 :
89 6 : var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, source_reference), source_reference), condition_block, null, source_reference);
90 6 : body.insert_statement (0, first_if);
91 6 : body.insert_statement (1, new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, source_reference), new BooleanLiteral (false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));
92 :
93 6 : block.add_statement (new LoopStatement (body, source_reference));
94 :
95 6 : unowned Block parent_block = (Block) parent_node;
96 6 : parent_block.replace_statement (this, block);
97 :
98 6 : if (!block.check (context)) {
99 0 : error = true;
100 : }
101 :
102 6 : return !error;
103 : }
104 : }
|