Exemple #1
0
        public override void return_with_exception(CCodeExpression error_expr)
        {
            if (!is_in_coroutine())
            {
                base.return_with_exception(error_expr);
                return;
            }

            var async_result_expr       = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), "_async_result");
            CCodeFunctionCall set_error = null;

            set_error = new CCodeFunctionCall(new CCodeIdentifier("g_task_return_error"));
            set_error.add_argument(async_result_expr);
            set_error.add_argument(error_expr);
            ccode.add_expression(set_error);

            append_local_free(current_symbol, false);

            // We already returned the error above, we must not return anything else here.
            var unref = new CCodeFunctionCall(new CCodeIdentifier("g_object_unref"));

            unref.add_argument(async_result_expr);
            ccode.add_expression(unref);

            ccode.add_return(new CCodeConstant("FALSE"));
        }
Exemple #2
0
        CCodeExpression get_array_length(CCodeExpression expr, int dim)
        {
            var id = expr as CCodeIdentifier;
            var ma = expr as CCodeMemberAccess;

            if (id != null)
            {
                return(new CCodeIdentifier("%s_length%d".printf(id.name, dim)));
            }
            else if (ma != null)
            {
                if (ma.is_pointer)
                {
                    return(CCodeMemberAccess.pointer(ma.inner, "%s_length%d".printf(ma.member_name, dim)));
                }
                else
                {
                    return(new CCodeMemberAccess(ma.inner, "%s_length%d".printf(ma.member_name, dim)));
                }
            }
            else
            {
                // must be NULL-terminated
                var len_call = new CCodeFunctionCall(new CCodeIdentifier("g_strv_length"));
                len_call.add_argument(expr);
                return(len_call);
            }
        }
Exemple #3
0
        void uncaught_error_statement(CCodeExpression inner_error, bool unexpected = false)
        {
            // free local variables
            append_local_free(current_symbol, false);

            var ccritical = new CCodeFunctionCall(new CCodeIdentifier("g_critical"));

            ccritical.add_argument(new CCodeConstant(unexpected ? "\"file %s: line %d: unexpected error: %s (%s, %d)\"" : "\"file %s: line %d: uncaught error: %s (%s, %d)\""));
            ccritical.add_argument(new CCodeConstant("__FILE__"));
            ccritical.add_argument(new CCodeConstant("__LINE__"));
            ccritical.add_argument(CCodeMemberAccess.pointer(inner_error, "message"));
            var domain_name = new CCodeFunctionCall(new CCodeIdentifier("g_quark_to_string"));

            domain_name.add_argument(CCodeMemberAccess.pointer(inner_error, "domain"));
            ccritical.add_argument(domain_name);
            ccritical.add_argument(CCodeMemberAccess.pointer(inner_error, "code"));

            var cclear = new CCodeFunctionCall(new CCodeIdentifier("g_clear_error"));

            cclear.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, inner_error));

            // print critical message
            ccode.add_expression(ccritical);
            ccode.add_expression(cclear);

            if (is_in_constructor() || is_in_destructor())
            {
                // just print critical, do not return prematurely
            }
            else if (current_method is CreationMethod)
            {
                if (current_method.parent_symbol is Struct)
                {
                    ccode.add_return();
                }
                else
                {
                    ccode.add_return(new CCodeConstant("NULL"));
                }
            }
            else if (is_in_coroutine())
            {
                var async_result_expr = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), "_async_result");
                var unref             = new CCodeFunctionCall(new CCodeIdentifier("g_object_unref"));
                unref.add_argument(async_result_expr);
                ccode.add_expression(unref);
                ccode.add_return(new CCodeConstant("FALSE"));
            }
            else if (current_return_type != null)
            {
                return_default_value(current_return_type);
            }
        }
Exemple #4
0
        void generate_async_ready_callback_wrapper(Method m, string function_name)
        {
            var function = new CCodeFunction(function_name, "void");

            function.modifiers = CCodeModifiers.STATIC;

            function.add_parameter(new CCodeParameter("*source_object", "GObject"));
            function.add_parameter(new CCodeParameter("*res", "GAsyncResult"));
            function.add_parameter(new CCodeParameter("*user_data", "void"));

            push_function(function);

            // Set _task_complete_ to false after calling back to the real func
            var async_result_cast = new CCodeFunctionCall(new CCodeIdentifier("G_TASK"));

            async_result_cast.add_argument(new CCodeIdentifier("res"));

            var dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_task_data_"));

            var get_data_call = new CCodeFunctionCall(new CCodeIdentifier("g_task_get_task_data"));

            get_data_call.add_argument(async_result_cast);

            var data_var = new CCodeIdentifier("_task_data_");

            ccode.add_assignment(data_var, get_data_call);

            var task_inner_callback = CCodeMemberAccess.pointer(data_var, "_callback_");
            var callback_is_nonnull = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, task_inner_callback, new CCodeConstant("NULL"));

            ccode.open_if(callback_is_nonnull);
            var nested_callback = new CCodeFunctionCall(task_inner_callback);

            nested_callback.add_argument(new CCodeIdentifier("source_object"));
            nested_callback.add_argument(new CCodeIdentifier("res"));
            nested_callback.add_argument(new CCodeIdentifier("user_data"));
            ccode.add_expression(nested_callback);
            ccode.close();

            ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_task_complete_"), new CCodeConstant("TRUE"));

            pop_function();

            cfile.add_function_declaration(function);
            cfile.add_function(function);
        }
Exemple #5
0
        public override string generate_ready_function(Method m)
        {
            // generate ready callback handler

            var dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";

            var readyfunc = new CCodeFunction(get_ccode_name(m) + "_ready", "void");

            if (!add_wrapper(readyfunc.name))
            {
                // wrapper already defined
                return(readyfunc.name);
            }

            readyfunc.add_parameter(new CCodeParameter("source_object", "GObject*"));
            readyfunc.add_parameter(new CCodeParameter("_res_", "GAsyncResult*"));
            readyfunc.add_parameter(new CCodeParameter("_user_data_", "gpointer"));

            push_function(readyfunc);

            var data_var = new CCodeIdentifier("_data_");

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_"));
            ccode.add_assignment(data_var, new CCodeIdentifier("_user_data_"));
            ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_source_object_"), new CCodeIdentifier("source_object"));
            ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_res_"), new CCodeIdentifier("_res_"));

            if (!context.require_glib_version(2, 44))
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_task_complete_"), new CCodeConstant("TRUE"));
            }

            var ccall = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_real_name(m) + "_co"));

            ccall.add_argument(data_var);
            ccode.add_expression(ccall);

            readyfunc.modifiers |= CCodeModifiers.STATIC;

            pop_function();

            cfile.add_function_declaration(readyfunc);
            cfile.add_function(readyfunc);

            return(readyfunc.name);
        }
Exemple #6
0
        public override void visit_yield_statement(YieldStatement stmt)
        {
            if (!is_in_coroutine())
            {
                return;
            }

            if (stmt.yield_expression == null)
            {
                int state = emit_context.next_coroutine_state++;

                ccode.add_assignment(CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), "_state_"), new CCodeConstant(state.ToString()));
                ccode.add_return(new CCodeConstant("FALSE"));
                ccode.add_label("_state_%d".printf(state));
                ccode.add_statement(new CCodeEmptyStatement());

                return;
            }

            if (stmt.yield_expression.error)
            {
                stmt.error = true;
                return;
            }

            ccode.add_expression(get_cvalue(stmt.yield_expression));

            if (stmt.tree_can_fail && stmt.yield_expression.tree_can_fail)
            {
                // simple case, no node breakdown necessary

                add_simple_check(stmt.yield_expression);
            }

            /* free temporary objects */

            foreach (var value in temp_ref_values)
            {
                ccode.add_expression(destroy_value(value));
            }

            temp_ref_values.Clear();
        }
Exemple #7
0
        public override void visit_constructor(Constructor c)
        {
            push_line(c.source_reference);

            var cl = (Class)c.parent_symbol;

            if (c.binding == MemberBinding.INSTANCE)
            {
                if (!cl.is_subtype_of(gobject_type))
                {
                    Report.error(c.source_reference, "construct blocks require GLib.Object");
                    c.error = true;
                    return;
                }

                push_context(new EmitContext(c));

                var function = new CCodeFunction("%s_constructor".printf(get_ccode_lower_case_name(cl, null)), "GObject *");
                function.modifiers = CCodeModifiers.STATIC;

                function.add_parameter(new CCodeParameter("type", "GType"));
                function.add_parameter(new CCodeParameter("n_construct_properties", "guint"));
                function.add_parameter(new CCodeParameter("construct_properties", "GObjectConstructParam *"));

                cfile.add_function_declaration(function);

                push_function(function);

                ccode.add_declaration("GObject *", new CCodeVariableDeclarator("obj"));
                ccode.add_declaration("GObjectClass *", new CCodeVariableDeclarator("parent_class"));

                var ccast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_CLASS"));
                ccast.add_argument(new CCodeIdentifier("%s_parent_class".printf(get_ccode_lower_case_name(cl, null))));
                ccode.add_assignment(new CCodeIdentifier("parent_class"), ccast);

                var ccall = new CCodeFunctionCall(CCodeMemberAccess.pointer(new CCodeIdentifier("parent_class"), "constructor"));
                ccall.add_argument(new CCodeIdentifier("type"));
                ccall.add_argument(new CCodeIdentifier("n_construct_properties"));
                ccall.add_argument(new CCodeIdentifier("construct_properties"));
                ccode.add_assignment(new CCodeIdentifier("obj"), ccall);


                ccall = generate_instance_cast(new CCodeIdentifier("obj"), cl);

                ccode.add_declaration("%s *".printf(get_ccode_name(cl)), new CCodeVariableDeclarator("self"));
                ccode.add_assignment(new CCodeIdentifier("self"), ccall);

                c.body.emit(this);

                if (current_method_inner_error)
                {
                    /* always separate error parameter and inner_error local variable
                     * as error may be set to NULL but we're always interested in inner errors
                     */
                    ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL")));
                }

                ccode.add_return(new CCodeIdentifier("obj"));

                pop_function();
                cfile.add_function(function);

                pop_context();
            }
            else if (c.binding == MemberBinding.CLASS)
            {
                // class constructor

                if (cl.is_compact)
                {
                    Report.error(c.source_reference, "class constructors are not supported in compact classes");
                    c.error = true;
                    return;
                }

                push_context(base_init_context);

                c.body.emit(this);

                if (current_method_inner_error)
                {
                    /* always separate error parameter and inner_error local variable
                     * as error may be set to NULL but we're always interested in inner errors
                     */
                    ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL")));
                }

                pop_context();
            }
            else if (c.binding == MemberBinding.STATIC)
            {
                // static class constructor
                // add to class_init

                if (cl.is_compact)
                {
                    Report.error(c.source_reference, "static constructors are not supported in compact classes");
                    c.error = true;
                    return;
                }

                push_context(class_init_context);

                c.body.emit(this);

                if (current_method_inner_error)
                {
                    /* always separate error parameter and inner_error local variable
                     * as error may be set to NULL but we're always interested in inner errors
                     */
                    ccode.add_declaration("GError *", CCodeVariableDeclarator.zero("_inner_error_", new CCodeConstant("NULL")));
                }

                pop_context();
            }
            else
            {
                Report.error(c.source_reference, "internal error: constructors must have instance, class, or static binding");
            }

            pop_line();
        }
Exemple #8
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);
            }
        }
Exemple #9
0
        private void add_set_property_function(Class cl)
        {
            var set_prop = new CCodeFunction("_vala_%s_set_property".printf(get_ccode_lower_case_name(cl, null)), "void");

            set_prop.modifiers = CCodeModifiers.STATIC;
            set_prop.add_parameter(new CCodeParameter("object", "GObject *"));
            set_prop.add_parameter(new CCodeParameter("property_id", "guint"));
            set_prop.add_parameter(new CCodeParameter("value", "const GValue *"));
            set_prop.add_parameter(new CCodeParameter("pspec", "GParamSpec *"));

            push_function(set_prop);

            CCodeFunctionCall ccall = generate_instance_cast(new CCodeIdentifier("object"), cl);

            ccode.add_declaration("%s *".printf(get_ccode_name(cl)), new CCodeVariableDeclarator("self", ccall));

            ccode.open_switch(new CCodeIdentifier("property_id"));
            var props = cl.get_properties();

            foreach (Property prop in props)
            {
                if (prop.set_accessor == null || prop.is_abstract)
                {
                    continue;
                }
                if (!is_gobject_property(prop))
                {
                    continue;
                }

                Property        base_prop = prop;
                CCodeExpression cself     = new CCodeIdentifier("self");
                if (prop.base_property != null)
                {
                    var base_type = (Class)prop.base_property.parent_symbol;
                    base_prop = prop.base_property;
                    cself     = get_cvalue_(transform_value(new GLibValue(new ObjectType(cl), cself, true), new ObjectType(base_type), prop));

                    generate_property_accessor_declaration(prop.base_property.set_accessor, cfile);
                }
                else if (prop.base_interface_property != null)
                {
                    var base_type = (Interface)prop.base_interface_property.parent_symbol;
                    base_prop = prop.base_interface_property;
                    cself     = get_cvalue_(transform_value(new GLibValue(new ObjectType(cl), cself, true), new ObjectType(base_type), prop));

                    generate_property_accessor_declaration(prop.base_interface_property.set_accessor, cfile);
                }

                CCodeExpression cfunc;
                if (!get_ccode_no_accessor_method(base_prop) && !get_ccode_concrete_accessor(base_prop))
                {
                    cfunc = new CCodeIdentifier(get_ccode_name(base_prop.set_accessor));
                }
                else
                {
                    // use the static real function as helper
                    cfunc = new CCodeIdentifier(get_ccode_real_name(prop.set_accessor));
                }

                ccode.add_case(new CCodeIdentifier(get_ccode_upper_case_name(prop)));
                ccall = new CCodeFunctionCall(cfunc);
                ccall.add_argument(cself);
                if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.data_type == string_type.data_type)
                {
                    ccode.open_block();
                    ccode.add_declaration("gpointer", new CCodeVariableDeclarator("boxed"));

                    var cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_boxed"));
                    cgetcall.add_argument(new CCodeIdentifier("value"));
                    ccode.add_assignment(new CCodeIdentifier("boxed"), cgetcall);
                    ccall.add_argument(new CCodeIdentifier("boxed"));

                    var cisnull  = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier("boxed"), new CCodeConstant("NULL"));
                    var cstrvlen = new CCodeFunctionCall(new CCodeIdentifier("g_strv_length"));
                    cstrvlen.add_argument(new CCodeIdentifier("boxed"));
                    var ccond = new CCodeConditionalExpression(cisnull, new CCodeConstant("0"), cstrvlen);

                    ccall.add_argument(ccond);
                    add_guarded_expression(prop, ccall);
                    ccode.close();
                }
                else
                {
                    var cgetcall = new CCodeFunctionCall();
                    if (prop.property_type.data_type != null)
                    {
                        cgetcall.call = new CCodeIdentifier(get_ccode_get_value_function(prop.property_type.data_type));
                    }
                    else
                    {
                        cgetcall.call = new CCodeIdentifier("g_value_get_pointer");
                    }
                    cgetcall.add_argument(new CCodeIdentifier("value"));
                    ccall.add_argument(cgetcall);
                    add_guarded_expression(prop, ccall);
                }
                ccode.add_break();
            }

            /* type, dup func, and destroy func properties for generic types */
            foreach (TypeParameter type_param in cl.get_type_parameters())
            {
                string            func_name, enum_value;
                CCodeMemberAccess cfield;
                CCodeFunctionCall cgetcall;

                func_name  = "%s_type".printf(type_param.name.ToLower());
                enum_value = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper();
                ccode.add_case(new CCodeIdentifier(enum_value));
                cfield   = CCodeMemberAccess.pointer(CCodeMemberAccess.pointer(new CCodeIdentifier("self"), "priv"), func_name);
                cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_gtype"));
                cgetcall.add_argument(new CCodeIdentifier("value"));
                ccode.add_assignment(cfield, cgetcall);
                ccode.add_break();

                func_name  = "%s_dup_func".printf(type_param.name.ToLower());
                enum_value = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper();
                ccode.add_case(new CCodeIdentifier(enum_value));
                cfield   = CCodeMemberAccess.pointer(CCodeMemberAccess.pointer(new CCodeIdentifier("self"), "priv"), func_name);
                cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_pointer"));
                cgetcall.add_argument(new CCodeIdentifier("value"));
                ccode.add_assignment(cfield, cgetcall);
                ccode.add_break();

                func_name  = "%s_destroy_func".printf(type_param.name.ToLower());
                enum_value = "%s_%s".printf(get_ccode_lower_case_name(cl, null), func_name).ToUpper();
                ccode.add_case(new CCodeIdentifier(enum_value));
                cfield   = CCodeMemberAccess.pointer(CCodeMemberAccess.pointer(new CCodeIdentifier("self"), "priv"), func_name);
                cgetcall = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_pointer"));
                cgetcall.add_argument(new CCodeIdentifier("value"));
                ccode.add_assignment(cfield, cgetcall);
                ccode.add_break();
            }
            ccode.add_default();
            emit_invalid_property_id_warn();
            ccode.add_break();

            ccode.close();

            pop_function();

            cfile.add_function_declaration(set_prop);
            cfile.add_function(set_prop);
        }
Exemple #10
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();
        }
Exemple #11
0
        void generate_async_function(Method m)
        {
            push_context(new EmitContext());

            string callback_wrapper = null;

            if (!context.require_glib_version(2, 44))
            {
                callback_wrapper = get_ccode_real_name(m) + "_async_ready_wrapper";
                generate_async_ready_callback_wrapper(m, callback_wrapper);
            }

            var dataname   = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";
            var asyncfunc  = new CCodeFunction(get_ccode_real_name(m), "void");
            var cparam_map = new Dictionary <int, CCodeParameter>();

            cparam_map[get_param_pos(-1)]   = new CCodeParameter("_callback_", "GAsyncReadyCallback");
            cparam_map[get_param_pos(-0.9)] = new CCodeParameter("_user_data_", "gpointer");

            generate_cparameters(m, cfile, cparam_map, asyncfunc, null, null, null, 1);

            if (m.base_method != null || m.base_interface_method != null)
            {
                // declare *_real_* function
                asyncfunc.modifiers |= CCodeModifiers.STATIC;
                cfile.add_function_declaration(asyncfunc);
            }
            else if (m.is_private_symbol())
            {
                asyncfunc.modifiers |= CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && m.is_internal_symbol())
            {
                asyncfunc.modifiers |= CCodeModifiers.INTERNAL;
            }

            push_function(asyncfunc);

            // logic copied from valaccodemethodmodule
            if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual))
            {
                Method base_method;

                if (m.overrides)
                {
                    base_method = m.base_method;
                }
                else
                {
                    base_method = m.base_interface_method;
                }

                var base_expression_type = new ObjectType((ObjectTypeSymbol)base_method.parent_symbol);
                var type_symbol          = m.parent_symbol as ObjectTypeSymbol;

                var self_target_type = new ObjectType(type_symbol);
                var cself            = get_cvalue_(transform_value(new GLibValue(base_expression_type, new CCodeIdentifier("base"), true), self_target_type, m));
                ccode.add_declaration("%s *".printf(get_ccode_name(type_symbol)), new CCodeVariableDeclarator("self"));
                ccode.add_assignment(new CCodeIdentifier("self"), cself);
            }

            var dataalloc = new CCodeFunctionCall(new CCodeIdentifier("g_slice_new0"));

            dataalloc.add_argument(new CCodeIdentifier(dataname));

            var data_var = new CCodeIdentifier("_data_");

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_"));
            ccode.add_assignment(data_var, dataalloc);

            if (!context.require_glib_version(2, 44))
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_callback_"), new CCodeConstant("_callback_"));
            }

            var create_result = new CCodeFunctionCall(new CCodeIdentifier("g_task_new"));

            var t = m.parent_symbol as TypeSymbol;

            if (!(m is CreationMethod) && m.binding == MemberBinding.INSTANCE &&
                t != null && t.is_subtype_of(gobject_type))
            {
                var gobject_cast = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT"));
                gobject_cast.add_argument(new CCodeIdentifier("self"));

                create_result.add_argument(gobject_cast);
            }
            else
            {
                create_result.add_argument(new CCodeConstant("NULL"));
            }

            Parameter cancellable_param = null;

            foreach (Parameter param in m.get_parameters())
            {
                if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name() == "GLib.Cancellable")
                {
                    cancellable_param = param;
                    break;
                }
            }

            if (cancellable_param == null)
            {
                create_result.add_argument(new CCodeConstant("NULL"));
            }
            else
            {
                create_result.add_argument(new CCodeIdentifier(get_variable_cname(cancellable_param.name)));
            }

            if (context.require_glib_version(2, 44))
            {
                create_result.add_argument(new CCodeIdentifier("_callback_"));
            }
            else
            {
                create_result.add_argument(new CCodeIdentifier(callback_wrapper));
            }
            create_result.add_argument(new CCodeIdentifier("_user_data_"));

            ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "_async_result"), create_result);

            if (!context.require_glib_version(2, 44))
            {
                var task_completed_var = CCodeMemberAccess.pointer(data_var, "_task_complete_");
                var callback           = new CCodeIdentifier("_callback_");
                var callback_is_null   = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, callback, new CCodeConstant("NULL"));

                ccode.open_if(callback_is_null);
                ccode.add_assignment(task_completed_var, new CCodeConstant("TRUE"));
                ccode.close();
            }

            var attach_data_call = new CCodeFunctionCall(new CCodeIdentifier("g_task_set_task_data"));

            attach_data_call.add_argument(CCodeMemberAccess.pointer(data_var, "_async_result"));
            attach_data_call.add_argument(data_var);
            attach_data_call.add_argument(new CCodeIdentifier(get_ccode_real_name(m) + "_data_free"));
            ccode.add_expression(attach_data_call);

            if (m is CreationMethod)
            {
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "object_type"), new CCodeIdentifier("object_type"));
            }
            else if (m.binding == MemberBinding.INSTANCE)
            {
                var this_type = m.this_parameter.variable_type.copy();
                this_type.value_owned = true;

                // create copy if necessary as variables in async methods may need to be kept alive
                CCodeExpression cself = new CCodeIdentifier("self");
                if (this_type.is_real_non_null_struct_type())
                {
                    cself = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, cself);
                }
                if (requires_copy(this_type))
                {
                    cself = get_cvalue_(copy_value(new GLibValue(m.this_parameter.variable_type, cself, true), m.this_parameter));
                }

                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "self"), cself);
            }

            emit_context.push_symbol(m);
            foreach (Parameter param in m.get_parameters())
            {
                if (param.direction != ParameterDirection.OUT)
                {
                    // create copy if necessary as variables in async methods may need to be kept alive
                    var old_captured = param.captured;
                    param.captured           = false;
                    current_method.coroutine = false;

                    TargetValue value;
                    if (param.variable_type.value_owned)
                    {
                        // do not use load_parameter for reference/ownership transfer
                        // otherwise delegate destroy notify will not be moved
                        value = get_parameter_cvalue(param);
                    }
                    else
                    {
                        value = load_parameter(param);
                    }

                    current_method.coroutine = true;

                    store_parameter(param, value);

                    param.captured = old_captured;
                }
            }
            emit_context.pop_symbol();

            foreach (var type_param in m.get_type_parameters())
            {
                var type         = "%s_type".printf(type_param.name.ToLower());
                var dup_func     = "%s_dup_func".printf(type_param.name.ToLower());
                var destroy_func = "%s_destroy_func".printf(type_param.name.ToLower());
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, type), new CCodeIdentifier(type));
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, dup_func), new CCodeIdentifier(dup_func));
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, destroy_func), new CCodeIdentifier(destroy_func));
            }

            var ccall = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_real_name(m) + "_co"));

            ccall.add_argument(data_var);
            ccode.add_expression(ccall);

            cfile.add_function(asyncfunc);

            pop_context();
        }
Exemple #12
0
        /* Returns lvalue access to the given local variable */
        public override TargetValue get_local_cvalue(LocalVariable local)
        {
            var result = new GLibValue(local.variable_type.copy());

            result.lvalue = true;

            var array_type    = local.variable_type as ArrayType;
            var delegate_type = local.variable_type as DelegateType;

            if (local.is_result)
            {
                // used in postconditions
                // structs are returned as out parameter
                if (local.variable_type != null && local.variable_type.is_real_non_null_struct_type())
                {
                    result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("result"));
                }
                else
                {
                    result.cvalue = new CCodeIdentifier("result");
                }
                if (array_type != null && !array_type.fixed_length && ((current_method != null && get_ccode_array_length(current_method)) || current_property_accessor != null))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression(get_array_length_cname("result", dim))));
                    }
                }
            }
            else if (local.captured)
            {
                // captured variables are stored on the heap
                var block = (Block)local.parent_symbol;
                result.cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_local_cname(local));
                if (array_type != null && !array_type.fixed_length)
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_array_length_cname(get_local_cname(local), dim)));
                    }
                    if (array_type.rank == 1)
                    {
                        result.array_size_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_array_size_cname(get_local_cname(local)));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                {
                    result.delegate_target_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_cname(get_local_cname(local)));
                    if (delegate_type.is_disposable())
                    {
                        result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_destroy_notify_cname(get_local_cname(local)));
                    }
                }
            }
            else
            {
                result.cvalue = get_local_cexpression(local);
                if (array_type != null && !array_type.fixed_length)
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(get_variable_cexpression(get_array_length_cname(get_local_cname(local), dim)));
                    }
                    if (array_type.rank == 1)
                    {
                        result.array_size_cvalue = get_variable_cexpression(get_array_size_cname(get_local_cname(local)));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                {
                    if (is_in_coroutine())
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_cname(get_local_cname(local)));
                        if (local.variable_type.value_owned)
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_destroy_notify_cname(get_local_cname(local)));
                        }
                    }
                    else
                    {
                        result.delegate_target_cvalue = new CCodeIdentifier(get_delegate_target_cname(get_local_cname(local)));
                        if (local.variable_type.value_owned)
                        {
                            result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_local_cname(local)));
                        }
                    }
                }
            }

            return(result);
        }
Exemple #13
0
        public override void visit_member_access(MemberAccess expr)
        {
            CCodeExpression pub_inst = null;

            if (expr.inner != null)
            {
                pub_inst = get_cvalue(expr.inner);
            }

            var array_type    = expr.value_type as ArrayType;
            var delegate_type = expr.value_type as DelegateType;

            if (expr.symbol_reference is Method)
            {
                var m = (Method)expr.symbol_reference;

                if (!(m is DynamicMethod || m is ArrayMoveMethod || m is ArrayResizeMethod || m is ArrayCopyMethod))
                {
                    generate_method_declaration(m, cfile);

                    if (!m.external && m.external_package)
                    {
                        // internal VAPI methods
                        // only add them once per source file
                        if (add_generated_external_symbol(m))
                        {
                            visit_method(m);
                        }
                    }
                }

                if (expr.inner is BaseAccess)
                {
                    if (m.base_method != null)
                    {
                        var base_class = (Class)m.base_method.parent_symbol;
                        var vcast      = new CCodeFunctionCall(new CCodeIdentifier("%s_CLASS".printf(get_ccode_upper_case_name(base_class, null))));
                        vcast.add_argument(new CCodeIdentifier("%s_parent_class".printf(get_ccode_lower_case_name(current_class, null))));

                        set_cvalue(expr, CCodeMemberAccess.pointer(vcast, get_ccode_vfunc_name(m)));
                        return;
                    }
                    else if (m.base_interface_method != null)
                    {
                        var    base_iface       = (Interface)m.base_interface_method.parent_symbol;
                        string parent_iface_var = "%s_%s_parent_iface".printf(get_ccode_lower_case_name(current_class), get_ccode_lower_case_name(base_iface));

                        set_cvalue(expr, CCodeMemberAccess.pointer(new CCodeIdentifier(parent_iface_var), get_ccode_vfunc_name(m)));
                        return;
                    }
                }

                if (m.base_method != null)
                {
                    if (!method_has_wrapper(m.base_method))
                    {
                        var base_class = (Class)m.base_method.parent_symbol;
                        var vclass     = new CCodeFunctionCall(new CCodeIdentifier("%s_GET_CLASS".printf(get_ccode_upper_case_name(base_class))));
                        vclass.add_argument(pub_inst);
                        set_cvalue(expr, CCodeMemberAccess.pointer(vclass, get_ccode_vfunc_name(m)));
                    }
                    else
                    {
                        set_cvalue(expr, new CCodeIdentifier(get_ccode_name(m.base_method)));
                    }
                }
                else if (m.base_interface_method != null)
                {
                    set_cvalue(expr, new CCodeIdentifier(get_ccode_name(m.base_interface_method)));
                }
                else if (m is CreationMethod)
                {
                    set_cvalue(expr, new CCodeIdentifier(get_ccode_real_name(m)));
                }
                else
                {
                    set_cvalue(expr, new CCodeIdentifier(get_ccode_name(m)));
                }

                set_delegate_target_destroy_notify(expr, new CCodeConstant("NULL"));
                if (m.binding == MemberBinding.STATIC)
                {
                    set_delegate_target(expr, new CCodeConstant("NULL"));
                }
                else if (m.is_async_callback)
                {
                    if (current_method.closure)
                    {
                        var block = ((Method)m.parent_symbol).body;
                        set_delegate_target(expr, CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), "_async_data_"));
                    }
                    else
                    {
                        set_delegate_target(expr, new CCodeIdentifier("_data_"));
                    }
                }
                else if (expr.inner != null && !expr.prototype_access)
                {
                    // expr.inner is null in the special case of referencing the method in a constant initializer
                    var delegate_target = (CCodeExpression)get_ccodenode(expr.inner);
                    delegate_type = expr.target_type as DelegateType;
                    if ((expr.value_type.value_owned || (delegate_type != null && delegate_type.is_called_once)) && expr.inner.value_type.data_type != null && is_reference_counting(expr.inner.value_type.data_type))
                    {
                        var ref_call = new CCodeFunctionCall(get_dup_func_expression(expr.inner.value_type, expr.source_reference));
                        ref_call.add_argument(delegate_target);
                        delegate_target = ref_call;
                        set_delegate_target_destroy_notify(expr, get_destroy_func_expression(expr.inner.value_type));
                    }
                    set_delegate_target(expr, delegate_target);
                }
            }
            else if (expr.symbol_reference is ArrayLengthField)
            {
                if (expr.value_type is ArrayType && !(expr.parent_node is ElementAccess))
                {
                    Report.error(expr.source_reference, "unsupported use of length field of multi-dimensional array");
                }
                set_cvalue(expr, get_array_length_cexpression(expr.inner, 1));
            }
            else if (expr.symbol_reference is Field)
            {
                var field = (Field)expr.symbol_reference;
                if (expr.lvalue)
                {
                    expr.target_value = get_field_cvalue(field, expr.inner != null ? expr.inner.target_value : null);
                }
                else
                {
                    expr.target_value = load_field(field, expr.inner != null ? expr.inner.target_value : null);
                }
            }
            else if (expr.symbol_reference is EnumValue)
            {
                var ev = (EnumValue)expr.symbol_reference;

                generate_enum_declaration((ValaEnum)ev.parent_symbol, cfile);

                set_cvalue(expr, new CCodeConstant(get_ccode_name(ev)));
            }
            else if (expr.symbol_reference is Constant)
            {
                var c = (Constant)expr.symbol_reference;

                generate_constant_declaration(c, cfile,
                                              c.source_reference != null && expr.source_reference != null &&
                                              c.source_reference.file == expr.source_reference.file);

                string fn = c.get_full_name();
                if (fn == "GLib.Log.FILE")
                {
                    string s = Path.GetFileName(expr.source_reference.file.filename);
                    set_cvalue(expr, new CCodeConstant("\"%s\"".printf(s)));
                }
                else if (fn == "GLib.Log.LINE")
                {
                    int i = expr.source_reference.begin.line;
                    set_cvalue(expr, new CCodeConstant("%d".printf(i)));
                }
                else if (fn == "GLib.Log.METHOD")
                {
                    string s = "";
                    if (current_method != null)
                    {
                        s = current_method.get_full_name();
                    }
                    set_cvalue(expr, new CCodeConstant("\"%s\"".printf(s)));
                }
                else
                {
                    set_cvalue(expr, new CCodeIdentifier(get_ccode_name(c)));
                }

                if (array_type != null)
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("G_N_ELEMENTS"));
                    ccall.add_argument(new CCodeIdentifier(get_ccode_name(c)));
                    append_array_length(expr, ccall);
                }
            }
            else if (expr.symbol_reference is Property)
            {
                var prop = (Property)expr.symbol_reference;

                if (!(prop is DynamicProperty))
                {
                    generate_property_accessor_declaration(prop.get_accessor, cfile);

                    if (!prop.external && prop.external_package)
                    {
                        // internal VAPI properties
                        // only add them once per source file
                        if (add_generated_external_symbol(prop))
                        {
                            visit_property(prop);
                        }
                    }
                }

                if (expr.inner is BaseAccess)
                {
                    var base_prop = prop;
                    if (prop.base_property != null)
                    {
                        base_prop = prop.base_property;
                    }
                    else if (prop.base_interface_property != null)
                    {
                        base_prop = prop.base_interface_property;
                    }
                    if (base_prop.parent_symbol is Class)
                    {
                        var base_class = (Class)base_prop.parent_symbol;
                        var vcast      = new CCodeFunctionCall(new CCodeIdentifier("%s_CLASS".printf(get_ccode_upper_case_name(base_class, null))));
                        vcast.add_argument(new CCodeIdentifier("%s_parent_class".printf(get_ccode_lower_case_name(current_class, null))));

                        var ccall = new CCodeFunctionCall(CCodeMemberAccess.pointer(vcast, "get_%s".printf(prop.name)));
                        ccall.add_argument(get_cvalue(expr.inner));
                        if (prop.property_type.is_real_non_null_struct_type())
                        {
                            var temp_value = (GLibValue)create_temp_value(prop.get_accessor.value_type, false, expr);
                            expr.target_value = load_temp_value(temp_value);
                            var ctemp = get_cvalue_(temp_value);
                            ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, ctemp));
                            ccode.add_expression(ccall);
                        }
                        else
                        {
                            set_cvalue(expr, ccall);
                        }
                    }
                    else if (base_prop.parent_symbol is Interface)
                    {
                        var    base_iface       = (Interface)base_prop.parent_symbol;
                        string parent_iface_var = "%s_%s_parent_iface".printf(get_ccode_lower_case_name(current_class), get_ccode_lower_case_name(base_iface));

                        var ccall = new CCodeFunctionCall(CCodeMemberAccess.pointer(new CCodeIdentifier(parent_iface_var), "get_%s".printf(prop.name)));
                        ccall.add_argument(get_cvalue(expr.inner));
                        if (prop.property_type.is_real_non_null_struct_type())
                        {
                            var temp_value = (GLibValue)create_temp_value(prop.get_accessor.value_type, false, expr);
                            expr.target_value = load_temp_value(temp_value);
                            var ctemp = get_cvalue_(temp_value);
                            ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, ctemp));
                            ccode.add_expression(ccall);
                        }
                        else
                        {
                            set_cvalue(expr, ccall);
                        }
                    }
                }
                else if (prop.binding == MemberBinding.INSTANCE &&
                         prop.get_accessor.automatic_body &&
                         !prop.get_accessor.value_type.value_owned &&
                         current_type_symbol == prop.parent_symbol &&
                         current_type_symbol is Class &&
                         prop.base_property == null &&
                         prop.base_interface_property == null &&
                         !(prop.property_type is ArrayType || prop.property_type is DelegateType))
                {
                    CCodeExpression inst;
                    inst = CCodeMemberAccess.pointer(pub_inst, "priv");
                    set_cvalue(expr, CCodeMemberAccess.pointer(inst, get_ccode_name(prop.field)));
                }
                else if (!get_ccode_no_accessor_method(prop))
                {
                    string getter_cname;
                    if (prop is DynamicProperty)
                    {
                        getter_cname = get_dynamic_property_getter_cname((DynamicProperty)prop);
                    }
                    else
                    {
                        getter_cname = get_ccode_name(prop.get_accessor);
                    }
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier(getter_cname));

                    if (prop.binding == MemberBinding.INSTANCE)
                    {
                        if (prop.parent_symbol is Struct && !((Struct)prop.parent_symbol).is_simple_type())
                        {
                            // we need to pass struct instance by reference
                            var instance = expr.inner.target_value;
                            if (!get_lvalue(instance))
                            {
                                instance = store_temp_value(instance, expr);
                            }
                            pub_inst = new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, get_cvalue_(instance));
                        }

                        ccall.add_argument(pub_inst);
                    }

                    bool prop_is_real_non_null_struct_type = prop.property_type.is_real_non_null_struct_type();
                    var  temp_value = (GLibValue)create_temp_value(prop.get_accessor.value_type, prop_is_real_non_null_struct_type, expr);
                    expr.target_value = load_temp_value(temp_value);
                    var ctemp = get_cvalue_(temp_value);

                    // Property access to real struct types is handled differently
                    // The value is returned by out parameter
                    if (prop_is_real_non_null_struct_type)
                    {
                        ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, ctemp));
                        ccode.add_expression(ccall);
                    }
                    else
                    {
                        ccode.add_assignment(ctemp, ccall);

                        array_type = prop.property_type as ArrayType;
                        if (array_type != null)
                        {
                            if (get_ccode_array_null_terminated(prop))
                            {
                                requires_array_length = true;
                                var len_call = new CCodeFunctionCall(new CCodeIdentifier("_vala_array_length"));
                                len_call.add_argument(ctemp);

                                ccode.add_assignment(temp_value.array_length_cvalues[0], len_call);
                            }
                            else if (get_ccode_array_length(prop))
                            {
                                for (int dim = 1; dim <= array_type.rank; dim++)
                                {
                                    ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, get_array_length_cvalue(temp_value, dim)));
                                }
                            }
                        }
                        else
                        {
                            delegate_type = prop.property_type as DelegateType;
                            if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                            {
                                ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_cvalue(temp_value)));
                            }
                        }
                    }
                }
                else
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_object_get"));
                    ccall.add_argument(pub_inst);

                    // property name is second argument of g_object_get
                    ccall.add_argument(get_property_canonical_cconstant(prop));

                    // g_object_get always returns owned values
                    // therefore, property getters of properties
                    // without accessor methods need to be marked as owned
                    if (!prop.get_accessor.value_type.value_owned)
                    {
                        // only report error for types where there actually
                        // is a difference between `owned' and `unowned'
                        var owned_value_type = prop.get_accessor.value_type.copy();
                        owned_value_type.value_owned = true;
                        if (requires_copy(owned_value_type))
                        {
                            Report.error(prop.get_accessor.source_reference, "unowned return value for getter of property `%s' not supported without accessor".printf(prop.get_full_name()));
                        }
                    }

                    if (expr.value_type.is_real_struct_type())
                    {
                        // gobject allocates structs on heap
                        expr.value_type.nullable = true;
                    }

                    var temp_var = get_temp_variable(expr.value_type);
                    var ctemp    = get_variable_cexpression(temp_var.name);
                    emit_temp_var(temp_var);
                    ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, ctemp));
                    ccall.add_argument(new CCodeConstant("NULL"));
                    ccode.add_expression(ccall);
                    set_cvalue(expr, ctemp);
                }
                expr.target_value.value_type = expr.value_type;
                expr.target_value            = store_temp_value(expr.target_value, expr);
            }
            else if (expr.symbol_reference is LocalVariable)
            {
                var local = (LocalVariable)expr.symbol_reference;

                if (expr.parent_node is ReturnStatement &&
                    current_return_type.value_owned &&
                    local.variable_type.value_owned &&
                    !local.captured &&
                    !variable_accessible_in_finally(local) &&
                    !(local.variable_type is ArrayType && ((ArrayType)local.variable_type).inline_allocated))
                {
                    /* return expression is local variable taking ownership and
                     * current method is transferring ownership */

                    // don't ref expression
                    expr.value_type.value_owned = true;

                    // don't unref variable
                    local.active = false;

                    var glib_value = (GLibValue)get_local_cvalue(local);
                    expr.target_value = glib_value;
                    if (glib_value.delegate_target_cvalue == null)
                    {
                        glib_value.delegate_target_cvalue = new CCodeConstant("NULL");
                    }
                    if (glib_value.delegate_target_destroy_notify_cvalue == null)
                    {
                        glib_value.delegate_target_destroy_notify_cvalue = new CCodeConstant("NULL");
                    }
                }
                else
                {
                    if (expr.lvalue)
                    {
                        expr.target_value = get_local_cvalue(local);
                    }
                    else
                    {
                        expr.target_value = load_local(local);
                    }
                }
            }
            else if (expr.symbol_reference is Parameter)
            {
                var param = (Parameter)expr.symbol_reference;
                if (expr.lvalue)
                {
                    expr.target_value = get_parameter_cvalue(param);
                }
                else
                {
                    expr.target_value = load_parameter(param);
                }
            }
        }
Exemple #14
0
        void generate_finish_function(Method m)
        {
            push_context(new EmitContext());

            string dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";

            var finishfunc = new CCodeFunction(get_ccode_finish_real_name(m));

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

            cparam_map[get_param_pos(0.1)] = new CCodeParameter("_res_", "GAsyncResult*");

            generate_cparameters(m, cfile, cparam_map, finishfunc, null, null, null, 2);

            if (m.is_private_symbol() || m.base_method != null || m.base_interface_method != null)
            {
                finishfunc.modifiers |= CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && m.is_internal_symbol())
            {
                finishfunc.modifiers |= CCodeModifiers.INTERNAL;
            }

            push_function(finishfunc);

            var return_type = m.return_type;

            if (m is CreationMethod)
            {
                var type_sym = (TypeSymbol)m.parent_symbol;
                if (type_sym is ObjectTypeSymbol)
                {
                    ccode.add_declaration(get_ccode_name(type_sym) + "*", new CCodeVariableDeclarator("result"));
                }
            }
            else if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type())
            {
                ccode.add_declaration(get_ccode_name(m.return_type), new CCodeVariableDeclarator("result"));
            }

            var data_var = new CCodeIdentifier("_data_");

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_"));

            var async_result_cast = new CCodeFunctionCall(new CCodeIdentifier("G_TASK"));

            async_result_cast.add_argument(new CCodeIdentifier("_res_"));

            var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_task_propagate_pointer"));

            ccall.add_argument(async_result_cast);

            if (m.get_error_types().Count > 0)
            {
                ccall.add_argument(new CCodeIdentifier("error"));
            }
            else
            {
                ccall.add_argument(new CCodeConstant("NULL"));
            }

            ccode.add_assignment(data_var, ccall);

            bool has_cancellable = false;

            foreach (Parameter param in m.get_parameters())
            {
                if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name() == "GLib.Cancellable")
                {
                    has_cancellable = true;
                    break;
                }
            }

            // If a task is cancelled, g_task_propagate_pointer returns NULL
            if (m.get_error_types().Count > 0 || has_cancellable)
            {
                var is_null = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeConstant("NULL"), data_var);

                ccode.open_if(is_null);
                return_default_value(return_type);
                ccode.close();
            }

            emit_context.push_symbol(m);
            foreach (Parameter param in m.get_parameters())
            {
                if (param.direction != ParameterDirection.IN)
                {
                    return_out_parameter(param);
                    if (!(param.variable_type is ValaValueType) || param.variable_type.nullable)
                    {
                        ccode.add_assignment(CCodeMemberAccess.pointer(data_var, get_variable_cname(param.name)), new CCodeConstant("NULL"));
                    }
                }
            }
            emit_context.pop_symbol();

            if (m is CreationMethod)
            {
                ccode.add_assignment(new CCodeIdentifier("result"), CCodeMemberAccess.pointer(data_var, "self"));
                ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "self"), new CCodeConstant("NULL"));
                ccode.add_return(new CCodeIdentifier("result"));
            }
            else if (return_type.is_real_non_null_struct_type())
            {
                // structs are returned via out parameter
                CCodeExpression cexpr = CCodeMemberAccess.pointer(data_var, "result");
                if (requires_copy(return_type))
                {
                    cexpr = get_cvalue_(copy_value(new GLibValue(return_type, cexpr, true), return_type));
                }
                ccode.add_assignment(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("result")), cexpr);
            }
            else if (!(return_type is VoidType))
            {
                ccode.add_assignment(new CCodeIdentifier("result"), CCodeMemberAccess.pointer(data_var, "result"));
                if (return_type is ArrayType)
                {
                    var array_type = (ArrayType)return_type;
                    if (get_ccode_array_length(m))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            ccode.add_assignment(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_array_length_cname("result", dim))), CCodeMemberAccess.pointer(data_var, get_array_length_cname("result", dim)));
                        }
                    }
                }
                else if (return_type is DelegateType && ((DelegateType)return_type).delegate_symbol.has_target)
                {
                    ccode.add_assignment(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_delegate_target_cname("result"))), CCodeMemberAccess.pointer(data_var, get_delegate_target_cname("result")));
                }
                if (!(return_type is ValaValueType) || return_type.nullable)
                {
                    ccode.add_assignment(CCodeMemberAccess.pointer(data_var, "result"), new CCodeConstant("NULL"));
                }
                ccode.add_return(new CCodeIdentifier("result"));
            }

            pop_function();

            cfile.add_function(finishfunc);

            pop_context();
        }
Exemple #15
0
        void generate_marshaller(List <Parameter> _params, DataType return_type)
        {
            string signature;
            int    n_params, i;

            /* check whether a signal with the same signature already exists for this source file (or predefined) */
            signature = get_marshaller_signature(_params, return_type);
            if (predefined_marshal_set.Contains(signature) || user_marshal_set.Contains(signature))
            {
                return;
            }

            var signal_marshaller = new CCodeFunction(get_marshaller_function(_params, return_type, null), "void");

            signal_marshaller.modifiers = CCodeModifiers.STATIC;

            signal_marshaller.add_parameter(new CCodeParameter("closure", "GClosure *"));
            signal_marshaller.add_parameter(new CCodeParameter("return_value", "GValue *"));
            signal_marshaller.add_parameter(new CCodeParameter("n_param_values", "guint"));
            signal_marshaller.add_parameter(new CCodeParameter("param_values", "const GValue *"));
            signal_marshaller.add_parameter(new CCodeParameter("invocation_hint", "gpointer"));
            signal_marshaller.add_parameter(new CCodeParameter("marshal_data", "gpointer"));

            push_function(signal_marshaller);

            var callback_decl = new CCodeFunctionDeclarator(get_marshaller_function(_params, return_type, "GMarshalFunc"));

            callback_decl.add_parameter(new CCodeParameter("data1", "gpointer"));
            n_params = 1;
            foreach (Parameter p in _params)
            {
                callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), get_value_type_name_from_parameter(p)));
                n_params++;
                if (p.variable_type.is_array())
                {
                    for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++)
                    {
                        callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), "gint"));
                        n_params++;
                    }
                }
            }
            callback_decl.add_parameter(new CCodeParameter("data2", "gpointer"));
            ccode.add_statement(new CCodeTypeDefinition(get_value_type_name_from_type_reference(return_type), callback_decl));

            ccode.add_declaration(get_marshaller_function(_params, return_type, "GMarshalFunc"), new CCodeVariableDeclarator("callback"), CCodeModifiers.REGISTER);

            ccode.add_declaration("GCClosure *", new CCodeVariableDeclarator("cc", new CCodeCastExpression(new CCodeIdentifier("closure"), "GCClosure *")), CCodeModifiers.REGISTER);

            ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data1"), CCodeModifiers.REGISTER);
            ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data2"), CCodeModifiers.REGISTER);

            CCodeFunctionCall fc;

            if (return_type.data_type != null || return_type.is_array())
            {
                ccode.add_declaration(get_value_type_name_from_type_reference(return_type), new CCodeVariableDeclarator("v_return"));

                fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail"));
                fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("return_value"), new CCodeConstant("NULL")));
                ccode.add_expression(fc);
            }

            fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail"));
            fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier("n_param_values"), new CCodeConstant(n_params.ToString())));
            ccode.add_expression(fc);

            var data  = new CCodeMemberAccess(new CCodeIdentifier("closure"), "data", true);
            var param = new CCodeMemberAccess(new CCodeMemberAccess(new CCodeIdentifier("param_values"), "data[0]", true), "v_pointer");
            var cond  = new CCodeFunctionCall(new CCodeConstant("G_CCLOSURE_SWAP_DATA"));

            cond.add_argument(new CCodeIdentifier("closure"));
            ccode.open_if(cond);
            ccode.add_assignment(new CCodeIdentifier("data1"), data);
            ccode.add_assignment(new CCodeIdentifier("data2"), param);
            ccode.add_else();
            ccode.add_assignment(new CCodeIdentifier("data1"), param);
            ccode.add_assignment(new CCodeIdentifier("data2"), data);
            ccode.close();

            var c_assign_rhs = new CCodeCastExpression(new CCodeConditionalExpression(new CCodeIdentifier("marshal_data"), new CCodeIdentifier("marshal_data"), new CCodeMemberAccess(new CCodeIdentifier("cc"), "callback", true)), get_marshaller_function(_params, return_type, "GMarshalFunc"));

            ccode.add_assignment(new CCodeIdentifier("callback"), c_assign_rhs);

            fc = new CCodeFunctionCall(new CCodeIdentifier("callback"));
            fc.add_argument(new CCodeIdentifier("data1"));
            i = 1;
            foreach (Parameter p in _params)
            {
                string get_value_function;
                bool   is_array = p.variable_type.is_array();
                if (p.direction != ParameterDirection.IN)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else if (is_array)
                {
                    if (((ArrayType)p.variable_type).element_type.data_type == string_type.data_type)
                    {
                        get_value_function = "g_value_get_boxed";
                    }
                    else
                    {
                        get_value_function = "g_value_get_pointer";
                    }
                }
                else if (p.variable_type is PointerType || p.variable_type.type_parameter != null)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else if (p.variable_type is ErrorType)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else if (p.variable_type is ValaValueType && p.variable_type.nullable)
                {
                    get_value_function = "g_value_get_pointer";
                }
                else
                {
                    get_value_function = get_ccode_get_value_function(p.variable_type.data_type);
                }
                var inner_fc = new CCodeFunctionCall(new CCodeIdentifier(get_value_function));
                inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString())));
                fc.add_argument(inner_fc);
                i++;
                if (is_array)
                {
                    for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++)
                    {
                        inner_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_int"));
                        inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString())));
                        fc.add_argument(inner_fc);
                        i++;
                    }
                }
            }
            fc.add_argument(new CCodeIdentifier("data2"));

            if (return_type.data_type != null || return_type.is_array())
            {
                ccode.add_assignment(new CCodeIdentifier("v_return"), fc);

                CCodeFunctionCall set_fc;
                if (return_type.is_array())
                {
                    if (((ArrayType)return_type).element_type.data_type == string_type.data_type)
                    {
                        set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_boxed"));
                    }
                    else
                    {
                        set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                    }
                }
                else if (return_type.type_parameter != null)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                }
                else if (return_type is ErrorType)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                }
                else if (return_type.data_type == string_type.data_type)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_string"));
                }
                else if (return_type.data_type is Class || return_type.data_type is Interface)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_object"));
                }
                else if (return_type is ValaValueType && return_type.nullable)
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer"));
                }
                else
                {
                    set_fc = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_set_value_function(return_type.data_type)));
                }
                set_fc.add_argument(new CCodeIdentifier("return_value"));
                set_fc.add_argument(new CCodeIdentifier("v_return"));

                ccode.add_expression(set_fc);
            }
            else
            {
                ccode.add_expression(fc);
            }

            pop_function();

            cfile.add_function_declaration(signal_marshaller);
            cfile.add_function(signal_marshaller);
            user_marshal_set.Add(signature);
        }
Exemple #16
0
        public override void visit_member_access(MemberAccess expr)
        {
            if (expr.symbol_reference is Signal)
            {
                CCodeExpression pub_inst = null;

                if (expr.inner != null)
                {
                    pub_inst = get_cvalue(expr.inner);
                }

                var sig = (Signal)expr.symbol_reference;
                var cl  = (TypeSymbol)sig.parent_symbol;

                if (expr.inner is BaseAccess && sig.is_virtual)
                {
                    var m          = sig.default_handler;
                    var base_class = (Class)m.parent_symbol;
                    var vcast      = new CCodeFunctionCall(new CCodeIdentifier("%s_CLASS".printf(get_ccode_upper_case_name(base_class, null))));
                    vcast.add_argument(new CCodeIdentifier("%s_parent_class".printf(get_ccode_lower_case_name(current_class))));

                    set_cvalue(expr, CCodeMemberAccess.pointer(vcast, m.name));
                    return;
                }

                if (!sig.external_package && expr.source_reference.file == sig.source_reference.file)
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_signal_emit"));
                    ccall.add_argument(pub_inst);
                    ccall.add_argument(get_signal_id_cexpression(sig));
                    ccall.add_argument(new CCodeConstant("0"));

                    set_cvalue(expr, ccall);
                }
                else if (get_signal_has_emitter(sig))
                {
                    string emitter_func;
                    if (sig.emitter != null)
                    {
                        if (!sig.external_package && expr.source_reference.file != sig.source_reference.file)
                        {
                            generate_method_declaration(sig.emitter, cfile);
                        }
                        emitter_func = get_ccode_lower_case_name(sig.emitter);
                    }
                    else
                    {
                        emitter_func = "%s_%s".printf(get_ccode_lower_case_name(cl), get_ccode_lower_case_name(sig));
                    }
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier(emitter_func));

                    ccall.add_argument(pub_inst);
                    set_cvalue(expr, ccall);
                }
                else
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_signal_emit_by_name"));
                    ccall.add_argument(pub_inst);

                    ccall.add_argument(get_signal_canonical_constant(sig));

                    set_cvalue(expr, ccall);
                }
            }
            else
            {
                base.visit_member_access(expr);
            }
        }
Exemple #17
0
        /* Returns access values to the given parameter */
        public override TargetValue get_parameter_cvalue(Parameter param)
        {
            var result = new GLibValue(param.variable_type.copy());

            result.lvalue = true;
            result.array_null_terminated = get_ccode_array_null_terminated(param);
            if (get_ccode_array_length_expr(param) != null)
            {
                result.array_length_cexpr = new CCodeConstant(get_ccode_array_length_expr(param));
            }
            result.ctype = get_ccode_type(param);

            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            bool is_unowned_delegate = delegate_type != null && !param.variable_type.value_owned;

            if ((param.captured || is_in_coroutine()) && !is_unowned_delegate)
            {
                result.value_type.value_owned = true;
            }

            if (param.name == "this")
            {
                if (is_in_coroutine())
                {
                    // use closure
                    result.cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), "self");
                }
                else
                {
                    var st = result.value_type.data_type as Struct;
                    if (st != null && !st.is_simple_type())
                    {
                        result.cvalue = new CCodeIdentifier("(*self)");
                    }
                    else
                    {
                        result.cvalue = new CCodeIdentifier("self");
                    }
                }
            }
            else
            {
                string name = param.name;

                if (param.captured)
                {
                    // captured variables are stored on the heap
                    var block = param.parent_symbol as Block;
                    if (block == null)
                    {
                        block = ((Method)param.parent_symbol).body;
                    }
                    result.cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_variable_cname(param.name));
                    if (array_type != null && get_ccode_array_length(param))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            result.append_array_length_cvalue(CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_parameter_array_length_cname(param, dim)));
                        }
                    }
                    else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_ccode_delegate_target_name(param));
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)));
                        }
                    }
                }
                else if (is_in_coroutine())
                {
                    // use closure
                    result.cvalue = get_variable_cexpression(param.name);
                    if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_ccode_delegate_target_name(param));
                        if (delegate_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)));
                        }
                    }
                }
                else
                {
                    var type_as_struct = result.value_type.data_type as Struct;

                    if (param.direction == ParameterDirection.OUT)
                    {
                        name = "_vala_%s".printf(name);
                    }

                    if (param.direction == ParameterDirection.REF ||
                        (param.direction == ParameterDirection.IN && type_as_struct != null && !type_as_struct.is_simple_type() && !result.value_type.nullable))
                    {
                        result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_variable_cname(name)));
                    }
                    else
                    {
                        // Property setters of non simple structs shall replace all occurrences
                        // of the "value" formal parameter with a dereferencing version of that
                        // parameter.
                        if (current_property_accessor != null &&
                            current_property_accessor.writable &&
                            current_property_accessor.value_parameter == param &&
                            current_property_accessor.prop.property_type.is_real_struct_type() &&
                            !current_property_accessor.prop.property_type.nullable)
                        {
                            result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("value"));
                        }
                        else
                        {
                            result.cvalue = get_variable_cexpression(name);
                        }
                    }
                    if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        var target_cname = get_ccode_delegate_target_name(param);
                        if (param.direction == ParameterDirection.OUT)
                        {
                            target_cname = "_vala_%s".printf(target_cname);
                        }
                        CCodeExpression target_expr = new CCodeIdentifier(target_cname);
                        CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_variable_cname(name)));
                        if (param.direction == ParameterDirection.REF)
                        {
                            // accessing argument of ref param
                            target_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
                            delegate_target_destroy_notify = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
                        }
                        result.delegate_target_cvalue = target_expr;
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = delegate_target_destroy_notify;
                        }
                    }
                }
                if (!param.captured && array_type != null)
                {
                    if (get_ccode_array_length(param) && !get_ccode_array_null_terminated(param))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            CCodeExpression length_expr = get_variable_cexpression(get_parameter_array_length_cname(param, dim));
                            if (param.direction == ParameterDirection.OUT)
                            {
                                length_expr = get_variable_cexpression(get_array_length_cname(get_variable_cname(name), dim));
                            }
                            else if (param.direction == ParameterDirection.REF)
                            {
                                // accessing argument of ref param
                                length_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, length_expr);
                            }
                            result.append_array_length_cvalue(length_expr);
                        }
                    }
                }
            }

            return(result);
        }
Exemple #18
0
        public override void add_simple_check(CodeNode node, bool always_fails = false)
        {
            current_method_inner_error = true;

            var inner_error = get_variable_cexpression("_inner_error_");

            if (always_fails)
            {
                // inner_error is always set, avoid unnecessary if statement
                // eliminates C warnings
            }
            else
            {
                var ccond    = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, inner_error, new CCodeConstant("NULL"));
                var unlikely = new CCodeFunctionCall(new CCodeIdentifier("G_UNLIKELY"));
                unlikely.add_argument(ccond);
                ccode.open_if(unlikely);
            }

            if (current_try != null)
            {
                // surrounding try found

                // free local variables
                if (is_in_catch)
                {
                    append_local_free(current_symbol, false, current_catch);
                }
                else
                {
                    append_local_free(current_symbol, false, current_try);
                }

                var error_types = new List <DataType>();
                foreach (DataType node_error_type in node.get_error_types())
                {
                    error_types.Add(node_error_type);
                }

                bool has_general_catch_clause = false;

                if (!is_in_catch)
                {
                    var handled_error_types = new List <DataType>();
                    foreach (CatchClause clause in current_try.get_catch_clauses())
                    {
                        // keep track of unhandled error types
                        foreach (DataType node_error_type in error_types)
                        {
                            if (clause.error_type == null || node_error_type.compatible(clause.error_type))
                            {
                                handled_error_types.Add(node_error_type);
                            }
                        }
                        foreach (DataType handled_error_type in handled_error_types)
                        {
                            error_types.Remove(handled_error_type);
                        }
                        handled_error_types.Clear();

                        if (clause.error_type.equals(gerror_type))
                        {
                            // general catch clause, this should be the last one
                            has_general_catch_clause = true;
                            ccode.add_goto(clause.clabel_name);
                            break;
                        }
                        else
                        {
                            var catch_type = clause.error_type as ErrorType;

                            if (catch_type.error_code != null)
                            {
                                /* catch clause specifies a specific error code */
                                var error_match = new CCodeFunctionCall(new CCodeIdentifier("g_error_matches"));
                                error_match.add_argument(inner_error);
                                error_match.add_argument(new CCodeIdentifier(get_ccode_upper_case_name(catch_type.data_type)));
                                error_match.add_argument(new CCodeIdentifier(get_ccode_name(catch_type.error_code)));

                                ccode.open_if(error_match);
                            }
                            else
                            {
                                /* catch clause specifies a full error domain */
                                var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY,
                                                                      CCodeMemberAccess.pointer(inner_error, "domain"), new CCodeIdentifier
                                                                          (get_ccode_upper_case_name(clause.error_type.data_type)));

                                ccode.open_if(ccond);
                            }

                            // go to catch clause if error domain matches
                            ccode.add_goto(clause.clabel_name);
                            ccode.close();
                        }
                    }
                }

                if (has_general_catch_clause)
                {
                    // every possible error is already caught
                    // as there is a general catch clause
                    // no need to do anything else
                }
                else if (error_types.Count > 0)
                {
                    // go to finally clause if no catch clause matches
                    // and there are still unhandled error types
                    ccode.add_goto("__finally%d".printf(current_try_id));
                }
                else if (in_finally_block(node))
                {
                    // do not check unexpected errors happening within finally blocks
                    // as jump out of finally block is not supported
                }
                else
                {
                    // should never happen with correct bindings
                    uncaught_error_statement(inner_error, true);
                }
            }
            else if (current_method != null && current_method.get_error_types().Count > 0)
            {
                // current method can fail, propagate error
                CCodeBinaryExpression ccond = null;

                foreach (DataType error_type in current_method.get_error_types())
                {
                    // If GLib.Error is allowed we propagate everything
                    if (error_type.equals(gerror_type))
                    {
                        ccond = null;
                        break;
                    }

                    // Check the allowed error domains to propagate
                    var domain_check = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, CCodeMemberAccess.pointer
                                                                     (inner_error, "domain"), new CCodeIdentifier(get_ccode_upper_case_name(error_type.data_type)));
                    if (ccond == null)
                    {
                        ccond = domain_check;
                    }
                    else
                    {
                        ccond = new CCodeBinaryExpression(CCodeBinaryOperator.OR, ccond, domain_check);
                    }
                }

                if (ccond != null)
                {
                    ccode.open_if(ccond);
                    return_with_exception(inner_error);

                    ccode.add_else();
                    uncaught_error_statement(inner_error);
                    ccode.close();
                }
                else
                {
                    return_with_exception(inner_error);
                }
            }
            else
            {
                uncaught_error_statement(inner_error);
            }

            if (!always_fails)
            {
                ccode.close();
            }
        }
Exemple #19
0
        /* Returns lvalue access to the given field */
        public override TargetValue get_field_cvalue(Field field, TargetValue instance)
        {
            var value_type = field.variable_type.copy();

            var result = new GLibValue(value_type);

            if (instance != null)
            {
                result.actual_value_type = field.variable_type.get_actual_type(instance.value_type, null, field);
            }
            result.lvalue = true;
            result.array_null_terminated = get_ccode_array_null_terminated(field);
            if (get_ccode_array_length_expr(field) != null)
            {
                result.array_length_cexpr = new CCodeConstant(get_ccode_array_length_expr(field));
            }
            result.ctype = get_ccode_type(field);

            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            if (field.binding == MemberBinding.INSTANCE)
            {
                CCodeExpression pub_inst = null;

                if (instance != null)
                {
                    pub_inst = get_cvalue_(instance);
                }

                var instance_target_type = get_data_type_for_symbol((TypeSymbol)field.parent_symbol);

                var  cl = instance_target_type.data_type as Class;
                bool is_gtypeinstance = ((instance_target_type.data_type == cl) && (cl == null || !cl.is_compact));

                CCodeExpression inst;
                if (is_gtypeinstance && field.access == SymbolAccessibility.PRIVATE)
                {
                    inst = CCodeMemberAccess.pointer(pub_inst, "priv");
                }
                else
                {
                    if (cl != null)
                    {
                        generate_class_struct_declaration(cl, cfile);
                    }
                    inst = pub_inst;
                }
                if (instance_target_type.data_type.is_reference_type() || (instance != null && instance.value_type is PointerType))
                {
                    result.cvalue = CCodeMemberAccess.pointer(inst, get_ccode_name(field));
                }
                else
                {
                    result.cvalue = new CCodeMemberAccess(inst, get_ccode_name(field));
                }

                if (array_type != null && get_ccode_array_length(field))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        CCodeExpression length_expr = null;

                        string length_cname;
                        if (get_ccode_array_length_name(field) != null)
                        {
                            length_cname = get_ccode_array_length_name(field);
                        }
                        else
                        {
                            length_cname = get_array_length_cname(get_ccode_name(field), dim);
                        }

                        if (((TypeSymbol)field.parent_symbol).is_reference_type())
                        {
                            length_expr = CCodeMemberAccess.pointer(inst, length_cname);
                        }
                        else
                        {
                            length_expr = new CCodeMemberAccess(inst, length_cname);
                        }

                        result.append_array_length_cvalue(length_expr);
                    }
                    if (array_type.rank == 1 && field.is_internal_symbol())
                    {
                        string size_cname = get_array_size_cname(get_ccode_name(field));

                        if (((TypeSymbol)field.parent_symbol).is_reference_type())
                        {
                            set_array_size_cvalue(result, CCodeMemberAccess.pointer(inst, size_cname));
                        }
                        else
                        {
                            set_array_size_cvalue(result, new CCodeMemberAccess(inst, size_cname));
                        }
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target(field))
                {
                    string target_cname = get_ccode_delegate_target_name(field);
                    string target_destroy_notify_cname = get_delegate_target_destroy_notify_cname(get_ccode_name(field));

                    if (((TypeSymbol)field.parent_symbol).is_reference_type())
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(inst, target_cname);
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(inst, target_destroy_notify_cname);
                        }
                    }
                    else
                    {
                        result.delegate_target_cvalue = new CCodeMemberAccess(inst, target_cname);
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess(inst, target_destroy_notify_cname);
                        }
                    }
                }
            }
            else if (field.binding == MemberBinding.CLASS)
            {
                var cl   = (Class)field.parent_symbol;
                var cast = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_upper_case_name(cl, null) + "_CLASS"));

                CCodeExpression klass;
                if (instance == null)
                {
                    if (get_this_type() == null)
                    {
                        // Accessing the field from a static or class constructor
                        klass = new CCodeIdentifier("klass");
                    }
                    else
                    {
                        // Accessing the field from within an instance method
                        var k = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_GET_CLASS"));
                        k.add_argument(new CCodeIdentifier("self"));
                        klass = k;
                    }
                }
                else
                {
                    // Accessing the field of an instance
                    var k = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_GET_CLASS"));
                    k.add_argument(get_cvalue_(instance));
                    klass = k;
                }
                cast.add_argument(klass);

                if (field.access == SymbolAccessibility.PRIVATE)
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("%s_GET_CLASS_PRIVATE".printf(get_ccode_upper_case_name(cl))));
                    ccall.add_argument(klass);
                    result.cvalue = CCodeMemberAccess.pointer(ccall, get_ccode_name(field));
                }
                else
                {
                    result.cvalue = CCodeMemberAccess.pointer(cast, get_ccode_name(field));
                }
            }
            else
            {
                generate_field_declaration(field, cfile);

                result.cvalue = new CCodeIdentifier(get_ccode_name(field));

                if (array_type != null && get_ccode_array_length(field))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        string length_cname;
                        if (get_ccode_array_length_name(field) != null)
                        {
                            length_cname = get_ccode_array_length_name(field);
                        }
                        else
                        {
                            length_cname = get_array_length_cname(get_ccode_name(field), dim);
                        }

                        result.append_array_length_cvalue(new CCodeIdentifier(length_cname));
                    }
                    if (array_type.rank == 1 && field.is_internal_symbol())
                    {
                        set_array_size_cvalue(result, new CCodeIdentifier(get_array_size_cname(get_ccode_name(field))));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target(field))
                {
                    result.delegate_target_cvalue = new CCodeIdentifier(get_ccode_delegate_target_name(field));
                    if (result.value_type.is_disposable())
                    {
                        result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_ccode_name(field)));
                    }
                }
            }

            return(result);
        }