Example #1
0
        public override void visit_method_call(MethodCall expr)
        {
            if (expr.call is MemberAccess)
            {
                push_line(expr.source_reference);

                var ma = expr.call as MemberAccess;
                if (ma.inner != null && ma.inner.symbol_reference == gobject_type &&
                    (ma.member_name == "new" || ma.member_name == "newv"))
                {
                    // Object.new (...) creation
                    // runtime check to ref_sink the instance if it's a floating type
                    base.visit_method_call(expr);

                    var initiallyunowned_ccall = new CCodeFunctionCall(new CCodeIdentifier("G_IS_INITIALLY_UNOWNED"));
                    initiallyunowned_ccall.add_argument(get_cvalue(expr));
                    var sink_ref_ccall = new CCodeFunctionCall(new CCodeIdentifier("g_object_ref_sink"));
                    sink_ref_ccall.add_argument(get_cvalue(expr));
                    var cexpr = new CCodeConditionalExpression(initiallyunowned_ccall, sink_ref_ccall, get_cvalue(expr));

                    expr.target_value = store_temp_value(new GLibValue(expr.value_type, cexpr), expr);
                    return;
                }
                else if (ma.symbol_reference == gobject_type)
                {
                    // Object (...) chain up
                    // check it's only used with valid properties
                    foreach (var arg in expr.get_argument_list())
                    {
                        var named_argument = arg as NamedArgument;
                        if (named_argument == null)
                        {
                            Report.error(arg.source_reference, "Named argument expected");
                            break;
                        }
                        var prop = SemanticAnalyzer.symbol_lookup_inherited(current_class, named_argument.name) as Property;
                        if (prop == null)
                        {
                            Report.error(arg.source_reference, "Property `%s' not found in `%s'".printf(named_argument.name, current_class.get_full_name()));
                            break;
                        }
                        if (!is_gobject_property(prop))
                        {
                            Report.error(arg.source_reference, "Property `%s' not supported in Object (property: value) constructor chain up".printf(named_argument.name));
                            break;
                        }
                        if (!arg.value_type.compatible(prop.property_type))
                        {
                            Report.error(arg.source_reference, "Cannot convert from `%s' to `%s'".printf(arg.value_type.ToString(), prop.property_type.ToString()));
                            break;
                        }
                    }
                }

                pop_line();
            }

            base.visit_method_call(expr);
        }
Example #2
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);
        }
Example #3
0
        void visit_string_switch_statement(SwitchStatement stmt)
        {
            // we need a temporary variable to save the property value
            var temp_value = create_temp_value(stmt.expression.value_type, false, stmt);
            var ctemp      = get_cvalue_(temp_value);

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

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

            free_call.add_argument(ctemp);

            var cisnull = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeConstant("NULL"), ctemp);
            var cquark  = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_string"));

            cquark.add_argument(ctemp);

            var ccond = new CCodeConditionalExpression(cisnull, new CCodeConstant("0"), cquark);

            int label_temp_id = next_temp_var_id++;

            temp_value = create_temp_value(gquark_type, true, stmt);

            int label_count = 0;

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

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

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

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

            ccode.add_expression(cinit);

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

            ccode.add_expression(cinit);

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

            SwitchSection default_section = null;

            label_count = 0;

            int n = 0;

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

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

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

                        ccall.add_argument(cexpr);

                        cexpr = new CCodeConditionalExpression(ccondition, cname, cinit);
                    }
                    else
                    {
                        var ccall = new CCodeFunctionCall(new CCodeIdentifier("g_quark_from_string"));
                        ccall.add_argument(cexpr);
                        cexpr = ccall;
                    }

                    var ccmp = new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, ctemp, cexpr);

                    if (cor == null)
                    {
                        cor = ccmp;
                    }
                    else
                    {
                        cor = new CCodeBinaryExpression(CCodeBinaryOperator.OR, cor, ccmp);
                    }
                }

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

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

                section.emit(this);

                ccode.close();

                n++;
            }

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

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

                default_section.emit(this);

                ccode.close();
            }

            if (n > 0)
            {
                ccode.close();
            }
        }