}
if (stop_at_loop) {
- if (b.parent_node is DoStatement || b.parent_node is WhileStatement ||
+ if (b.parent_node is DoStatement || b.parent_node is Loop ||
b.parent_node is ForStatement || b.parent_node is ForeachStatement ||
b.parent_node is SwitchStatement) {
return;
label.accept_children (codegen);
}
- public override void visit_while_statement (WhileStatement stmt) {
+ public override void visit_loop (Loop stmt) {
stmt.accept_children (codegen);
- stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
-
- create_temp_decl (stmt, stmt.condition.temp_vars);
+ stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("TRUE"), (CCodeStatement) stmt.body.ccodenode);
}
public override void visit_do_statement (DoStatement stmt) {
head.visit_switch_label (label);
}
- public override void visit_while_statement (WhileStatement stmt) {
- head.visit_while_statement (stmt);
+ public override void visit_loop (Loop stmt) {
+ head.visit_loop (stmt);
}
public override void visit_do_statement (DoStatement stmt) {
next.visit_switch_label (label);
}
- public virtual void visit_while_statement (WhileStatement stmt) {
- next.visit_while_statement (stmt);
+ public virtual void visit_loop (Loop stmt) {
+ next.visit_loop (stmt);
}
public virtual void visit_do_statement (DoStatement stmt) {
valalocalvariable.vala \
valalockable.vala \
valalockstatement.vala \
+ valaloop.vala \
valamember.vala \
valamemberaccess.vala \
valamemberinitializer.vala \
* @param stmt a statement
*/
public void add_statement (Statement stmt) {
+ stmt.parent_node = this;
statement_list.add (stmt);
}
public void insert_statement (int index, Statement stmt) {
+ stmt.parent_node = this;
statement_list.insert (index, stmt);
}
public virtual void visit_switch_label (SwitchLabel label) {
}
+ /**
+ * Visit operation called for loops.
+ *
+ * @param stmt a loop
+ */
+ public virtual void visit_loop (Loop stmt) {
+ }
+
/**
* Visit operation called for while statements.
*
}
}
+ public override void visit_loop (Loop stmt) {
+ write_indent ();
+ write_string ("loop");
+ stmt.body.accept (this);
+ write_newline ();
+ }
+
public override void visit_while_statement (WhileStatement stmt) {
write_indent ();
write_string ("while (");
}
public Block prepare_condition_split (SemanticAnalyzer analyzer) {
- var while_stmt = parent_statement as WhileStatement;
var do_stmt = parent_statement as DoStatement;
var for_stmt = parent_statement as ForStatement;
- if (while_stmt != null) {
- return while_stmt.prepare_condition_split (analyzer);
- } else if (do_stmt != null) {
+ if (do_stmt != null) {
return do_stmt.prepare_condition_split (analyzer);
} else if (for_stmt != null) {
return for_stmt.prepare_condition_split (analyzer);
jump_stack.remove_at (jump_stack.size - 1);
}
- public override void visit_while_statement (WhileStatement stmt) {
+ public override void visit_loop (Loop stmt) {
if (unreachable (stmt)) {
return;
}
- var condition_block = new BasicBlock ();
- jump_stack.add (new JumpTarget.continue_target (condition_block));
+ var loop_block = new BasicBlock ();
+ jump_stack.add (new JumpTarget.continue_target (loop_block));
var after_loop_block = new BasicBlock ();
jump_stack.add (new JumpTarget.break_target (after_loop_block));
- // condition
+ // loop block
var last_block = current_block;
- last_block.connect (condition_block);
- current_block = condition_block;
- current_block.add_node (stmt.condition);
-
- handle_errors (stmt.condition);
+ last_block.connect (loop_block);
+ current_block = loop_block;
- // loop block
- if (always_false (stmt.condition)) {
- current_block = null;
- unreachable_reported = false;
- } else {
- current_block = new BasicBlock ();
- condition_block.connect (current_block);
- }
stmt.body.accept (this);
// end of loop block reachable?
if (current_block != null) {
- current_block.connect (condition_block);
+ current_block.connect (loop_block);
}
// after loop
// reachable?
- if (always_true (stmt.condition) && after_loop_block.get_predecessors ().size == 0) {
+ if (after_loop_block.get_predecessors ().size == 0) {
+ // after loop block not reachable
current_block = null;
unreachable_reported = false;
} else {
- condition_block.connect (after_loop_block);
+ // after loop block reachable
current_block = after_loop_block;
}
--- /dev/null
+/* valaloop.vala
+ *
+ * Copyright (C) 2009 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents an endless loop.
+ */
+public class Vala.Loop : CodeNode, Statement {
+ /**
+ * Specifies the loop body.
+ */
+ public Block body {
+ get {
+ return _body;
+ }
+ set {
+ _body = value;
+ _body.parent_node = this;
+ }
+ }
+
+ private Block _body;
+
+ /**
+ * Creates a new loop.
+ *
+ * @param body loop body
+ * @param source reference to source code
+ * @return newly created while statement
+ */
+ public Loop (Block body, SourceReference? source_reference = null) {
+ this.body = body;
+ this.source_reference = source_reference;
+ }
+
+ public override void accept (CodeVisitor visitor) {
+ visitor.visit_loop (this);
+ }
+
+ public override void accept_children (CodeVisitor visitor) {
+ body.accept (visitor);
+ }
+
+ public override bool check (SemanticAnalyzer analyzer) {
+ if (checked) {
+ return !error;
+ }
+
+ checked = true;
+
+ body.check (analyzer);
+
+ add_error_types (body.get_error_types ());
+
+ return !error;
+ }
+}
+
/* valanullchecker.vala
*
- * Copyright (C) 2008 Jürg Billeter
+ * Copyright (C) 2008-2009 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
section.accept_children (this);
}
- public override void visit_while_statement (WhileStatement stmt) {
+ public override void visit_loop (Loop stmt) {
stmt.accept_children (this);
-
- check_non_null (stmt.condition);
}
public override void visit_do_statement (DoStatement stmt) {
label.accept_children (this);
}
+ public override void visit_loop (Loop stmt) {
+ stmt.accept_children (this);
+ }
+
public override void visit_while_statement (WhileStatement stmt) {
stmt.accept_children (this);
}
/* valawhilestatement.vala
*
- * Copyright (C) 2006-2008 Jürg Billeter
+ * Copyright (C) 2006-2009 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
body.accept (visitor);
}
- public override void replace_expression (Expression old_node, Expression new_node) {
- if (condition == old_node) {
- condition = new_node;
- }
+ bool always_true (Expression condition) {
+ var literal = condition as BooleanLiteral;
+ return (literal != null && literal.value);
}
public override bool check (SemanticAnalyzer analyzer) {
- if (checked) {
- return !error;
- }
-
- checked = true;
-
- condition.check (analyzer);
-
- body.check (analyzer);
-
- if (condition.error) {
- /* if there was an error in the condition, skip this check */
- error = true;
- return false;
+ // convert to simple loop
+
+ // do not generate if block if condition is always true
+ if (!always_true (condition)) {
+ var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
+ var true_block = new Block (condition.source_reference);
+ true_block.add_statement (new BreakStatement (condition.source_reference));
+ var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
+ body.insert_statement (0, if_stmt);
}
- if (!condition.value_type.compatible (analyzer.bool_type)) {
- error = true;
- Report.error (condition.source_reference, "Condition must be boolean");
- return false;
- }
-
- add_error_types (condition.get_error_types ());
- add_error_types (body.get_error_types ());
-
- return !error;
- }
-
- public Block prepare_condition_split (SemanticAnalyzer analyzer) {
- // move condition into the loop body to allow split
- // in multiple statements
-
- var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
- var true_block = new Block (condition.source_reference);
- true_block.add_statement (new BreakStatement (condition.source_reference));
- var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
- body.insert_statement (0, if_stmt);
+ var loop = new Loop (body, source_reference);
- condition = new BooleanLiteral (true, source_reference);
- condition.check (analyzer);
+ var parent_block = (Block) parent_node;
+ parent_block.replace_statement (this, loop);
- return body;
+ return loop.check (analyzer);
}
}