コード例 #1
0
        public override void visit_foreach_statement(ForeachStatement stmt)
        {
            ccode.open_block();

            var collection_backup = stmt.collection_variable;
            var collection_type   = collection_backup.variable_type;

            var array_type = collection_type as ArrayType;

            if (array_type != null)
            {
                // avoid assignment issues
                array_type.inline_allocated = false;
                array_type.fixed_length     = false;
            }

            visit_local_variable(collection_backup);
            ccode.add_assignment(get_variable_cexpression(get_local_cname(collection_backup)), get_cvalue(stmt.collection));

            if (stmt.tree_can_fail && stmt.collection.tree_can_fail)
            {
                // exception handling
                add_simple_check(stmt.collection);
            }

            if (stmt.collection.value_type is ArrayType)
            {
                array_type = (ArrayType)stmt.collection.value_type;

                var array_len = get_array_length_cexpression(stmt.collection);

                // store array length for use by _vala_array_free
                ccode.add_assignment(get_variable_cexpression(get_array_length_cname(get_local_cname(collection_backup), 1)), array_len);

                var iterator_variable = new LocalVariable(int_type.copy(), stmt.variable_name + "_it");
                visit_local_variable(iterator_variable);
                var it_name = get_local_cname(iterator_variable);

                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, get_variable_cexpression(it_name), array_len);

                ccode.open_for(new CCodeAssignment(get_variable_cexpression(it_name), new CCodeConstant("0")),
                               ccond,
                               new CCodeAssignment(get_variable_cexpression(it_name), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, get_variable_cexpression(it_name), new CCodeConstant("1"))));

                CCodeExpression element_expr = new CCodeElementAccess(get_variable_cexpression(get_local_cname(collection_backup)), get_variable_cexpression(it_name));

                var element_type = array_type.element_type.copy();
                element_type.value_owned = false;
                element_expr             = get_cvalue_(transform_value(new GLibValue(element_type, element_expr, true), stmt.type_reference, stmt));

                visit_local_variable(stmt.element_variable);
                ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr);

                // set array length 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++)
                    {
                        ccode.add_assignment(get_variable_cexpression(get_array_length_cname(get_local_cname(stmt.element_variable), dim)), new CCodeConstant("-1"));
                    }
                }

                stmt.body.emit(this);

                ccode.close();
            }
            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 iterator_variable = new LocalVariable(collection_type.copy(), stmt.variable_name + "_it");
                visit_local_variable(iterator_variable);
                var it_name = get_local_cname(iterator_variable);

                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, get_variable_cexpression(it_name), new CCodeConstant("NULL"));

                ccode.open_for(new CCodeAssignment(get_variable_cexpression(it_name), get_variable_cexpression(get_local_cname(collection_backup))),
                               ccond,
                               new CCodeAssignment(get_variable_cexpression(it_name), CCodeMemberAccess.pointer(get_variable_cexpression(it_name), "next")));

                CCodeExpression element_expr = CCodeMemberAccess.pointer(get_variable_cexpression(it_name), "data");

                if (collection_type.get_type_arguments().Count != 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()[0].copy();
                element_data_type.value_owned = false;
                element_expr = convert_from_generic_pointer(element_expr, element_data_type);
                element_expr = get_cvalue_(transform_value(new GLibValue(element_data_type, element_expr), stmt.type_reference, stmt));

                visit_local_variable(stmt.element_variable);
                ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr);

                stmt.body.emit(this);

                ccode.close();
            }
            else if (stmt.collection.value_type.compatible(new ObjectType(gvaluearray_type)))
            {
                // iterating over a GValueArray

                var iterator_variable = new LocalVariable(uint_type.copy(), "%s_index".printf(stmt.variable_name));
                visit_local_variable(iterator_variable);
                var arr_index = get_variable_cname(get_local_cname(iterator_variable));

                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, get_variable_cexpression(arr_index), CCodeMemberAccess.pointer(get_variable_cexpression(get_local_cname(collection_backup)), "n_values"));

                ccode.open_for(new CCodeAssignment(get_variable_cexpression(arr_index), new CCodeConstant("0")),
                               ccond,
                               new CCodeAssignment(get_variable_cexpression(arr_index), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, get_variable_cexpression(arr_index), new CCodeConstant("1"))));

                var get_item = new CCodeFunctionCall(new CCodeIdentifier("g_value_array_get_nth"));
                get_item.add_argument(get_variable_cexpression(get_local_cname(collection_backup)));
                get_item.add_argument(get_variable_cexpression(arr_index));

                CCodeExpression element_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, get_item);

                if (stmt.type_reference.value_owned)
                {
                    element_expr = get_cvalue_(copy_value(new GLibValue(stmt.type_reference, element_expr), new StructValueType(gvalue_type)));
                }

                visit_local_variable(stmt.element_variable);
                ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr);

                stmt.body.emit(this);

                ccode.close();
            }

            foreach (LocalVariable local in stmt.get_local_variables())
            {
                if (requires_destroy(local.variable_type))
                {
                    ccode.add_expression(destroy_local(local));
                }
            }

            ccode.close();
        }