From: Juerg Billeter Date: Sun, 20 Apr 2008 18:50:28 +0000 (+0000) Subject: Improve support for dynamic types, add `dynamic' type modifier, port X-Git-Tag: VALA_0_3_1~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ef89124bf751d257789f664561cf91e6836e9bc;p=thirdparty%2Fvala.git Improve support for dynamic types, add `dynamic' type modifier, port 2008-04-20 Juerg Billeter * vala/Makefile.am, vala/valaclasstype.vala, vala/valacodecontext.vala, vala/valacodegenerator.vala, vala/valadatatype.vala, vala/valadynamicmethod.vala, vala/valadynamicsignal.vala, vala/valainterface.vala, vala/valainterfacetype.vala, vala/valamethod.vala, vala/valamethodtype.vala, vala/valaparser.vala, vala/valascanner.vala, vala/valasemanticanalyzer.vala, vala/valasymbolresolver.vala, vala/valatokentype.vala, vala/valaunresolvedtype.vala, vala/valavaluetype.vala, gobject/Makefile.am, gobject/valaccodeassignmentbinding.vala, gobject/valaccodebinding.vala, gobject/valaccodedynamicmethodbinding.vala, gobject/valaccodedynamicsignalbinding.vala, gobject/valaccodegenerator.vala, gobject/valaccodegeneratorsourcefile.vala, gobject/valaccodeinterfacebinding.vala, gobject/valaccodeinvocationexpressionbinding.vala, gobject/valaccodemethodbinding.vala, compiler/valacompiler.vala, vapi/dbus-glib-1.vapi: Improve support for dynamic types, add `dynamic' type modifier, port dynamic D-Bus client support svn path=/trunk/; revision=1288 --- diff --git a/ChangeLog b/ChangeLog index bf8d2bfa4..20672346d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2008-04-20 Jürg Billeter + + * vala/Makefile.am, vala/valaclasstype.vala, + vala/valacodecontext.vala, vala/valacodegenerator.vala, + vala/valadatatype.vala, vala/valadynamicmethod.vala, + vala/valadynamicsignal.vala, vala/valainterface.vala, + vala/valainterfacetype.vala, vala/valamethod.vala, + vala/valamethodtype.vala, vala/valaparser.vala, + vala/valascanner.vala, vala/valasemanticanalyzer.vala, + vala/valasymbolresolver.vala, vala/valatokentype.vala, + vala/valaunresolvedtype.vala, vala/valavaluetype.vala, + gobject/Makefile.am, gobject/valaccodeassignmentbinding.vala, + gobject/valaccodebinding.vala, + gobject/valaccodedynamicmethodbinding.vala, + gobject/valaccodedynamicsignalbinding.vala, + gobject/valaccodegenerator.vala, + gobject/valaccodegeneratorsourcefile.vala, + gobject/valaccodeinterfacebinding.vala, + gobject/valaccodeinvocationexpressionbinding.vala, + gobject/valaccodemethodbinding.vala, compiler/valacompiler.vala, + vapi/dbus-glib-1.vapi: + + Improve support for dynamic types, add `dynamic' type modifier, + port dynamic D-Bus client support + 2008-04-20 Jürg Billeter * vapi/packages/gtk+-2.0/: fix GtkDialog.vbox binding diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index 4f795679f..d792713fc 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -234,11 +234,7 @@ class Vala.Compiler : Object { return quit (); } - var dbus_binding_provider = new DBusBindingProvider (); - dbus_binding_provider.context = context; - var analyzer = new SemanticAnalyzer (); - analyzer.add_binding_provider (dbus_binding_provider); analyzer.analyze (context); if (Report.get_errors () > 0) { diff --git a/gobject/Makefile.am b/gobject/Makefile.am index ba57b5f09..eee0c5938 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -18,6 +18,8 @@ libvala_la_VALASOURCES = \ valaccodeclassbinding.vala \ valaccodecompiler.vala \ valaccodecreationmethodbinding.vala \ + valaccodedynamicmethodbinding.vala \ + valaccodedynamicsignalbinding.vala \ valaccodeelementaccessbinding.vala \ valaccodeexpressionbinding.vala \ valaccodegenerator.vala \ @@ -30,9 +32,6 @@ libvala_la_VALASOURCES = \ valaccodemethodbinding.vala \ valaccodetypesymbolbinding.vala \ valaclassregisterfunction.vala \ - valadbusbindingprovider.vala \ - valadbusmethod.vala \ - valadbussignal.vala \ valagidlwriter.vala \ valainterfaceregisterfunction.vala \ valatyperegisterfunction.vala \ diff --git a/gobject/valaccodeassignmentbinding.vala b/gobject/valaccodeassignmentbinding.vala index 5e12b5362..870e7cafa 100644 --- a/gobject/valaccodeassignmentbinding.vala +++ b/gobject/valaccodeassignmentbinding.vala @@ -106,8 +106,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { bool disconnect = false; if (assignment.operator == AssignmentOperator.ADD) { - if (sig is DBusSignal) { - connect_func = "dbus_g_proxy_connect_signal"; + if (sig is DynamicSignal) { + connect_func = codegen.dynamic_signal_binding ((DynamicSignal) sig).get_connect_wrapper_name (); } else { connect_func = "g_signal_connect_object"; if (!m.instance) { @@ -115,8 +115,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { } } } else if (assignment.operator == AssignmentOperator.SUB) { - if (sig is DBusSignal) { - connect_func = "dbus_g_proxy_disconnect_signal"; + if (sig is DynamicSignal) { + connect_func = codegen.dynamic_signal_binding ((DynamicSignal) sig).get_disconnect_wrapper_name (); } else { connect_func = "g_signal_handlers_disconnect_matched"; } @@ -136,8 +136,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { ccall.add_argument (new CCodeIdentifier ("self")); } - if (sig is DBusSignal) { - // dbus_g_proxy_connect_signal or dbus_g_proxy_disconnect_signal + if (sig is DynamicSignal) { + // dynamic_signal_connect or dynamic_signal_disconnect // second argument: signal name ccall.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name))); @@ -176,8 +176,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { } // third resp. sixth argument: handler - if (sig is DBusSignal) { - // signal handler wrappers not used for D-Bus signals + if (sig is DynamicSignal) { + // signal handler wrappers not used for dynamic signals ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback")); m.cinstance_parameter_position = -1; } else { @@ -186,7 +186,7 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { if (m.instance) { // g_signal_connect_object or g_signal_handlers_disconnect_matched - // or dbus_g_proxy_connect_signal or dbus_g_proxy_disconnect_signal + // or dynamic_signal_connect or dynamic_signal_disconnect // fourth resp. seventh argument: object/user_data if (assignment.right is MemberAccess) { @@ -199,98 +199,21 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { } else if (assignment.right is LambdaExpression) { ccall.add_argument (new CCodeIdentifier ("self")); } - if (!disconnect) { - if (sig is DBusSignal) { - // dbus_g_proxy_connect_signal + if (!disconnect && !(sig is DynamicSignal)) { + // g_signal_connect_object - // fifth argument: free_data_func - ccall.add_argument (new CCodeConstant ("NULL")); - } else { - // g_signal_connect_object - - // fifth argument: connect_flags - ccall.add_argument (new CCodeConstant ("0")); - } + // fifth argument: connect_flags + ccall.add_argument (new CCodeConstant ("0")); } } else { // g_signal_connect or g_signal_handlers_disconnect_matched - // or dbus_g_proxy_connect_signal or dbus_g_proxy_disconnect_signal + // or dynamic_signal_connect or dynamic_signal_disconnect // fourth resp. seventh argument: user_data ccall.add_argument (new CCodeConstant ("NULL")); - - if (sig is DBusSignal && !disconnect) { - // fifth argument: free_data_func - ccall.add_argument (new CCodeConstant ("NULL")); - } } codenode = ccall; - - if (sig is DBusSignal && !disconnect) { - bool first = true; - foreach (FormalParameter param in m.get_parameters ()) { - if (first) { - // skip sender parameter - first = false; - continue; - } - sig.add_parameter (param.copy ()); - } - - sig.accept (codegen); - - // FIXME should only be done once per marshaller - var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller")); - register_call.add_argument (new CCodeIdentifier (codegen.get_signal_marshaller_function (sig))); - register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE")); - - var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal")); - if (ma.inner != null) { - add_call.add_argument ((CCodeExpression) ma.inner.ccodenode); - } else { - add_call.add_argument (new CCodeIdentifier ("self")); - } - add_call.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name))); - - first = true; - foreach (FormalParameter param in m.get_parameters ()) { - if (first) { - // skip sender parameter - first = false; - continue; - } - if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) { - var array_type = (ArrayType) param.type_reference; - if (array_type.element_type.data_type.get_type_id () == null) { - Report.error (param.source_reference, "unsupported parameter type for D-Bus signals"); - return; - } - - var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection")); - carray_type.add_argument (new CCodeConstant ("\"GArray\"")); - carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ())); - register_call.add_argument (carray_type); - add_call.add_argument (carray_type); - } else { - if (param.type_reference.get_type_id () == null) { - Report.error (param.source_reference, "unsupported parameter type for D-Bus signals"); - return; - } - - register_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ())); - add_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ())); - } - } - register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); - add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (register_call); - ccomma.append_expression (add_call); - ccomma.append_expression (ccall); - codenode = ccomma; - } } private string generate_signal_handler_wrapper (Method m, Signal sig) { diff --git a/gobject/valaccodebinding.vala b/gobject/valaccodebinding.vala index b0aeda336..525ad7641 100644 --- a/gobject/valaccodebinding.vala +++ b/gobject/valaccodebinding.vala @@ -34,7 +34,8 @@ public abstract class Vala.CCodeBinding : CodeBinding { /** * Generate code for this source code node. */ - public abstract void emit (); + public virtual void emit () { + } public CCodeIdentifier get_value_setter_function (DataType type_reference) { if (type_reference.data_type != null) { diff --git a/gobject/valaccodedynamicmethodbinding.vala b/gobject/valaccodedynamicmethodbinding.vala new file mode 100644 index 000000000..145414c39 --- /dev/null +++ b/gobject/valaccodedynamicmethodbinding.vala @@ -0,0 +1,257 @@ +/* valaccodedynamicmethodbinding.vala + * + * Copyright (C) 2007-2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; +using Gee; + +/** + * The link between a dynamic method and generated code. + */ +public class Vala.CCodeDynamicMethodBinding : CCodeMethodBinding { + public CCodeDynamicMethodBinding (CCodeGenerator codegen, DynamicMethod method) { + this.method = method; + this.codegen = codegen; + } + + public void generate_wrapper () { + var dynamic_method = (DynamicMethod) method; + + var func = new CCodeFunction (method.get_cname (), method.return_type.get_cname ()); + + var cparam_map = new HashMap (direct_hash, direct_equal); + + var instance_param = new CCodeFormalParameter ("obj", "gpointer"); + cparam_map.set (codegen.get_param_pos (method.cinstance_parameter_position), instance_param); + + generate_cparameters (method, method.return_type, cparam_map, func); + + var block = new CCodeBlock (); + if (dynamic_method.dynamic_type.data_type == codegen.dbus_object_type) { + generate_dbus_method_wrapper (block); + } else { + Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ())); + } + + // append to C source file + codegen.source_type_member_declaration.append (func.copy ()); + + func.block = block; + codegen.source_type_member_definition.append (func); + } + + void generate_dbus_method_wrapper (CCodeBlock block) { + var dynamic_method = (DynamicMethod) method; + + var expr = dynamic_method.invocation; + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_begin_call")); + + ccall.add_argument (new CCodeIdentifier ("obj")); + + bool found_out = false; + Expression callback = null; + int callback_index = -1; + int arg_index = 1; + foreach (Expression arg in expr.get_argument_list ()) { + if (arg.symbol_reference is Method) { + // callback + if (callback != null) { + Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method"); + expr.error = true; + return; + } else if (found_out) { + Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method"); + expr.error = true; + return; + } + callback = arg; + callback_index = arg_index; + } else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) { + // out arg + if (callback != null) { + Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method"); + expr.error = true; + return; + } + found_out = true; + } else { + // in arg + if (callback != null || found_out) { + Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method"); + expr.error = true; + return; + } + } + arg_index++; + } + + ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method.name))); + + if (callback != null) { + var reply_method = (Method) callback.symbol_reference; + + var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void"); + cb_fun.modifiers = CCodeModifiers.STATIC; + cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*")); + cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*")); + cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*")); + cb_fun.block = new CCodeBlock (); + var cerrdecl = new CCodeDeclaration ("GError*"); + cerrdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("error", new CCodeConstant ("NULL"))); + cb_fun.block.add_statement (cerrdecl); + var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call")); + cend_call.add_argument (new CCodeIdentifier ("proxy")); + cend_call.add_argument (new CCodeIdentifier ("call")); + cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error"))); + var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode); + creply_call.add_argument (new CCodeIdentifier ("user_data")); + int param_count = reply_method.get_parameters ().size; + int i = 0; + foreach (FormalParameter param in reply_method.get_parameters ()) { + if ((++i) == param_count) { + // error parameter + break; + } + if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) { + var array_type = (ArrayType) param.type_reference; + var cdecl = new CCodeDeclaration ("GArray*"); + cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); + cb_fun.block.add_statement (cdecl); + cend_call.add_argument (get_dbus_array_type (array_type)); + cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); + creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "data")); + creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len")); + } else { + var cdecl = new CCodeDeclaration (param.type_reference.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); + cb_fun.block.add_statement (cdecl); + if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type == codegen.string_type.data_type) { + // special case string array + cend_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV")); + var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); + cstrvlen.add_argument (new CCodeIdentifier (param.name)); + creply_call.add_argument (cstrvlen); + } else { + cend_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ())); + } + cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); + creply_call.add_argument (new CCodeIdentifier (param.name)); + } + } + cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); + cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call)); + creply_call.add_argument (new CCodeIdentifier ("error")); + cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call)); + codegen.source_type_member_definition.append (cb_fun); + + ccall.add_argument (new CCodeIdentifier (cb_fun.name)); + ccall.add_argument (new CCodeConstant ("param%d_target".printf (callback_index))); + ccall.add_argument (new CCodeConstant ("NULL")); + } else if (found_out || !(method.return_type is VoidType)) { + ccall.call = new CCodeIdentifier ("dbus_g_proxy_call"); + + ccall.add_argument (new CCodeIdentifier ("error")); + } else { + ccall.call = new CCodeIdentifier ("dbus_g_proxy_call_no_reply"); + } + + foreach (FormalParameter param in method.get_parameters ()) { + if (param.type_reference is MethodType) { + // callback parameter + break; + } + + ccall.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ())); + ccall.add_argument (new CCodeIdentifier (param.name)); + } + + ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); + + if (!(method.return_type is VoidType)) { + // synchronous D-Bus method call with reply + var array_type = method.return_type as ArrayType; + if (array_type != null && array_type.element_type.data_type != codegen.string_type.data_type) { + // non-string arrays (use GArray) + ccall.add_argument (get_dbus_array_type (array_type)); + + var garray_type_reference = codegen.get_data_type_for_symbol (codegen.garray_type); + var cdecl = new CCodeDeclaration (garray_type_reference.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator ("result")); + block.add_statement (cdecl); + + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result"))); + ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); + + block.add_statement (new CCodeExpressionStatement (ccall)); + + block.add_statement (new CCodeReturnStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "data"))); + + if (!method.no_array_length) { + expr.append_array_size (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "len")); + } else { + expr.append_array_size (new CCodeConstant ("-1")); + } + } else { + // string arrays or other datatypes + + if (method.return_type is ArrayType) { + // string arrays + ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRV")); + } else { + // other types + ccall.add_argument (new CCodeIdentifier (method.return_type.data_type.get_type_id ())); + } + + var cdecl = new CCodeDeclaration (method.return_type.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator ("result")); + block.add_statement (cdecl); + + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result"))); + ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); + + block.add_statement (new CCodeExpressionStatement (ccall)); + + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + + if (array_type != null) { + // special case string array + if (!method.no_array_length) { + var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); + cstrvlen.add_argument (new CCodeIdentifier ("result")); + expr.append_array_size (cstrvlen); + } else { + expr.append_array_size (new CCodeConstant ("-1")); + } + } + } + } else { + block.add_statement (new CCodeExpressionStatement (ccall)); + } + } + + CCodeExpression get_dbus_array_type (ArrayType array_type) { + var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection")); + carray_type.add_argument (new CCodeConstant ("\"GArray\"")); + carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ())); + return carray_type; + } +} diff --git a/gobject/valaccodedynamicsignalbinding.vala b/gobject/valaccodedynamicsignalbinding.vala new file mode 100644 index 000000000..36919dbcc --- /dev/null +++ b/gobject/valaccodedynamicsignalbinding.vala @@ -0,0 +1,174 @@ +/* valaccodedynamicsignalbinding.vala + * + * Copyright (C) 2007-2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; +using Gee; + +/** + * The link between a dynamic signal and generated code. + */ +public class Vala.CCodeDynamicSignalBinding : CCodeBinding { + public Signal node { get; set; } + + public CCodeDynamicSignalBinding (CCodeGenerator codegen, DynamicSignal node) { + this.node = node; + this.codegen = codegen; + } + + string? connect_wrapper_name; + string? disconnect_wrapper_name; + + public string get_connect_wrapper_name () { + var dynamic_signal = (DynamicSignal) node; + + if (connect_wrapper_name == null) { + connect_wrapper_name = "_dynamic_%s_connect".printf (node.name); + var func = new CCodeFunction (connect_wrapper_name, "void"); + func.add_parameter (new CCodeFormalParameter ("obj", "gpointer")); + func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *")); + func.add_parameter (new CCodeFormalParameter ("handler", "GCallback")); + func.add_parameter (new CCodeFormalParameter ("data", "gpointer")); + var block = new CCodeBlock (); + if (dynamic_signal.dynamic_type.data_type == codegen.dbus_object_type) { + generate_dbus_connect_wrapper (block); + } else { + Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ())); + } + + // append to C source file + codegen.source_type_member_declaration.append (func.copy ()); + + func.block = block; + codegen.source_type_member_definition.append (func); + } + + return connect_wrapper_name; + } + + public string get_disconnect_wrapper_name () { + var dynamic_signal = (DynamicSignal) node; + + if (disconnect_wrapper_name == null) { + disconnect_wrapper_name = "_dynamic_%s_disconnect".printf (node.name); + var func = new CCodeFunction (disconnect_wrapper_name, "void"); + func.add_parameter (new CCodeFormalParameter ("obj", "gpointer")); + func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *")); + func.add_parameter (new CCodeFormalParameter ("handler", "GCallback")); + func.add_parameter (new CCodeFormalParameter ("data", "gpointer")); + var block = new CCodeBlock (); + if (dynamic_signal.dynamic_type.data_type == codegen.dbus_object_type) { + generate_dbus_disconnect_wrapper (block); + } else { + Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ())); + } + + // append to C source file + codegen.source_type_member_declaration.append (func.copy ()); + + func.block = block; + codegen.source_type_member_definition.append (func); + } + + return disconnect_wrapper_name; + } + + void generate_dbus_connect_wrapper (CCodeBlock block) { + var dynamic_signal = (DynamicSignal) node; + + var m = (Method) dynamic_signal.handler.symbol_reference; + + bool first = true; + foreach (FormalParameter param in m.get_parameters ()) { + if (first) { + // skip sender parameter + first = false; + continue; + } + node.add_parameter (param.copy ()); + } + + node.accept (codegen); + + // FIXME should only be done once per marshaller + var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller")); + register_call.add_argument (new CCodeIdentifier (codegen.get_signal_marshaller_function (node))); + register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE")); + + var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal")); + add_call.add_argument (new CCodeIdentifier ("obj")); + add_call.add_argument (new CCodeConstant ("\"%s\"".printf (node.name))); + + first = true; + foreach (FormalParameter param in m.get_parameters ()) { + if (first) { + // skip sender parameter + first = false; + continue; + } + if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) { + var array_type = (ArrayType) param.type_reference; + if (array_type.element_type.data_type.get_type_id () == null) { + Report.error (param.source_reference, "unsupported parameter type for D-Bus signals"); + return; + } + + var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection")); + carray_type.add_argument (new CCodeConstant ("\"GArray\"")); + carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ())); + register_call.add_argument (carray_type); + add_call.add_argument (carray_type); + } else { + if (param.type_reference.get_type_id () == null) { + Report.error (param.source_reference, "unsupported parameter type for D-Bus signals"); + return; + } + + register_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ())); + add_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ())); + } + } + register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); + add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); + + block.add_statement (new CCodeExpressionStatement (register_call)); + block.add_statement (new CCodeExpressionStatement (add_call)); + + var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal")); + call.add_argument (new CCodeIdentifier ("obj")); + call.add_argument (new CCodeIdentifier ("signal_name")); + call.add_argument (new CCodeIdentifier ("handler")); + call.add_argument (new CCodeIdentifier ("data")); + call.add_argument (new CCodeConstant ("NULL")); + block.add_statement (new CCodeExpressionStatement (call)); + } + + void generate_dbus_disconnect_wrapper (CCodeBlock block) { + var dynamic_signal = (DynamicSignal) node; + + var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_disconnect_signal")); + call.add_argument (new CCodeIdentifier ("obj")); + call.add_argument (new CCodeIdentifier ("signal_name")); + call.add_argument (new CCodeIdentifier ("handler")); + call.add_argument (new CCodeIdentifier ("data")); + block.add_statement (new CCodeExpressionStatement (call)); + } +} diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index f24adc0fd..eca37eb4a 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -113,7 +113,7 @@ public class Vala.CCodeGenerator : CodeGenerator { public Interface iterator_type; public Interface list_type; public Interface map_type; - public Typesymbol connection_type; + public Typesymbol dbus_object_type; public Method substring_method; @@ -257,7 +257,7 @@ public class Vala.CCodeGenerator : CodeGenerator { var dbus_ns = root_symbol.scope.lookup ("DBus"); if (dbus_ns != null) { - connection_type = (Typesymbol) dbus_ns.scope.lookup ("Connection"); + dbus_object_type = (Typesymbol) dbus_ns.scope.lookup ("Object"); } /* we're only interested in non-pkg source files */ @@ -3624,7 +3624,7 @@ public class Vala.CCodeGenerator : CodeGenerator { public CCodeStatement? create_type_check_statement (CodeNode method_node, DataType ret_type, Typesymbol t, bool non_null, string var_name) { var ccheck = new CCodeFunctionCall (); - if ((t is Class && ((Class) t).is_subtype_of (gobject_type)) || (t is Interface && !((Interface) t).declaration_only)) { + if ((t is Class && ((Class) t).is_subtype_of (gobject_type)) || t is Interface) { var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (t.get_upper_case_cname ("IS_"))); ctype_check.add_argument (new CCodeIdentifier (var_name)); @@ -3723,6 +3723,10 @@ public class Vala.CCodeGenerator : CodeGenerator { return new CCodeMethodBinding (this, node); } + public override CodeBinding? create_dynamic_method_binding (DynamicMethod node) { + return new CCodeDynamicMethodBinding (this, node); + } + public override CodeBinding? create_creation_method_binding (CreationMethod node) { return new CCodeCreationMethodBinding (this, node); } @@ -3743,6 +3747,10 @@ public class Vala.CCodeGenerator : CodeGenerator { return null; } + public override CodeBinding? create_dynamic_signal_binding (DynamicSignal node) { + return new CCodeDynamicSignalBinding (this, node); + } + public override CodeBinding? create_constructor_binding (Constructor node) { return null; } @@ -3955,6 +3963,14 @@ public class Vala.CCodeGenerator : CodeGenerator { return (CCodeMethodBinding) node.get_code_binding (this); } + public CCodeDynamicMethodBinding dynamic_method_binding (DynamicMethod node) { + return (CCodeDynamicMethodBinding) node.get_code_binding (this); + } + + public CCodeDynamicSignalBinding dynamic_signal_binding (DynamicSignal node) { + return (CCodeDynamicSignalBinding) node.get_code_binding (this); + } + public CCodeArrayCreationExpressionBinding array_creation_expression_binding (ArrayCreationExpression node) { return (CCodeArrayCreationExpressionBinding) node.get_code_binding (this); } diff --git a/gobject/valaccodegeneratorsourcefile.vala b/gobject/valaccodegeneratorsourcefile.vala index 7d64f8886..de7f9bc12 100644 --- a/gobject/valaccodegeneratorsourcefile.vala +++ b/gobject/valaccodegeneratorsourcefile.vala @@ -251,7 +251,7 @@ public class Vala.CCodeGenerator { } } else if (node is Interface) { var iface = (Interface) node; - if (!iface.is_static && !iface.declaration_only) { + if (!iface.is_static) { header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ()))); header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_type_cname ()), new CCodeVariableDeclarator (iface.get_type_cname ()))); } diff --git a/gobject/valaccodeinterfacebinding.vala b/gobject/valaccodeinterfacebinding.vala index bde841e60..949bc9bcc 100644 --- a/gobject/valaccodeinterfacebinding.vala +++ b/gobject/valaccodeinterfacebinding.vala @@ -51,7 +51,7 @@ public class Vala.CCodeInterfaceBinding : CCodeTypesymbolBinding { def_frag = codegen.source_type_definition; } - if (!iface.is_static && !iface.declaration_only) { + if (!iface.is_static) { codegen.type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ())); decl_frag.append (new CCodeNewline ()); @@ -84,7 +84,7 @@ public class Vala.CCodeInterfaceBinding : CCodeTypesymbolBinding { iface.accept_children (codegen); - if (!iface.is_static && !iface.declaration_only) { + if (!iface.is_static) { add_interface_base_init_function (iface); var type_fun = new InterfaceRegisterFunction (iface); diff --git a/gobject/valaccodeinvocationexpressionbinding.vala b/gobject/valaccodeinvocationexpressionbinding.vala index c7a00fd87..8da52f370 100644 --- a/gobject/valaccodeinvocationexpressionbinding.vala +++ b/gobject/valaccodeinvocationexpressionbinding.vala @@ -122,111 +122,31 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); csizeof.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ())); carg_map.set (codegen.get_param_pos (0.1), csizeof); - } else if (m is DBusMethod) { - bool found_out = false; - Expression callback = null; + } else if (m is DynamicMethod) { + m.clear_parameters (); + int param_nr = 1; foreach (Expression arg in expr.get_argument_list ()) { - if (arg.symbol_reference is Method) { - // callback - if (callback != null) { - Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method"); - expr.error = true; - return; - } else if (found_out) { - Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method"); - expr.error = true; - return; - } - callback = arg; - } else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) { - // out arg - if (callback != null) { - Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method"); - expr.error = true; - return; - } - found_out = true; + var unary = arg as UnaryExpression; + if (unary != null && unary.operator == UnaryOperator.OUT) { + // out argument + var param = new FormalParameter ("param%d".printf (param_nr), unary.inner.static_type); + param.direction = ParameterDirection.OUT; + m.add_parameter (param); + } else if (unary != null && unary.operator == UnaryOperator.REF) { + // ref argument + var param = new FormalParameter ("param%d".printf (param_nr), unary.inner.static_type); + param.direction = ParameterDirection.REF; + m.add_parameter (param); } else { - // in arg - if (callback != null || found_out) { - Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method"); - expr.error = true; - return; - } + // in argument + m.add_parameter (new FormalParameter ("param%d".printf (param_nr), arg.static_type)); } + param_nr++; } - - carg_map.set (codegen.get_param_pos (0.1), new CCodeConstant ("\"%s\"".printf (m.name))); - - if (callback != null) { - var reply_method = (Method) callback.symbol_reference; - - var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void"); - cb_fun.modifiers = CCodeModifiers.STATIC; - cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*")); - cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*")); - cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*")); - cb_fun.block = new CCodeBlock (); - var cerrdecl = new CCodeDeclaration ("GError*"); - cerrdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("error", new CCodeConstant ("NULL"))); - cb_fun.block.add_statement (cerrdecl); - var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call")); - cend_call.add_argument (new CCodeIdentifier ("proxy")); - cend_call.add_argument (new CCodeIdentifier ("call")); - cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error"))); - var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode); - creply_call.add_argument (new CCodeIdentifier ("user_data")); - int param_count = reply_method.get_parameters ().size; - int i = 0; - foreach (FormalParameter param in reply_method.get_parameters ()) { - if ((++i) == param_count) { - // error parameter - break; - } - if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) { - var array_type = (ArrayType) param.type_reference; - var cdecl = new CCodeDeclaration ("GArray*"); - cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); - cb_fun.block.add_statement (cdecl); - cend_call.add_argument (get_dbus_array_type (array_type)); - cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); - creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "data")); - creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len")); - } else { - var cdecl = new CCodeDeclaration (param.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); - cb_fun.block.add_statement (cdecl); - if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type == codegen.string_type.data_type) { - // special case string array - cend_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV")); - var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); - cstrvlen.add_argument (new CCodeIdentifier (param.name)); - creply_call.add_argument (cstrvlen); - } else { - cend_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ())); - } - cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); - creply_call.add_argument (new CCodeIdentifier (param.name)); - } - } - cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); - cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call)); - creply_call.add_argument (new CCodeIdentifier ("error")); - cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call)); - codegen.source_type_member_definition.append (cb_fun); - - carg_map.set (codegen.get_param_pos (0.2), new CCodeIdentifier (cb_fun.name)); - carg_map.set (codegen.get_param_pos (0.3), new CCodeConstant ("self")); - carg_map.set (codegen.get_param_pos (0.4), new CCodeConstant ("NULL")); - } else if (found_out || !(m.return_type is VoidType)) { - ccall.call = new CCodeIdentifier ("dbus_g_proxy_call"); - - // method can fail - codegen.current_method_inner_error = true; - carg_map.set (codegen.get_param_pos (0.2), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error"))); - } else { - ccall.call = new CCodeIdentifier ("dbus_g_proxy_call_no_reply"); + foreach (FormalParameter param in m.get_parameters ()) { + param.accept (codegen); } + codegen.dynamic_method_binding ((DynamicMethod) m).generate_wrapper (); } bool ellipsis = false; @@ -235,15 +155,6 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { int arg_pos; Iterator params_it = params.iterator (); foreach (Expression arg in expr.get_argument_list ()) { - if (m is DBusMethod) { - if (arg.symbol_reference is Method) { - // callback parameter - break; - } - - carg_map.set (codegen.get_param_pos (i - 0.1, true), new CCodeIdentifier (arg.static_type.data_type.get_type_id ())); - } - CCodeExpression cexpr = (CCodeExpression) arg.ccodenode; Gee.List extra_args = new ArrayList (); if (params_it.next ()) { @@ -270,6 +181,9 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), codegen.get_delegate_target_cexpression (arg)); multiple_cargs = true; } + } else if (param.type_reference is MethodType) { + carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), codegen.get_delegate_target_cexpression (arg)); + multiple_cargs = true; } cexpr = codegen.get_implicit_cast_expression (cexpr, arg.static_type, param.type_reference); @@ -389,7 +303,7 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { } /* add length argument for methods returning arrays */ - if (m != null && m.return_type is ArrayType && !(m is DBusMethod)) { + if (m != null && m.return_type is ArrayType) { var array_type = (ArrayType) m.return_type; for (int dim = 1; dim <= array_type.rank; dim++) { if (!m.no_array_length) { @@ -420,15 +334,7 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { } } - if (codegen.connection_type != null && ma.inner != null && ma.inner.static_type != null && ma.inner.static_type.data_type == codegen.connection_type && m.name == "get_object") { - var dbus_iface = (Interface) m.return_type.data_type; - var dbus_attr = dbus_iface.get_attribute ("DBusInterface"); - carg_map.set (codegen.get_param_pos (-1), new CCodeConstant ("\"%s\"".printf (dbus_attr.get_string ("name")))); - } else if (m is DBusMethod) { - carg_map.set (codegen.get_param_pos (-1, true), new CCodeIdentifier ("G_TYPE_INVALID")); - } - - if (expr.can_fail && !(m is DBusMethod)) { + if (expr.can_fail) { // method can fail codegen.current_method_inner_error = true; // add &inner_error before the ellipsis arguments @@ -438,7 +344,7 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { if (ellipsis) { /* ensure variable argument list ends with NULL * except when using printf-style arguments */ - if ((m == null || !m.printf_format) && !(m is DBusMethod)) { + if ((m == null || !m.printf_format)) { carg_map.set (codegen.get_param_pos (-1, true), new CCodeConstant (m.sentinel)); } } else if (itype is DelegateType) { @@ -540,72 +446,7 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { ccomma.append_expression (cndupcall); expr.ccodenode = ccomma; - } else if (m is DBusMethod && !(m.return_type is VoidType)) { - // synchronous D-Bus method call with reply - if (m.return_type is ArrayType && ((ArrayType) m.return_type).element_type.data_type != codegen.string_type.data_type) { - // non-string arrays (use GArray) - var array_type = (ArrayType) m.return_type; - - ccall.add_argument (get_dbus_array_type (array_type)); - - var garray_type_reference = codegen.get_data_type_for_symbol (codegen.garray_type); - var temp_decl = codegen.get_temp_variable (garray_type_reference); - codegen.temp_vars.insert (0, temp_decl); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name))); - - ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (ccall); - ccomma.append_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier (temp_decl.name), "data")); - expr.ccodenode = ccomma; - - if (!m.no_array_length) { - expr.append_array_size (new CCodeMemberAccess.pointer (new CCodeIdentifier (temp_decl.name), "len")); - } else { - expr.append_array_size (new CCodeConstant ("-1")); - } - } else if (m.return_type is ArrayType || m.return_type.data_type != null) { - // string arrays or other datatypes - - if (m.return_type is ArrayType) { - // string arrays - ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRV")); - } else { - // other types - ccall.add_argument (new CCodeIdentifier (m.return_type.data_type.get_type_id ())); - } - - var temp_decl = codegen.get_temp_variable (m.return_type); - codegen.temp_vars.insert (0, temp_decl); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name))); - - ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID")); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (ccall); - ccomma.append_expression (new CCodeIdentifier (temp_decl.name)); - expr.ccodenode = ccomma; - - if (m.return_type is ArrayType && ((ArrayType) m.return_type).element_type.data_type == codegen.string_type.data_type) { - // special case string array - if (!m.no_array_length) { - var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); - cstrvlen.add_argument (new CCodeIdentifier (temp_decl.name)); - expr.append_array_size (cstrvlen); - } else { - expr.append_array_size (new CCodeConstant ("-1")); - } - } - } } } - - private CCodeExpression get_dbus_array_type (ArrayType array_type) { - var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection")); - carray_type.add_argument (new CCodeConstant ("\"GArray\"")); - carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ())); - return carray_type; - } } diff --git a/gobject/valaccodemethodbinding.vala b/gobject/valaccodemethodbinding.vala index 1c6c46b78..9bef1157f 100644 --- a/gobject/valaccodemethodbinding.vala +++ b/gobject/valaccodemethodbinding.vala @@ -188,76 +188,7 @@ public class Vala.CCodeMethodBinding : CCodeBinding { } } - var params = m.get_parameters (); - foreach (FormalParameter param in params) { - if (!param.no_array_length && param.type_reference is ArrayType) { - var array_type = (ArrayType) param.type_reference; - - var length_ctype = "int"; - if (param.direction != ParameterDirection.IN) { - length_ctype = "int*"; - } - - for (int dim = 1; dim <= array_type.rank; dim++) { - var cparam = new CCodeFormalParameter (codegen.get_array_length_cname (param.name, dim), length_ctype); - cparam_map.set (codegen.get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam); - } - } - - cparam_map.set (codegen.get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode); - - if (param.type_reference is DelegateType) { - var deleg_type = (DelegateType) param.type_reference; - var d = deleg_type.delegate_symbol; - if (d.instance) { - var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname (param.name), "void*"); - cparam_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), cparam); - } - } - } - - if (!m.no_array_length && creturn_type is ArrayType) { - // return array length if appropriate - var array_type = (ArrayType) creturn_type; - - for (int dim = 1; dim <= array_type.rank; dim++) { - var cparam = new CCodeFormalParameter (codegen.get_array_length_cname ("result", dim), "int*"); - cparam_map.set (codegen.get_param_pos (m.carray_length_parameter_position + 0.01 * dim), cparam); - } - } else if (creturn_type is DelegateType) { - // return delegate target if appropriate - var deleg_type = (DelegateType) creturn_type; - var d = deleg_type.delegate_symbol; - if (d.instance) { - var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname ("result"), "void*"); - cparam_map.set (codegen.get_param_pos (m.cdelegate_target_parameter_position), cparam); - } - } - - if (m.get_error_domains ().size > 0) { - var cparam = new CCodeFormalParameter ("error", "GError**"); - cparam_map.set (codegen.get_param_pos (-1), cparam); - } - - // append C parameters in the right order - int last_pos = -1; - int min_pos; - while (true) { - min_pos = -1; - foreach (int pos in cparam_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - codegen.function.add_parameter (cparam_map.get (min_pos)); - if (vdeclarator != null) { - vdeclarator.add_parameter (cparam_map.get (min_pos)); - } - last_pos = min_pos; - } + generate_cparameters (m, creturn_type, cparam_map, codegen.function, vdeclarator); bool visible = !m.is_internal_symbol (); @@ -649,6 +580,81 @@ public class Vala.CCodeMethodBinding : CCodeBinding { } } + public void generate_cparameters (Method m, DataType creturn_type, Map cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null) { + foreach (FormalParameter param in m.get_parameters ()) { + if (!param.no_array_length && param.type_reference is ArrayType) { + var array_type = (ArrayType) param.type_reference; + + var length_ctype = "int"; + if (param.direction != ParameterDirection.IN) { + length_ctype = "int*"; + } + + for (int dim = 1; dim <= array_type.rank; dim++) { + var cparam = new CCodeFormalParameter (codegen.get_array_length_cname (param.name, dim), length_ctype); + cparam_map.set (codegen.get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam); + } + } + + cparam_map.set (codegen.get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode); + + if (param.type_reference is DelegateType) { + var deleg_type = (DelegateType) param.type_reference; + var d = deleg_type.delegate_symbol; + if (d.instance) { + var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname (param.name), "void*"); + cparam_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), cparam); + } + } else if (param.type_reference is MethodType) { + var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname (param.name), "void*"); + cparam_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), cparam); + } + } + + if (!m.no_array_length && creturn_type is ArrayType) { + // return array length if appropriate + var array_type = (ArrayType) creturn_type; + + for (int dim = 1; dim <= array_type.rank; dim++) { + var cparam = new CCodeFormalParameter (codegen.get_array_length_cname ("result", dim), "int*"); + cparam_map.set (codegen.get_param_pos (m.carray_length_parameter_position + 0.01 * dim), cparam); + } + } else if (creturn_type is DelegateType) { + // return delegate target if appropriate + var deleg_type = (DelegateType) creturn_type; + var d = deleg_type.delegate_symbol; + if (d.instance) { + var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname ("result"), "void*"); + cparam_map.set (codegen.get_param_pos (m.cdelegate_target_parameter_position), cparam); + } + } + + if (m.get_error_domains ().size > 0) { + var cparam = new CCodeFormalParameter ("error", "GError**"); + cparam_map.set (codegen.get_param_pos (-1), cparam); + } + + // append C parameters in the right order + int last_pos = -1; + int min_pos; + while (true) { + min_pos = -1; + foreach (int pos in cparam_map.get_keys ()) { + if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { + min_pos = pos; + } + } + if (min_pos == -1) { + break; + } + func.add_parameter (cparam_map.get (min_pos)); + if (vdeclarator != null) { + vdeclarator.add_parameter (cparam_map.get (min_pos)); + } + last_pos = min_pos; + } + } + private CCodeStatement create_method_type_check_statement (Method m, DataType return_type, Typesymbol t, bool non_null, string var_name) { return codegen.create_type_check_statement (m, return_type, t, non_null, var_name); } diff --git a/gobject/valadbusbindingprovider.vala b/gobject/valadbusbindingprovider.vala deleted file mode 100644 index 2edf0aa20..000000000 --- a/gobject/valadbusbindingprovider.vala +++ /dev/null @@ -1,115 +0,0 @@ -/* valadbusbindingprovider.vala - * - * Copyright (C) 2007-2008 Jürg Billeter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter - */ - -using GLib; -using Gee; - -/** - * Dynamic binding provider for DBus objects. - */ -public class Vala.DBusBindingProvider : Object, BindingProvider { - public CodeContext context { - set { - _context = value; - - string_type = (Class) _context.root.scope.lookup ("string"); - - var dbus_ns = _context.root.scope.lookup ("DBus"); - if (dbus_ns != null) { - connection_type = (Typesymbol) dbus_ns.scope.lookup ("Connection"); - dbus_error_type = (Typesymbol) dbus_ns.scope.lookup ("Error"); - } - } - } - - private CodeContext _context; - private Class string_type; - private Typesymbol connection_type; - private Typesymbol dbus_error_type; - - private Collection symbols = new ArrayList (); - - public DBusBindingProvider () { - } - - public Symbol? get_binding (MemberAccess ma) { - if (connection_type != null && ma.inner != null && ma.inner.static_type != null && ma.inner.static_type.data_type == connection_type) { - var type_args = ma.get_type_arguments (); - if (type_args.size != 1) { - return null; - } - Iterator type_args_it = type_args.iterator (); - type_args_it.next (); - var ret_type = type_args_it.get ().copy (); - if (!is_dbus_interface (ret_type)) { - return null; - } - var m = new Method ("get_object", ret_type, ma.source_reference); - m.set_cname ("dbus_g_proxy_new_for_name"); - m.add_cheader_filename ("dbus/dbus-glib.h"); - m.access = SymbolAccessibility.PUBLIC; - var string_type_ref = new ClassType (string_type); - m.add_parameter (new FormalParameter ("name", string_type_ref)); - m.add_parameter (new FormalParameter ("path", string_type_ref)); - symbols.add (m); - return m; - } else if (ma.inner != null && ma.inner.static_type != null && is_dbus_interface (ma.inner.static_type)) { - if (ma.parent_node is InvocationExpression) { - var expr = (InvocationExpression) ma.parent_node; - DataType ret_type; - if (expr.expected_type != null) { - ret_type = expr.expected_type.copy (); - ret_type.transfers_ownership = ret_type.is_reference_type_or_type_parameter (); - } else { - ret_type = new VoidType (); - } - var m = new DBusMethod (ma.member_name, ret_type, ma.source_reference); - if (expr.expected_type != null) { - var error_type = CCodeGenerator.get_data_type_for_symbol (dbus_error_type); - m.add_error_domain (error_type); - } - m.access = SymbolAccessibility.PUBLIC; - m.add_parameter (new FormalParameter.with_ellipsis ()); - symbols.add (m); - return m; - } else if (ma.parent_node is Assignment) { - var a = (Assignment) ma.parent_node; - if (a.left != ma) { - return null; - } - var s = new DBusSignal (ma.member_name, new VoidType (), ma.source_reference); - s.access = SymbolAccessibility.PUBLIC; - symbols.add (s); - return s; - } - } - return null; - } - - private bool is_dbus_interface (DataType t) { - if (!(t.data_type is Interface)) { - return false; - } - return (t.data_type.get_attribute ("DBusInterface") != null); - } -} - diff --git a/gobject/valadbussignal.vala b/gobject/valadbussignal.vala deleted file mode 100644 index 7fdb5464a..000000000 --- a/gobject/valadbussignal.vala +++ /dev/null @@ -1,34 +0,0 @@ -/* valadbussignal.vala - * - * Copyright (C) 2007 Jürg Billeter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter - */ - -using GLib; - -/** - * Represents a dynamic bound DBus signal. - */ -public class Vala.DBusSignal : Signal { - public DBusSignal (string name, DataType return_type, SourceReference? source_reference = null) { - this.return_type = return_type; - this.source_reference = source_reference; - this.name = name; - } -} diff --git a/vala/Makefile.am b/vala/Makefile.am index bcdc94738..c951a22f9 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -26,7 +26,6 @@ libvalacore_la_VALASOURCES = \ valabaseaccess.vala \ valabasicblock.vala \ valabinaryexpression.vala \ - valabindingprovider.vala \ valablock.vala \ valabooleanliteral.vala \ valabreakstatement.vala \ @@ -53,6 +52,8 @@ libvalacore_la_VALASOURCES = \ valadeletestatement.vala \ valadestructor.vala \ valadostatement.vala \ + valadynamicmethod.vala \ + valadynamicsignal.vala \ valaelementaccess.vala \ valaemptystatement.vala \ valaenum.vala \ diff --git a/vala/valabindingprovider.vala b/vala/valabindingprovider.vala deleted file mode 100644 index ea12a9f19..000000000 --- a/vala/valabindingprovider.vala +++ /dev/null @@ -1,37 +0,0 @@ -/* valabindingprovider.vala - * - * Copyright (C) 2007-2008 Jürg Billeter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter - */ - -using GLib; - -/** - * Interface for dynamic binding providers. - */ -public interface Vala.BindingProvider : Object { - /** - * Return custom binding for the specified member access expression. - * - * @param ma member access expression - * @return resolved symbol or null if no binding can be provided - */ - public abstract Symbol? get_binding (MemberAccess ma); -} - diff --git a/vala/valaclasstype.vala b/vala/valaclasstype.vala index 506630c24..0bd7159dc 100644 --- a/vala/valaclasstype.vala +++ b/vala/valaclasstype.vala @@ -42,6 +42,7 @@ public class Vala.ClassType : ReferenceType { result.transfers_ownership = transfers_ownership; result.takes_ownership = takes_ownership; result.nullable = nullable; + result.is_dynamic = is_dynamic; result.floating_reference = floating_reference; foreach (DataType arg in get_type_arguments ()) { diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index e884aaa4d..953faedf7 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -128,6 +128,8 @@ public class Vala.CodeContext : Object { private Gee.List defines = new ArrayList (str_equal); + private Gee.List dynamic_members = new ArrayList (); + /** * The root namespace of the symbol tree. * @@ -408,4 +410,8 @@ public class Vala.CodeContext : Object { return null; } + + public void add_dynamic_member (Symbol dynamic_member) { + dynamic_members.add (dynamic_member); + } } diff --git a/vala/valacodegenerator.vala b/vala/valacodegenerator.vala index 85467fc7a..3367e8378 100644 --- a/vala/valacodegenerator.vala +++ b/vala/valacodegenerator.vala @@ -82,6 +82,10 @@ public class Vala.CodeGenerator : CodeVisitor { return null; } + public virtual CodeBinding? create_dynamic_method_binding (DynamicMethod node) { + return null; + } + public virtual CodeBinding? create_creation_method_binding (CreationMethod node) { return null; } @@ -102,6 +106,10 @@ public class Vala.CodeGenerator : CodeVisitor { return null; } + public virtual CodeBinding? create_dynamic_signal_binding (DynamicSignal node) { + return null; + } + public virtual CodeBinding? create_constructor_binding (Constructor node) { return null; } diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index e3b120870..90c78d2f9 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -60,6 +60,11 @@ public abstract class Vala.DataType : CodeNode { */ public bool floating_reference { get; set; } + /** + * Specifies that the type supports dynamic lookup. + */ + public bool is_dynamic { get; set; } + private Gee.List type_argument_list = new ArrayList (); /** diff --git a/vala/valadynamicmethod.vala b/vala/valadynamicmethod.vala new file mode 100644 index 000000000..d63146c34 --- /dev/null +++ b/vala/valadynamicmethod.vala @@ -0,0 +1,59 @@ +/* valadynamicmethod.vala + * + * Copyright (C) 2007-2008 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; +using Gee; + +/** + * Represents a late bound method. + */ +public class Vala.DynamicMethod : Method { + public DataType dynamic_type { get; set; } + + public InvocationExpression invocation { get; set; } + + private string cname; + + public DynamicMethod (DataType dynamic_type, string name, DataType return_type, SourceReference? source_reference = null) { + this.dynamic_type = dynamic_type; + this.name = name; + this.return_type = return_type; + this.source_reference = source_reference; + } + + public override Collection get_cheader_filenames () { + return new ReadOnlyCollection (); + } + + public override string get_default_cname () { + // return cname of wrapper method + if (cname == null) { + // FIXME support multiple dynamic methods with the same name + cname = "_dynamic_%s".printf (name); + } + return cname; + } + + public override CodeBinding? create_code_binding (CodeGenerator codegen) { + return codegen.create_dynamic_method_binding (this); + } +} diff --git a/gobject/valadbusmethod.vala b/vala/valadynamicsignal.vala similarity index 63% rename from gobject/valadbusmethod.vala rename to vala/valadynamicsignal.vala index 57a330565..459ddb370 100644 --- a/gobject/valadbusmethod.vala +++ b/vala/valadynamicsignal.vala @@ -1,6 +1,6 @@ -/* valadbusmethod.vala +/* valadynamicsignal.vala * - * Copyright (C) 2007 Jürg Billeter + * Copyright (C) 2007-2008 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,23 +21,23 @@ */ using GLib; -using Gee; /** - * Represents a dynamic bound DBus method. + * Represents a late bound signal. */ -public class Vala.DBusMethod : Method { - public DBusMethod (string name, DataType return_type, SourceReference? source_reference = null) { +public class Vala.DynamicSignal : Signal { + public DataType dynamic_type { get; set; } + + public Expression handler { get; set; } + + public DynamicSignal (DataType dynamic_type, string name, DataType return_type, SourceReference? source_reference = null) { + this.dynamic_type = dynamic_type; + this.name = name; this.return_type = return_type; this.source_reference = source_reference; - this.name = name; - } - - public override Collection get_cheader_filenames () { - return new ReadOnlyCollection (); } - public override string get_default_cname () { - return "dbus_g_proxy_begin_call"; + public override CodeBinding? create_code_binding (CodeGenerator codegen) { + return codegen.create_dynamic_signal_binding (this); } } diff --git a/vala/valainterface.vala b/vala/valainterface.vala index 7c1b3ed0b..fa09b047a 100644 --- a/vala/valainterface.vala +++ b/vala/valainterface.vala @@ -33,8 +33,6 @@ public class Vala.Interface : Typesymbol { */ public bool is_static { get; set; } - public bool declaration_only { get; set; } - private Gee.List type_parameters = new ArrayList (); private Gee.List prerequisites = new ArrayList (); @@ -407,12 +405,6 @@ public class Vala.Interface : Typesymbol { } } - private void process_dbus_interface_attribute (Attribute a) { - if (declaration_only) { - cname = "DBusGProxy"; - } - } - /** * Process all associated attributes. */ @@ -420,8 +412,6 @@ public class Vala.Interface : Typesymbol { foreach (Attribute a in attributes) { if (a.name == "CCode") { process_ccode_attribute (a); - } else if (a.name == "DBusInterface") { - process_dbus_interface_attribute (a); } } } diff --git a/vala/valainterfacetype.vala b/vala/valainterfacetype.vala index 3d202f2ac..bc389a9d7 100644 --- a/vala/valainterfacetype.vala +++ b/vala/valainterfacetype.vala @@ -42,6 +42,7 @@ public class Vala.InterfaceType : ReferenceType { result.transfers_ownership = transfers_ownership; result.takes_ownership = takes_ownership; result.nullable = nullable; + result.is_dynamic = is_dynamic; result.floating_reference = floating_reference; foreach (DataType arg in get_type_arguments ()) { diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 10cd38d57..cf3fa03e9 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -246,6 +246,18 @@ public class Vala.Method : Member { return new ReadOnlyCollection (parameters); } + /** + * Remove all parameters from this method. + */ + public void clear_parameters () { + foreach (FormalParameter param in parameters) { + if (!param.ellipsis) { + scope.remove (param.name); + } + } + parameters.clear (); + } + public override void accept (CodeVisitor visitor) { visitor.visit_method (this); } diff --git a/vala/valamethodtype.vala b/vala/valamethodtype.vala index 09f6bf88a..0b5d68e5f 100644 --- a/vala/valamethodtype.vala +++ b/vala/valamethodtype.vala @@ -62,4 +62,8 @@ public class Vala.MethodType : DataType { public override string to_string () { return method_symbol.get_full_name (); } + + public override string? get_cname (bool var_type, bool const_type) { + return "gpointer"; + } } diff --git a/vala/valaparser.vala b/vala/valaparser.vala index f17363fe4..fc59158f3 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -183,6 +183,7 @@ public class Vala.Parser : CodeVisitor { case TokenType.DELEGATE: case TokenType.DELETE: case TokenType.DO: + case TokenType.DYNAMIC: case TokenType.ELSE: case TokenType.ENUM: case TokenType.ENSURES: @@ -312,8 +313,7 @@ public class Vala.Parser : CodeVisitor { } return; } - accept (TokenType.REF); - accept (TokenType.OUT); + accept (TokenType.DYNAMIC); accept (TokenType.WEAK); skip_symbol_name (); skip_type_argument_list (); @@ -343,6 +343,8 @@ public class Vala.Parser : CodeVisitor { return type; } + bool is_dynamic = accept (TokenType.DYNAMIC); + bool is_weak = accept (TokenType.WEAK); var sym = parse_symbol_name (); @@ -383,6 +385,7 @@ public class Vala.Parser : CodeVisitor { type.add_type_argument (type_arg); } } + type.is_dynamic = is_dynamic; type.is_weak = is_weak; type.pointer_level = stars; type.array_rank = array_rank; @@ -737,6 +740,7 @@ public class Vala.Parser : CodeVisitor { next (); switch (current ()) { case TokenType.VOID: + case TokenType.DYNAMIC: case TokenType.WEAK: case TokenType.IDENTIFIER: var type = parse_type (); @@ -2319,12 +2323,7 @@ public class Vala.Parser : CodeVisitor { iface.add_prerequisite (base_type); } - if (accept (TokenType.SEMICOLON)) { - iface.external = true; - iface.declaration_only = true; - } else { - parse_declarations (iface); - } + parse_declarations (iface); Symbol result = iface; while (sym.inner != null) { @@ -2708,6 +2707,7 @@ public class Vala.Parser : CodeVisitor { do { switch (current ()) { case TokenType.VOID: + case TokenType.DYNAMIC: case TokenType.WEAK: case TokenType.IDENTIFIER: var type = parse_type (); diff --git a/vala/valascanner.vala b/vala/valascanner.vala index 62017b7c7..e94640680 100644 --- a/vala/valascanner.vala +++ b/vala/valascanner.vala @@ -239,7 +239,14 @@ public class Vala.Scanner : Object { case 7: switch (begin[0]) { case 'd': - if (matches (begin, "default")) return TokenType.DEFAULT; + switch (begin[1]) { + case 'e': + if (matches (begin, "default")) return TokenType.DEFAULT; + break; + case 'y': + if (matches (begin, "dynamic")) return TokenType.DYNAMIC; + break; + } break; case 'e': if (matches (begin, "ensures")) return TokenType.ENSURES; diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 9ed52631e..790048bcc 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -59,15 +59,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor { private int next_lambda_id = 0; - private Collection binding_providers = new ArrayList (); - public SemanticAnalyzer () { } - public void add_binding_provider (BindingProvider binding_provider) { - binding_providers.add (binding_provider); - } - /** * Analyze and check code in the specified context. * @@ -1586,31 +1580,55 @@ public class Vala.SemanticAnalyzer : CodeVisitor { // check for named struct creation method expr.symbol_reference = base_symbol.scope.lookup (".new." + expr.member_name); } - } - if (expr.symbol_reference == null) { - /* allow plug-ins to provide custom member bindings */ - foreach (BindingProvider binding_provider in binding_providers) { - expr.symbol_reference = binding_provider.get_binding (expr); + if (expr.symbol_reference == null && expr.inner.static_type != null && expr.inner.static_type.is_dynamic) { + // allow late bound members for dynamic types + if (expr.parent_node is InvocationExpression) { + var invoc = (InvocationExpression) expr.parent_node; + DataType ret_type; + if (invoc.expected_type != null) { + ret_type = invoc.expected_type.copy (); + ret_type.transfers_ownership = ret_type.is_reference_type_or_type_parameter (); + } else { + ret_type = new VoidType (); + } + var m = new DynamicMethod (expr.inner.static_type, expr.member_name, ret_type, expr.source_reference); + m.invocation = invoc; + m.add_error_domain (new ErrorType (null)); + m.access = SymbolAccessibility.PUBLIC; + m.add_parameter (new FormalParameter.with_ellipsis ()); + context.add_dynamic_member (m); + expr.symbol_reference = m; + } else if (expr.parent_node is Assignment) { + var a = (Assignment) expr.parent_node; + if (a.left == expr + && (a.operator == AssignmentOperator.ADD + || a.operator == AssignmentOperator.SUB)) { + var s = new DynamicSignal (expr.inner.static_type, expr.member_name, new VoidType (), expr.source_reference); + s.handler = a.right; + s.access = SymbolAccessibility.PUBLIC; + context.add_dynamic_member (s); + expr.symbol_reference = s; + } + } if (expr.symbol_reference != null) { may_access_instance_members = true; - break; } } + } - if (expr.symbol_reference == null) { - expr.error = true; - - string base_type_name = "(null)"; - if (expr.inner != null && expr.inner.static_type != null) { - base_type_name = expr.inner.static_type.to_string (); - } else if (base_symbol != null) { - base_type_name = base_symbol.get_full_name (); - } + if (expr.symbol_reference == null) { + expr.error = true; - Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_type_name)); - return; + string base_type_name = "(null)"; + if (expr.inner != null && expr.inner.static_type != null) { + base_type_name = expr.inner.static_type.to_string (); + } else if (base_symbol != null) { + base_type_name = base_symbol.get_full_name (); } + + Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_type_name)); + return; } var member = expr.symbol_reference; diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala index db86996bc..3f1b68634 100644 --- a/vala/valasymbolresolver.vala +++ b/vala/valasymbolresolver.vala @@ -268,6 +268,7 @@ public class Vala.SymbolResolver : CodeVisitor { type.takes_ownership = unresolved_type.takes_ownership; type.transfers_ownership = unresolved_type.transfers_ownership; type.nullable = unresolved_type.nullable; + type.is_dynamic = unresolved_type.is_dynamic; foreach (DataType type_arg in unresolved_type.get_type_arguments ()) { type.add_type_argument (type_arg); } @@ -277,6 +278,7 @@ public class Vala.SymbolResolver : CodeVisitor { base_type.takes_ownership = false; base_type.transfers_ownership = false; base_type.nullable = false; + base_type.is_dynamic = false; type = new PointerType (base_type); } diff --git a/vala/valatokentype.vala b/vala/valatokentype.vala index decb2905a..9137c6d79 100644 --- a/vala/valatokentype.vala +++ b/vala/valatokentype.vala @@ -59,6 +59,7 @@ public enum Vala.TokenType { DIV, DO, DOT, + DYNAMIC, ELLIPSIS, ELSE, ENUM, diff --git a/vala/valaunresolvedtype.vala b/vala/valaunresolvedtype.vala index 0e05b7cd4..5be00955c 100644 --- a/vala/valaunresolvedtype.vala +++ b/vala/valaunresolvedtype.vala @@ -108,6 +108,7 @@ public class Vala.UnresolvedType : DataType { result.transfers_ownership = transfers_ownership; result.takes_ownership = takes_ownership; result.nullable = nullable; + result.is_dynamic = is_dynamic; result.unresolved_symbol = unresolved_symbol.copy (); result.array_rank = array_rank; result.pointer_level = pointer_level; diff --git a/vala/valavaluetype.vala b/vala/valavaluetype.vala index d7b668ab8..1ff207dd6 100644 --- a/vala/valavaluetype.vala +++ b/vala/valavaluetype.vala @@ -42,6 +42,7 @@ public class Vala.ValueType : DataType { result.transfers_ownership = transfers_ownership; result.takes_ownership = takes_ownership; result.nullable = nullable; + result.is_dynamic = is_dynamic; result.floating_reference = floating_reference; foreach (DataType arg in get_type_arguments ()) { diff --git a/vapi/dbus-glib-1.vapi b/vapi/dbus-glib-1.vapi index a3adac31b..e26216420 100644 --- a/vapi/dbus-glib-1.vapi +++ b/vapi/dbus-glib-1.vapi @@ -95,19 +95,20 @@ namespace DBus { [CCode (ref_function = "dbus_g_connection_ref", unref_function = "dbus_g_connection_unref", cname = "DBusGConnection")] public class Connection { + [CCode (cname = "dbus_g_proxy_new_for_name")] + public Object get_object (string name, string path, string interface_); } [CCode (cname = "DBusGProxy", lower_case_csuffix = "g_proxy")] - public class Proxy { - public Proxy.for_name (Connection connection, string name, string path, string interface_); + public class Object : GLib.Object { public bool call (string method, out GLib.Error error, GLib.Type first_arg_type, ...); - public weak ProxyCall begin_call (string method, ProxyCallNotify notify, void* data, GLib.DestroyNotify destroy, GLib.Type first_arg_type, ...); + public weak ProxyCall begin_call (string method, ProxyCallNotify notify, GLib.DestroyNotify destroy, GLib.Type first_arg_type, ...); public bool end_call (ProxyCall call, out GLib.Error error, GLib.Type first_arg_type, ...); public void cancel_call (ProxyCall call); } [CCode (cname = "DBusGProxyCallNotify")] - public static delegate void ProxyCallNotify (Proxy proxy, ProxyCall call_id, void* user_data); + public delegate void ProxyCallNotify (Object obj, ProxyCall call_id); [CCode (cname = "DBusGProxyCall")] public class ProxyCall {