]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
free array elements
authorJuerg Billeter <j@bitron.ch>
Thu, 26 Jul 2007 14:24:22 +0000 (14:24 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 26 Jul 2007 14:24:22 +0000 (14:24 +0000)
2007-07-26  Juerg Billeter  <j@bitron.ch>

* gobject/valacodegenerator.vala,
  gobject/valacodegeneratorassignment.vala,
  gobject/valacodegeneratorsourcefile.vala: free array elements

svn path=/trunk/; revision=391

ChangeLog
gobject/valacodegenerator.vala
gobject/valacodegeneratorassignment.vala
gobject/valacodegeneratorsourcefile.vala

index ba958a93bfe24ad82a0f4991d1db2bce51b5513d..c22a4e7598e5fa5d947b72bc80d43c2d13f136f0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2007-07-26  Jürg Billeter  <j@bitron.ch>
+
+       * gobject/valacodegenerator.vala,
+         gobject/valacodegeneratorassignment.vala,
+         gobject/valacodegeneratorsourcefile.vala: free array elements
+
 2007-07-26  Jürg Billeter  <j@bitron.ch>
 
        * vala/valamemorymanager.vala, vala/valasemanticanalyzer.vala,
index 812ddd3611f92a84231e06bbf38632bc455abd0f..431df52075676a43c55791e718484631230c2562 100644 (file)
@@ -97,6 +97,7 @@ public class Vala.CodeGenerator : CodeVisitor {
        TypeReference double_type;
        DataType glist_type;
        DataType gslist_type;
+       DataType gstring_type;
        TypeReference mutex_type;
        DataType type_module_type;
        DataType iterable_type;
@@ -110,6 +111,8 @@ public class Vala.CodeGenerator : CodeVisitor {
        private string module_init_param_name;
        
        private bool string_h_needed;
+       private bool requires_free_checked;
+       private bool requires_array_free;
 
        public CodeGenerator (bool manage_memory = true) {
                memory_management = manage_memory;
@@ -240,6 +243,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                
                glist_type = (DataType) glib_ns.scope.lookup ("List");
                gslist_type = (DataType) glib_ns.scope.lookup ("SList");
+               gstring_type = (DataType) glib_ns.scope.lookup ("String");
                
                mutex_type = new TypeReference ();
                mutex_type.data_type = (DataType) glib_ns.scope.lookup ("Mutex");
@@ -346,6 +350,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                                                        get_symbol_lock_name (m)),
                                        new CCodeFunctionCall (new CCodeIdentifier (((Struct)mutex_type.data_type).default_construction_method.get_cname ())))));
                        
+                       requires_free_checked = true;
                        var fc = new CCodeFunctionCall (new CCodeIdentifier ("VALA_FREE_CHECKED"));
                        fc.add_argument (
                                new CCodeMemberAccess.pointer (
@@ -439,7 +444,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                        }
                        
                        if (f.type_reference.takes_ownership && instance_dispose_fragment != null) {
-                               instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference)));
+                               var ma = new MemberAccess.simple (f.name);
+                               ma.symbol_reference = f;
+                               instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference, ma)));
                        }
                }
        }
@@ -719,7 +726,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                if (memory_management) {
                        foreach (VariableDeclarator decl in local_vars) {
                                if (decl.type_reference.takes_ownership) {
-                                       cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference)));
+                                       var ma = new MemberAccess.simple (decl.name);
+                                       ma.symbol_reference = decl;
+                                       cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma)));
                                }
                        }
                }
@@ -921,7 +930,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                }
        }
 
-       private CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type) {
+       private CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type, Expression expr) {
                /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */
                
                /* can be simplified to
@@ -950,33 +959,54 @@ public class Vala.CodeGenerator : CodeVisitor {
                /* set freed references to NULL to prevent further use */
                var ccomma = new CCodeCommaExpression ();
 
-               // TODO cleanup
-               if (type.data_type != null && !type.data_type.is_reference_counting ()) {
-                       string unref_function = type.data_type.get_free_function ();
-                       if (unref_function == "g_list_free") {
-                               bool is_ref = false;
-                               bool is_class = false;
-                               bool is_interface = false;
+               if (type.data_type == glist_type) {
+                       bool is_ref = false;
+                       bool is_class = false;
+                       bool is_interface = false;
 
-                               foreach (TypeReference type_arg in type.get_type_arguments ()) {
-                                       is_ref |= type_arg.takes_ownership;
-                                       is_class |= type_arg.data_type is Class;
-                                       is_interface |= type_arg.data_type is Interface;
+                       foreach (TypeReference type_arg in type.get_type_arguments ()) {
+                               is_ref |= type_arg.takes_ownership;
+                               is_class |= type_arg.data_type is Class;
+                               is_interface |= type_arg.data_type is Interface;
+                       }
+                       
+                       if (is_ref) {
+                               var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach"));
+                               cunrefcall.add_argument (cvar);
+                               if (is_class || is_interface) {
+                                       cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref"));
+                               } else {
+                                       cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free"));
                                }
-                               
-                               if (is_ref) {
-                                       var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach"));
-                                       cunrefcall.add_argument (cvar);
-                                       if (is_class || is_interface) {
-                                               cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref"));
+                               cunrefcall.add_argument (new CCodeConstant ("NULL"));
+                               ccomma.append_expression (cunrefcall);
+                       }
+               } else if (type.data_type == gstring_type) {
+                       ccall.add_argument (new CCodeConstant ("TRUE"));
+               } else if (type.data_type is Array) {
+                       var arr = (Array) type.data_type;
+                       if (arr.element_type == string_type.data_type) {
+                               ccall.call = new CCodeIdentifier ("g_strfreev");
+                       } else if (arr.element_type == null || arr.element_type.is_reference_type ()) {
+                               requires_array_free = true;
+
+                               bool first = true;
+                               CCodeExpression csizeexpr = null;
+                               for (int dim = 1; dim <= arr.rank; dim++) {
+                                       if (first) {
+                                               csizeexpr = get_array_length_cexpression (expr, dim);
+                                               first = false;
                                        } else {
-                                               cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free"));
+                                               csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, get_array_length_cexpression (expr, dim));
                                        }
-                                       cunrefcall.add_argument (new CCodeConstant ("NULL"));
-                                       ccomma.append_expression (cunrefcall);
                                }
-                       } else if (unref_function == "g_string_free") {
-                               ccall.add_argument (new CCodeConstant ("TRUE"));
+
+                               ccall.call = new CCodeIdentifier ("_vala_array_free");
+                               ccall.add_argument (csizeexpr);
+                               var element_type = new TypeReference ();
+                               element_type.data_type = arr.element_type;
+                               element_type.type_parameter = arr.element_type_parameter;
+                               ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (element_type), "GDestroyNotify"));
                        }
                }
                
@@ -1032,7 +1062,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                expr_list.append_expression (new CCodeAssignment (new CCodeIdentifier (full_expr_decl.name), (CCodeExpression) expr.ccodenode));
                
                foreach (VariableDeclarator decl in temp_ref_vars) {
-                       expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference));
+                       var ma = new MemberAccess.simple (decl.name);
+                       ma.symbol_reference = decl;
+                       expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference, ma));
                }
                
                expr_list.append_expression (new CCodeIdentifier (full_expr_decl.name));
@@ -1158,7 +1190,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                cfrag.append (stmt.ccodenode);
                
                foreach (VariableDeclarator decl in temp_ref_vars) {
-                       cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference)));
+                       var ma = new MemberAccess.simple (decl.name);
+                       ma.symbol_reference = decl;
+                       cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference, ma)));
                }
                
                stmt.ccodenode = cfrag;
@@ -1450,7 +1484,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                }
                
                if (memory_management && stmt.collection.static_type.transfers_ownership) {
-                       cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type)));
+                       var ma = new MemberAccess.simple (collection_backup.name);
+                       ma.symbol_reference = collection_backup;
+                       cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type, ma)));
                }
        }
 
@@ -1468,7 +1504,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                var local_vars = b.get_local_variables ();
                foreach (VariableDeclarator decl in local_vars) {
                        if (decl.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) {
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference)));
+                               var ma = new MemberAccess.simple (decl.name);
+                               ma.symbol_reference = decl;
+                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma)));
                        }
                }
                
@@ -1499,7 +1537,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                foreach (VariableDeclarator decl in local_vars) {
                        if (decl.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) {
                                found = true;
-                               ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference));
+                               var ma = new MemberAccess.simple (decl.name);
+                               ma.symbol_reference = decl;
+                               ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma));
                        }
                }
                
@@ -1816,6 +1856,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                                array_expr = unary_expr.inner;
                                is_out = true;
                        }
+               } else if (array_expr is ReferenceTransferExpression) {
+                       var reftransfer_expr = (ReferenceTransferExpression) array_expr;
+                       array_expr = reftransfer_expr.inner;
                }
                
                if (array_expr is ArrayCreationExpression) {
index 3e027ccd3071ed08bdea609642dea9e2d8412541..062dd071559c9877c58117e44418dc71ed97bcbe 100644 (file)
@@ -259,7 +259,7 @@ public class Vala.CodeGenerator {
                                ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
                                if (unref_old) {
                                        /* unref old value */
-                                       ccomma.append_expression (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type));
+                                       ccomma.append_expression (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type, a.left));
                                }
                                
                                if (array) {
index 14b8cc1ed7a432cec95a7b75dc8639a25a02e7ae..ae0cecb9c102665597290a47615bc3c27ea1c0e5 100644 (file)
@@ -45,6 +45,8 @@ public class Vala.CodeGenerator {
                next_temp_var_id = 0;
                
                string_h_needed = false;
+               requires_free_checked = false;
+               requires_array_free = false;
                
                header_begin.append (new CCodeIncludeDirective ("glib.h"));
                header_begin.append (new CCodeIncludeDirective ("glib-object.h"));
@@ -97,10 +99,6 @@ public class Vala.CodeGenerator {
                                }
                        }
                }
-               
-               /* generate hardcoded "well-known" macros */
-               source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
-               source_begin.append (new CCodeMacroReplacement ("VALA_FREE_UNCHECKED(o,f)", "((o) = (f (o), NULL))"));
 
                source_file.accept_children (this);
 
@@ -110,6 +108,49 @@ public class Vala.CodeGenerator {
                        source_include_directives.append (new CCodeIncludeDirective ("string.h"));
                }
                
+               /* generate hardcoded "well-known" macros */
+               if (requires_free_checked) {
+                       source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
+               }
+               if (requires_array_free) {
+                       var fun = new CCodeFunction ("_vala_array_free", "void");
+                       fun.modifiers = CCodeModifiers.STATIC;
+                       fun.add_parameter (new CCodeFormalParameter ("array", "gpointer"));
+                       fun.add_parameter (new CCodeFormalParameter ("array_length", "gint"));
+                       fun.add_parameter (new CCodeFormalParameter ("destroy_func", "GDestroyNotify"));
+                       source_type_member_declaration.append (fun.copy ());
+
+                       var cdofree = new CCodeBlock ();
+
+                       var citdecl = new CCodeDeclaration ("int");
+                       citdecl.add_declarator (new CCodeVariableDeclarator ("i"));
+                       cdofree.add_statement (citdecl);
+                       
+                       var cbody = new CCodeBlock ();
+                       
+                       var cptrarray = new CCodeCastExpression (new CCodeIdentifier ("array"), "gpointer*");
+                       var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i"));
+                       var cfreecond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant ("NULL"));
+                       var cfreecall = new CCodeFunctionCall (new CCodeIdentifier ("destroy_func"));
+                       cfreecall.add_argument (cea);
+                       cbody.add_statement (new CCodeIfStatement (cfreecond, new CCodeExpressionStatement (cfreecall)));
+
+                       var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length"));
+                       
+                       var cfor = new CCodeForStatement (cforcond, cbody);
+                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
+                       cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1"))));
+                       cdofree.add_statement (cfor);
+
+                       var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL"));
+                       var ccondfunc = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("destroy_func"), new CCodeConstant ("NULL"));
+                       var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccondarr, ccondfunc), cdofree);
+                       fun.block = new CCodeBlock ();
+                       fun.block.add_statement (cif);
+
+                       source_type_member_definition.append (fun);
+               }
+               
                CCodeComment comment = null;
                if (source_file.comment != null) {
                        comment = new CCodeComment (source_file.comment);