[vala] Support virtual default handler for signals
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Subject: [vala] Support virtual default handler for signals
- Date: Tue, 28 Jul 2009 15:53:33 +0000 (UTC)
commit 9b37307b035e75c858ed648728db83a8bc70a4c8
Author: Jürg Billeter <j bitron ch>
Date: Tue Jul 28 17:20:37 2009 +0200
Support virtual default handler for signals
Based on patch by Yu Feng, fixes part of 571685.
codegen/valaccodemethodcallmodule.vala | 2 +-
codegen/valaccodemethodmodule.vala | 7 +++-
codegen/valagsignalmodule.vala | 12 +++++-
codegen/valagtypemodule.vala | 16 ++++++++
vala/valamethod.vala | 2 +-
vala/valaparser.vala | 5 ++-
vala/valasignal.vala | 61 +++++++++++++++++++++-----------
7 files changed, 78 insertions(+), 27 deletions(-)
---
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 8fc87db..4cf641d 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -53,7 +53,7 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
} else if (itype is SignalType) {
var sig_type = (SignalType) itype;
if (ma != null && ma.inner is BaseAccess && sig_type.signal_symbol.is_virtual) {
- m = sig_type.signal_symbol.get_method_handler ();
+ m = sig_type.signal_symbol.default_handler;
} else {
ccall = (CCodeFunctionCall) expr.call.ccodenode;
}
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index d76fbce..d8342a6 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -599,7 +599,12 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
}
}
- if ((m.is_abstract || m.is_virtual) && !m.coroutine) {
+ if ((m.is_abstract || m.is_virtual) && !m.coroutine &&
+ /* If the method is a signal handler, the declaration
+ * is not needed. -- the name should be reserved for the
+ * emitter! */
+ m.signal_reference == null) {
+
cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index f4ed94d..fe7c864 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -355,10 +355,18 @@ internal class Vala.GSignalModule : GObjectModule {
public override CCodeFunctionCall get_signal_creation (Signal sig, TypeSymbol type) {
var csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new"));
+ var cl = sig.parent_symbol as Class;
csignew.add_argument (new CCodeConstant ("\"%s\"".printf (sig.get_cname ())));
csignew.add_argument (new CCodeIdentifier (type.get_type_id ()));
csignew.add_argument (new CCodeConstant ("G_SIGNAL_RUN_LAST"));
- csignew.add_argument (new CCodeConstant ("0"));
+ if (sig.default_handler == null) {
+ csignew.add_argument (new CCodeConstant ("0"));
+ } else {
+ var struct_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET"));
+ struct_offset.add_argument (new CCodeIdentifier ("%sClass".printf (cl.get_cname ())));
+ struct_offset.add_argument (new CCodeIdentifier (sig.default_handler.vfunc_name));
+ csignew.add_argument (struct_offset);
+ }
csignew.add_argument (new CCodeConstant ("NULL"));
csignew.add_argument (new CCodeConstant ("NULL"));
@@ -608,7 +616,7 @@ internal class Vala.GSignalModule : GObjectModule {
var cl = (TypeSymbol) sig.parent_symbol;
if (expr.inner is BaseAccess && sig.is_virtual) {
- var m = sig.get_method_handler ();
+ var m = sig.default_handler;
var base_class = (Class) m.parent_symbol;
var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index e5bf70e..81573a6 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -206,6 +206,12 @@ internal class Vala.GTypeModule : GErrorModule {
generate_virtual_method_declaration (m, decl_space, type_struct);
}
+ foreach (Signal sig in cl.get_signals ()) {
+ if (sig.default_handler != null) {
+ generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+ }
+ }
+
foreach (Property prop in cl.get_properties ()) {
if (!prop.is_abstract && !prop.is_virtual) {
continue;
@@ -1140,6 +1146,16 @@ internal class Vala.GTypeModule : GErrorModule {
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))));
}
+ /* connect default signal handlers */
+ foreach (Signal sig in cl.get_signals ()) {
+ if (sig.default_handler == null) {
+ continue;
+ }
+ var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
+ ccast.add_argument (new CCodeIdentifier ("klass"));
+ init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ()))));
+ }
+
/* connect overridden properties */
foreach (Property prop in cl.get_properties ()) {
if (prop.base_property == null) {
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 5fa7dd0..79e9d5c 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -593,7 +593,7 @@ public class Vala.Method : Member {
} else if (sym is Signal) {
var sig = (Signal) sym;
if (sig.is_virtual) {
- var base_method = sig.get_method_handler ();
+ var base_method = sig.default_handler;
string invalid_match;
if (!compatible (base_method, out invalid_match)) {
error = true;
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 88dacd5..93e5cbf 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -2390,7 +2390,10 @@ public class Vala.Parser : CodeVisitor {
} while (accept (TokenType.COMMA));
}
expect (TokenType.CLOSE_PARENS);
- expect (TokenType.SEMICOLON);
+ if (!accept (TokenType.SEMICOLON)) {
+ sig.body = parse_block ();
+ }
+
return sig;
}
diff --git a/vala/valasignal.vala b/vala/valasignal.vala
index 9b85e89..3a69f59 100644
--- a/vala/valasignal.vala
+++ b/vala/valasignal.vala
@@ -38,6 +38,16 @@ public class Vala.Signal : Member, Lockable {
}
}
+ public Block body {
+ get { return _body; }
+ set {
+ _body = value;
+ if (_body != null) {
+ _body.owner = scope;
+ }
+ }
+ }
+
/**
* Specifies whether this signal has an emitter wrapper function.
*/
@@ -49,7 +59,11 @@ public class Vala.Signal : Member, Lockable {
public bool is_virtual { get; set; }
private Gee.List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
- private Method generated_method;
+ /**
+ * Refers to the default signal handler, which is an anonymous
+ * function in the scope.
+ * */
+ public Method default_handler { get; private set; }
private string cname;
@@ -57,6 +71,8 @@ public class Vala.Signal : Member, Lockable {
private DataType _return_type;
+ private Block _body;
+
/**
* Creates a new signal.
*
@@ -179,6 +195,9 @@ public class Vala.Signal : Member, Lockable {
foreach (FormalParameter param in parameters) {
param.accept (visitor);
}
+ if (default_handler != null) {
+ default_handler.accept (visitor);
+ }
}
/**
@@ -206,26 +225,6 @@ public class Vala.Signal : Member, Lockable {
}
}
- public Method get_method_handler () {
- assert (is_virtual);
-
- if (generated_method == null) {
- generated_method = new Method (name, return_type, source_reference);
- generated_method.access = access;
- generated_method.is_virtual = true;
- generated_method.vfunc_name = name;
- generated_method.signal_reference = this;
-
- foreach (FormalParameter param in parameters) {
- generated_method.add_parameter (param);
- }
-
- parent_symbol.scope.add (null, generated_method);
- }
-
- return generated_method;
- }
-
public override bool check (SemanticAnalyzer analyzer) {
if (checked) {
return !error;
@@ -241,6 +240,26 @@ public class Vala.Signal : Member, Lockable {
param.check (analyzer);
}
+ if (!is_virtual && body != null) {
+ Report.error (source_reference, "Only virtual signals can have a default signal handler body");
+ }
+
+
+ if (is_virtual) {
+ default_handler = new Method (name, return_type, source_reference);
+ default_handler.access = access;
+ default_handler.is_virtual = true;
+ default_handler.vfunc_name = name;
+ default_handler.signal_reference = this;
+ default_handler.body = body;
+
+ foreach (FormalParameter param in parameters) {
+ default_handler.add_parameter (param);
+ }
+
+ parent_symbol.scope.add (null, default_handler);
+ default_handler.check (analyzer);
+ }
return !error;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]