vala r837 - in trunk: . gobject tests vala



Author: juergbi
Date: Mon Jan 14 20:47:21 2008
New Revision: 837
URL: http://svn.gnome.org/viewvc/vala?rev=837&view=rev

Log:
2008-01-14  Juerg Billeter  <j bitron ch>

	* vala/parser.y, vala/valainvocationexpression.vala,
	  gobject/valaccodegenerator.vala,
	  gobject/valaccodegeneratorinvocationexpression.vala,
	  gobject/valaccodegeneratormethod.vala: add support for instance
	  delegates, fixes bug 508734

	* tests/delegates.exp, tests/delegates.vala: test instance delegates


Modified:
   trunk/ChangeLog
   trunk/gobject/valaccodegenerator.vala
   trunk/gobject/valaccodegeneratorinvocationexpression.vala
   trunk/gobject/valaccodegeneratormethod.vala
   trunk/tests/delegates.exp
   trunk/tests/delegates.vala
   trunk/vala/parser.y
   trunk/vala/valainvocationexpression.vala

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Mon Jan 14 20:47:21 2008
@@ -298,17 +298,21 @@
 		}
 	}
 
-	public override void visit_delegate (Delegate! cb) {
-		cb.accept_children (this);
+	public override void visit_delegate (Delegate! d) {
+		d.accept_children (this);
 
-		var cfundecl = new CCodeFunctionDeclarator (cb.get_cname ());
-		foreach (FormalParameter param in cb.get_parameters ()) {
+		var cfundecl = new CCodeFunctionDeclarator (d.get_cname ());
+		foreach (FormalParameter param in d.get_parameters ()) {
 			cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode);
 		}
-		
-		var ctypedef = new CCodeTypeDefinition (cb.return_type.get_cname (), cfundecl);
-		
-		if (!cb.is_internal_symbol ()) {
+		if (d.instance) {
+			var cparam = new CCodeFormalParameter ("user_data", "void*");
+			cfundecl.add_parameter (cparam);
+		}
+
+		var ctypedef = new CCodeTypeDefinition (d.return_type.get_cname (), cfundecl);
+
+		if (!d.is_internal_symbol ()) {
 			header_type_definition.append (ctypedef);
 		} else {
 			source_type_member_declaration.append (ctypedef);
@@ -876,6 +880,16 @@
 
 				temp_vars.insert (0, len_decl);
 			}
+		} else if (decl.type_reference is DelegateType) {
+			var deleg_type = (DelegateType) decl.type_reference;
+			var d = deleg_type.delegate_symbol;
+			if (d.instance) {
+				// create variable to store delegate target
+				var target_decl = new VariableDeclarator (get_delegate_target_cname (decl.name));
+				target_decl.type_reference = new PointerType (new VoidType ());
+
+				temp_vars.insert (0, target_decl);
+			}
 		}
 	
 		CCodeExpression rhs = null;
@@ -901,6 +915,24 @@
 				ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
 				
 				rhs = ccomma;
+			} else if (decl.type_reference is DelegateType) {
+				var deleg_type = (DelegateType) decl.type_reference;
+				var d = deleg_type.delegate_symbol;
+				if (d.instance) {
+					var ccomma = new CCodeCommaExpression ();
+
+					var temp_decl = get_temp_variable_declarator (decl.type_reference, true, decl);
+					temp_vars.insert (0, temp_decl);
+					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
+
+					var lhs_delegate_target = new CCodeIdentifier (get_delegate_target_cname (decl.name));
+					var rhs_delegate_target = get_delegate_target_cexpression (decl.initializer);
+					ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
+				
+					ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
+				
+					rhs = ccomma;
+				}
 			}
 		} else if (decl.type_reference.data_type != null && decl.type_reference.data_type.is_reference_type ()) {
 			rhs = new CCodeConstant ("NULL");
@@ -2034,6 +2066,10 @@
 
 		visit_expression (expr);
 	}
+	
+	private string! get_array_length_cname (string! array_cname, int dim) {
+		return "%s_length%d".printf (array_cname, dim);
+	}
 
 	public CCodeExpression! get_array_length_cexpression (Expression! array_expr, int dim) {
 		bool is_out = false;
@@ -2150,6 +2186,115 @@
 			return new CCodeConstant ("NULL");
 		}
 	}
+	
+	private string! get_delegate_target_cname (string! delegate_cname) {
+		return "%s_target".printf (delegate_cname);
+	}
+
+	public CCodeExpression! get_delegate_target_cexpression (Expression! delegate_expr) {
+		bool is_out = false;
+	
+		if (delegate_expr is UnaryExpression) {
+			var unary_expr = (UnaryExpression) delegate_expr;
+			if (unary_expr.operator == UnaryOperator.OUT || unary_expr.operator == UnaryOperator.REF) {
+				delegate_expr = unary_expr.inner;
+				is_out = true;
+			}
+		}
+		
+		if (delegate_expr is InvocationExpression) {
+			var invocation_expr = (InvocationExpression) delegate_expr;
+			return invocation_expr.delegate_target;
+		} else if (delegate_expr.symbol_reference != null) {
+			if (delegate_expr.symbol_reference is FormalParameter) {
+				var param = (FormalParameter) delegate_expr.symbol_reference;
+				CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (param.name));
+				if (param.type_reference.is_out || param.type_reference.is_ref) {
+					// accessing argument of out/ref param
+					target_expr = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr));
+				}
+				if (is_out) {
+					// passing array as out/ref
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+				} else {
+					return target_expr;
+				}
+			} else if (delegate_expr.symbol_reference is VariableDeclarator) {
+				var decl = (VariableDeclarator) delegate_expr.symbol_reference;
+				var target_expr = new CCodeIdentifier (get_delegate_target_cname (decl.name));
+				if (is_out) {
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+				} else {
+					return target_expr;
+				}
+			} else if (delegate_expr.symbol_reference is Field) {
+				var field = (Field) delegate_expr.symbol_reference;
+				var target_cname = get_delegate_target_cname (field.name);
+
+				var ma = (MemberAccess) delegate_expr;
+
+				CCodeExpression pub_inst = null;
+				Typesymbol base_type = null;
+				CCodeExpression target_expr = null;
+			
+				if (ma.inner == null) {
+					pub_inst = new CCodeIdentifier ("self");
+
+					if (current_type_symbol != null) {
+						/* base type is available if this is a type method */
+						base_type = (Typesymbol) current_type_symbol;
+					}
+				} else {
+					pub_inst = (CCodeExpression) ma.inner.ccodenode;
+
+					if (ma.inner.static_type != null) {
+						base_type = ma.inner.static_type.data_type;
+					}
+				}
+
+				if (field.instance) {
+					var instance_expression_type = new DataType ();
+					instance_expression_type.data_type = base_type;
+					var instance_target_type = new DataType ();
+					instance_target_type.data_type = (Typesymbol) field.parent_symbol;
+					CCodeExpression typed_inst = get_implicit_cast_expression (pub_inst, instance_expression_type, instance_target_type);
+
+					CCodeExpression inst;
+					if (field.access == SymbolAccessibility.PRIVATE) {
+						inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
+					} else {
+						inst = typed_inst;
+					}
+					if (((Typesymbol) field.parent_symbol).is_reference_type ()) {
+						target_expr = new CCodeMemberAccess.pointer (inst, target_cname);
+					} else {
+						target_expr = new CCodeMemberAccess (inst, target_cname);
+					}
+				} else {
+					target_expr = new CCodeIdentifier (target_cname);
+				}
+
+				if (is_out) {
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+				} else {
+					return target_expr;
+				}
+			} else if (delegate_expr.symbol_reference is Method) {
+				var ma = (MemberAccess) delegate_expr;
+				if (ma.inner == null) {
+					if (current_method != null && current_method.instance) {
+						return new CCodeIdentifier ("self");
+					} else {
+						return new CCodeConstant ("NULL");
+					}
+				} else {
+					return (CCodeExpression) ma.inner.ccodenode;
+				}
+			}
+		}
+
+		return new CCodeConstant ("NULL");
+	}
 
 	public override void visit_element_access (ElementAccess! expr) {
 		expr.code_binding.emit ();

Modified: trunk/gobject/valaccodegeneratorinvocationexpression.vala
==============================================================================
--- trunk/gobject/valaccodegeneratorinvocationexpression.vala	(original)
+++ trunk/gobject/valaccodegeneratorinvocationexpression.vala	Mon Jan 14 20:47:21 2008
@@ -221,6 +221,7 @@
 			}
 
 			CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
+			Gee.List<CCodeExpression> extra_args = new ArrayList<CCodeExpression> ();
 			if (params_it.next ()) {
 				var param = params_it.get ();
 				ellipsis = param.ellipsis;
@@ -233,6 +234,12 @@
 							for (int dim = 1; dim <= arr.rank; dim++) {
 								ccall.add_argument (get_array_length_cexpression (arg, dim));
 							}
+						} else if (param.type_reference is DelegateType) {
+							var deleg_type = (DelegateType) param.type_reference;
+							var d = deleg_type.delegate_symbol;
+							if (d.instance) {
+								extra_args.add (get_delegate_target_cexpression (arg));
+							}
 						}
 						cexpr = get_implicit_cast_expression (cexpr, arg.static_type, param.type_reference);
 
@@ -287,6 +294,11 @@
 			}
 					
 			ccall.add_argument (cexpr);
+
+			foreach (CCodeExpression extra_arg in extra_args) {
+				ccall.add_argument (extra_arg);
+			}
+
 			i++;
 		}
 		while (params_it.next ()) {
@@ -341,6 +353,19 @@
 					expr.append_array_size (new CCodeConstant ("-1"));
 				}
 			}
+		} else if (m != null && m.return_type is DelegateType) {
+			var deleg_type = (DelegateType) m.return_type;
+			var d = deleg_type.delegate_symbol;
+			if (d.instance) {
+				var temp_decl = get_temp_variable_declarator (new PointerType (new VoidType ()));
+				var temp_ref = new CCodeIdentifier (temp_decl.name);
+
+				temp_vars.insert (0, temp_decl);
+
+				ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+				expr.delegate_target = temp_ref;
+			}
 		}
 
 		if (connection_type != null && ma.inner != null && ma.inner.static_type != null && ma.inner.static_type.data_type == connection_type && m.name == "get_object") {
@@ -365,6 +390,12 @@
 			if ((m == null || !m.printf_format) && !(m is DBusMethod)) {
 				ccall.add_argument (new CCodeConstant (m.sentinel));
 			}
+		} else if (itype is DelegateType) {
+			var deleg_type = (DelegateType) itype;
+			var d = deleg_type.delegate_symbol;
+			if (d.instance) {
+				ccall.add_argument (get_delegate_target_cexpression (expr.call));
+			}
 		}
 		
 		if (m != null && m.instance && m.returns_modified_pointer) {

Modified: trunk/gobject/valaccodegeneratormethod.vala
==============================================================================
--- trunk/gobject/valaccodegeneratormethod.vala	(original)
+++ trunk/gobject/valaccodegeneratormethod.vala	Mon Jan 14 20:47:21 2008
@@ -197,10 +197,22 @@
 			if (vdeclarator != null) {
 				vdeclarator.add_parameter ((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 (get_delegate_target_cname (param.name), "void*");
+					function.add_parameter (cparam);
+					if (vdeclarator != null) {
+						vdeclarator.add_parameter (cparam);
+					}
+				}
+			}
 		}
 
-		// return array length if appropriate
 		if (!m.no_array_length && creturn_type.data_type is Array) {
+			// return array length if appropriate
 			var arr = (Array) creturn_type.data_type;
 
 			for (int dim = 1; dim <= arr.rank; dim++) {
@@ -210,6 +222,17 @@
 					vdeclarator.add_parameter (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 (get_delegate_target_cname ("result"), "void*");
+				function.add_parameter (cparam);
+				if (vdeclarator != null) {
+					vdeclarator.add_parameter (cparam);
+				}
+			}
 		}
 
 		if (m.instance && m.instance_last) {
@@ -627,10 +650,6 @@
 		}
 		return null;
 	}
-	
-	private string! get_array_length_cname (string! array_cname, int dim) {
-		return "%s_length%d".printf (array_cname, dim);
-	}
 
 	public override void visit_creation_method (CreationMethod! m) {
 		if (m.body != null && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {

Modified: trunk/tests/delegates.exp
==============================================================================
--- trunk/tests/delegates.exp	(original)
+++ trunk/tests/delegates.exp	Mon Jan 14 20:47:21 2008
@@ -1 +1 @@
-Delegate Test: 1 2 3 4 5
+Delegate Test: 1 2 3 4 5 6 7

Modified: trunk/tests/delegates.vala
==============================================================================
--- trunk/tests/delegates.vala	(original)
+++ trunk/tests/delegates.vala	Mon Jan 14 20:47:21 2008
@@ -4,7 +4,12 @@
 
 public static delegate int Maman.ActionCallback ();
 
+public delegate void Maman.InstanceCallback ();
+
 class Maman.Bar : Object {
+	public Bar () {
+	}
+
 	static void do_void_action () {
 		stdout.printf (" 2");
 	}
@@ -13,6 +18,14 @@
 		return 4;
 	}
 
+	void do_instance_action () {
+		stdout.printf (" 6");
+	}
+
+	static void call_instance_delegate (InstanceCallback instance_cb) {
+		instance_cb ();
+	}
+
 	static int main (string[] args) {
 		stdout.printf ("Delegate Test: 1");
 		
@@ -25,9 +38,16 @@
 		ActionCallback cb = do_action;
 		
 		stdout.printf (" %d", cb ());
-		
-		stdout.printf (" 5\n");
-		
+
+		stdout.printf (" 5");
+
+		var bar = new Bar ();
+
+		InstanceCallback instance_cb = bar.do_instance_action;
+		call_instance_delegate (instance_cb);
+
+		stdout.printf (" 7\n");
+
 		return 0;
 	}
 }

Modified: trunk/vala/parser.y
==============================================================================
--- trunk/vala/parser.y	(original)
+++ trunk/vala/parser.y	Mon Jan 14 20:47:21 2008
@@ -3797,7 +3797,10 @@
 			vala_symbol_set_access (VALA_SYMBOL (cb), $3);
 		}
 		VALA_CODE_NODE (cb)->attributes = $2;
-		
+		if (($4 & VALA_MODIFIER_STATIC) == 0) {
+			vala_delegate_set_instance (cb, TRUE);
+		}
+
 		if ($9 != NULL) {
 			for (l = $9; l != NULL; l = l->next) {
 				vala_delegate_add_type_parameter (cb, l->data);

Modified: trunk/vala/valainvocationexpression.vala
==============================================================================
--- trunk/vala/valainvocationexpression.vala	(original)
+++ trunk/vala/valainvocationexpression.vala	Mon Jan 14 20:47:21 2008
@@ -1,6 +1,6 @@
 /* valainvocationexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-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
@@ -38,6 +38,8 @@
 		}
 	}
 
+	public CCodeExpression delegate_target { get; set; }
+
 	public Expression! _call;
 	
 	private Gee.List<Expression> argument_list = new ArrayList<Expression> ();



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