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