[vala/wip/transform: 16/102] Move ForStatement transformation into the code transformer
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 16/102] Move ForStatement transformation into the code transformer
- Date: Tue, 23 Oct 2018 20:43:20 +0000 (UTC)
commit b8e1bef94589e5c6df43f2ba27cc60de2ce873cd
Author: Luca Bruno <lucabru src gnome org>
Date: Wed Aug 31 10:51:08 2011 +0200
Move ForStatement transformation into the code transformer
vala/valacodetransformer.vala | 44 ++++++++++++++++++++++++++-
vala/valaflowanalyzer.vala | 69 +++++++++++++++++++++++++++++++++++++++++++
vala/valaforstatement.vala | 65 ++++++++++++++++------------------------
3 files changed, 138 insertions(+), 40 deletions(-)
---
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 826403338..893bb18c4 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -244,7 +244,49 @@ public class Vala.CodeTransformer : CodeVisitor {
}
public override void visit_for_statement (ForStatement stmt) {
- stmt.accept_children (this);
+ // convert to simple loop
+
+ var block = new Block (stmt.source_reference);
+
+ // initializer
+ foreach (var init_expr in stmt.get_initializer ()) {
+ block.add_statement (new ExpressionStatement (init_expr, init_expr.source_reference));
+ }
+
+ // do not generate if block if condition is always true
+ if (stmt.condition == null || always_true (stmt.condition)) {
+ } else if (always_false (stmt.condition)) {
+ // do not generate if block if condition is always false
+ stmt.body.insert_statement (0, new BreakStatement (stmt.condition.source_reference));
+ } else {
+ // condition
+ var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION,
stmt.condition, stmt.condition.source_reference);
+ var true_block = new Block (stmt.condition.source_reference);
+ true_block.add_statement (new BreakStatement (stmt.condition.source_reference));
+ var if_stmt = new IfStatement (if_condition, true_block, null,
stmt.condition.source_reference);
+ stmt.body.insert_statement (0, if_stmt);
+ }
+
+ // iterator
+ var first_local = new LocalVariable (context.analyzer.bool_type.copy (), stmt.get_temp_name
(), new BooleanLiteral (true, stmt.source_reference), stmt.source_reference);
+ block.add_statement (new DeclarationStatement (first_local, stmt.source_reference));
+
+ var iterator_block = new Block (stmt.source_reference);
+ foreach (var it_expr in stmt.get_iterator ()) {
+ iterator_block.add_statement (new ExpressionStatement (it_expr,
it_expr.source_reference));
+ }
+
+ var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new
MemberAccess.simple (first_local.name, stmt.source_reference), stmt.source_reference), iterator_block, null,
stmt.source_reference);
+ stmt.body.insert_statement (0, first_if);
+ stmt.body.insert_statement (1, new ExpressionStatement (new Assignment (new
MemberAccess.simple (first_local.name, stmt.source_reference), new BooleanLiteral (false,
stmt.source_reference), AssignmentOperator.SIMPLE, stmt.source_reference), stmt.source_reference));
+
+ block.add_statement (new Loop (stmt.body, stmt.source_reference));
+
+ var parent_block = (Block) stmt.parent_node;
+ parent_block.replace_statement (stmt, block);
+
+ stmt.body.checked = false;
+ check (block);
}
public override void visit_foreach_statement (ForeachStatement stmt) {
diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index d91675e3a..a1cbcb24d 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -804,6 +804,75 @@ public class Vala.FlowAnalyzer : CodeVisitor {
jump_stack.remove_at (jump_stack.size - 1);
}
+
+ public override void visit_for_statement (ForStatement stmt) {
+ if (unreachable (stmt)) {
+ return;
+ }
+
+ var outer_block = new BasicBlock ();
+ all_basic_blocks.add (outer_block);
+ foreach (var init_expr in stmt.get_initializer ()) {
+ outer_block.add_node (init_expr);
+ }
+
+ var iterator_block = new BasicBlock ();
+ all_basic_blocks.add (iterator_block);
+ foreach (var it_expr in stmt.get_iterator ()) {
+ iterator_block.add_node (it_expr);
+ }
+
+ var loop_block = new BasicBlock ();
+ all_basic_blocks.add (loop_block);
+
+ var after_loop_block = new BasicBlock ();
+ all_basic_blocks.add (after_loop_block);
+
+ jump_stack.add (new JumpTarget.continue_target (iterator_block));
+ jump_stack.add (new JumpTarget.break_target (after_loop_block));
+
+ current_block.connect (outer_block);
+ outer_block.connect (loop_block);
+ current_block = loop_block;
+
+ // condition
+ if (stmt.condition != null) {
+ loop_block.add_node (stmt.condition);
+ handle_errors (stmt.condition);
+
+ if (always_false (stmt.condition)) {
+ mark_unreachable ();
+ } else {
+ current_block = new BasicBlock ();
+ all_basic_blocks.add (current_block);
+ loop_block.connect (current_block);
+ }
+
+ if (!always_true (stmt.condition)) {
+ loop_block.connect (after_loop_block);
+ }
+ }
+
+ // loop block
+ stmt.body.accept (this);
+ // end of loop block reachable?
+ if (current_block != null) {
+ current_block.connect (iterator_block);
+ }
+
+ // after loop block reachable?
+ if (after_loop_block.get_predecessors ().size == 0) {
+ // after loop block not reachable
+ mark_unreachable ();
+ } else {
+ // after loop block reachable
+ current_block = after_loop_block;
+ }
+
+ jump_stack.remove_at (jump_stack.size - 1);
+ jump_stack.remove_at (jump_stack.size - 1);
+ }
+
public override void visit_do_statement (DoStatement stmt) {
if (unreachable (stmt)) {
return;
diff --git a/vala/valaforstatement.vala b/vala/valaforstatement.vala
index bd3229ad5..380effcc5 100644
--- a/vala/valaforstatement.vala
+++ b/vala/valaforstatement.vala
@@ -154,58 +154,45 @@ public class Vala.ForStatement : CodeNode, Statement {
}
}
- bool always_true (Expression condition) {
- var literal = condition as BooleanLiteral;
- return (literal != null && literal.value);
- }
-
- bool always_false (Expression condition) {
- var literal = condition as BooleanLiteral;
- return (literal != null && !literal.value);
- }
-
public override bool check (CodeContext context) {
- // convert to simple loop
+ if (checked) {
+ return !error;
+ }
- var block = new Block (source_reference);
+ checked = true;
// initializer
foreach (var init_expr in initializer) {
- block.add_statement (new ExpressionStatement (init_expr, init_expr.source_reference));
+ if (!init_expr.check (context)) {
+ error = true;
+ }
}
- // do not generate if block if condition is always true
- if (condition == null || always_true (condition)) {
- } else if (always_false (condition)) {
- // do not generate if block if condition is always false
- body.insert_statement (0, new BreakStatement (condition.source_reference));
- } else {
- // 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);
+ // condition
+ if (condition != null) {
+ condition.target_type = context.analyzer.bool_type.copy ();
+ if (!condition.check (context)) {
+ error = true;
+ }
+
+ if (condition.value_type == null || !condition.value_type.compatible
(context.analyzer.bool_type)) {
+ error = true;
+ Report.error (condition.source_reference, "Condition must be boolean");
+ }
}
// iterator
- var first_local = new LocalVariable (context.analyzer.bool_type.copy (), get_temp_name (),
new BooleanLiteral (true, source_reference), source_reference);
- block.add_statement (new DeclarationStatement (first_local, source_reference));
-
- var iterator_block = new Block (source_reference);
foreach (var it_expr in iterator) {
- iterator_block.add_statement (new ExpressionStatement (it_expr,
it_expr.source_reference));
+ if (!it_expr.check (context)) {
+ error = true;
+ }
}
- var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new
MemberAccess.simple (first_local.name, source_reference), source_reference), iterator_block, null,
source_reference);
- body.insert_statement (0, first_if);
- 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));
-
- block.add_statement (new Loop (body, source_reference));
-
- var parent_block = (Block) parent_node;
- parent_block.replace_statement (this, block);
+ // body
+ if (!body.check (context)) {
+ error = true;
+ }
- return block.check (context);
+ return !error;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]