[vala] Support [GenericAccessors] attribute for interfaces
- From: JÃrg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Support [GenericAccessors] attribute for interfaces
- Date: Mon, 6 Aug 2012 10:57:09 +0000 (UTC)
commit 6a6a2cf59b7302b0b3b111c6a0c879c00d36ddce
Author: Jeremy Whiting <jpwhiting kde org>
Date: Wed Jul 11 11:54:45 2012 -0600
Support [GenericAccessors] attribute for interfaces
This adds internal abstract functions to enable access to the element
type from within a generic interface. These functions are implicitly
implemented by all classes that implement interfaces with the
[GenericAccessors] attribute.
Fixes bug 640330.
codegen/valaccodebasemodule.vala | 49 ++++++++++++++++++++++++-
codegen/valagtypemodule.vala | 74 ++++++++++++++++++++++++++++++++++++++
2 files changed, 122 insertions(+), 1 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 9a82e5d..2e0fded 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2501,9 +2501,30 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
}
+ void require_generic_accessors (Interface iface) {
+ if (iface.get_attribute ("GenericAccessors") == null) {
+ Report.error (iface.source_reference,
+ "missing generic type for interface `%s', add GenericAccessors attribute to interface declaration"
+ .printf (iface.get_full_name ()));
+ }
+ }
+
public CCodeExpression get_type_id_expression (DataType type, bool is_chainup = false) {
if (type is GenericType) {
string var_name = "%s_type".printf (type.type_parameter.name.down ());
+
+ if (type.type_parameter.parent_symbol is Interface) {
+ var iface = (Interface) type.type_parameter.parent_symbol;
+ require_generic_accessors (iface);
+
+ string method_name = "get_%s_type".printf (type.type_parameter.name.down ());
+ var cast_self = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_INTERFACE".printf (get_ccode_upper_case_name (iface))));
+ cast_self.add_argument (new CCodeIdentifier ("self"));
+ var function_call = new CCodeFunctionCall (new CCodeMemberAccess.pointer (cast_self, method_name));
+ function_call.add_argument (new CCodeIdentifier ("self"));
+ return function_call;
+ }
+
if (is_in_generic_type (type) && !is_chainup && !in_creation_method) {
return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (get_result_cexpression ("self"), "priv"), var_name);
} else {
@@ -2560,6 +2581,19 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return new CCodeIdentifier (dup_function);
} else if (type.type_parameter != null) {
string func_name = "%s_dup_func".printf (type.type_parameter.name.down ());
+
+ if (type.type_parameter.parent_symbol is Interface) {
+ var iface = (Interface) type.type_parameter.parent_symbol;
+ require_generic_accessors (iface);
+
+ string method_name = "get_%s_dup_func".printf (type.type_parameter.name.down ());
+ var cast_self = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_INTERFACE".printf (get_ccode_upper_case_name (iface))));
+ cast_self.add_argument (new CCodeIdentifier ("self"));
+ var function_call = new CCodeFunctionCall (new CCodeMemberAccess.pointer (cast_self, method_name));
+ function_call.add_argument (new CCodeIdentifier ("self"));
+ return function_call;
+ }
+
if (is_in_generic_type (type) && !is_chainup && !in_creation_method) {
return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (get_result_cexpression ("self"), "priv"), func_name);
} else {
@@ -3035,6 +3069,19 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return new CCodeIdentifier (unref_function);
} else if (type.type_parameter != null) {
string func_name = "%s_destroy_func".printf (type.type_parameter.name.down ());
+
+ if (type.type_parameter.parent_symbol is Interface) {
+ var iface = (Interface) type.type_parameter.parent_symbol;
+ require_generic_accessors (iface);
+
+ string method_name = "get_%s_destroy_func".printf (type.type_parameter.name.down ());
+ var cast_self = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_INTERFACE".printf (get_ccode_upper_case_name (iface))));
+ cast_self.add_argument (new CCodeIdentifier ("self"));
+ var function_call = new CCodeFunctionCall (new CCodeMemberAccess.pointer (cast_self, method_name));
+ function_call.add_argument (new CCodeIdentifier ("self"));
+ return function_call;
+ }
+
if (is_in_generic_type (type) && !is_chainup && !in_creation_method) {
return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (get_result_cexpression ("self"), "priv"), func_name);
} else {
@@ -3238,7 +3285,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
if (type.type_parameter != null) {
var parent = type.type_parameter.parent_symbol;
var cl = parent as Class;
- if ((!(parent is Method) && !(parent is ObjectTypeSymbol)) || (cl != null && cl.is_compact) || parent is Interface) {
+ if ((!(parent is Method) && !(parent is ObjectTypeSymbol)) || (cl != null && cl.is_compact)) {
return new CCodeConstant ("NULL");
}
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index eca78af..487918f 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -1281,6 +1281,27 @@ public class Vala.GTypeModule : GErrorModule {
cfile.add_function (class_init_context.ccode);
}
+ private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) {
+ string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name);
+
+ var function = new CCodeFunction (name, return_type);
+ function.modifiers = CCodeModifiers.STATIC;
+ var this_type = get_data_type_for_symbol (cl);
+ function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
+ push_function (function);
+ ccode.add_return (expression);
+ pop_function ();
+ cfile.add_function (function);
+
+ CCodeExpression cfunc = new CCodeIdentifier (function.name);
+ string cast = return_type + "(*)";
+ string cast_args = get_ccode_name (iface) + "*";
+ cast += "(" + cast_args + ")";
+ cfunc = new CCodeCastExpression (cfunc, cast);
+ var ciface = new CCodeIdentifier ("iface");
+ ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc);
+ }
+
private void add_interface_init_function (Class cl, Interface iface) {
var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void");
iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
@@ -1332,6 +1353,28 @@ public class Vala.GTypeModule : GErrorModule {
}
}
+ if (iface.get_attribute ("GenericAccessors") != null) {
+ foreach (TypeParameter p in iface.get_type_parameters ()) {
+ GenericType p_type = new GenericType (p);
+ DataType p_data_type = p_type.get_actual_type (get_data_type_for_symbol (cl), null, cl);
+
+ add_generic_accessor_function ("get_%s_type".printf (p.name.down ()),
+ "GType",
+ get_type_id_expression (p_data_type),
+ p, cl, iface);
+
+ add_generic_accessor_function ("get_%s_dup_func".printf (p.name.down ()),
+ "GBoxedCopyFunc",
+ get_dup_func_expression (p_data_type, null),
+ p, cl, iface);
+
+ add_generic_accessor_function ("get_%s_destroy_func".printf (p.name.down ()),
+ "GDestroyNotify",
+ get_destroy_func_expression (p_data_type),
+ p, cl, iface);
+ }
+ }
+
// connect inherited implementations
foreach (Method m in iface.get_methods ()) {
if (m.is_abstract) {
@@ -1894,6 +1937,37 @@ public class Vala.GTypeModule : GErrorModule {
type_struct.add_field ("GTypeInterface", "parent_iface");
+ if (iface.get_attribute ("GenericAccessors") != null) {
+ foreach (TypeParameter p in iface.get_type_parameters ()) {
+ string method_name = "get_%s_type".printf (p.name.down ());
+ var vdeclarator = new CCodeFunctionDeclarator (method_name);
+ var this_type = get_data_type_for_symbol (iface);
+ vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
+
+ var vdecl = new CCodeDeclaration ("GType");
+ vdecl.add_declarator (vdeclarator);
+ type_struct.add_declaration (vdecl);
+
+ method_name = "get_%s_dup_func".printf (p.name.down ());
+ vdeclarator = new CCodeFunctionDeclarator (method_name);
+ this_type = get_data_type_for_symbol (iface);
+ vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
+
+ vdecl = new CCodeDeclaration ("GBoxedCopyFunc");
+ vdecl.add_declarator (vdeclarator);
+ type_struct.add_declaration (vdecl);
+
+ method_name = "get_%s_destroy_func".printf (p.name.down ());
+ vdeclarator = new CCodeFunctionDeclarator (method_name);
+ this_type = get_data_type_for_symbol (iface);
+ vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
+
+ vdecl = new CCodeDeclaration ("GDestroyNotify");
+ vdecl.add_declarator (vdeclarator);
+ type_struct.add_declaration (vdecl);
+ }
+ }
+
foreach (Method m in iface.get_methods ()) {
generate_virtual_method_declaration (m, decl_space, type_struct);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]