vala r1398 - in trunk: . gobject vala



Author: juergbi
Date: Sun May 18 16:57:27 2008
New Revision: 1398
URL: http://svn.gnome.org/viewvc/vala?rev=1398&view=rev

Log:
2008-05-18  Juerg Billeter  <j bitron ch>

	* vala/Makefile.am:
	* vala/valacodegenerator.vala:
	* vala/valadynamicproperty.vala:
	* vala/valasemanticanalyzer.vala:
	* gobject/Makefile.am:
	* gobject/valaccodedynamicmethodbinding.vala:
	* gobject/valaccodedynamicpropertybinding.vala:
	* gobject/valaccodegenerator.vala:
	* gobject/valaccodememberaccessbinding.vala:

	Add support for dynamic properties


Added:
   trunk/gobject/valaccodedynamicpropertybinding.vala
   trunk/vala/valadynamicproperty.vala
Modified:
   trunk/ChangeLog
   trunk/gobject/Makefile.am
   trunk/gobject/valaccodedynamicmethodbinding.vala
   trunk/gobject/valaccodegenerator.vala
   trunk/gobject/valaccodememberaccessbinding.vala
   trunk/vala/Makefile.am
   trunk/vala/valacodegenerator.vala
   trunk/vala/valasemanticanalyzer.vala

Modified: trunk/gobject/Makefile.am
==============================================================================
--- trunk/gobject/Makefile.am	(original)
+++ trunk/gobject/Makefile.am	Sun May 18 16:57:27 2008
@@ -19,6 +19,7 @@
 	valaccodecompiler.vala \
 	valaccodecreationmethodbinding.vala \
 	valaccodedynamicmethodbinding.vala \
+	valaccodedynamicpropertybinding.vala \
 	valaccodedynamicsignalbinding.vala \
 	valaccodeelementaccessbinding.vala \
 	valaccodeexpressionbinding.vala \

Modified: trunk/gobject/valaccodedynamicmethodbinding.vala
==============================================================================
--- trunk/gobject/valaccodedynamicmethodbinding.vala	(original)
+++ trunk/gobject/valaccodedynamicmethodbinding.vala	Sun May 18 16:57:27 2008
@@ -39,7 +39,7 @@
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
-		var instance_param = new CCodeFormalParameter ("obj", "gpointer");
+		var instance_param = new CCodeFormalParameter ("obj", dynamic_method.dynamic_type.get_cname ());
 		cparam_map.set (codegen.get_param_pos (method.cinstance_parameter_position), instance_param);
 
 		generate_cparameters (method, method.return_type, cparam_map, func);

Added: trunk/gobject/valaccodedynamicpropertybinding.vala
==============================================================================
--- (empty file)
+++ trunk/gobject/valaccodedynamicpropertybinding.vala	Sun May 18 16:57:27 2008
@@ -0,0 +1,92 @@
+/* valaccodedynamicpropertybinding.vala
+ *
+ * Copyright (C) 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 property and generated code.
+ */
+public class Vala.CCodeDynamicPropertyBinding : CCodeBinding {
+	public Property node { get; set; }
+
+	string? getter_cname;
+	string? setter_cname;
+
+	static int dynamic_property_id;
+
+	public CCodeDynamicPropertyBinding (CCodeGenerator codegen, DynamicProperty property) {
+		this.node = property;
+		this.codegen = codegen;
+	}
+
+	public string get_getter_cname () {
+		if (getter_cname != null) {
+			return getter_cname;
+		}
+
+		getter_cname = "_dynamic_get_%s%d".printf (node.name, dynamic_property_id++);
+
+		var dynamic_property = (DynamicProperty) node;
+
+		var func = new CCodeFunction (getter_cname, node.property_type.get_cname ());
+
+		func.add_parameter (new CCodeFormalParameter ("obj", dynamic_property.dynamic_type.get_cname ()));
+
+		var block = new CCodeBlock ();
+		Report.error (node.source_reference, "dynamic properties are not supported for `%s'".printf (dynamic_property.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 getter_cname;
+	}
+
+	public string get_setter_cname () {
+		if (setter_cname != null) {
+			return setter_cname;
+		}
+
+		getter_cname = "_dynamic_set_%s%d".printf (node.name, dynamic_property_id++);
+
+		var dynamic_property = (DynamicProperty) node;
+
+		var func = new CCodeFunction (getter_cname, "void");
+
+		func.add_parameter (new CCodeFormalParameter ("obj", dynamic_property.dynamic_type.get_cname ()));
+		func.add_parameter (new CCodeFormalParameter ("value", node.property_type.get_cname ()));
+
+		var block = new CCodeBlock ();
+		Report.error (node.source_reference, "dynamic properties are not supported for `%s'".printf (dynamic_property.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 getter_cname;
+	}
+}

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Sun May 18 16:57:27 2008
@@ -3629,6 +3629,9 @@
 			}
 			var base_property_type = (Typesymbol) base_property.parent_symbol;
 			set_func = "%s_set_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name);
+			if (prop is DynamicProperty) {
+				set_func = dynamic_property_binding ((DynamicProperty) prop).get_setter_cname ();
+			}
 		}
 		
 		var ccall = new CCodeFunctionCall (new CCodeIdentifier (set_func));
@@ -3875,6 +3878,10 @@
 		return null;
 	}
 
+	public override CodeBinding? create_dynamic_property_binding (DynamicProperty node) {
+		return new CCodeDynamicPropertyBinding (this, node);
+	}
+
 	public override CodeBinding? create_property_accessor_binding (PropertyAccessor node) {
 		return null;
 	}
@@ -4103,6 +4110,10 @@
 		return (CCodeDynamicMethodBinding) node.get_code_binding (this);
 	}
 
+	public CCodeDynamicPropertyBinding dynamic_property_binding (DynamicProperty node) {
+		return (CCodeDynamicPropertyBinding) node.get_code_binding (this);
+	}
+
 	public CCodeDynamicSignalBinding dynamic_signal_binding (DynamicSignal node) {
 		return (CCodeDynamicSignalBinding) node.get_code_binding (this);
 	}

Modified: trunk/gobject/valaccodememberaccessbinding.vala
==============================================================================
--- trunk/gobject/valaccodememberaccessbinding.vala	(original)
+++ trunk/gobject/valaccodememberaccessbinding.vala	Sun May 18 16:57:27 2008
@@ -131,7 +131,13 @@
 					base_property = prop.base_interface_property;
 				}
 				var base_property_type = (Typesymbol) base_property.parent_symbol;
-				var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name)));
+				string getter_cname;
+				if (prop is DynamicProperty) {
+					getter_cname = codegen.dynamic_property_binding ((DynamicProperty) prop).get_getter_cname ();
+				} else {
+					getter_cname = "%s_get_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name);
+				}
+				var ccall = new CCodeFunctionCall (new CCodeIdentifier (getter_cname));
 
 				var instance_expression_type = base_type;
 				var instance_target_type = codegen.get_data_type_for_symbol (base_property_type);

Modified: trunk/vala/Makefile.am
==============================================================================
--- trunk/vala/Makefile.am	(original)
+++ trunk/vala/Makefile.am	Sun May 18 16:57:27 2008
@@ -54,6 +54,7 @@
 	valadestructor.vala \
 	valadostatement.vala \
 	valadynamicmethod.vala \
+	valadynamicproperty.vala \
 	valadynamicsignal.vala \
 	valaelementaccess.vala \
 	valaemptystatement.vala \

Modified: trunk/vala/valacodegenerator.vala
==============================================================================
--- trunk/vala/valacodegenerator.vala	(original)
+++ trunk/vala/valacodegenerator.vala	Sun May 18 16:57:27 2008
@@ -98,6 +98,10 @@
 		return null;
 	}
 
+	public virtual CodeBinding? create_dynamic_property_binding (DynamicProperty node) {
+		return null;
+	}
+
 	public virtual CodeBinding? create_property_accessor_binding (PropertyAccessor node) {
 		return null;
 	}

Added: trunk/vala/valadynamicproperty.vala
==============================================================================
--- (empty file)
+++ trunk/vala/valadynamicproperty.vala	Sun May 18 16:57:27 2008
@@ -0,0 +1,47 @@
+/* valadynamicproperty.vala
+ *
+ * Copyright (C) 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 property.
+ */
+public class Vala.DynamicProperty : Property {
+	public DataType dynamic_type { get; set; }
+
+	private string cname;
+
+	public DynamicProperty (DataType dynamic_type, string name, SourceReference? source_reference = null) {
+		this.dynamic_type = dynamic_type;
+		this.name = name;
+		this.source_reference = source_reference;
+	}
+
+	public override Collection<string> get_cheader_filenames () {
+		return new ReadOnlyCollection<string> ();
+	}
+
+	public override CodeBinding? create_code_binding (CodeGenerator codegen) {
+		return codegen.create_dynamic_property_binding (this);
+	}
+}

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Sun May 18 16:57:27 2008
@@ -1380,9 +1380,11 @@
 			return c.type_reference;
 		} else if (sym is Property) {
 			var prop = (Property) sym;
-			var type = prop.property_type.copy ();
-			type.value_owned = false;
-			return type;
+			if (prop.property_type != null) {
+				var type = prop.property_type.copy ();
+				type.value_owned = false;
+				return type;
+			}
 		} else if (sym is FormalParameter) {
 			var p = (FormalParameter) sym;
 			var type = p.parameter_type.copy ();
@@ -1587,31 +1589,64 @@
 				// 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.value_owned = true;
-					} else {
-						ret_type = new VoidType ();
+					if (invoc.call == expr) {
+						// dynamic method
+						DataType ret_type;
+						if (invoc.expected_type != null) {
+							ret_type = invoc.expected_type.copy ();
+							ret_type.value_owned = true;
+						} else if (invoc.parent_node is ExpressionStatement) {
+							ret_type = new VoidType ();
+						} else {
+							// expect dynamic object of the same type
+							ret_type = expr.inner.value_type.copy ();
+						}
+						var m = new DynamicMethod (expr.inner.value_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;
 					}
-					var m = new DynamicMethod (expr.inner.value_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)) {
+						// dynamic signal
 						var s = new DynamicSignal (expr.inner.value_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;
+					} else if (a.left == expr) {
+						// dynamic property assignment
+						var prop = new DynamicProperty (expr.inner.value_type, expr.member_name, expr.source_reference);
+						prop.access = SymbolAccessibility.PUBLIC;
+						prop.set_accessor = new PropertyAccessor (false, true, false, null, null);
+						prop.set_accessor.access = SymbolAccessibility.PUBLIC;
+						prop.owner = expr.inner.value_type.data_type.scope;
+						context.add_dynamic_member (prop);
+						expr.symbol_reference = prop;
+					}
+				}
+				if (expr.symbol_reference == null) {
+					// dynamic property read access
+					var prop = new DynamicProperty (expr.inner.value_type, expr.member_name, expr.source_reference);
+					if (expr.expected_type != null) {
+						prop.property_type = expr.expected_type;
+					} else {
+						// expect dynamic object of the same type
+						prop.property_type = expr.inner.value_type.copy ();
 					}
+					prop.access = SymbolAccessibility.PUBLIC;
+					prop.get_accessor = new PropertyAccessor (true, false, false, null, null);
+					prop.get_accessor.access = SymbolAccessibility.PUBLIC;
+					prop.owner = expr.inner.value_type.data_type.scope;
+					// maybe better move add_dynamic_member to Symbol class
+					context.add_dynamic_member (prop);
+					expr.symbol_reference = prop;
 				}
 				if (expr.symbol_reference != null) {
 					may_access_instance_members = true;
@@ -2970,7 +3005,7 @@
 		if (a.left is MemberAccess) {
 			var ma = (MemberAccess) a.left;
 
-			if (!(ma.symbol_reference is Signal) && ma.value_type == null) {
+			if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
 				a.error = true;
 				Report.error (a.source_reference, "unsupported lvalue in assignment");
 				return;
@@ -3069,6 +3104,12 @@
 			} else if (ma.symbol_reference is Property) {
 				var prop = (Property) ma.symbol_reference;
 
+				var dynamic_prop = prop as DynamicProperty;
+				if (dynamic_prop != null) {
+					dynamic_prop.property_type = a.right.value_type.copy ();
+					a.left.value_type = dynamic_prop.property_type.copy ();
+				}
+
 				if (prop.set_accessor == null
 				    || (!prop.set_accessor.writable && !(find_current_method () is CreationMethod || is_in_constructor ()))) {
 					ma.error = true;



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