Ejemplo n.º 1
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();
        }
Ejemplo n.º 2
0
        private void add_get_property_function(Class cl)
        {
            var get_prop = new CCodeFunction("_vala_%s_get_property".printf(get_ccode_lower_case_name(cl, null)), "void");

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

            push_function(get_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.get_accessor == null || prop.is_abstract)
                {
                    continue;
                }
                if (!is_gobject_property(prop))
                {
                    // don't register private properties
                    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.get_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.get_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.get_accessor));
                }
                else
                {
                    // use the static real function as helper
                    cfunc = new CCodeIdentifier(get_ccode_real_name(prop.get_accessor));
                }

                ccode.add_case(new CCodeIdentifier(get_ccode_upper_case_name(prop)));
                if (prop.property_type.is_real_struct_type())
                {
                    var st = prop.property_type.data_type as Struct;

                    ccode.open_block();
                    ccode.add_declaration(get_ccode_name(st), new CCodeVariableDeclarator("boxed"));

                    ccall = new CCodeFunctionCall(cfunc);
                    ccall.add_argument(cself);
                    var boxed_addr = new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier("boxed"));
                    ccall.add_argument(boxed_addr);
                    ccode.add_expression(ccall);

                    var csetcall = new CCodeFunctionCall();
                    csetcall.call = get_value_setter_function(prop.property_type);
                    csetcall.add_argument(new CCodeIdentifier("value"));
                    csetcall.add_argument(boxed_addr);
                    add_guarded_expression(prop, csetcall);

                    if (requires_destroy(prop.get_accessor.value_type))
                    {
                        ccode.add_expression(destroy_value(new GLibValue(prop.get_accessor.value_type, new CCodeIdentifier("boxed"), true)));
                    }
                    ccode.close();
                }
                else
                {
                    ccall = new CCodeFunctionCall(cfunc);
                    ccall.add_argument(cself);
                    var array_type = prop.property_type as ArrayType;
                    if (array_type != null && array_type.element_type.data_type == string_type.data_type)
                    {
                        // G_TYPE_STRV
                        ccode.open_block();
                        ccode.add_declaration("int", new CCodeVariableDeclarator("length"));
                        ccall.add_argument(new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier("length")));
                    }
                    var csetcall = new CCodeFunctionCall();
                    if (prop.get_accessor.value_type.value_owned)
                    {
                        csetcall.call = get_value_taker_function(prop.property_type);
                    }
                    else
                    {
                        csetcall.call = get_value_setter_function(prop.property_type);
                    }
                    csetcall.add_argument(new CCodeIdentifier("value"));
                    csetcall.add_argument(ccall);
                    add_guarded_expression(prop, csetcall);
                    if (array_type != null && array_type.element_type.data_type == string_type.data_type)
                    {
                        ccode.close();
                    }
                }
                ccode.add_break();
            }
            ccode.add_default();
            emit_invalid_property_id_warn();
            ccode.add_break();

            ccode.close();

            pop_function();

            cfile.add_function_declaration(get_prop);
            cfile.add_function(get_prop);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        CCodeFunction generate_free_function(Method m)
        {
            var dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";

            var freefunc = new CCodeFunction(get_ccode_real_name(m) + "_data_free", "void");

            freefunc.modifiers = CCodeModifiers.STATIC;
            freefunc.add_parameter(new CCodeParameter("_data", "gpointer"));

            push_context(new EmitContext(m));
            push_function(freefunc);

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

            foreach (Parameter param in m.get_parameters())
            {
                if (!param.captured && param.direction != ParameterDirection.OUT)
                {
                    var param_type = param.variable_type.copy();
                    if (!param_type.value_owned)
                    {
                        param_type.value_owned = !no_implicit_copy(param_type);
                    }

                    if (requires_destroy(param_type))
                    {
                        ccode.add_expression(destroy_parameter(param));
                    }
                }
            }

            if (requires_destroy(m.return_type))
            {
                if (get_ccode_array_length(m) || !(m.return_type is ArrayType))
                {
                    /* this is very evil. */
                    var v = new LocalVariable(m.return_type, ".result");
                    ccode.add_expression(destroy_local(v));
                }
                else
                {
                    var v = new GLibValue(m.return_type, new CCodeIdentifier("_data_->result"), true);
                    v.array_null_terminated = get_ccode_array_null_terminated(m);
                    ccode.add_expression(destroy_value(v));
                }
            }

            if (m.binding == MemberBinding.INSTANCE)
            {
                var this_type = m.this_parameter.variable_type.copy();
                this_type.value_owned = true;

                if (requires_destroy(this_type))
                {
                    ccode.add_expression(destroy_parameter(m.this_parameter));
                }
            }

            var freecall = new CCodeFunctionCall(new CCodeIdentifier("g_slice_free"));

            freecall.add_argument(new CCodeIdentifier(dataname));
            freecall.add_argument(new CCodeIdentifier("_data_"));
            ccode.add_expression(freecall);

            pop_context();

            cfile.add_function_declaration(freefunc);
            cfile.add_function(freefunc);

            return(freefunc);
        }