vala r1288 - in trunk: . compiler gobject vala vapi



Author: juergbi
Date: Sun Apr 20 18:50:28 2008
New Revision: 1288
URL: http://svn.gnome.org/viewvc/vala?rev=1288&view=rev

Log:
2008-04-20  Juerg Billeter  <j bitron ch>

	* 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


Added:
   trunk/gobject/valaccodedynamicmethodbinding.vala
   trunk/gobject/valaccodedynamicsignalbinding.vala
   trunk/vala/valadynamicmethod.vala
   trunk/vala/valadynamicsignal.vala
Removed:
   trunk/gobject/valadbusbindingprovider.vala
   trunk/gobject/valadbusmethod.vala
   trunk/gobject/valadbussignal.vala
   trunk/vala/valabindingprovider.vala
Modified:
   trunk/ChangeLog
   trunk/compiler/valacompiler.vala
   trunk/gobject/Makefile.am
   trunk/gobject/valaccodeassignmentbinding.vala
   trunk/gobject/valaccodebinding.vala
   trunk/gobject/valaccodegenerator.vala
   trunk/gobject/valaccodegeneratorsourcefile.vala
   trunk/gobject/valaccodeinterfacebinding.vala
   trunk/gobject/valaccodeinvocationexpressionbinding.vala
   trunk/gobject/valaccodemethodbinding.vala
   trunk/vala/Makefile.am
   trunk/vala/valaclasstype.vala
   trunk/vala/valacodecontext.vala
   trunk/vala/valacodegenerator.vala
   trunk/vala/valadatatype.vala
   trunk/vala/valainterface.vala
   trunk/vala/valainterfacetype.vala
   trunk/vala/valamethod.vala
   trunk/vala/valamethodtype.vala
   trunk/vala/valaparser.vala
   trunk/vala/valascanner.vala
   trunk/vala/valasemanticanalyzer.vala
   trunk/vala/valasymbolresolver.vala
   trunk/vala/valatokentype.vala
   trunk/vala/valaunresolvedtype.vala
   trunk/vala/valavaluetype.vala
   trunk/vapi/dbus-glib-1.vapi

Modified: trunk/compiler/valacompiler.vala
==============================================================================
--- trunk/compiler/valacompiler.vala	(original)
+++ trunk/compiler/valacompiler.vala	Sun Apr 20 18:50:28 2008
@@ -234,11 +234,7 @@
 			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) {

Modified: trunk/gobject/Makefile.am
==============================================================================
--- trunk/gobject/Makefile.am	(original)
+++ trunk/gobject/Makefile.am	Sun Apr 20 18:50:28 2008
@@ -18,6 +18,8 @@
 	valaccodeclassbinding.vala \
 	valaccodecompiler.vala \
 	valaccodecreationmethodbinding.vala \
+	valaccodedynamicmethodbinding.vala \
+	valaccodedynamicsignalbinding.vala \
 	valaccodeelementaccessbinding.vala \
 	valaccodeexpressionbinding.vala \
 	valaccodegenerator.vala \
@@ -30,9 +32,6 @@
 	valaccodemethodbinding.vala \
 	valaccodetypesymbolbinding.vala \
 	valaclassregisterfunction.vala \
-	valadbusbindingprovider.vala \
-	valadbusmethod.vala \
-	valadbussignal.vala \
 	valagidlwriter.vala \
 	valainterfaceregisterfunction.vala \
 	valatyperegisterfunction.vala \

Modified: trunk/gobject/valaccodeassignmentbinding.vala
==============================================================================
--- trunk/gobject/valaccodeassignmentbinding.vala	(original)
+++ trunk/gobject/valaccodeassignmentbinding.vala	Sun Apr 20 18:50:28 2008
@@ -106,8 +106,8 @@
 		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 @@
 				}
 			}
 		} 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 @@
 			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 @@
 		}
 
 		// 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 @@
 
 		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 @@
 			} 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) {

Modified: trunk/gobject/valaccodebinding.vala
==============================================================================
--- trunk/gobject/valaccodebinding.vala	(original)
+++ trunk/gobject/valaccodebinding.vala	Sun Apr 20 18:50:28 2008
@@ -34,7 +34,8 @@
 	/**
 	 * 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) {

Added: trunk/gobject/valaccodedynamicmethodbinding.vala
==============================================================================
--- (empty file)
+++ trunk/gobject/valaccodedynamicmethodbinding.vala	Sun Apr 20 18:50:28 2008
@@ -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 <j bitron ch>
+ */
+
+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<int,CCodeFormalParameter> (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;
+	}
+}

Added: trunk/gobject/valaccodedynamicsignalbinding.vala
==============================================================================
--- (empty file)
+++ trunk/gobject/valaccodedynamicsignalbinding.vala	Sun Apr 20 18:50:28 2008
@@ -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 <j bitron ch>
+ */
+
+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));
+	}
+}

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Sun Apr 20 18:50:28 2008
@@ -113,7 +113,7 @@
 	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 @@
 
 		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 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 @@
 		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 @@
 		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 @@
 		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);
 	}

Modified: trunk/gobject/valaccodegeneratorsourcefile.vala
==============================================================================
--- trunk/gobject/valaccodegeneratorsourcefile.vala	(original)
+++ trunk/gobject/valaccodegeneratorsourcefile.vala	Sun Apr 20 18:50:28 2008
@@ -251,7 +251,7 @@
 						}
 					} 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 ())));
 						}

Modified: trunk/gobject/valaccodeinterfacebinding.vala
==============================================================================
--- trunk/gobject/valaccodeinterfacebinding.vala	(original)
+++ trunk/gobject/valaccodeinterfacebinding.vala	Sun Apr 20 18:50:28 2008
@@ -51,7 +51,7 @@
 			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 @@
 
 		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);

Modified: trunk/gobject/valaccodeinvocationexpressionbinding.vala
==============================================================================
--- trunk/gobject/valaccodeinvocationexpressionbinding.vala	(original)
+++ trunk/gobject/valaccodeinvocationexpressionbinding.vala	Sun Apr 20 18:50:28 2008
@@ -122,111 +122,31 @@
 			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 @@
 		int arg_pos;
 		Iterator<FormalParameter> 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<CCodeExpression> extra_args = new ArrayList<CCodeExpression> ();
 			if (params_it.next ()) {
@@ -270,6 +181,9 @@
 							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 @@
 		}
 
 		/* 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 @@
 			}
 		}
 
-		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 @@
 		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 @@
 			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;
-	}
 }
 

Modified: trunk/gobject/valaccodemethodbinding.vala
==============================================================================
--- trunk/gobject/valaccodemethodbinding.vala	(original)
+++ trunk/gobject/valaccodemethodbinding.vala	Sun Apr 20 18:50:28 2008
@@ -188,76 +188,7 @@
 			}
 		}
 
-		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 void generate_cparameters (Method m, DataType creturn_type, Map<int,CCodeFormalParameter> 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);
 	}

Modified: trunk/vala/Makefile.am
==============================================================================
--- trunk/vala/Makefile.am	(original)
+++ trunk/vala/Makefile.am	Sun Apr 20 18:50:28 2008
@@ -26,7 +26,6 @@
 	valabaseaccess.vala \
 	valabasicblock.vala \
 	valabinaryexpression.vala \
-	valabindingprovider.vala \
 	valablock.vala \
 	valabooleanliteral.vala \
 	valabreakstatement.vala \
@@ -53,6 +52,8 @@
 	valadeletestatement.vala \
 	valadestructor.vala \
 	valadostatement.vala \
+	valadynamicmethod.vala \
+	valadynamicsignal.vala \
 	valaelementaccess.vala \
 	valaemptystatement.vala \
 	valaenum.vala \

Modified: trunk/vala/valaclasstype.vala
==============================================================================
--- trunk/vala/valaclasstype.vala	(original)
+++ trunk/vala/valaclasstype.vala	Sun Apr 20 18:50:28 2008
@@ -42,6 +42,7 @@
 		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 ()) {

Modified: trunk/vala/valacodecontext.vala
==============================================================================
--- trunk/vala/valacodecontext.vala	(original)
+++ trunk/vala/valacodecontext.vala	Sun Apr 20 18:50:28 2008
@@ -128,6 +128,8 @@
 
 	private Gee.List<string> defines = new ArrayList<string> (str_equal);
 
+	private Gee.List<Symbol> dynamic_members = new ArrayList<Symbol> ();
+
 	/**
 	 * The root namespace of the symbol tree.
 	 *
@@ -408,4 +410,8 @@
 
 		return null;
 	}
+
+	public void add_dynamic_member (Symbol dynamic_member) {
+		dynamic_members.add (dynamic_member);
+	}
 }

Modified: trunk/vala/valacodegenerator.vala
==============================================================================
--- trunk/vala/valacodegenerator.vala	(original)
+++ trunk/vala/valacodegenerator.vala	Sun Apr 20 18:50:28 2008
@@ -82,6 +82,10 @@
 		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 @@
 		return null;
 	}
 
+	public virtual CodeBinding? create_dynamic_signal_binding (DynamicSignal node) {
+		return null;
+	}
+
 	public virtual CodeBinding? create_constructor_binding (Constructor node) {
 		return null;
 	}

Modified: trunk/vala/valadatatype.vala
==============================================================================
--- trunk/vala/valadatatype.vala	(original)
+++ trunk/vala/valadatatype.vala	Sun Apr 20 18:50:28 2008
@@ -60,6 +60,11 @@
 	 */
 	public bool floating_reference { get; set; }
 
+	/**
+	 * Specifies that the type supports dynamic lookup.
+	 */
+	public bool is_dynamic { get; set; }
+
 	private Gee.List<DataType> type_argument_list = new ArrayList<DataType> ();
 
 	/**

Added: trunk/vala/valadynamicmethod.vala
==============================================================================
--- (empty file)
+++ trunk/vala/valadynamicmethod.vala	Sun Apr 20 18:50:28 2008
@@ -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 <j bitron ch>
+ */
+
+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<string> get_cheader_filenames () {
+		return new ReadOnlyCollection<string> ();
+	}
+
+	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);
+	}
+}

Added: trunk/vala/valadynamicsignal.vala
==============================================================================
--- (empty file)
+++ trunk/vala/valadynamicsignal.vala	Sun Apr 20 18:50:28 2008
@@ -0,0 +1,43 @@
+/* valadynamicsignal.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 <j bitron ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a late bound signal.
+ */
+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;
+	}
+
+	public override CodeBinding? create_code_binding (CodeGenerator codegen) {
+		return codegen.create_dynamic_signal_binding (this);
+	}
+}

Modified: trunk/vala/valainterface.vala
==============================================================================
--- trunk/vala/valainterface.vala	(original)
+++ trunk/vala/valainterface.vala	Sun Apr 20 18:50:28 2008
@@ -33,8 +33,6 @@
 	 */
 	public bool is_static { get; set; }
 
-	public bool declaration_only { get; set; }
-
 	private Gee.List<TypeParameter> type_parameters = new ArrayList<TypeParameter> ();
 	
 	private Gee.List<DataType> prerequisites = new ArrayList<DataType> ();
@@ -407,12 +405,6 @@
 		}
 	}
 
-	private void process_dbus_interface_attribute (Attribute a) {
-		if (declaration_only) {
-			cname = "DBusGProxy";
-		}
-	}
-
 	/**
 	 * Process all associated attributes.
 	 */
@@ -420,8 +412,6 @@
 		foreach (Attribute a in attributes) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
-			} else if (a.name == "DBusInterface") {
-				process_dbus_interface_attribute (a);
 			}
 		}
 	}

Modified: trunk/vala/valainterfacetype.vala
==============================================================================
--- trunk/vala/valainterfacetype.vala	(original)
+++ trunk/vala/valainterfacetype.vala	Sun Apr 20 18:50:28 2008
@@ -42,6 +42,7 @@
 		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 ()) {

Modified: trunk/vala/valamethod.vala
==============================================================================
--- trunk/vala/valamethod.vala	(original)
+++ trunk/vala/valamethod.vala	Sun Apr 20 18:50:28 2008
@@ -246,6 +246,18 @@
 		return new ReadOnlyCollection<FormalParameter> (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);
 	}

Modified: trunk/vala/valamethodtype.vala
==============================================================================
--- trunk/vala/valamethodtype.vala	(original)
+++ trunk/vala/valamethodtype.vala	Sun Apr 20 18:50:28 2008
@@ -62,4 +62,8 @@
 	public override string to_string () {
 		return method_symbol.get_full_name ();
 	}
+
+	public override string? get_cname (bool var_type, bool const_type) {
+		return "gpointer";
+	}
 }

Modified: trunk/vala/valaparser.vala
==============================================================================
--- trunk/vala/valaparser.vala	(original)
+++ trunk/vala/valaparser.vala	Sun Apr 20 18:50:28 2008
@@ -183,6 +183,7 @@
 		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 @@
 			}
 			return;
 		}
-		accept (TokenType.REF);
-		accept (TokenType.OUT);
+		accept (TokenType.DYNAMIC);
 		accept (TokenType.WEAK);
 		skip_symbol_name ();
 		skip_type_argument_list ();
@@ -343,6 +343,8 @@
 			return type;
 		}
 
+		bool is_dynamic = accept (TokenType.DYNAMIC);
+
 		bool is_weak = accept (TokenType.WEAK);
 
 		var sym = parse_symbol_name ();
@@ -383,6 +385,7 @@
 				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 @@
 			next ();
 			switch (current ()) {
 			case TokenType.VOID:
+			case TokenType.DYNAMIC:
 			case TokenType.WEAK:
 			case TokenType.IDENTIFIER:
 				var type = parse_type ();
@@ -2319,12 +2323,7 @@
 			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 @@
 			do {
 				switch (current ()) {
 				case TokenType.VOID:
+				case TokenType.DYNAMIC:
 				case TokenType.WEAK:
 				case TokenType.IDENTIFIER:
 					var type = parse_type ();

Modified: trunk/vala/valascanner.vala
==============================================================================
--- trunk/vala/valascanner.vala	(original)
+++ trunk/vala/valascanner.vala	Sun Apr 20 18:50:28 2008
@@ -239,7 +239,14 @@
 		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;

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Sun Apr 20 18:50:28 2008
@@ -59,15 +59,9 @@
 
 	private int next_lambda_id = 0;
 
-	private Collection<BindingProvider> binding_providers = new ArrayList<BindingProvider> ();
-
 	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 @@
 				// 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;

Modified: trunk/vala/valasymbolresolver.vala
==============================================================================
--- trunk/vala/valasymbolresolver.vala	(original)
+++ trunk/vala/valasymbolresolver.vala	Sun Apr 20 18:50:28 2008
@@ -268,6 +268,7 @@
 		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 @@
 			base_type.takes_ownership = false;
 			base_type.transfers_ownership = false;
 			base_type.nullable = false;
+			base_type.is_dynamic = false;
 
 			type = new PointerType (base_type);
 		}

Modified: trunk/vala/valatokentype.vala
==============================================================================
--- trunk/vala/valatokentype.vala	(original)
+++ trunk/vala/valatokentype.vala	Sun Apr 20 18:50:28 2008
@@ -59,6 +59,7 @@
 	DIV,
 	DO,
 	DOT,
+	DYNAMIC,
 	ELLIPSIS,
 	ELSE,
 	ENUM,

Modified: trunk/vala/valaunresolvedtype.vala
==============================================================================
--- trunk/vala/valaunresolvedtype.vala	(original)
+++ trunk/vala/valaunresolvedtype.vala	Sun Apr 20 18:50:28 2008
@@ -108,6 +108,7 @@
 		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;

Modified: trunk/vala/valavaluetype.vala
==============================================================================
--- trunk/vala/valavaluetype.vala	(original)
+++ trunk/vala/valavaluetype.vala	Sun Apr 20 18:50:28 2008
@@ -42,6 +42,7 @@
 		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 ()) {

Modified: trunk/vapi/dbus-glib-1.vapi
==============================================================================
--- trunk/vapi/dbus-glib-1.vapi	(original)
+++ trunk/vapi/dbus-glib-1.vapi	Sun Apr 20 18:50:28 2008
@@ -95,19 +95,20 @@
 
 	[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 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]