]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add CCodeControlFlowModule
authorJürg Billeter <j@bitron.ch>
Wed, 5 Nov 2008 18:03:10 +0000 (18:03 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 5 Nov 2008 18:03:10 +0000 (18:03 +0000)
2008-11-05  Jürg Billeter  <j@bitron.ch>

* gobject/Makefile.am:
* gobject/valaccodebasemodule.vala:
* gobject/valaccodecontrolflowmodule.vala:
* gobject/valaccodegenerator.vala:
* gobject/valaccodememberaccessmodule.vala:

Add CCodeControlFlowModule

svn path=/trunk/; revision=1981

ChangeLog
gobject/Makefile.am
gobject/valaccodebasemodule.vala
gobject/valaccodecontrolflowmodule.vala [new file with mode: 0644]
gobject/valaccodegenerator.vala
gobject/valaccodememberaccessmodule.vala

index 2240b90aacc5f7b42255a80150880e33e8584e3a..d734a33d0f62278d45397ff76ce481d237102b06 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-11-05  Jürg Billeter  <j@bitron.ch>
+
+       * gobject/Makefile.am:
+       * gobject/valaccodebasemodule.vala:
+       * gobject/valaccodecontrolflowmodule.vala:
+       * gobject/valaccodegenerator.vala:
+       * gobject/valaccodememberaccessmodule.vala:
+
+       Add CCodeControlFlowModule
+
 2008-11-04  Jürg Billeter  <j@bitron.ch>
 
        * vala/valadynamicproperty.vala:
index 8e4e6d10ca4e61d3d5dcd946232ef4aeda311a44..f7b57fd57220719e35b7027bb0f9b3a2d9600455 100644 (file)
@@ -16,6 +16,7 @@ libvala_la_VALASOURCES = \
        valaccodeassignmentmodule.vala \
        valaccodebasemodule.vala \
        valaccodecompiler.vala \
+       valaccodecontrolflowmodule.vala \
        valaccodedelegatemodule.vala \
        valaccodedynamicpropertymodule.vala \
        valaccodedynamicsignalmodule.vala \
index e3a55d4c3b5a71c82bc3b498c4f4cf1f6964baf9..f2e9570eef47d35730706e5b64fe706232cd4684 100644 (file)
@@ -908,7 +908,7 @@ public class Vala.CCodeBaseModule : CCodeModule {
                }
        }
 
-       private bool is_constant_ccode_expression (CCodeExpression cexpr) {
+       public bool is_constant_ccode_expression (CCodeExpression cexpr) {
                if (cexpr is CCodeConstant) {
                        return true;
                } else if (cexpr is CCodeBinaryExpression) {
@@ -1979,546 +1979,6 @@ public class Vala.CCodeBaseModule : CCodeModule {
                ((CodeNode) stmt).ccodenode = cfrag;
        }
 
-       public override void visit_if_statement (IfStatement stmt) {
-               stmt.accept_children (codegen);
-
-               if (stmt.false_statement != null) {
-                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
-               } else {
-                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode);
-               }
-               
-               create_temp_decl (stmt, stmt.condition.temp_vars);
-       }
-
-       void visit_string_switch_statement (SwitchStatement stmt) {
-               // we need a temporary variable to save the property value
-               var temp_var = get_temp_variable (stmt.expression.value_type, true, stmt);
-               stmt.expression.temp_vars.insert (0, temp_var);
-
-               var ctemp = new CCodeIdentifier (temp_var.name);
-               var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
-               var czero = new CCodeConstant ("0");
-
-               var cswitchblock = new CCodeFragment ();
-               stmt.ccodenode = cswitchblock;
-
-               var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
-               var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
-               cquark.add_argument (ctemp);
-
-               var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
-
-               temp_var = get_temp_variable (gquark_type);
-               stmt.expression.temp_vars.insert (0, temp_var);
-
-               int label_count = 0;
-
-               foreach (SwitchSection section in stmt.get_sections ()) {
-                       if (section.has_default_label ()) {
-                               continue;
-                       }
-
-                       foreach (SwitchLabel label in section.get_labels ()) {
-                               var cexpr = (CCodeExpression) label.expression.ccodenode;
-
-                               if (is_constant_ccode_expression (cexpr)) {
-                                       var cname = "%s_label%d".printf (temp_var.name, label_count++);
-                                       var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
-
-                                       cdecl.modifiers = CCodeModifiers.STATIC;
-                                       cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero));
-
-                                       cswitchblock.append (cdecl);
-                               }
-                       }
-               }
-
-               cswitchblock.append (new CCodeExpressionStatement (cinit));
-
-               ctemp = new CCodeIdentifier (temp_var.name);
-               cinit = new CCodeAssignment (ctemp, ccond);
-
-               cswitchblock.append (new CCodeExpressionStatement (cinit));
-               create_temp_decl (stmt, stmt.expression.temp_vars);
-
-               Gee.List<Statement> default_statements = null;
-               label_count = 0;
-
-               // generate nested if statements                
-               CCodeStatement ctopstmt = null;
-               CCodeIfStatement coldif = null;
-
-               foreach (SwitchSection section in stmt.get_sections ()) {
-                       if (section.has_default_label ()) {
-                               default_statements = section.get_statements ();
-                               continue;
-                       }
-
-                       CCodeBinaryExpression cor = null;
-                       foreach (SwitchLabel label in section.get_labels ()) {
-                               var cexpr = (CCodeExpression) label.expression.ccodenode;
-
-                               if (is_constant_ccode_expression (cexpr)) {
-                                       var cname = new CCodeIdentifier ("%s_label%d".printf (temp_var.name, label_count++));
-                                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
-                                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
-                                       var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall));
-
-                                       ccall.add_argument (cexpr);
-
-                                       cexpr = new CCodeConditionalExpression (ccond, cname, cinit);
-                               } else {
-                                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
-                                       ccall.add_argument (cexpr);
-                                       cexpr = ccall;
-                               }
-
-                               var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
-
-                               if (cor == null) {
-                                       cor = ccmp;
-                               } else {
-                                       cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
-                               }
-                       }
-
-                       var cblock = new CCodeBlock ();
-                       foreach (CodeNode body_stmt in section.get_statements ()) {
-                               if (body_stmt.ccodenode is CCodeFragment) {
-                                       foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
-                                               cblock.add_statement (cstmt);
-                                       }
-                               } else {
-                                       cblock.add_statement (body_stmt.ccodenode);
-                               }
-                       }
-
-                       var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
-                       var cif = new CCodeIfStatement (cor, cdo);
-
-                       if (coldif != null) {
-                               coldif.false_statement = cif;
-                       } else {
-                               ctopstmt = cif;
-                       }
-
-                       coldif = cif;
-               }
-       
-               if (default_statements != null) {
-                       var cblock = new CCodeBlock ();
-                       foreach (CodeNode body_stmt in default_statements) {
-                               cblock.add_statement (body_stmt.ccodenode);
-                       }
-               
-                       var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
-
-                       if (coldif == null) {
-                               // there is only one section and that section
-                               // contains a default label
-                               ctopstmt = cdo;
-                       } else {
-                               coldif.false_statement = cdo;
-                       }
-               }
-       
-               cswitchblock.append (ctopstmt);
-       }
-
-       public override void visit_switch_statement (SwitchStatement stmt) {
-               if (stmt.expression.value_type.compatible (string_type)) {
-                       visit_string_switch_statement (stmt);
-                       return;
-               }
-
-               var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode);
-               stmt.ccodenode = cswitch;
-
-               foreach (SwitchSection section in stmt.get_sections ()) {
-                       if (section.has_default_label ()) {
-                               cswitch.add_statement (new CCodeLabel ("default"));
-                               var cdefaultblock = new CCodeBlock ();
-                               cswitch.add_statement (cdefaultblock);
-                               foreach (CodeNode default_stmt in section.get_statements ()) {
-                                       cdefaultblock.add_statement (default_stmt.ccodenode);
-                               }
-                               continue;
-                       }
-
-                       foreach (SwitchLabel label in section.get_labels ()) {
-                               cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
-                       }
-
-                       var cblock = new CCodeBlock ();
-                       cswitch.add_statement (cblock);
-                       foreach (CodeNode body_stmt in section.get_statements ()) {
-                               cblock.add_statement (body_stmt.ccodenode);
-                       }
-               }
-       }
-
-       public override void visit_switch_section (SwitchSection section) {
-               visit_block (section);
-       }
-
-       public override void visit_while_statement (WhileStatement 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);
-       }
-
-       public override void visit_do_statement (DoStatement stmt) {
-               stmt.accept_children (codegen);
-
-               stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
-               
-               create_temp_decl (stmt, stmt.condition.temp_vars);
-       }
-
-       public override void visit_for_statement (ForStatement stmt) {
-               stmt.accept_children (codegen);
-
-               CCodeExpression ccondition = null;
-               if (stmt.condition != null) {
-                       ccondition = (CCodeExpression) stmt.condition.ccodenode;
-               }
-
-               var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode);
-               stmt.ccodenode = cfor;
-               
-               foreach (Expression init_expr in stmt.get_initializer ()) {
-                       cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
-                       create_temp_decl (stmt, init_expr.temp_vars);
-               }
-               
-               foreach (Expression it_expr in stmt.get_iterator ()) {
-                       cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
-                       create_temp_decl (stmt, it_expr.temp_vars);
-               }
-
-               if (stmt.condition != null) {
-                       create_temp_decl (stmt, stmt.condition.temp_vars);
-               }
-       }
-
-       public override void visit_foreach_statement (ForeachStatement stmt) {
-               stmt.element_variable.active = true;
-               stmt.collection_variable.active = true;
-               if (stmt.iterator_variable != null) {
-                       stmt.iterator_variable.active = true;
-               }
-
-               visit_block (stmt);
-
-               var cblock = new CCodeBlock ();
-               // sets #line
-               stmt.ccodenode = cblock;
-
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, stmt.collection.temp_vars);
-               cblock.add_statement (cfrag);
-               
-               var collection_backup = stmt.collection_variable;
-               var collection_type = collection_backup.variable_type.copy ();
-               var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
-               var ccolvardecl = new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
-               ccolvardecl.line = cblock.line;
-               ccoldecl.add_declarator (ccolvardecl);
-               cblock.add_statement (ccoldecl);
-               
-               if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
-                       // exception handling
-                       var cfrag = new CCodeFragment ();
-                       head.add_simple_check (stmt.collection, cfrag);
-                       cblock.add_statement (cfrag);
-               }
-
-               if (stmt.collection.value_type is ArrayType) {
-                       var array_type = (ArrayType) stmt.collection.value_type;
-                       
-                       var array_len = head.get_array_length_cexpression (stmt.collection);
-
-                       // store array length for use by _vala_array_free
-                       var clendecl = new CCodeDeclaration ("int");
-                       clendecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (collection_backup.name, 1), array_len));
-                       cblock.add_statement (clendecl);
-
-                       if (array_len is CCodeConstant) {
-                               // the array has no length parameter i.e. it is NULL-terminated array
-
-                               var it_name = "%s_it".printf (stmt.variable_name);
-                       
-                               var citdecl = new CCodeDeclaration (collection_type.get_cname ());
-                               citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-                               cblock.add_statement (citdecl);
-                               
-                               var cbody = new CCodeBlock ();
-
-                               CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
-
-                               var element_type = array_type.element_type.copy ();
-                               element_type.value_owned = false;
-                               element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-                               var cfrag = new CCodeFragment ();
-                               append_temp_decl (cfrag, temp_vars);
-                               cbody.add_statement (cfrag);
-                               temp_vars.clear ();
-
-                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
-                               cbody.add_statement (cdecl);
-
-                               // add array length variable for stacked arrays
-                               if (stmt.type_reference is ArrayType) {
-                                       var inner_array_type = (ArrayType) stmt.type_reference;
-                                       for (int dim = 1; dim <= inner_array_type.rank; dim++) {
-                                               cdecl = new CCodeDeclaration ("int");
-                                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
-                                               cbody.add_statement (cdecl);
-                                       }
-                               }
-
-                               cbody.add_statement (stmt.body.ccodenode);
-                               
-                               var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
-                               
-                               var cfor = new CCodeForStatement (ccond, cbody);
-
-                               cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
-               
-                               cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-                               cblock.add_statement (cfor);
-                       } else {
-                               // the array has a length parameter
-
-                               var it_name = (stmt.variable_name + "_it");
-                       
-                               var citdecl = new CCodeDeclaration ("int");
-                               citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-                               cblock.add_statement (citdecl);
-                               
-                               var cbody = new CCodeBlock ();
-
-                               CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
-
-                               var element_type = array_type.element_type.copy ();
-                               element_type.value_owned = false;
-                               element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-                               var cfrag = new CCodeFragment ();
-                               append_temp_decl (cfrag, temp_vars);
-                               cbody.add_statement (cfrag);
-                               temp_vars.clear ();
-
-                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
-                               cbody.add_statement (cdecl);
-
-                               // add array length variable for stacked arrays
-                               if (stmt.type_reference is ArrayType) {
-                                       var inner_array_type = (ArrayType) stmt.type_reference;
-                                       for (int dim = 1; dim <= inner_array_type.rank; dim++) {
-                                               cdecl = new CCodeDeclaration ("int");
-                                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
-                                               cbody.add_statement (cdecl);
-                                       }
-                               }
-
-                               cbody.add_statement (stmt.body.ccodenode);
-                               
-                               var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1"));
-                               var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
-                               var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2);
-                               
-                               /* only check for null if the containers elements are of reference-type */
-                               CCodeBinaryExpression ccond;
-                               if (array_type.element_type.is_reference_type_or_type_parameter ()) {
-                                       var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1"));
-                                       var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL"));
-                                       var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2);
-
-                                       ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term));
-                               } else {
-                                       /* assert when trying to iterate over value-type arrays of unknown length */
-                                       var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
-                                       cassert.add_argument (ccond_ind1);
-                                       cblock.add_statement (new CCodeExpressionStatement (cassert));
-
-                                       ccond = ccond_ind2;
-                               }
-                               
-                               var cfor = new CCodeForStatement (ccond, cbody);
-                               cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
-                               cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-                               cblock.add_statement (cfor);
-                       }
-               } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
-                       // iterating over a GList or GSList
-
-                       var it_name = "%s_it".printf (stmt.variable_name);
-               
-                       var citdecl = new CCodeDeclaration (collection_type.get_cname ());
-                       var citvardecl = new CCodeVariableDeclarator (it_name);
-                       citvardecl.line = cblock.line;
-                       citdecl.add_declarator (citvardecl);
-                       cblock.add_statement (citdecl);
-                       
-                       var cbody = new CCodeBlock ();
-
-                       CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data");
-
-                       if (collection_type.get_type_arguments ().size != 1) {
-                               Report.error (stmt.source_reference, "internal error: missing generic type argument");
-                               stmt.error = true;
-                               return;
-                       }
-
-                       var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
-                       element_data_type.value_owned = false;
-                       element_data_type.is_type_argument = true;
-                       element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
-
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
-                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-                       cvardecl.line = cblock.line;
-                       cdecl.add_declarator (cvardecl);
-                       cbody.add_statement (cdecl);
-                       
-                       cbody.add_statement (stmt.body.ccodenode);
-                       
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL"));
-                       
-                       var cfor = new CCodeForStatement (ccond, cbody);
-                       
-                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
-
-                       cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
-                       cblock.add_statement (cfor);
-               } else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
-                       // iterating over a Gee.List, use integer to avoid the cost of an iterator object
-
-                       var it_name = "%s_it".printf (stmt.variable_name);
-
-                       var citdecl = new CCodeDeclaration ("int");
-                       citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-                       cblock.add_statement (citdecl);
-                       
-                       var cbody = new CCodeBlock ();
-
-                       var get_method = (Method) list_type.scope.lookup ("get");
-                       var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
-                       get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
-                       get_ccall.add_argument (new CCodeIdentifier (it_name));
-                       CCodeExpression element_expr = get_ccall;
-
-                       var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, get_method, get_method.return_type, stmt);
-
-                       element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
-                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-                       cvardecl.line = cblock.line;
-                       cdecl.add_declarator (cvardecl);
-                       cbody.add_statement (cdecl);
-
-                       cbody.add_statement (stmt.body.ccodenode);
-
-                       var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
-                       list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
-
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
-
-                       var cfor = new CCodeForStatement (ccond, cbody);
-                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
-                       cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-                       cfor.line = cblock.line;
-                       cblock.add_statement (cfor);
-               } else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
-                       // iterating over a Gee.Iterable, use iterator
-
-                       var it_name = "%s_it".printf (stmt.variable_name);
-
-                       var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
-                       var it_method = (Method) iterable_type.scope.lookup ("iterator");
-                       var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
-                       it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
-                       var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
-                       citvardecl.line = cblock.line;
-                       citdecl.add_declarator (citvardecl);
-                       cblock.add_statement (citdecl);
-                       
-                       var cbody = new CCodeBlock ();
-
-                       var get_method = (Method) iterator_type.scope.lookup ("get");
-                       var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
-                       get_ccall.add_argument (new CCodeIdentifier (it_name));
-                       CCodeExpression element_expr = get_ccall;
-
-                       Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
-                       type_arg_it.next ();
-                       var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, it_method, type_arg_it.get (), stmt);
-
-                       element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
-
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
-                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-                       cvardecl.line = cblock.line;
-                       cdecl.add_declarator (cvardecl);
-                       cbody.add_statement (cdecl);
-                       
-                       cbody.add_statement (stmt.body.ccodenode);
-
-                       var next_method = (Method) iterator_type.scope.lookup ("next");
-                       var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
-                       next_ccall.add_argument (new CCodeIdentifier (it_name));
-
-                       var cwhile = new CCodeWhileStatement (next_ccall, cbody);
-                       cwhile.line = cblock.line;
-                       cblock.add_statement (cwhile);
-               }
-
-               foreach (LocalVariable local in stmt.get_local_variables ()) {
-                       if (requires_destroy (local.variable_type)) {
-                               var ma = new MemberAccess.simple (local.name);
-                               ma.symbol_reference = local;
-                               var cunref = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
-                               cunref.line = cblock.line;
-                               cblock.add_statement (cunref);
-                       }
-               }
-       }
-
-       public override void visit_break_statement (BreakStatement stmt) {
-               stmt.ccodenode = new CCodeBreakStatement ();
-
-               create_local_free (stmt, true);
-       }
-
-       public override void visit_continue_statement (ContinueStatement stmt) {
-               stmt.ccodenode = new CCodeContinueStatement ();
-
-               create_local_free (stmt, true);
-       }
-
        public void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) {
                var b = (Block) sym;
 
@@ -2556,7 +2016,7 @@ public class Vala.CCodeBaseModule : CCodeModule {
                }
        }
 
-       private void create_local_free (CodeNode stmt, bool stop_at_loop = false) {
+       public void create_local_free (CodeNode stmt, bool stop_at_loop = false) {
                var cfrag = new CCodeFragment ();
        
                append_local_free (current_symbol, cfrag, stop_at_loop);
diff --git a/gobject/valaccodecontrolflowmodule.vala b/gobject/valaccodecontrolflowmodule.vala
new file mode 100644 (file)
index 0000000..011bc30
--- /dev/null
@@ -0,0 +1,572 @@
+/* valaccodecontrolflowmodule.vala
+ *
+ * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
+ *
+ * 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>
+ *     Raffaele Sandrini <raffaele@sandrini.ch>
+ */
+
+using GLib;
+using Gee;
+
+public class Vala.CCodeControlFlowModule : CCodeMethodModule {
+       public CCodeControlFlowModule (CCodeGenerator codegen, CCodeModule? next) {
+               base (codegen, next);
+       }
+
+       public override void visit_if_statement (IfStatement stmt) {
+               stmt.accept_children (codegen);
+
+               if (stmt.false_statement != null) {
+                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
+               } else {
+                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode);
+               }
+               
+               create_temp_decl (stmt, stmt.condition.temp_vars);
+       }
+
+       void visit_string_switch_statement (SwitchStatement stmt) {
+               // we need a temporary variable to save the property value
+               var temp_var = get_temp_variable (stmt.expression.value_type, true, stmt);
+               stmt.expression.temp_vars.insert (0, temp_var);
+
+               var ctemp = new CCodeIdentifier (temp_var.name);
+               var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
+               var czero = new CCodeConstant ("0");
+
+               var cswitchblock = new CCodeFragment ();
+               stmt.ccodenode = cswitchblock;
+
+               var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
+               var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
+               cquark.add_argument (ctemp);
+
+               var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
+
+               temp_var = get_temp_variable (gquark_type);
+               stmt.expression.temp_vars.insert (0, temp_var);
+
+               int label_count = 0;
+
+               foreach (SwitchSection section in stmt.get_sections ()) {
+                       if (section.has_default_label ()) {
+                               continue;
+                       }
+
+                       foreach (SwitchLabel label in section.get_labels ()) {
+                               var cexpr = (CCodeExpression) label.expression.ccodenode;
+
+                               if (is_constant_ccode_expression (cexpr)) {
+                                       var cname = "%s_label%d".printf (temp_var.name, label_count++);
+                                       var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
+
+                                       cdecl.modifiers = CCodeModifiers.STATIC;
+                                       cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero));
+
+                                       cswitchblock.append (cdecl);
+                               }
+                       }
+               }
+
+               cswitchblock.append (new CCodeExpressionStatement (cinit));
+
+               ctemp = new CCodeIdentifier (temp_var.name);
+               cinit = new CCodeAssignment (ctemp, ccond);
+
+               cswitchblock.append (new CCodeExpressionStatement (cinit));
+               create_temp_decl (stmt, stmt.expression.temp_vars);
+
+               Gee.List<Statement> default_statements = null;
+               label_count = 0;
+
+               // generate nested if statements                
+               CCodeStatement ctopstmt = null;
+               CCodeIfStatement coldif = null;
+
+               foreach (SwitchSection section in stmt.get_sections ()) {
+                       if (section.has_default_label ()) {
+                               default_statements = section.get_statements ();
+                               continue;
+                       }
+
+                       CCodeBinaryExpression cor = null;
+                       foreach (SwitchLabel label in section.get_labels ()) {
+                               var cexpr = (CCodeExpression) label.expression.ccodenode;
+
+                               if (is_constant_ccode_expression (cexpr)) {
+                                       var cname = new CCodeIdentifier ("%s_label%d".printf (temp_var.name, label_count++));
+                                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
+                                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
+                                       var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall));
+
+                                       ccall.add_argument (cexpr);
+
+                                       cexpr = new CCodeConditionalExpression (ccond, cname, cinit);
+                               } else {
+                                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
+                                       ccall.add_argument (cexpr);
+                                       cexpr = ccall;
+                               }
+
+                               var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
+
+                               if (cor == null) {
+                                       cor = ccmp;
+                               } else {
+                                       cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
+                               }
+                       }
+
+                       var cblock = new CCodeBlock ();
+                       foreach (CodeNode body_stmt in section.get_statements ()) {
+                               if (body_stmt.ccodenode is CCodeFragment) {
+                                       foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
+                                               cblock.add_statement (cstmt);
+                                       }
+                               } else {
+                                       cblock.add_statement (body_stmt.ccodenode);
+                               }
+                       }
+
+                       var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
+                       var cif = new CCodeIfStatement (cor, cdo);
+
+                       if (coldif != null) {
+                               coldif.false_statement = cif;
+                       } else {
+                               ctopstmt = cif;
+                       }
+
+                       coldif = cif;
+               }
+       
+               if (default_statements != null) {
+                       var cblock = new CCodeBlock ();
+                       foreach (CodeNode body_stmt in default_statements) {
+                               cblock.add_statement (body_stmt.ccodenode);
+                       }
+               
+                       var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
+
+                       if (coldif == null) {
+                               // there is only one section and that section
+                               // contains a default label
+                               ctopstmt = cdo;
+                       } else {
+                               coldif.false_statement = cdo;
+                       }
+               }
+       
+               cswitchblock.append (ctopstmt);
+       }
+
+       public override void visit_switch_statement (SwitchStatement stmt) {
+               if (stmt.expression.value_type.compatible (string_type)) {
+                       visit_string_switch_statement (stmt);
+                       return;
+               }
+
+               var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode);
+               stmt.ccodenode = cswitch;
+
+               foreach (SwitchSection section in stmt.get_sections ()) {
+                       if (section.has_default_label ()) {
+                               cswitch.add_statement (new CCodeLabel ("default"));
+                               var cdefaultblock = new CCodeBlock ();
+                               cswitch.add_statement (cdefaultblock);
+                               foreach (CodeNode default_stmt in section.get_statements ()) {
+                                       cdefaultblock.add_statement (default_stmt.ccodenode);
+                               }
+                               continue;
+                       }
+
+                       foreach (SwitchLabel label in section.get_labels ()) {
+                               cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
+                       }
+
+                       var cblock = new CCodeBlock ();
+                       cswitch.add_statement (cblock);
+                       foreach (CodeNode body_stmt in section.get_statements ()) {
+                               cblock.add_statement (body_stmt.ccodenode);
+                       }
+               }
+       }
+
+       public override void visit_switch_section (SwitchSection section) {
+               visit_block (section);
+       }
+
+       public override void visit_while_statement (WhileStatement 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);
+       }
+
+       public override void visit_do_statement (DoStatement stmt) {
+               stmt.accept_children (codegen);
+
+               stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
+               
+               create_temp_decl (stmt, stmt.condition.temp_vars);
+       }
+
+       public override void visit_for_statement (ForStatement stmt) {
+               stmt.accept_children (codegen);
+
+               CCodeExpression ccondition = null;
+               if (stmt.condition != null) {
+                       ccondition = (CCodeExpression) stmt.condition.ccodenode;
+               }
+
+               var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode);
+               stmt.ccodenode = cfor;
+               
+               foreach (Expression init_expr in stmt.get_initializer ()) {
+                       cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
+                       create_temp_decl (stmt, init_expr.temp_vars);
+               }
+               
+               foreach (Expression it_expr in stmt.get_iterator ()) {
+                       cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
+                       create_temp_decl (stmt, it_expr.temp_vars);
+               }
+
+               if (stmt.condition != null) {
+                       create_temp_decl (stmt, stmt.condition.temp_vars);
+               }
+       }
+
+       public override void visit_foreach_statement (ForeachStatement stmt) {
+               stmt.element_variable.active = true;
+               stmt.collection_variable.active = true;
+               if (stmt.iterator_variable != null) {
+                       stmt.iterator_variable.active = true;
+               }
+
+               visit_block (stmt);
+
+               var cblock = new CCodeBlock ();
+               // sets #line
+               stmt.ccodenode = cblock;
+
+               var cfrag = new CCodeFragment ();
+               append_temp_decl (cfrag, stmt.collection.temp_vars);
+               cblock.add_statement (cfrag);
+               
+               var collection_backup = stmt.collection_variable;
+               var collection_type = collection_backup.variable_type.copy ();
+               var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
+               var ccolvardecl = new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
+               ccolvardecl.line = cblock.line;
+               ccoldecl.add_declarator (ccolvardecl);
+               cblock.add_statement (ccoldecl);
+               
+               if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
+                       // exception handling
+                       var cfrag = new CCodeFragment ();
+                       head.add_simple_check (stmt.collection, cfrag);
+                       cblock.add_statement (cfrag);
+               }
+
+               if (stmt.collection.value_type is ArrayType) {
+                       var array_type = (ArrayType) stmt.collection.value_type;
+                       
+                       var array_len = head.get_array_length_cexpression (stmt.collection);
+
+                       // store array length for use by _vala_array_free
+                       var clendecl = new CCodeDeclaration ("int");
+                       clendecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (collection_backup.name, 1), array_len));
+                       cblock.add_statement (clendecl);
+
+                       if (array_len is CCodeConstant) {
+                               // the array has no length parameter i.e. it is NULL-terminated array
+
+                               var it_name = "%s_it".printf (stmt.variable_name);
+                       
+                               var citdecl = new CCodeDeclaration (collection_type.get_cname ());
+                               citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+                               cblock.add_statement (citdecl);
+                               
+                               var cbody = new CCodeBlock ();
+
+                               CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
+
+                               var element_type = array_type.element_type.copy ();
+                               element_type.value_owned = false;
+                               element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+
+                               var cfrag = new CCodeFragment ();
+                               append_temp_decl (cfrag, temp_vars);
+                               cbody.add_statement (cfrag);
+                               temp_vars.clear ();
+
+                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+                               cbody.add_statement (cdecl);
+
+                               // add array length variable for stacked arrays
+                               if (stmt.type_reference is ArrayType) {
+                                       var inner_array_type = (ArrayType) stmt.type_reference;
+                                       for (int dim = 1; dim <= inner_array_type.rank; dim++) {
+                                               cdecl = new CCodeDeclaration ("int");
+                                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
+                                               cbody.add_statement (cdecl);
+                                       }
+                               }
+
+                               cbody.add_statement (stmt.body.ccodenode);
+                               
+                               var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
+                               
+                               var cfor = new CCodeForStatement (ccond, cbody);
+
+                               cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
+               
+                               cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+                               cblock.add_statement (cfor);
+                       } else {
+                               // the array has a length parameter
+
+                               var it_name = (stmt.variable_name + "_it");
+                       
+                               var citdecl = new CCodeDeclaration ("int");
+                               citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+                               cblock.add_statement (citdecl);
+                               
+                               var cbody = new CCodeBlock ();
+
+                               CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
+
+                               var element_type = array_type.element_type.copy ();
+                               element_type.value_owned = false;
+                               element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+
+                               var cfrag = new CCodeFragment ();
+                               append_temp_decl (cfrag, temp_vars);
+                               cbody.add_statement (cfrag);
+                               temp_vars.clear ();
+
+                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+                               cbody.add_statement (cdecl);
+
+                               // add array length variable for stacked arrays
+                               if (stmt.type_reference is ArrayType) {
+                                       var inner_array_type = (ArrayType) stmt.type_reference;
+                                       for (int dim = 1; dim <= inner_array_type.rank; dim++) {
+                                               cdecl = new CCodeDeclaration ("int");
+                                               cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
+                                               cbody.add_statement (cdecl);
+                                       }
+                               }
+
+                               cbody.add_statement (stmt.body.ccodenode);
+                               
+                               var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1"));
+                               var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
+                               var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2);
+                               
+                               /* only check for null if the containers elements are of reference-type */
+                               CCodeBinaryExpression ccond;
+                               if (array_type.element_type.is_reference_type_or_type_parameter ()) {
+                                       var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1"));
+                                       var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL"));
+                                       var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2);
+
+                                       ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term));
+                               } else {
+                                       /* assert when trying to iterate over value-type arrays of unknown length */
+                                       var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
+                                       cassert.add_argument (ccond_ind1);
+                                       cblock.add_statement (new CCodeExpressionStatement (cassert));
+
+                                       ccond = ccond_ind2;
+                               }
+                               
+                               var cfor = new CCodeForStatement (ccond, cbody);
+                               cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
+                               cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+                               cblock.add_statement (cfor);
+                       }
+               } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
+                       // iterating over a GList or GSList
+
+                       var it_name = "%s_it".printf (stmt.variable_name);
+               
+                       var citdecl = new CCodeDeclaration (collection_type.get_cname ());
+                       var citvardecl = new CCodeVariableDeclarator (it_name);
+                       citvardecl.line = cblock.line;
+                       citdecl.add_declarator (citvardecl);
+                       cblock.add_statement (citdecl);
+                       
+                       var cbody = new CCodeBlock ();
+
+                       CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data");
+
+                       if (collection_type.get_type_arguments ().size != 1) {
+                               Report.error (stmt.source_reference, "internal error: missing generic type argument");
+                               stmt.error = true;
+                               return;
+                       }
+
+                       var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
+                       element_data_type.value_owned = false;
+                       element_data_type.is_type_argument = true;
+                       element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
+
+                       var cfrag = new CCodeFragment ();
+                       append_temp_decl (cfrag, temp_vars);
+                       cbody.add_statement (cfrag);
+                       temp_vars.clear ();
+
+                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+                       cvardecl.line = cblock.line;
+                       cdecl.add_declarator (cvardecl);
+                       cbody.add_statement (cdecl);
+                       
+                       cbody.add_statement (stmt.body.ccodenode);
+                       
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL"));
+                       
+                       var cfor = new CCodeForStatement (ccond, cbody);
+                       
+                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
+
+                       cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
+                       cblock.add_statement (cfor);
+               } else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
+                       // iterating over a Gee.List, use integer to avoid the cost of an iterator object
+
+                       var it_name = "%s_it".printf (stmt.variable_name);
+
+                       var citdecl = new CCodeDeclaration ("int");
+                       citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+                       cblock.add_statement (citdecl);
+                       
+                       var cbody = new CCodeBlock ();
+
+                       var get_method = (Method) list_type.scope.lookup ("get");
+                       var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+                       get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
+                       get_ccall.add_argument (new CCodeIdentifier (it_name));
+                       CCodeExpression element_expr = get_ccall;
+
+                       var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, get_method, get_method.return_type, stmt);
+
+                       element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+
+                       var cfrag = new CCodeFragment ();
+                       append_temp_decl (cfrag, temp_vars);
+                       cbody.add_statement (cfrag);
+                       temp_vars.clear ();
+
+                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+                       cvardecl.line = cblock.line;
+                       cdecl.add_declarator (cvardecl);
+                       cbody.add_statement (cdecl);
+
+                       cbody.add_statement (stmt.body.ccodenode);
+
+                       var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
+                       list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
+
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
+
+                       var cfor = new CCodeForStatement (ccond, cbody);
+                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
+                       cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+                       cfor.line = cblock.line;
+                       cblock.add_statement (cfor);
+               } else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
+                       // iterating over a Gee.Iterable, use iterator
+
+                       var it_name = "%s_it".printf (stmt.variable_name);
+
+                       var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
+                       var it_method = (Method) iterable_type.scope.lookup ("iterator");
+                       var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
+                       it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
+                       var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
+                       citvardecl.line = cblock.line;
+                       citdecl.add_declarator (citvardecl);
+                       cblock.add_statement (citdecl);
+                       
+                       var cbody = new CCodeBlock ();
+
+                       var get_method = (Method) iterator_type.scope.lookup ("get");
+                       var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+                       get_ccall.add_argument (new CCodeIdentifier (it_name));
+                       CCodeExpression element_expr = get_ccall;
+
+                       Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
+                       type_arg_it.next ();
+                       var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, it_method, type_arg_it.get (), stmt);
+
+                       element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
+
+                       var cfrag = new CCodeFragment ();
+                       append_temp_decl (cfrag, temp_vars);
+                       cbody.add_statement (cfrag);
+                       temp_vars.clear ();
+
+                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+                       cvardecl.line = cblock.line;
+                       cdecl.add_declarator (cvardecl);
+                       cbody.add_statement (cdecl);
+                       
+                       cbody.add_statement (stmt.body.ccodenode);
+
+                       var next_method = (Method) iterator_type.scope.lookup ("next");
+                       var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
+                       next_ccall.add_argument (new CCodeIdentifier (it_name));
+
+                       var cwhile = new CCodeWhileStatement (next_ccall, cbody);
+                       cwhile.line = cblock.line;
+                       cblock.add_statement (cwhile);
+               }
+
+               foreach (LocalVariable local in stmt.get_local_variables ()) {
+                       if (requires_destroy (local.variable_type)) {
+                               var ma = new MemberAccess.simple (local.name);
+                               ma.symbol_reference = local;
+                               var cunref = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
+                               cunref.line = cblock.line;
+                               cblock.add_statement (cunref);
+                       }
+               }
+       }
+
+       public override void visit_break_statement (BreakStatement stmt) {
+               stmt.ccodenode = new CCodeBreakStatement ();
+
+               create_local_free (stmt, true);
+       }
+
+       public override void visit_continue_statement (ContinueStatement stmt) {
+               stmt.ccodenode = new CCodeContinueStatement ();
+
+               create_local_free (stmt, true);
+       }
+}
+
index eca06bd1c4b38f444e884d4582d487c867512554..5c53bb7870120d4b51c2fcde189bf0cbeb60633f 100644 (file)
@@ -35,6 +35,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
                head = new CCodeBaseModule (this, head);
                head = new CCodeStructModule (this, head);
                head = new CCodeMethodModule (this, head);
+               head = new CCodeControlFlowModule (this, head);
                head = new CCodeMemberAccessModule (this, head);
                head = new CCodeAssignmentModule (this, head);
                head = new CCodeInvocationExpressionModule (this, head);
index 0c3e1ab6eb2fd95cfc1d87ed667ecfe78522a576..bc77bb1a0f3a36e58c3e37338ba8599f65b21e8a 100644 (file)
@@ -23,7 +23,7 @@
 
 using GLib;
 
-public class Vala.CCodeMemberAccessModule : CCodeMethodModule {
+public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
        public CCodeMemberAccessModule (CCodeGenerator codegen, CCodeModule? next) {
                base (codegen, next);
        }