Based on patch by Yu Feng, fixes part of 571685.
} 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;
}
}
}
- 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);
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"));
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))));
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;
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) {
} 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;
} while (accept (TokenType.COMMA));
}
expect (TokenType.CLOSE_PARENS);
- expect (TokenType.SEMICOLON);
+ if (!accept (TokenType.SEMICOLON)) {
+ sig.body = parse_block ();
+ }
+
return sig;
}
}
}
+ public Block body {
+ get { return _body; }
+ set {
+ _body = value;
+ if (_body != null) {
+ _body.owner = scope;
+ }
+ }
+ }
+
/**
* Specifies whether this signal has an emitter wrapper function.
*/
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;
private DataType _return_type;
+ private Block _body;
+
/**
* Creates a new signal.
*
foreach (FormalParameter param in parameters) {
param.accept (visitor);
}
+ if (default_handler != null) {
+ default_handler.accept (visitor);
+ }
}
/**
}
}
- 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;
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;
}
}