Commit 22ec8fe6 authored by Jürg Billeter's avatar Jürg Billeter

Support subclassing of GLib.Source

parent 3126a8e1
......@@ -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)) {
......
......@@ -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) {
......
......@@ -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"));
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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)]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment