예제 #1
0
        /// <summary>
        /// Constructs the C function from the specified type.
        /// </summary>
        public void init_from_type(bool plugin, bool declaration_only)
        {
            bool use_thread_safe = !plugin;

            bool  fundamental = false;
            Class cl          = get_type_declaration() as Class;

            if (cl != null && !cl.is_compact && cl.base_class == null)
            {
                fundamental = true;
            }

            string type_id_name = "%s_type_id".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration()));

            var type_block = new CCodeBlock();
            CCodeDeclaration cdecl;

            if (use_thread_safe)
            {
                cdecl = new CCodeDeclaration("gsize");
                cdecl.add_declarator(new CCodeVariableDeclarator(type_id_name + "__volatile", new CCodeConstant("0")));
            }
            else
            {
                cdecl = new CCodeDeclaration("GType");
                cdecl.add_declarator(new CCodeVariableDeclarator(type_id_name, new CCodeConstant("0")));
            }
            cdecl.modifiers = CCodeModifiers.STATIC;
            if (use_thread_safe)
            {
                cdecl.modifiers |= CCodeModifiers.VOLATILE;
            }
            if (!plugin)
            {
                type_block.add_statement(cdecl);
            }
            else
            {
                source_declaration_fragment.append(cdecl);
            }

            CCodeFunction fun;

            if (!plugin)
            {
                fun           = new CCodeFunction("%s_get_type".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())), "GType");
                fun.modifiers = CCodeModifiers.CONST;

                /* Function will not be prototyped anyway */
                if (get_accessibility() == SymbolAccessibility.PRIVATE)
                {
                    // avoid C warning as this function is not always used
                    fun.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
                }
                else if (context.hide_internal && get_accessibility() == SymbolAccessibility.INTERNAL)
                {
                    // avoid C warning as this function is not always used
                    fun.modifiers |= CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
                }

                fun.is_declaration = true;
                declaration_fragment.append(fun.copy());
                fun.is_declaration = false;
            }
            else
            {
                fun = new CCodeFunction("%s_register_type".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())), "GType");
                fun.add_parameter(new CCodeParameter("module", "GTypeModule *"));

                var get_fun = new CCodeFunction("%s_get_type".printf(CCodeBaseModule.get_ccode_lower_case_name(get_type_declaration())), "GType");
                get_fun.modifiers = CCodeModifiers.CONST;

                get_fun.is_declaration = true;
                declaration_fragment.append(get_fun.copy());
                get_fun.is_declaration = false;

                get_fun.block = new CCodeBlock();
                get_fun.block.add_statement(new CCodeReturnStatement(new CCodeIdentifier(type_id_name)));

                definition_fragment.append(get_fun);
            }

            string type_value_table_decl_name = null;
            var    type_init = new CCodeBlock();

            if (fundamental)
            {
                var cgtypetabledecl = new CCodeDeclaration("const GTypeValueTable");
                cgtypetabledecl.modifiers = CCodeModifiers.STATIC;

                cgtypetabledecl.add_declarator(new CCodeVariableDeclarator("g_define_type_value_table", new CCodeConstant("{ %s, %s, %s, %s, \"p\", %s, \"p\", %s }".printf(get_gtype_value_table_init_function_name(), get_gtype_value_table_free_function_name(), get_gtype_value_table_copy_function_name(), get_gtype_value_table_peek_pointer_function_name(), get_gtype_value_table_collect_value_function_name(), get_gtype_value_table_lcopy_value_function_name()))));
                type_value_table_decl_name = "&g_define_type_value_table";
                type_init.add_statement(cgtypetabledecl);
            }
            else
            {
                type_value_table_decl_name = "NULL";
            }


            if (get_type_declaration() is ObjectTypeSymbol)
            {
                var ctypedecl = new CCodeDeclaration("const GTypeInfo");
                ctypedecl.modifiers = CCodeModifiers.STATIC;
                ctypedecl.add_declarator(new CCodeVariableDeclarator("g_define_type_info", new CCodeConstant("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) %s, (GClassInitFunc) %s, (GClassFinalizeFunc) %s, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf(get_type_struct_name(), get_base_init_func_name(), (plugin) ? get_base_finalize_func_name() : "NULL", get_class_init_func_name(), get_class_finalize_func_name(), get_instance_struct_size(), get_instance_init_func_name(), type_value_table_decl_name))));
                type_init.add_statement(ctypedecl);
                if (fundamental)
                {
                    var ctypefundamentaldecl = new CCodeDeclaration("const GTypeFundamentalInfo");
                    ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC;
                    ctypefundamentaldecl.add_declarator(new CCodeVariableDeclarator("g_define_type_fundamental_info", new CCodeConstant("{ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }")));
                    type_init.add_statement(ctypefundamentaldecl);
                }
            }

            type_init.add_statement(get_type_interface_init_declaration());

            CCodeFunctionCall reg_call;

            if (get_type_declaration() is Struct)
            {
                reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_boxed_type_register_static"));
            }
            else if (get_type_declaration() is ValaEnum)
            {
                var en = get_type_declaration() as ValaEnum;
                if (en.is_flags)
                {
                    reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_flags_register_static"));
                }
                else
                {
                    reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_enum_register_static"));
                }
            }
            else if (fundamental)
            {
                reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_register_fundamental"));
                reg_call.add_argument(new CCodeFunctionCall(new CCodeIdentifier("g_type_fundamental_next")));
            }
            else if (!plugin)
            {
                reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_register_static"));
                reg_call.add_argument(new CCodeIdentifier(get_parent_type_name()));
            }
            else
            {
                reg_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_module_register_type"));
                reg_call.add_argument(new CCodeIdentifier("module"));
                reg_call.add_argument(new CCodeIdentifier(get_parent_type_name()));
            }
            reg_call.add_argument(new CCodeConstant("\"%s\"".printf(CCodeBaseModule.get_ccode_name(get_type_declaration()))));
            if (get_type_declaration() is Struct)
            {
                var st = (Struct)get_type_declaration();
                reg_call.add_argument(new CCodeCastExpression(new CCodeIdentifier(CCodeBaseModule.get_ccode_dup_function(st)), "GBoxedCopyFunc"));
                reg_call.add_argument(new CCodeCastExpression(new CCodeIdentifier(CCodeBaseModule.get_ccode_free_function(st)), "GBoxedFreeFunc"));
            }
            else if (get_type_declaration() is ValaEnum)
            {
                var en    = get_type_declaration() as ValaEnum;
                var clist = new CCodeInitializerList();                 /* or during visit time? */

                CCodeInitializerList clist_ev = null;
                foreach (EnumValue ev in en.get_values())
                {
                    clist_ev = new CCodeInitializerList();
                    clist_ev.append(new CCodeConstant(CCodeBaseModule.get_ccode_name(ev)));
                    clist_ev.append(new CCodeIdentifier("\"%s\"".printf(CCodeBaseModule.get_ccode_name(ev))));
                    clist_ev.append(CCodeBaseModule.get_enum_value_canonical_cconstant(ev));
                    clist.append(clist_ev);
                }

                clist_ev = new CCodeInitializerList();
                clist_ev.append(new CCodeConstant("0"));
                clist_ev.append(new CCodeConstant("NULL"));
                clist_ev.append(new CCodeConstant("NULL"));
                clist.append(clist_ev);

                var enum_decl = new CCodeVariableDeclarator("values[]", clist);

                if (en.is_flags)
                {
                    cdecl = new CCodeDeclaration("const GFlagsValue");
                }
                else
                {
                    cdecl = new CCodeDeclaration("const GEnumValue");
                }

                cdecl.add_declarator(enum_decl);
                cdecl.modifiers = CCodeModifiers.STATIC;

                type_init.add_statement(cdecl);

                reg_call.add_argument(new CCodeIdentifier("values"));
            }
            else
            {
                reg_call.add_argument(new CCodeIdentifier("&g_define_type_info"));
                if (fundamental)
                {
                    reg_call.add_argument(new CCodeIdentifier("&g_define_type_fundamental_info"));
                }
                reg_call.add_argument(new CCodeConstant(get_type_flags()));
            }

            if (use_thread_safe && !plugin)
            {
                var temp_decl = new CCodeDeclaration("GType");
                temp_decl.add_declarator(new CCodeVariableDeclarator(type_id_name, reg_call));
                type_init.add_statement(temp_decl);
            }
            else
            {
                type_init.add_statement(new CCodeExpressionStatement(new CCodeAssignment(new CCodeIdentifier(type_id_name), reg_call)));
            }

            if (cl != null && cl.has_class_private_fields)
            {
                CCodeFunctionCall add_class_private_call;

                add_class_private_call = new CCodeFunctionCall(new CCodeIdentifier("g_type_add_class_private"));
                add_class_private_call.add_argument(new CCodeIdentifier(type_id_name));
                add_class_private_call.add_argument(new CCodeIdentifier("sizeof (%sClassPrivate)".printf(CCodeBaseModule.get_ccode_name(get_type_declaration()))));
                type_init.add_statement(new CCodeExpressionStatement(add_class_private_call));
            }

            if (!declaration_only)
            {
                get_type_interface_init_statements(type_init, plugin);
            }

            if (!plugin)
            {
                CCodeExpression condition;                 // the condition that guards the type initialisation
                if (use_thread_safe)
                {
                    var enter = new CCodeFunctionCall(new CCodeIdentifier("g_once_init_enter"));
                    enter.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(type_id_name + "__volatile")));
                    condition = enter;

                    var leave = new CCodeFunctionCall(new CCodeIdentifier("g_once_init_leave"));
                    leave.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier(type_id_name + "__volatile")));
                    leave.add_argument(new CCodeIdentifier(type_id_name));
                    type_init.add_statement(new CCodeExpressionStatement(leave));
                }
                else
                {
                    var id   = new CCodeIdentifier(type_id_name);
                    var zero = new CCodeConstant("0");
                    condition = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, id, zero);
                }

                CCodeExpression cond;
                if (use_thread_safe)
                {
                    cond = condition;
                }
                else
                {
                    cond = new CCodeFunctionCall(new CCodeIdentifier("G_UNLIKELY"));
                    (cond as CCodeFunctionCall).add_argument(condition);
                }
                var cif = new CCodeIfStatement(cond, type_init);
                type_block.add_statement(cif);
            }
            else
            {
                type_block = type_init;
            }

            if (use_thread_safe)
            {
                type_block.add_statement(new CCodeReturnStatement(new CCodeIdentifier(type_id_name + "__volatile")));
            }
            else
            {
                type_block.add_statement(new CCodeReturnStatement(new CCodeIdentifier(type_id_name)));
            }

            fun.block = type_block;

            definition_fragment.append(fun);
        }
예제 #2
0
        public string generate_delegate_wrapper(Method m, DelegateType dt, CodeNode node)
        {
            var    d = dt.delegate_symbol;
            string delegate_name;
            var    sig         = d.parent_symbol as Signal;
            var    dynamic_sig = sig as DynamicSignal;

            if (dynamic_sig != null)
            {
                delegate_name = get_dynamic_signal_cname(dynamic_sig);
            }
            else if (sig != null)
            {
                delegate_name = get_ccode_lower_case_prefix(sig.parent_symbol) + get_ccode_lower_case_name(sig);
            }
            else
            {
                delegate_name = Symbol.camel_case_to_lower_case(get_ccode_name(d));
            }

            string wrapper_name = "_%s_%s".printf(get_ccode_name(m), delegate_name);

            if (!add_wrapper(wrapper_name))
            {
                // wrapper already defined
                return(wrapper_name);
            }

            // declaration

            string return_type_cname = get_ccode_name(d.return_type);

            if (d.return_type.is_real_non_null_struct_type())
            {
                // structs are returned via out parameter
                return_type_cname = "void";
            }

            var function = new CCodeFunction(wrapper_name, return_type_cname);

            function.modifiers = CCodeModifiers.STATIC;

            push_function(function);

            var cparam_map = new Dictionary <int, CCodeParameter>();

            if (d.has_target)
            {
                var cparam = new CCodeParameter("self", "gpointer");
                cparam_map[get_param_pos(get_ccode_instance_pos(d))] = cparam;
            }

            if (d.sender_type != null)
            {
                var param = new Parameter("_sender", d.sender_type);
                generate_parameter(param, cfile, cparam_map, null);
            }

            var d_params = d.get_parameters();

            foreach (Parameter param in d_params)
            {
                if (dynamic_sig != null &&
                    param.variable_type is ArrayType &&
                    ((ArrayType)param.variable_type).element_type.data_type == string_type.data_type)
                {
                    // use null-terminated string arrays for dynamic signals for compatibility reasons
                    param.set_attribute_bool("CCode", "array_length", false);
                    param.set_attribute_bool("CCode", "array_null_terminated", true);
                }

                generate_parameter(param, cfile, cparam_map, null);
            }
            if (get_ccode_array_length(d) && d.return_type is ArrayType)
            {
                // return array length if appropriate
                var array_type        = (ArrayType)d.return_type;
                var array_length_type = get_ccode_array_length_type(d) != null?get_ccode_array_length_type(d) : "int";

                array_length_type += "*";

                for (int dim = 1; dim <= array_type.rank; dim++)
                {
                    var cparam = new CCodeParameter(get_array_length_cname("result", dim), array_length_type);
                    cparam_map[get_param_pos(get_ccode_array_length_pos(d) + 0.01 * dim)] = cparam;
                }
            }
            else if (d.return_type is DelegateType)
            {
                // return delegate target if appropriate
                var deleg_type = (DelegateType)d.return_type;

                if (deleg_type.delegate_symbol.has_target)
                {
                    var cparam = new CCodeParameter(get_delegate_target_cname("result"), "void**");
                    cparam_map[get_param_pos(get_ccode_delegate_target_pos(d))] = cparam;
                    if (deleg_type.is_disposable())
                    {
                        cparam = new CCodeParameter(get_delegate_target_destroy_notify_cname("result"), "GDestroyNotify*");
                        cparam_map[get_param_pos(get_ccode_delegate_target_pos(d) + 0.01)] = cparam;
                    }
                }
            }
            else if (d.return_type.is_real_non_null_struct_type())
            {
                var cparam = new CCodeParameter("result", "%s*".printf(get_ccode_name(d.return_type)));
                cparam_map[get_param_pos(-3)] = cparam;
            }

            if (m.get_error_types().Count > 0)
            {
                var cparam = new CCodeParameter("error", "GError**");
                cparam_map[get_param_pos(-1)] = cparam;
            }

            // append C parameters in the right order
            int last_pos = -1;
            int min_pos;

            while (true)
            {
                min_pos = -1;
                foreach (int pos in cparam_map.Keys)
                {
                    if (pos > last_pos && (min_pos == -1 || pos < min_pos))
                    {
                        min_pos = pos;
                    }
                }
                if (min_pos == -1)
                {
                    break;
                }
                function.add_parameter(cparam_map[min_pos]);
                last_pos = min_pos;
            }


            // definition

            var carg_map = new Dictionary <int, CCodeExpression>();

            int i = 0;

            if (m.binding == MemberBinding.INSTANCE || m.closure)
            {
                CCodeExpression arg;
                if (d.has_target)
                {
                    arg = new CCodeIdentifier("self");
                    if (!m.closure && m.this_parameter != null)
                    {
                        arg = convert_from_generic_pointer(arg, m.this_parameter.variable_type);
                    }
                }
                else
                {
                    // use first delegate parameter as instance
                    if (d_params.Count == 0 || m.closure)
                    {
                        Report.error(node != null ? node.source_reference : null, "Cannot create delegate without target for instance method or closure");
                        arg = new CCodeConstant("NULL");
                    }
                    else
                    {
                        arg = new CCodeIdentifier(get_variable_cname(d_params[0].name));
                        i   = 1;
                    }
                }
                carg_map[get_param_pos(get_ccode_instance_pos(m))] = arg;
            }

            bool first = true;

            foreach (Parameter param in m.get_parameters())
            {
                if (first && d.sender_type != null && m.get_parameters().Count == d.get_parameters().Count + 1)
                {
                    // sender parameter
                    carg_map[get_param_pos(get_ccode_pos(param))] = new CCodeIdentifier("_sender");

                    first = false;
                    continue;
                }

                CCodeExpression arg;
                arg = new CCodeIdentifier(get_variable_cname(d_params[i].name));
                if (d_params[i].variable_type is GenericType)
                {
                    arg = convert_from_generic_pointer(arg, param.variable_type);
                }
                carg_map[get_param_pos(get_ccode_pos(param))] = arg;

                // handle array arguments
                if (get_ccode_array_length(param) && param.variable_type is ArrayType)
                {
                    var array_type = (ArrayType)param.variable_type;
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        CCodeExpression clength;
                        if (get_ccode_array_null_terminated(d_params[i]))
                        {
                            requires_array_length = true;
                            var len_call = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_length"));
                            len_call.add_argument(new CCodeIdentifier(d_params[i].name));
                            clength = len_call;
                        }
                        else if (!get_ccode_array_length(d_params[i]))
                        {
                            clength = new CCodeConstant("-1");
                        }
                        else
                        {
                            clength = new CCodeIdentifier(get_parameter_array_length_cname(d_params[i], dim));
                        }
                        carg_map[get_param_pos(get_ccode_array_length_pos(param) + 0.01 * dim)] = clength;
                    }
                }
                else if (param.variable_type is DelegateType)
                {
                    var deleg_type = (DelegateType)param.variable_type;

                    if (deleg_type.delegate_symbol.has_target)
                    {
                        var ctarget = new CCodeIdentifier(get_ccode_delegate_target_name(d_params[i]));
                        carg_map[get_param_pos(get_ccode_delegate_target_pos(param))] = ctarget;
                        if (deleg_type.is_disposable())
                        {
                            var ctarget_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(d_params[i].name));
                            carg_map[get_param_pos(get_ccode_delegate_target_pos(m) + 0.01)] = ctarget_destroy_notify;
                        }
                    }
                }

                i++;
            }
            if (get_ccode_array_length(m) && m.return_type is ArrayType)
            {
                var array_type = (ArrayType)m.return_type;
                for (int dim = 1; dim <= array_type.rank; dim++)
                {
                    CCodeExpression clength;
                    if (!get_ccode_array_length(d))
                    {
                        clength = new CCodeConstant("NULL");
                    }
                    else
                    {
                        clength = new CCodeIdentifier(get_array_length_cname("result", dim));
                    }
                    carg_map[get_param_pos(get_ccode_array_length_pos(m) + 0.01 * dim)] = clength;
                }
            }
            else if (m.return_type is DelegateType)
            {
                var deleg_type = (DelegateType)m.return_type;

                if (deleg_type.delegate_symbol.has_target)
                {
                    var ctarget = new CCodeIdentifier(get_delegate_target_cname("result"));
                    carg_map[get_param_pos(get_ccode_delegate_target_pos(m))] = ctarget;
                    if (deleg_type.is_disposable())
                    {
                        var ctarget_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname("result"));
                        carg_map[get_param_pos(get_ccode_delegate_target_pos(m) + 0.01)] = ctarget_destroy_notify;
                    }
                }
            }
            else if (m.return_type.is_real_non_null_struct_type())
            {
                carg_map[get_param_pos(-3)] = new CCodeIdentifier("result");
            }

            if (m.get_error_types().Count > 0)
            {
                carg_map[get_param_pos(-1)] = new CCodeIdentifier("error");
            }

            var ccall = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_name(m)));

            // append C arguments in the right order
            last_pos = -1;
            while (true)
            {
                min_pos = -1;
                foreach (int pos in carg_map.Keys)
                {
                    if (pos > last_pos && (min_pos == -1 || pos < min_pos))
                    {
                        min_pos = pos;
                    }
                }
                if (min_pos == -1)
                {
                    break;
                }
                ccall.add_argument(carg_map[min_pos]);
                last_pos = min_pos;
            }

            if (m.coroutine)
            {
                ccall.add_argument(new CCodeConstant("NULL"));
                ccall.add_argument(new CCodeConstant("NULL"));
            }

            if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type())
            {
                ccode.add_expression(ccall);
                if (!(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type()))
                {
                    // return a default value
                    ccode.add_declaration(return_type_cname, new CCodeVariableDeclarator("result", default_value_for_type(d.return_type, true)));
                }
            }
            else
            {
                CCodeExpression result = ccall;
                if (d.return_type is GenericType)
                {
                    result = convert_to_generic_pointer(result, m.return_type);
                }
                ccode.add_declaration(return_type_cname, new CCodeVariableDeclarator("result", result));
            }

            if (d.has_target /* TODO: && dt.value_owned */ && dt.is_called_once)
            {
                // destroy notify "self" after the call
                CCodeExpression destroy_notify = null;
                if (m.closure)
                {
                    int block_id = get_block_id(current_closure_block);
                    destroy_notify = new CCodeIdentifier("block%d_data_unref".printf(block_id));
                }
                else if (get_this_type() != null && m.binding != MemberBinding.STATIC && !m.is_async_callback && is_reference_counting(m.this_parameter.variable_type.data_type))
                {
                    destroy_notify = get_destroy_func_expression(m.this_parameter.variable_type);
                }

                if (destroy_notify != null)
                {
                    var unref_call = new CCodeFunctionCall(destroy_notify);
                    unref_call.add_argument(new CCodeIdentifier("self"));
                    ccode.add_expression(unref_call);
                }
            }

            if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type()) ||
                !(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type()))
            {
                ccode.add_return(new CCodeIdentifier("result"));
            }

            pop_function();

            // append to file
            cfile.add_function_declaration(function);
            cfile.add_function(function);

            return(wrapper_name);
        }
예제 #3
0
        void visit_string_switch_statement(SwitchStatement stmt)
        {
            // we need a temporary variable to save the property value
            var temp_value = create_temp_value(stmt.expression.value_type, false, stmt);
            var ctemp      = get_cvalue_(temp_value);

            var cinit = new CCodeAssignment(ctemp, get_cvalue(stmt.expression));
            var czero = new CCodeConstant("0");

            var free_call = new CCodeFunctionCall(new CCodeIdentifier("g_free"));

            free_call.add_argument(ctemp);

            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);

            int label_temp_id = next_temp_var_id++;

            temp_value = create_temp_value(gquark_type, true, stmt);

            int label_count = 0;

            foreach (SwitchSection section in stmt.get_sections())
            {
                if (section.has_default_label())
                {
                    continue;
                }

                foreach (SwitchLabel label in section.get_labels())
                {
                    label.expression.emit(this);
                    var cexpr = get_cvalue(label.expression);

                    if (is_constant_ccode_expression(cexpr))
                    {
                        var cname = "_tmp%d_label%d".printf(label_temp_id, label_count++);

                        ccode.add_declaration(get_ccode_name(gquark_type), new CCodeVariableDeclarator(cname, czero), CCodeModifiers.STATIC);
                    }
                }
            }

            ccode.add_expression(cinit);

            ctemp = get_cvalue_(temp_value);
            cinit = new CCodeAssignment(ctemp, ccond);

            ccode.add_expression(cinit);

            if (stmt.expression.value_type.value_owned)
            {
                // free owned string
                ccode.add_expression(free_call);
            }

            SwitchSection default_section = null;

            label_count = 0;

            int n = 0;

            foreach (SwitchSection section in stmt.get_sections())
            {
                if (section.has_default_label())
                {
                    default_section = section;
                    continue;
                }

                CCodeBinaryExpression cor = null;
                foreach (SwitchLabel label in section.get_labels())
                {
                    label.expression.emit(this);
                    var cexpr = get_cvalue(label.expression);

                    if (is_constant_ccode_expression(cexpr))
                    {
                        var cname      = new CCodeIdentifier("_tmp%d_label%d".printf(label_temp_id, label_count++));
                        var ccondition = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, czero, cname);
                        var ccall      = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_static_string"));
                        cinit = new CCodeAssignment(cname, ccall);

                        ccall.add_argument(cexpr);

                        cexpr = new CCodeConditionalExpression(ccondition, 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);
                    }
                }

                if (n > 0)
                {
                    ccode.else_if(cor);
                }
                else
                {
                    ccode.open_if(cor);
                }

                ccode.open_switch(new CCodeConstant("0"));
                ccode.add_default();

                section.emit(this);

                ccode.close();

                n++;
            }

            if (default_section != null)
            {
                if (n > 0)
                {
                    ccode.add_else();
                }

                ccode.open_switch(new CCodeConstant("0"));
                ccode.add_default();

                default_section.emit(this);

                ccode.close();
            }

            if (n > 0)
            {
                ccode.close();
            }
        }
예제 #4
0
        public override void generate_class_init(Class cl)
        {
            if (!cl.is_subtype_of(gobject_type))
            {
                return;
            }

            /* set property handlers */
            var ccall = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_CLASS"));

            ccall.add_argument(new CCodeIdentifier("klass"));
            if (class_has_readable_properties(cl) || cl.get_type_parameters().Count > 0)
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(ccall, "get_property"), new CCodeIdentifier("_vala_%s_get_property".printf(get_ccode_lower_case_name(cl, null))));
            }
            if (class_has_writable_properties(cl) || cl.get_type_parameters().Count > 0)
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(ccall, "set_property"), new CCodeIdentifier("_vala_%s_set_property".printf(get_ccode_lower_case_name(cl, null))));
            }

            /* set constructor */
            if (cl.constructor != null)
            {
                var ccast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_CLASS"));
                ccast.add_argument(new CCodeIdentifier("klass"));
                ccode.add_assignment(CCodeMemberAccess.pointer(ccast, "constructor"), new CCodeIdentifier("%s_constructor".printf(get_ccode_lower_case_name(cl, null))));
            }

            /* set finalize function */
            if (cl.get_fields().Count > 0 || cl.destructor != null)
            {
                var ccast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_CLASS"));
                ccast.add_argument(new CCodeIdentifier("klass"));
                ccode.add_assignment(CCodeMemberAccess.pointer(ccast, "finalize"), new CCodeIdentifier("%s_finalize".printf(get_ccode_lower_case_name(cl, null))));
            }

            /* create type, dup_func, and destroy_func properties for generic types */
            foreach (TypeParameter type_param in cl.get_type_parameters())
            {
                string            func_name, enum_value;
                CCodeConstant     func_name_constant;
                CCodeFunctionCall cinst, cspec;

                var name_prefix      = type_param.name.ToLower();
                var canonical_prefix = name_prefix.Replace("_", "-");

                func_name          = "%s_type".printf(name_prefix);
                func_name_constant = new CCodeConstant("\"%s-type\"".printf(canonical_prefix));
                enum_value         = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper();
                cinst = new CCodeFunctionCall(new CCodeIdentifier("g_object_class_install_property"));
                cinst.add_argument(ccall);
                cinst.add_argument(new CCodeConstant(enum_value));
                cspec = new CCodeFunctionCall(new CCodeIdentifier("g_param_spec_gtype"));
                cspec.add_argument(func_name_constant);
                cspec.add_argument(new CCodeConstant("\"type\""));
                cspec.add_argument(new CCodeConstant("\"type\""));
                cspec.add_argument(new CCodeIdentifier("G_TYPE_NONE"));
                cspec.add_argument(new CCodeConstant("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
                cinst.add_argument(cspec);
                ccode.add_expression(cinst);
                prop_enum.add_value(new CCodeEnumValue(enum_value));


                func_name          = "%s_dup_func".printf(name_prefix);
                func_name_constant = new CCodeConstant("\"%s-dup-func\"".printf(canonical_prefix));
                enum_value         = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper();
                cinst = new CCodeFunctionCall(new CCodeIdentifier("g_object_class_install_property"));
                cinst.add_argument(ccall);
                cinst.add_argument(new CCodeConstant(enum_value));
                cspec = new CCodeFunctionCall(new CCodeIdentifier("g_param_spec_pointer"));
                cspec.add_argument(func_name_constant);
                cspec.add_argument(new CCodeConstant("\"dup func\""));
                cspec.add_argument(new CCodeConstant("\"dup func\""));
                cspec.add_argument(new CCodeConstant("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
                cinst.add_argument(cspec);
                ccode.add_expression(cinst);
                prop_enum.add_value(new CCodeEnumValue(enum_value));


                func_name          = "%s_destroy_func".printf(name_prefix);
                func_name_constant = new CCodeConstant("\"%s-destroy-func\"".printf(canonical_prefix));
                enum_value         = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper();
                cinst = new CCodeFunctionCall(new CCodeIdentifier("g_object_class_install_property"));
                cinst.add_argument(ccall);
                cinst.add_argument(new CCodeConstant(enum_value));
                cspec = new CCodeFunctionCall(new CCodeIdentifier("g_param_spec_pointer"));
                cspec.add_argument(func_name_constant);
                cspec.add_argument(new CCodeConstant("\"destroy func\""));
                cspec.add_argument(new CCodeConstant("\"destroy func\""));
                cspec.add_argument(new CCodeConstant("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
                cinst.add_argument(cspec);
                ccode.add_expression(cinst);
                prop_enum.add_value(new CCodeEnumValue(enum_value));
            }

            /* create properties */
            var props = cl.get_properties();

            foreach (Property prop in props)
            {
                if (!is_gobject_property(prop))
                {
                    continue;
                }

                if (prop.comment != null)
                {
                    ccode.add_statement(new CCodeComment(prop.comment.content));
                }

                var cinst = new CCodeFunctionCall(new CCodeIdentifier("g_object_class_install_property"));
                cinst.add_argument(ccall);
                cinst.add_argument(new CCodeConstant(get_ccode_upper_case_name(prop)));
                cinst.add_argument(get_param_spec(prop));

                ccode.add_expression(cinst);
            }
        }
예제 #5
0
        public override TargetValue load_variable(Variable variable, TargetValue value)
        {
            var result        = (GLibValue)value;
            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            if (array_type != null)
            {
                if (array_type.fixed_length)
                {
                    result.array_length_cvalues = null;
                    result.append_array_length_cvalue(get_ccodenode(array_type.length));
                    result.lvalue = false;
                }
                else if (get_ccode_array_null_terminated(variable))
                {
                    requires_array_length = true;
                    var len_call = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_length"));
                    len_call.add_argument(result.cvalue);

                    result.array_length_cvalues = null;
                    result.append_array_length_cvalue(len_call);
                    result.lvalue = false;
                }
                else if (get_ccode_array_length_expr(variable) != null)
                {
                    var length_expr = new CCodeConstant(get_ccode_array_length_expr(variable));

                    result.array_length_cvalues = null;
                    result.append_array_length_cvalue(length_expr);
                    result.lvalue = false;
                }
                else if (!get_ccode_array_length(variable))
                {
                    result.array_length_cvalues = null;
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(new CCodeConstant("-1"));
                    }
                    result.lvalue = false;
                }
                else if (get_ccode_array_length_type(variable) != null)
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        // cast if variable does not use int for array length
                        result.array_length_cvalues[dim - 1] = new CCodeCastExpression(result.array_length_cvalues[dim - 1], "gint");
                    }
                    result.lvalue = false;
                }
                result.array_size_cvalue = null;
            }
            else if (delegate_type != null)
            {
                if (!delegate_type.delegate_symbol.has_target || !get_ccode_delegate_target(variable))
                {
                    result.delegate_target_cvalue = new CCodeConstant("NULL");
                }

                result.delegate_target_destroy_notify_cvalue = new CCodeConstant("NULL");
                result.lvalue = false;
            }
            result.value_type.value_owned = false;

            bool use_temp = true;

            if (!is_lvalue_access_allowed(result.value_type))
            {
                // special handling for types such as va_list
                use_temp = false;
            }
            if (variable is Parameter && variable.name == "this")
            {
                use_temp = false;
            }
            if (variable.single_assignment && !result.value_type.is_real_non_null_struct_type())
            {
                // no need to copy values from variables that are assigned exactly once
                // as there is no risk of modification
                // except for structs that are always passed by reference
                use_temp = false;
            }
            var local = variable as LocalVariable;

            if (local != null && local.name[0] == '.')
            {
                // already a temporary variable generated internally
                // and safe to access without temporary variable
                use_temp = false;
            }

            if (use_temp)
            {
                result = (GLibValue)store_temp_value(result, variable);
            }

            return(result);
        }