ignore file-internal dependencies mark string literals as non-null, add
authorJürg Billeter <j@bitron.ch>
Fri, 14 Jul 2006 16:09:47 +0000 (16:09 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 14 Jul 2006 16:09:47 +0000 (16:09 +0000)
2006-07-14  Jürg Billeter  <j@bitron.ch>

* vala/valacodecontext.vala: ignore file-internal dependencies
* vala/valasemanticanalyzer.vala: mark string literals as non-null, add
  some implicit casts
* vala/valamemorymanager.vala: only check for leaks with reference
  types, manage memory in field initializers
* vala/valacodegenerator.vala: add non-null parameter typechecks for
  structs, simplify ref expression if expression is known to be non-null
* vapi/glib-2.0.vala: unichar, string, String, and Path enhancements,
  add Base64 and Dir

svn path=/trunk/; revision=77

vala/ChangeLog
vala/vala/valacodecontext.vala
vala/vala/valacodegenerator.vala
vala/vala/valamemorymanager.vala
vala/vala/valasemanticanalyzer.vala
vala/vapi/glib-2.0.vala

index 1c7fd6d..278ecb4 100644 (file)
@@ -1,3 +1,15 @@
+2006-07-14  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valacodecontext.vala: ignore file-internal dependencies
+       * vala/valasemanticanalyzer.vala: mark string literals as non-null, add
+         some implicit casts
+       * vala/valamemorymanager.vala: only check for leaks with reference
+         types, manage memory in field initializers
+       * vala/valacodegenerator.vala: add non-null parameter typechecks for
+         structs, simplify ref expression if expression is known to be non-null
+       * vapi/glib-2.0.vala: unichar, string, String, and Path enhancements,
+         add Base64 and Dir
+
 2006-07-10  Jürg Billeter  <j@bitron.ch>
 
        * vala/parser.y: adapt to changes in InvocationExpression,
index f38726a..d4a72a3 100644 (file)
@@ -120,6 +120,11 @@ public class Vala.CodeContext {
        
        private SourceFile find_cycle_head (SourceFile! file) {
                foreach (SourceFile dep in file.header_internal_full_dependencies) {
+                       if (dep == file) {
+                               /* ignore file-internal dependencies */
+                               continue;
+                       }
+                       
                        foreach (SourceFile cycle_file in file.cycle.files) {
                                if (dep == cycle_file) {
                                        return find_cycle_head (dep);
index 8ea8a27..2f5d122 100644 (file)
@@ -813,16 +813,23 @@ public class Vala.CodeGenerator : CodeVisitor {
        private ref CCodeStatement create_type_check_statement (CodeNode! method_node, DataType ret_type, DataType! t, bool non_null, string! var_name) {
                var ccheck = new CCodeFunctionCall ();
                
-               var ctype_check = new CCodeFunctionCall (call = new CCodeIdentifier (name = t.get_upper_case_cname ("IS_")));
-               ctype_check.add_argument (new CCodeIdentifier (name = var_name));
-               
-               ref CCodeExpression cexpr = ctype_check;
-               if (!non_null) {
-                       var cnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = new CCodeIdentifier (name = var_name), right = new CCodeConstant (name = "NULL"));
-               
-                       cexpr = new CCodeBinaryExpression (operator = CCodeBinaryOperator.OR, left = cnull, right = ctype_check);
+               if (t is Class || t is Interface) {
+                       var ctype_check = new CCodeFunctionCall (call = new CCodeIdentifier (name = t.get_upper_case_cname ("IS_")));
+                       ctype_check.add_argument (new CCodeIdentifier (name = var_name));
+                       
+                       ref CCodeExpression cexpr = ctype_check;
+                       if (!non_null) {
+                               var cnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = new CCodeIdentifier (name = var_name), right = new CCodeConstant (name = "NULL"));
+                       
+                               cexpr = new CCodeBinaryExpression (operator = CCodeBinaryOperator.OR, left = cnull, right = ctype_check);
+                       }
+                       ccheck.add_argument (cexpr);
+               } else if (!non_null) {
+                       return null;
+               } else {
+                       var cnonnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.INEQUALITY, left = new CCodeIdentifier (name = var_name), right = new CCodeConstant (name = "NULL"));
+                       ccheck.add_argument (cnonnull);
                }
-               ccheck.add_argument (cexpr);
                
                if (ret_type == null) {
                        /* void function */
@@ -942,8 +949,11 @@ public class Vala.CodeGenerator : CodeVisitor {
                                }
                                foreach (FormalParameter param in m.get_parameters ()) {
                                        var t = param.type_reference.type;
-                                       if (t != null && (t is Class || t is Interface) && !param.type_reference.is_out) {
-                                               cinit.append (create_method_type_check_statement (m, t, param.type_reference.non_null, param.name));
+                                       if (t != null && t.is_reference_type () && !param.type_reference.is_out) {
+                                               var type_check = create_method_type_check_statement (m, t, param.type_reference.non_null, param.name);
+                                               if (type_check != null) {
+                                                       cinit.append (type_check);
+                                               }
                                        }
                                }
 
@@ -1333,7 +1343,12 @@ public class Vala.CodeGenerator : CodeVisitor {
                foreach (VariableDeclarator decl in temp_vars) {
                        var cdecl = new CCodeDeclaration (type_name = decl.type_reference.get_cname (true));
                
-                       cdecl.add_declarator (new CCodeVariableDeclarator (name = decl.name));
+                       var vardecl = new CCodeVariableDeclarator (name = decl.name);
+                       cdecl.add_declarator (vardecl);
+                       
+                       if (decl.type_reference.type != null && decl.type_reference.type.is_reference_type ()) {
+                               vardecl.initializer = new CCodeConstant (name = "NULL");
+                       }
                        
                        cfrag.append (cdecl);
                }
@@ -1856,19 +1871,8 @@ public class Vala.CodeGenerator : CodeVisitor {
                 * can be simplified to
                 * ref (expr)
                 * if static type of expr is non-null
-                *
-                * can be simplified to
-                * (expr == NULL ? expr : ref (expr))
-                * if expr.ccodenode is CCodeSimpleName or CCodeMemberAccess
                 */
        
-               var decl = get_temp_variable_declarator (expr.static_type);
-               temp_vars.prepend (decl);
-
-               var ctemp = new CCodeIdentifier (name = decl.name);
-               
-               var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = ctemp, right = new CCodeConstant (name = "NULL"));
-               
                string ref_function;
                if (expr.static_type.type.is_reference_counting ()) {
                        ref_function = expr.static_type.type.get_ref_function ();
@@ -1877,13 +1881,27 @@ public class Vala.CodeGenerator : CodeVisitor {
                }
        
                var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = ref_function));
-               ccall.add_argument (ctemp);
-               
-               var ccomma = new CCodeCommaExpression ();
-               ccomma.append_expression (new CCodeAssignment (left = ctemp, right = expr.ccodenode));
-               ccomma.append_expression (new CCodeConditionalExpression (condition = cisnull, true_expression = ctemp, false_expression = ccall));
 
-               return ccomma;
+               if (expr.static_type.non_null) {
+                       ccall.add_argument ((CCodeExpression) expr.ccodenode);
+                       
+                       return ccall;
+               } else {
+                       var decl = get_temp_variable_declarator (expr.static_type);
+                       temp_vars.prepend (decl);
+
+                       var ctemp = new CCodeIdentifier (name = decl.name);
+                       
+                       var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = ctemp, right = new CCodeConstant (name = "NULL"));
+                       
+                       ccall.add_argument (ctemp);
+                       
+                       var ccomma = new CCodeCommaExpression ();
+                       ccomma.append_expression (new CCodeAssignment (left = ctemp, right = expr.ccodenode));
+                       ccomma.append_expression (new CCodeConditionalExpression (condition = cisnull, true_expression = ctemp, false_expression = ccall));
+
+                       return ccomma;
+               }
        }
        
        private void visit_expression (Expression! expr) {
index 62c95e0..c3ee368 100644 (file)
@@ -40,6 +40,8 @@ public class Vala.MemoryManager : CodeVisitor {
        
        private void visit_possibly_leaked_expression (Expression! expr) {
                if (expr.static_type != null &&
+                   (expr.static_type.type != null &&
+                    expr.static_type.type.is_reference_type ()) &&
                    expr.static_type.is_ref) {
                        /* mark reference as leaked */
                        expr.ref_leaked = true;
@@ -56,6 +58,16 @@ public class Vala.MemoryManager : CodeVisitor {
                }
        }
 
+       public override void visit_field (Field! f) {
+               if (f.initializer != null) {
+                       if (f.type_reference.is_lvalue_ref) {
+                               visit_possibly_missing_copy_expression (f.initializer);
+                       } else {
+                               visit_possibly_leaked_expression (f.initializer);
+                       }
+               }
+       }
+
        public override void visit_begin_method (Method! m) {
                current_symbol = m.symbol;
        }
index 3fd2b06..bfc0de0 100644 (file)
@@ -413,7 +413,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_string_literal (StringLiteral! expr) {
-               expr.static_type = string_type;
+               expr.static_type = string_type.copy ();
+               expr.static_type.non_null = true;
        }
 
        public override void visit_null_literal (NullLiteral! expr) {
@@ -589,11 +590,41 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        return true;
                }
                
+               /* int may be implicitly casted to ulong */
+               if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("ulong").node) {
+                       return true;
+               }
+               
+               /* uint may be implicitly casted to long */
+               if (expression_type.type == root_symbol.lookup ("uint").node && expected_type.type == root_symbol.lookup ("long").node) {
+                       return true;
+               }
+               
+               /* uint may be implicitly casted to ulong */
+               if (expression_type.type == root_symbol.lookup ("uint").node && expected_type.type == root_symbol.lookup ("ulong").node) {
+                       return true;
+               }
+               
                /* int may be implicitly casted to uint */
                if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("uint").node) {
                        return true;
                }
                
+               /* uint may be implicitly casted to int */
+               if (expression_type.type == root_symbol.lookup ("uint").node && expected_type.type == root_symbol.lookup ("int").node) {
+                       return true;
+               }
+               
+               /* long may be implicitly casted to ulong */
+               if (expression_type.type == root_symbol.lookup ("long").node && expected_type.type == root_symbol.lookup ("ulong").node) {
+                       return true;
+               }
+               
+               /* ulong may be implicitly casted to long */
+               if (expression_type.type == root_symbol.lookup ("ulong").node && expected_type.type == root_symbol.lookup ("long").node) {
+                       return true;
+               }
+               
                /* int may be implicitly casted to double */
                if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("double").node) {
                        return true;
index 49d1a1b..fd1cfdd 100644 (file)
@@ -104,25 +104,37 @@ public struct double {
 public struct unichar {
        [CCode (cname = "g_unichar_isalnum")]
        public bool isalnum ();
+       [CCode (cname = "g_unichar_isdigit")]
+       public bool isdigit ();
        [CCode (cname = "g_unichar_isupper")]
        public bool isupper ();
+       [CCode (cname = "g_unichar_isxdigit")]
+       public bool isxdigit ();
        [CCode (cname = "g_unichar_toupper")]
        public unichar toupper ();
        [CCode (cname = "g_unichar_tolower")]
        public unichar tolower ();
+       [CCode (cname = "g_unichar_digit_value")]
+       public int digit_value ();
+       [CCode (cname = "g_unichar_xdigit_value")]
+       public int xdigit_value ();
 }
 
 [ReferenceType (dup_function = "g_strdup", free_function = "g_free", type_id = "G_TYPE_STRING", ref_function = "g_strdup")]
 [CCode (cname = "char", cheader_filename = "string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING")]
 public struct string {
+       [CCode (cname = "g_strstr")]
+       public string str (string! needle);
+       [CCode (cname = "g_str_has_prefix")]
+       public bool has_prefix (string! prefix);
        [CCode (cname = "g_str_has_suffix")]
-       public bool has_suffix (string suffix);
+       public bool has_suffix (string! suffix);
        [CCode (cname = "g_strdup_printf")]
        public ref string printf (...);
        [CCode (cname = "g_strconcat")]
        public ref string concat (string string2, ...);
        [CCode (cname = "g_strndup")]
-       public ref string ndup (uint n); /* FIXME: only UTF-8 */
+       public ref string ndup (ulong n); /* FIXME: only UTF-8 */
        [CCode (cname = "g_strcompress")]
        public ref string compress ();
        [CCode (cname = "g_strsplit")]
@@ -140,14 +152,21 @@ public struct string {
        [CCode (cname = "g_utf8_prev_char")]
        public string prev_char ();
        [CCode (cname = "g_utf8_strlen")]
-       public long len (int max = -1);
+       public long len (long max = -1);
        [CCode (cname = "g_utf8_strchr")]
-       public string chr (int len, unichar c);
+       public string chr (long len, unichar c);
+       [CCode (cname = "g_utf8_validate")]
+       public bool validate (long max_len = -1, out string end = null);
        
        [CCode (cname = "g_utf8_strup")]
-       public ref string up (int len = -1);
+       public ref string up (long len = -1);
+       [CCode (cname = "g_utf8_casefold")]
+       public ref string casefold (long len = -1);
        [CCode (cname = "g_utf8_collate")]
        public int collate (string str2);
+       
+       [CCode (cname = "atoi")]
+       public int to_int ();
 }
 
 [Import ()]
@@ -254,8 +273,19 @@ namespace GLib {
        public static void assert (bool expr);
        public static void assert_not_reached ();
        
+       public static ref string convert (string! str, long len, string! to_codeset, string! from_codeset, ref int bytes_read, ref int bytes_written, out Error error);
+       
+       public struct Base64 {
+               public static int encode_step (string! _in, int len, bool break_lines, string _out, ref int state, ref int save);
+               public static int encode_close (bool break_lines, string _out, ref int state, ref int save);
+               public static ref string encode (string! data, int len);
+               public static int decode_step (string! _in, int len, ref int state, ref uint save);
+               public static ref string decode (string! text, ref ulong out_len);
+       }
+       
        public struct Path {
                public static ref string get_basename (string file_name);
+               public static ref string get_dirname (string file_name);
                [CCode (cname = "g_build_filename")]
                public static ref string build_filename (string first_element, ...);
        }
@@ -286,8 +316,11 @@ namespace GLib {
                [CCode (cname = "fclose")]
                public void close ();
                
+               public static bool get_contents (string! filename, out string contents, ref long length, out Error error);
+               public static bool set_contents (string! filename, string contents, long length, out Error error);
                public static bool test (string filename, FileTest test);
                public static int open_tmp (string tmpl, out string name_used, out Error error);
+               public static ref string read_link (string filename, out Error error);
                
                [CCode (cname = "g_rename")]
                public static int rename (string oldfilename, string newfilename);
@@ -295,6 +328,17 @@ namespace GLib {
                public static int unlink (string filename);
        }
        
+       [ReferenceType (free_function = "g_dir_close")]
+       public struct Dir {
+               public static ref Dir open (string filename, uint _flags, out Error error);
+               public string read_name ();
+               
+               [CCode (cname = "g_mkdir")]
+               public static int create (string pathname, int mode);
+               [CCode (cname = "g_mkdir_with_parents")]
+               public static int create_with_parents (string pathname, int mode);
+       }
+       
        [ReferenceType (free_function = "g_mapped_file_free")]
        public struct MappedFile {
                public static ref MappedFile new (string filename, bool writable, out Error error);
@@ -371,6 +415,8 @@ namespace GLib {
                [ReturnsModifiedPointer ()]
                public void remove_link (List<G> llink);
                [ReturnsModifiedPointer ()]
+               public void delete_link (List<G> link_);
+               [ReturnsModifiedPointer ()]
                public void remove_all (G data);
                public void free ();
                
@@ -431,10 +477,14 @@ namespace GLib {
        
        [ReferenceType (free_function = "g_string_free")]
        public struct String {
-               public static ref String new (string init);
-               public String append (string val);
+               public static ref String! new (string init = "");
+               public static ref String! sized_new (ulong dfl_size);
+               public String assign (string! rval);
+               public String append (string! val);
                public String append_c (char c);
                public String append_unichar (unichar wc);
+               public String append_len (string! val, long len);
+               public String insert (long pos, string! val);
                public String erase (long pos, long len);
                
                public string str;