[vala] Add support for properties in structs



commit 472db6e7c82ddc95fa0135652dc2481f9c53c6c4
Author: Jürg Billeter <j bitron ch>
Date:   Sat Sep 5 18:16:07 2009 +0200

    Add support for properties in structs

 codegen/valaccodebasemodule.vala         |   40 ++++++++++++++++++++++++++---
 codegen/valaccodememberaccessmodule.vala |   22 ++++++++++++++++
 vala/valacodewriter.vala                 |    1 +
 vala/valaparser.vala                     |    2 +
 vala/valastruct.vala                     |   35 ++++++++++++++++++++++++++
 5 files changed, 95 insertions(+), 5 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index a5f628b..f701903 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1250,10 +1250,13 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 
 		if (prop.binding == MemberBinding.INSTANCE) {
-			var t = (ObjectTypeSymbol) prop.parent_symbol;
-			var this_type = new ObjectType (t);
+			var t = (TypeSymbol) prop.parent_symbol;
+			var this_type = get_data_type_for_symbol (t);
 			generate_type_declaration (this_type, decl_space);
 			var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
+			if (t is Struct) {
+				cselfparam.type_name += "*";
+			}
 
 			function.add_parameter (cselfparam);
 		}
@@ -1295,7 +1298,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		acc.accept_children (codegen);
 
-		var t = (ObjectTypeSymbol) prop.parent_symbol;
+		var t = (TypeSymbol) prop.parent_symbol;
 
 		if (acc.construction && !t.is_subtype_of (gobject_type)) {
 			Report.error (acc.source_reference, "construct properties require GLib.Object");
@@ -1319,8 +1322,11 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			}
 		}
 
-		var this_type = new ObjectType (t);
+		var this_type = get_data_type_for_symbol (t);
 		var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
+		if (t is Struct) {
+			cselfparam.type_name += "*";
+		}
 		CCodeFormalParameter cvalueparam;
 		if (returns_real_struct) {
 			cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname () + "*");
@@ -3966,7 +3972,31 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		if (prop.binding == MemberBinding.INSTANCE) {
 			/* target instance is first argument */
-			ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
+			var instance = (CCodeExpression) get_ccodenode (ma.inner);
+
+			if (prop.parent_symbol is Struct) {
+				// we need to pass struct instance by reference
+				var unary = instance as CCodeUnaryExpression;
+				if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
+					// *expr => expr
+					instance = unary.inner;
+				} else if (instance is CCodeIdentifier || instance is CCodeMemberAccess) {
+					instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance);
+				} else {
+					// if instance is e.g. a function call, we can't take the address of the expression
+					// (tmp = expr, &tmp)
+					var ccomma = new CCodeCommaExpression ();
+
+					var temp_var = get_temp_variable (ma.inner.target_type);
+					temp_vars.insert (0, temp_var);
+					ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance));
+					ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
+
+					instance = ccomma;
+				}
+			}
+
+			ccall.add_argument (instance);
 		}
 
 		if (prop.no_accessor_method) {
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index b002309..d698a03 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -244,6 +244,28 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 				var ccall = new CCodeFunctionCall (new CCodeIdentifier (getter_cname));
 
 				if (prop.binding == MemberBinding.INSTANCE) {
+					if (prop.parent_symbol is Struct) {
+						// we need to pass struct instance by reference
+						var unary = pub_inst as CCodeUnaryExpression;
+						if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
+							// *expr => expr
+							pub_inst = unary.inner;
+						} else if (pub_inst is CCodeIdentifier || pub_inst is CCodeMemberAccess) {
+							pub_inst = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, pub_inst);
+						} else {
+							// if instance is e.g. a function call, we can't take the address of the expression
+							// (tmp = expr, &tmp)
+							var ccomma = new CCodeCommaExpression ();
+
+							var temp_var = get_temp_variable (expr.inner.target_type);
+							temp_vars.insert (0, temp_var);
+							ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), pub_inst));
+							ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
+
+							pub_inst = ccomma;
+						}
+					}
+
 					ccall.add_argument (pub_inst);
 				}
 
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index dbc1cb8..164a25a 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -362,6 +362,7 @@ public class Vala.CodeWriter : CodeVisitor {
 		}
 		visit_sorted (st.get_constants ());
 		visit_sorted (st.get_methods ());
+		visit_sorted (st.get_properties ());
 
 		current_scope = current_scope.parent_scope;
 
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 569bff4..fa5bc3d 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -2517,6 +2517,8 @@ public class Vala.Parser : CodeVisitor {
 			st.add_field ((Field) sym);
 		} else if (sym is Constant) {
 			st.add_constant ((Constant) sym);
+		} else if (sym is Property) {
+			st.add_property ((Property) sym);
 		} else {
 			Report.error (sym.source_reference, "unexpected declaration in struct");
 		}
diff --git a/vala/valastruct.vala b/vala/valastruct.vala
index e060d8c..17ed9ec 100644
--- a/vala/valastruct.vala
+++ b/vala/valastruct.vala
@@ -31,6 +31,7 @@ public class Vala.Struct : TypeSymbol {
 	private Gee.List<Constant> constants = new ArrayList<Constant> ();
 	private Gee.List<Field> fields = new ArrayList<Field> ();
 	private Gee.List<Method> methods = new ArrayList<Method> ();
+	private Gee.List<Property> properties = new ArrayList<Property> ();
 	private DataType _base_type = null;
 
 	private string cname;
@@ -210,6 +211,32 @@ public class Vala.Struct : TypeSymbol {
 		return new ReadOnlyList<Method> (methods);
 	}
 
+	/**
+	 * Adds the specified property as a member to this struct.
+	 *
+	 * @param prop a property
+	 */
+	public void add_property (Property prop) {
+		properties.add (prop);
+		scope.add (prop.name, prop);
+
+		prop.this_parameter = new FormalParameter ("this", SemanticAnalyzer.get_data_type_for_symbol (this));
+		prop.scope.add (prop.this_parameter.name, prop.this_parameter);
+
+		if (prop.field != null) {
+			add_field (prop.field);
+		}
+	}
+
+	/**
+	 * Returns a copy of the list of properties.
+	 *
+	 * @return list of properties
+	 */
+	public Gee.List<Property> get_properties () {
+		return new ReadOnlyList<Property> (properties);
+	}
+
 	public override void accept (CodeVisitor visitor) {
 		visitor.visit_struct (this);
 	}
@@ -234,6 +261,10 @@ public class Vala.Struct : TypeSymbol {
 		foreach (Method m in methods) {
 			m.accept (visitor);
 		}
+
+		foreach (Property prop in properties) {
+			prop.accept (visitor);
+		}
 	}
 
 	public override string get_cname (bool const_type = false) {
@@ -758,6 +789,10 @@ public class Vala.Struct : TypeSymbol {
 			m.check (analyzer);
 		}
 
+		foreach (Property prop in properties) {
+			prop.check (analyzer);
+		}
+
 		if (!external && !external_package && base_type == null && get_fields ().size == 0
 		    && !is_boolean_type () && !is_integer_type () && !is_floating_type ()) {
 			error = true;



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