summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2012-08-15 22:22:34 +0200
committerJürg Billeter <j@bitron.ch>2012-08-15 22:22:34 +0200
commit22ec8fe6c183fce66917136787dd6b9e28c49419 (patch)
tree95a2e354db888c039e8ada4fa1540f226152ce3d
parent3126a8e1af2deca94c5d3cad1e82ab1dac6f7a67 (diff)
downloadvala-gsource.tar.gz
Support subclassing of GLib.Sourcegsource
-rw-r--r--codegen/valaccodebasemodule.vala2
-rw-r--r--codegen/valaccodemethodcallmodule.vala21
-rw-r--r--codegen/valagtypemodule.vala31
-rw-r--r--vala/valaclass.vala2
-rw-r--r--vala/valamethod.vala2
-rw-r--r--vala/valasemanticanalyzer.vala3
-rw-r--r--vapi/glib-2.0.vapi8
7 files changed, 56 insertions, 13 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 0d1472c99..5881751b2 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -318,6 +318,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
public Struct grecmutex_type;
public Struct grwlock_type;
public Struct gcond_type;
+ public Class gsource_type;
public TypeSymbol type_module_type;
public TypeSymbol dbus_proxy_type;
@@ -460,6 +461,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark"));
gvalue_type = (Struct) glib_ns.scope.lookup ("Value");
gvariant_type = (Class) glib_ns.scope.lookup ("Variant");
+ gsource_type = (Class) glib_ns.scope.lookup ("Source");
mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
if (context.require_glib_version (2, 32)) {
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index bd8160926..8cb117140 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -150,6 +150,21 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
type_param_index++;
}
}
+ } else if (current_class.base_class == gsource_type) {
+ // g_source_new
+
+ string class_prefix = CCodeBaseModule.get_ccode_lower_case_name (current_class);
+
+ var funcs = new CCodeDeclaration ("const GSourceFuncs");
+ funcs.modifiers = CCodeModifiers.STATIC;
+ funcs.add_declarator (new CCodeVariableDeclarator ("_source_funcs", new CCodeConstant ("{ %s_real_prepare, %s_real_check, %s_real_dispatch, %s_finalize}".printf (class_prefix, class_prefix, class_prefix, class_prefix))));
+ ccode.add_statement (funcs);
+
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_source_funcs")));
+
+ var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+ csizeof.add_argument (new CCodeIdentifier (get_ccode_name (current_class)));
+ ccall.add_argument (csizeof);
}
} else if (m is CreationMethod && m.parent_symbol is Struct) {
ccall.add_argument (get_this_cexpression ());
@@ -795,6 +810,12 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
// assign new value
store_value (unary.inner.target_value, transform_value (unary.target_value, unary.inner.value_type, arg));
}
+
+ if (m is CreationMethod && m.parent_symbol is Class && current_class.base_class == gsource_type) {
+ var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (get_ccode_lower_case_name (current_class, null))));
+ cinitcall.add_argument (get_this_cexpression ());
+ ccode.add_expression (cinitcall);
+ }
}
private string generate_enum_tostring_function (Enum en) {
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index ab29c5846..3be2d29f6 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -60,6 +60,7 @@ public class Vala.GTypeModule : GErrorModule {
bool is_gtypeinstance = !cl.is_compact;
bool is_fundamental = is_gtypeinstance && cl.base_class == null;
+ bool is_gsource = cl.base_class == gsource_type;
if (is_gtypeinstance) {
decl_space.add_type_declaration (new CCodeNewline ());
@@ -83,7 +84,7 @@ public class Vala.GTypeModule : GErrorModule {
decl_space.add_type_declaration (new CCodeNewline ());
}
- if (cl.is_compact && cl.base_class != null) {
+ if (cl.is_compact && cl.base_class != null && !is_gsource) {
decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl))));
} else {
decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl))));
@@ -155,7 +156,7 @@ public class Vala.GTypeModule : GErrorModule {
}
decl_space.add_function_declaration (function);
- } else if (!is_gtypeinstance) {
+ } else if (!is_gtypeinstance && !is_gsource) {
if (cl.base_class == null) {
var function = new CCodeFunction (get_ccode_lower_case_prefix (cl) + "free", "void");
if (cl.access == SymbolAccessibility.PRIVATE) {
@@ -197,6 +198,7 @@ public class Vala.GTypeModule : GErrorModule {
bool is_gtypeinstance = !cl.is_compact;
bool is_fundamental = is_gtypeinstance && cl.base_class == null;
+ bool is_gsource = cl.base_class == gsource_type;
var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl)));
var type_struct = new CCodeStruct ("_%sClass".printf (get_ccode_name (cl)));
@@ -350,7 +352,7 @@ public class Vala.GTypeModule : GErrorModule {
}
}
- if (!cl.is_compact || cl.base_class == null) {
+ if (!cl.is_compact || cl.base_class == null || is_gsource) {
// derived compact classes do not have a struct
decl_space.add_type_definition (instance_struct);
}
@@ -574,7 +576,7 @@ public class Vala.GTypeModule : GErrorModule {
begin_class_finalize_function (cl);
begin_finalize_function (cl);
} else {
- if (cl.base_class == null) {
+ if (cl.base_class == null || cl.base_class == gsource_type) {
begin_instance_init_function (cl);
begin_finalize_function (cl);
}
@@ -698,7 +700,7 @@ public class Vala.GTypeModule : GErrorModule {
cfile.add_function (unref_fun);
}
} else {
- if (cl.base_class == null) {
+ if (cl.base_class == null || cl.base_class == gsource_type) {
// derived compact classes do not have fields
add_instance_init_function (cl);
add_finalize_function (cl);
@@ -1645,7 +1647,9 @@ public class Vala.GTypeModule : GErrorModule {
private void begin_finalize_function (Class cl) {
push_context (instance_finalize_context);
- if (!cl.is_compact) {
+ bool is_gsource = cl.base_class == gsource_type;
+
+ if (!cl.is_compact || is_gsource) {
var fundamental_class = cl;
while (fundamental_class.base_class != null) {
fundamental_class = fundamental_class.base_class;
@@ -1657,10 +1661,19 @@ public class Vala.GTypeModule : GErrorModule {
push_function (func);
- CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
+ if (is_gsource) {
+ cfile.add_function_declaration (func);
+ }
+
+ CCodeExpression ccast;
+ if (!cl.is_compact) {
+ ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
+ } else {
+ ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), get_ccode_name (cl) + "*");
+ }
ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
- ccode.add_assignment (new CCodeIdentifier ("self"), ccall);
+ ccode.add_assignment (new CCodeIdentifier ("self"), ccast);
} else {
var function = new CCodeFunction (get_ccode_lower_case_prefix (cl) + "free", "void");
if (cl.access == SymbolAccessibility.PRIVATE) {
@@ -1707,7 +1720,7 @@ public class Vala.GTypeModule : GErrorModule {
}
cfile.add_function_declaration (instance_finalize_context.ccode);
- } else {
+ } else if (cl.base_class == null) {
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
ccall.add_argument (new CCodeIdentifier ("self"));
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 63278788a..5110a7aa6 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -720,7 +720,7 @@ public class Vala.Class : ObjectTypeSymbol {
}
}
- if (!external && !external_package && base_class != null) {
+ if (!external && !external_package && base_class != null && base_class != context.analyzer.gsource_type) {
foreach (Field f in fields) {
if (f.binding == MemberBinding.INSTANCE) {
error = true;
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 942f0d2fd..7af50e8e8 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -589,7 +589,7 @@ public class Vala.Method : Subroutine {
if (parent_symbol is Class) {
var cl = (Class) parent_symbol;
- if (cl.is_compact) {
+ if (cl.is_compact && cl != context.analyzer.gsource_type) {
Report.error (source_reference, "Virtual methods may not be declared in compact classes");
return false;
}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 8afe17582..90923ac2c 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -161,6 +161,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public DataType list_type;
public DataType tuple_type;
public DataType error_type;
+ public Class gsource_type;
public int next_lambda_id = 0;
@@ -216,6 +217,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
gerror_type = (Class) glib_ns.scope.lookup ("Error");
regex_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Regex"));
+ gsource_type = (Class) glib_ns.scope.lookup ("Source");
+
current_symbol = root_symbol;
context.root.check (context);
context.accept (this);
diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi
index cb7ccd03a..50805233c 100644
--- a/vapi/glib-2.0.vapi
+++ b/vapi/glib-2.0.vapi
@@ -1584,8 +1584,8 @@ namespace GLib {
[Compact]
[CCode (ref_function = "g_source_ref", unref_function = "g_source_unref")]
- public class Source {
- public Source (SourceFuncs source_funcs, uint struct_size /* = sizeof (Source) */);
+ public abstract class Source {
+ protected Source ();
public void set_funcs (SourceFuncs funcs);
public uint attach (MainContext? context);
public void destroy ();
@@ -1611,6 +1611,10 @@ namespace GLib {
public static bool remove (uint id);
public static bool remove_by_funcs_user_data (void* user_data);
public static bool remove_by_user_data (void* user_data);
+
+ protected abstract bool prepare (out int timeout_);
+ protected abstract bool check ();
+ protected abstract bool dispatch (SourceFunc _callback);
}
[CCode (has_target = false)]