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