]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add support for properties in structs
authorJürg Billeter <j@bitron.ch>
Sat, 5 Sep 2009 16:16:07 +0000 (18:16 +0200)
committerJürg Billeter <j@bitron.ch>
Sat, 5 Sep 2009 17:29:09 +0000 (19:29 +0200)
codegen/valaccodebasemodule.vala
codegen/valaccodememberaccessmodule.vala
vala/valacodewriter.vala
vala/valaparser.vala
vala/valastruct.vala

index a5f628b99424ee7acdca17ae794100916099d811..f7019036306ce2e2d659870754cc575843015f62 100644 (file)
@@ -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) {
index b00230918b7203774499ab7dad32b7bfbc235a0e..d698a0317229d39b44558789bb869782e81b8f29 100644 (file)
@@ -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);
                                }
 
index dbc1cb8916edcd33b444006acdd669bfb7cfe306..164a25afde621d9d1a6dd3f22399efa4f223eadf 100644 (file)
@@ -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;
 
index 569bff4777b90c33d1128fa6c91b38617bb2bf0c..fa5bc3d1cb41528de44ff1d47663003dbd5d865d 100644 (file)
@@ -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");
                }
index e060d8c7966add65cef16463212da93b4017d871..17ed9ecbc78c1638505f7cfaaa8b6306a8e39ba7 100644 (file)
@@ -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;