]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
set is_lvalue_ref in property declarations use non-null parameter types
authorJürg Billeter <j@bitron.ch>
Wed, 14 Jun 2006 20:55:58 +0000 (20:55 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 14 Jun 2006 20:55:58 +0000 (20:55 +0000)
2006-06-14  Jürg Billeter  <j@bitron.ch>

* vala/parser.y: set is_lvalue_ref in property declarations
* vala/valacodecontext.vala: use non-null parameter types
* vala/valasymbolresolver.vala: fix lookup in namespaces of using
  directives, reset is_lvalue_ref where appropriate
* vala/valasemanticanalyzer.vala: use non-null parameter types,
  correctly set is_ref and is_lvalue_ref in variable declarators
* vala/valamemorymanager.vala: support methods which transfer ownership
  of arguments and or return value, analyze assignments
* vala/valacodegenerator.vala: add missing reference increment calls,
  small memory management improvements
* vala/valaclass.vala: use non-null parameter types
* vala/valaexpression.vala: add ref_missing
* vala/valastruct.vala: support ref_function attribute, use non-null
  parameter types
* vala/valatype.vala: let get_upper_case_cname return ref string
* vala/valatypereference.vala: add copy method
* ccode/valaccodeconditionalexpression.vala
* ccode/valaccodefunctioncall.vala: use non-null parameter types
* ccode/Makefile.am: update
* compiler/valacompiler.vala: process attributes before resolving
  symbols to have reference_type information available in resolver
* vapi/glib-2.0.vala: add ref_function attributes to string and List,
  use ref parameters in List and HashTable until the compiler can handle
  it correctly

svn path=/trunk/; revision=44

17 files changed:
vala/ChangeLog
vala/ccode/Makefile.am
vala/ccode/valaccodeconditionalexpression.vala [new file with mode: 0644]
vala/ccode/valaccodefunctioncall.vala
vala/compiler/valacompiler.vala
vala/vala/parser.y
vala/vala/valaclass.vala
vala/vala/valacodecontext.vala
vala/vala/valacodegenerator.vala
vala/vala/valaexpression.vala
vala/vala/valamemorymanager.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valastruct.vala
vala/vala/valasymbolresolver.vala
vala/vala/valatype.vala
vala/vala/valatypereference.vala
vala/vapi/glib-2.0.vala

index 5eb5b425640b11d24ee573fbb918ea58d6a19a9b..6572cc8eea218576fbc4e46e05176081b2bed36d 100644 (file)
@@ -1,3 +1,30 @@
+2006-06-14  Jürg Billeter  <j@bitron.ch>
+
+       * vala/parser.y: set is_lvalue_ref in property declarations
+       * vala/valacodecontext.vala: use non-null parameter types
+       * vala/valasymbolresolver.vala: fix lookup in namespaces of using
+         directives, reset is_lvalue_ref where appropriate
+       * vala/valasemanticanalyzer.vala: use non-null parameter types,
+         correctly set is_ref and is_lvalue_ref in variable declarators
+       * vala/valamemorymanager.vala: support methods which transfer ownership
+         of arguments and or return value, analyze assignments
+       * vala/valacodegenerator.vala: add missing reference increment calls,
+         small memory management improvements
+       * vala/valaclass.vala: use non-null parameter types
+       * vala/valaexpression.vala: add ref_missing
+       * vala/valastruct.vala: support ref_function attribute, use non-null
+         parameter types
+       * vala/valatype.vala: let get_upper_case_cname return ref string
+       * vala/valatypereference.vala: add copy method
+       * ccode/valaccodeconditionalexpression.vala
+       * ccode/valaccodefunctioncall.vala: use non-null parameter types
+       * ccode/Makefile.am: update
+       * compiler/valacompiler.vala: process attributes before resolving
+         symbols to have reference_type information available in resolver
+       * vapi/glib-2.0.vala: add ref_function attributes to string and List,
+         use ref parameters in List and HashTable until the compiler can handle
+         it correctly
+
 2006-06-14  Jürg Billeter  <j@bitron.ch>
 
        * vala/parser.y: set is_lvalue_ref for variables and fields
index 85006f8b0b3dded1eba47f247e856600fafd6bb8..6b5f945d077322b4e4b7ea79bf5e0b7a50b2dd4e 100644 (file)
@@ -36,6 +36,9 @@ libvalaccode_la_SOURCES = \
        valaccodecomment.c \
        valaccodecomment.h \
        valaccodecomment.vala \
+       valaccodeconditionalexpression.c \
+       valaccodeconditionalexpression.h \
+       valaccodeconditionalexpression.vala \
        valaccodeconstant.c \
        valaccodeconstant.h \
        valaccodeconstant.vala \
diff --git a/vala/ccode/valaccodeconditionalexpression.vala b/vala/ccode/valaccodeconditionalexpression.vala
new file mode 100644 (file)
index 0000000..f1e2f3a
--- /dev/null
@@ -0,0 +1,41 @@
+/* valaccodeconditionalexpression.vala
+ *
+ * Copyright (C) 2006  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 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;
+
+namespace Vala {
+       public class CCodeConditionalExpression : CCodeExpression {
+               public CCodeExpression condition { get; construct; }
+               public CCodeExpression true_expression { get; construct; }
+               public CCodeExpression false_expression { get; construct; }
+               
+               public override void write (CCodeWriter writer) {
+                       writer.write_string ("(");
+                       condition.write (writer);
+                       writer.write_string (" ? ");
+                       true_expression.write (writer);
+                       writer.write_string (" : ");
+                       false_expression.write (writer);
+                       writer.write_string (")");
+               }
+       }
+}
index bcd9b614bf7f903e57ed7e05e354c091935607bf..4e0e6a061cd1e0809c38d25e71d766265f3eae0d 100644 (file)
@@ -27,11 +27,11 @@ namespace Vala {
                public CCodeExpression call { get; construct; }
                List<CCodeExpression> arguments;
                
-               public void add_argument (CCodeExpression expr) {
+               public void add_argument (CCodeExpression! expr) {
                        arguments.append (expr);
                }
                
-               public override void write (CCodeWriter writer) {
+               public override void write (CCodeWriter! writer) {
                        call.write (writer);
                        writer.write_string (" (");
 
index 97a69ee2ffd839e7f238a73cbeb1085ee78b4cde..09078e1edecba7c9d5ab74104bbf9aa936ea6589 100644 (file)
@@ -54,7 +54,7 @@ namespace Vala {
                        }
                }
                
-               private ref string get_package_path (string pkg) {
+               private ref string get_package_path (string! pkg) {
                        var basename = "%s.vala".printf (pkg);
                
                        if (vapi_directories != null) {
@@ -74,7 +74,7 @@ namespace Vala {
                        return null;
                }
                
-               private bool add_package (string pkg) {
+               private bool add_package (string! pkg) {
                        var package_path = get_package_path (pkg);
                        
                        if (package_path == null) {
@@ -132,15 +132,15 @@ namespace Vala {
                                return quit ();
                        }
                        
-                       var resolver = new SymbolResolver ();
-                       resolver.resolve (context);
+                       var attributeprocessor = new AttributeProcessor ();
+                       attributeprocessor.process (context);
                        
                        if (Report.get_errors () > 0) {
                                return quit ();
                        }
                        
-                       var attributeprocessor = new AttributeProcessor ();
-                       attributeprocessor.process (context);
+                       var resolver = new SymbolResolver ();
+                       resolver.resolve (context);
                        
                        if (Report.get_errors () > 0) {
                                return quit ();
index f142dfb9bbd4ac287211522f1701e225f7b5cb57..be7e40181ac204e12238c272067b68d3250eb554 100644 (file)
@@ -1419,10 +1419,18 @@ fixed_parameter
 property_declaration
        : comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration CLOSE_BRACE
          {
+               if (!vala_type_reference_get_is_weak ($5)) {
+                       vala_type_reference_set_is_lvalue_ref ($5, TRUE);
+               }
+               
                $$ = vala_property_new ($6, $5, $8, $9, src_com (@5, $1));
          }
        | comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_BRACE set_accessor_declaration CLOSE_BRACE
          {
+               if (!vala_type_reference_get_is_weak ($5)) {
+                       vala_type_reference_set_is_lvalue_ref ($5, TRUE);
+               }
+               
                $$ = vala_property_new ($6, $5, NULL, $8, src_com (@5, $1));
          }
        ;
index b99d02b7bc4082ba40bd7a1c0a210f890d8785b0..31c7b1818880a98385bab7292553c0a1cef56ed1 100644 (file)
@@ -42,24 +42,24 @@ namespace Vala {
                public string lower_case_csuffix;
                public bool has_private_fields;
                
-               public static ref Class new (string name, SourceReference source) {
+               public static ref Class new (string! name, SourceReference source) {
                        return (new Class (name = name, source_reference = source));
                }
 
-               public void add_base_type (TypeReference type) {
+               public void add_base_type (TypeReference! type) {
                        base_types.append (type);
                }
 
-               public void add_type_parameter (TypeParameter p) {
+               public void add_type_parameter (TypeParameter! p) {
                        type_parameters.append (p);
                        p.type = this;
                }
                
-               public void add_constant (Constant c) {
+               public void add_constant (Constant! c) {
                        constants.append (c);
                }
                
-               public void add_field (Field f) {
+               public void add_field (Field! f) {
                        fields.append (f);
                        if (f.access == MemberAccessibility.PRIVATE) {
                                has_private_fields = true;
@@ -70,9 +70,7 @@ namespace Vala {
                        return fields.copy ();
                }
                
-               public void add_method (Method m) {
-                       return_if_fail (m != null);
-                       
+               public void add_method (Method! m) {
                        methods.append (m);
                }
                
@@ -80,7 +78,7 @@ namespace Vala {
                        return methods.copy ();
                }
                
-               public void add_property (Property prop) {
+               public void add_property (Property! prop) {
                        properties.append (prop);
                        
                        if (prop.set_accessor != null && prop.set_accessor.body == null) {
@@ -95,7 +93,7 @@ namespace Vala {
                        return properties.copy ();
                }
                
-               public void add_signal (Signal sig) {
+               public void add_signal (Signal! sig) {
                        signals.append (sig);
                }
                
@@ -103,7 +101,7 @@ namespace Vala {
                        return signals.copy ();
                }
                
-               public override void accept (CodeVisitor visitor) {
+               public override void accept (CodeVisitor! visitor) {
                        visitor.visit_begin_class (this);
                        
                        foreach (TypeReference type in base_types) {
@@ -152,7 +150,7 @@ namespace Vala {
                        return cname;
                }
                
-               public void set_cname (string cname) {
+               public void set_cname (string! cname) {
                        this.cname = cname;
                }
                
@@ -163,7 +161,7 @@ namespace Vala {
                        return lower_case_csuffix;
                }
                
-               public void set_lower_case_csuffix (string csuffix) {
+               public void set_lower_case_csuffix (string! csuffix) {
                        this.lower_case_csuffix = csuffix;
                }
                
@@ -174,7 +172,7 @@ namespace Vala {
                        return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
                }
                
-               public override ref string get_upper_case_cname (string infix) {
+               public override ref string get_upper_case_cname (string! infix) {
                        return get_lower_case_cname (infix).up ();
                }
 
@@ -182,7 +180,7 @@ namespace Vala {
                        return true;
                }
                
-               void process_ccode_attribute (Attribute a) {
+               void process_ccode_attribute (Attribute! a) {
                        foreach (NamedArgument arg in a.args) {
                                if (arg.name == "cname") {
                                        /* this will already be checked during semantic analysis */
index 55a322a2ded5b490aafbbcbdace3df0bfeea14e1..896d937ebcf7c2d4c4965c4e8ef0a3de7d8a3e07 100644 (file)
@@ -33,11 +33,11 @@ namespace Vala {
                        return source_files.copy ();
                }
                
-               public void add_source_file (SourceFile file) {
+               public void add_source_file (SourceFile! file) {
                        source_files.append (file);
                }
                
-               public void accept (CodeVisitor visitor) {
+               public void accept (CodeVisitor! visitor) {
                        foreach (SourceFile file in source_files) {
                                file.accept (visitor);
                        }
@@ -85,7 +85,7 @@ namespace Vala {
                        
                }
                
-               private SourceFile find_cycle_head (SourceFile file) {
+               private SourceFile find_cycle_head (SourceFile! file) {
                        foreach (SourceFile dep in file.header_internal_full_dependencies) {
                                foreach (SourceFile cycle_file in file.cycle.files) {
                                        if (dep == cycle_file) {
@@ -99,7 +99,7 @@ namespace Vala {
                        return file;
                }
                
-               private void visit (SourceFile file, List<SourceFile> chain) {
+               private void visit (SourceFile! file, List<SourceFile> chain) {
                        var l = chain.copy ();
                        l.append (file);
 
index 067154d5ac6ff77ec994687baf7c06fb288a3c85..109290b2a8be6550e3772d43188ec5b1fbbdda1e 100644 (file)
@@ -45,7 +45,10 @@ namespace Vala {
                CCodeFunction function;
                CCodeBlock block;
                
+               /* all temporary variables */
                List<VariableDeclarator> temp_vars;
+               /* temporary variables that own their content */
+               List<VariableDeclarator> temp_ref_vars;
                
                private int next_temp_var_id = 0;
 
@@ -924,6 +927,7 @@ namespace Vala {
                public override void visit_end_full_expression (Expression! expr) {
                        if (!memory_management) {
                                temp_vars = null;
+                               temp_ref_vars = null;
                                return;
                        }
                
@@ -935,17 +939,21 @@ namespace Vala {
                         * expression
                         */
                        
-                       if (temp_vars == null) {
+                       expr.temp_vars = temp_vars;
+                       temp_vars = null;
+
+                       if (temp_ref_vars == null) {
                                /* nothing to do without temporary variables */
                                return;
                        }
                        
                        var full_expr_decl = get_temp_variable_declarator (expr.static_type);
+                       expr.temp_vars.append (full_expr_decl);
                        
                        var expr_list = new CCodeCommaExpression ();
                        expr_list.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = full_expr_decl.name), right = expr.ccodenode));
                        
-                       foreach (VariableDeclarator decl in temp_vars) {
+                       foreach (VariableDeclarator decl in temp_ref_vars) {
                                expr_list.inner.append (get_unref_expression (decl.name, decl.type_reference));
                        }
                        
@@ -953,10 +961,7 @@ namespace Vala {
                        
                        expr.ccodenode = expr_list;
                        
-                       temp_vars.append (full_expr_decl);
-                       
-                       expr.temp_vars = temp_vars;
-                       temp_vars = null;
+                       temp_ref_vars = null;
                }
                
                private void append_temp_decl (CCodeFragment! cfrag, List<VariableDeclarator> temp_vars) {
@@ -975,6 +980,7 @@ namespace Vala {
                        /* free temporary objects */
                        if (!memory_management) {
                                temp_vars = null;
+                               temp_ref_vars = null;
                                return;
                        }
                        
@@ -988,13 +994,14 @@ namespace Vala {
                        
                        cfrag.append (stmt.ccodenode);
                        
-                       foreach (VariableDeclarator decl in temp_vars) {
+                       foreach (VariableDeclarator decl in temp_ref_vars) {
                                cfrag.append (new CCodeExpressionStatement (expression = get_unref_expression (decl.name, decl.type_reference)));
                        }
                        
                        stmt.ccodenode = cfrag;
                        
                        temp_vars = null;
+                       temp_ref_vars = null;
                }
                
                private void create_temp_decl (Statement! stmt, List<VariableDeclarator> temp_vars) {
@@ -1218,10 +1225,14 @@ namespace Vala {
                        var base_type = (Type_) current_symbol.node;
                        
                        process_cmember (expr, pub_inst, base_type);
+
+                       visit_expression (expr);
                }
 
                public override void visit_parenthesized_expression (ParenthesizedExpression! expr) {
                        expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode);
+
+                       visit_expression (expr);
                }
 
                public override void visit_member_access (MemberAccess! expr) {
@@ -1232,6 +1243,8 @@ namespace Vala {
                        }
 
                        process_cmember (expr, pub_inst, base_type);
+
+                       visit_expression (expr);
                }
 
                public override void visit_invocation_expression (InvocationExpression! expr) {
@@ -1339,11 +1352,34 @@ namespace Vala {
                        }
                }
                
+               private ref CCodeExpression get_ref_expression (Expression! expr) {
+                       /* (temp = expr, temp == NULL ? temp : ref (temp)) */
+               
+                       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"));
+               
+                       var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = expr.static_type.type.get_ref_function ()));
+                       ccall.add_argument (ctemp);
+                       
+                       var ccomma = new CCodeCommaExpression ();
+                       ccomma.inner.append (new CCodeAssignment (left = ctemp, right = expr.ccodenode));
+                       ccomma.inner.append (new CCodeConditionalExpression (condition = cisnull, true_expression = ctemp, false_expression = ccall));
+
+                       return ccomma;
+               }
+               
                private void visit_expression (Expression! expr) {
                        if (expr.ref_leaked) {
                                var decl = get_temp_variable_declarator (expr.static_type);
                                temp_vars.prepend (decl);
+                               temp_ref_vars.prepend (decl);
                                expr.ccodenode = new CCodeAssignment (left = new CCodeIdentifier (name = decl.name), right = expr.ccodenode);
+                       } else if (expr.ref_missing) {
+                               expr.ccodenode = get_ref_expression (expr);
                        }
                }
 
index 2ed8ef4f546fc0bc11afe200f1fb355647254af5..7f51b2978a9837700716d5fa6d8c6fe70f52fee6 100644 (file)
@@ -35,6 +35,7 @@ namespace Vala {
                
                /* set by memory manager, used by code generator */
                public bool ref_leaked;
+               public bool ref_missing;
                
                /* set and used by code generator */
                public List<VariableDeclarator> temp_vars;
index 72664e7d2792bc6f896e8d930c2befa17336a97c..4677da489feec5fd7aac4947e371351cede1f65a 100644 (file)
@@ -24,6 +24,8 @@ using GLib;
 
 namespace Vala {
        public class MemoryManager : CodeVisitor {
+               Symbol current_symbol;
+
                public void analyze (CodeContext! context) {
                        context.accept (this);
                }
@@ -36,13 +38,31 @@ namespace Vala {
                        }
                }
 
+               private void visit_possibly_missing_copy_expression (Expression! expr) {
+                       if (expr.static_type != null &&
+                           !expr.static_type.is_ref) {
+                               /* mark reference as missing */
+                               expr.ref_missing = true;
+                       }
+               }
+
+               public override void visit_begin_method (Method! m) {
+                       current_symbol = m.symbol;
+               }
+
                public override void visit_expression_statement (ExpressionStatement! stmt) {
                        visit_possibly_leaked_expression (stmt.expression);
                }
 
                public override void visit_return_statement (ReturnStatement! stmt) {
                        if (stmt.return_expression != null) {
-                               visit_possibly_leaked_expression (stmt.return_expression);
+                               var m = (Method) current_symbol.node;
+                               
+                               if (m.return_type.is_ref) {
+                                       visit_possibly_missing_copy_expression (stmt.return_expression);
+                               } else {
+                                       visit_possibly_leaked_expression (stmt.return_expression);
+                               }
                        }
                }
 
@@ -51,8 +71,26 @@ namespace Vala {
                }
 
                public override void visit_invocation_expression (InvocationExpression! expr) {
+                       var m = (Method) expr.call.symbol_reference.node;
+                       var params = m.get_parameters ();
                        foreach (Expression arg in expr.argument_list) {
-                               visit_possibly_leaked_expression (arg);
+                               if (params != null) {
+                                       var param = (FormalParameter) params.data;
+                                       if (!param.ellipsis
+                                           && ((param.type_reference.type != null
+                                           && param.type_reference.type.is_reference_type ())
+                                           || param.type_reference.type_parameter != null)) {
+                                               if (param.type_reference.is_ref) {
+                                                       visit_possibly_missing_copy_expression (arg);
+                                               } else {
+                                                       visit_possibly_leaked_expression (arg);
+                                               }
+                                       }
+
+                                       params = params.next;
+                               } else {
+                                       visit_possibly_leaked_expression (arg);
+                               }
                        }
                }
 
@@ -60,5 +98,13 @@ namespace Vala {
                        visit_possibly_leaked_expression (expr.left);
                        visit_possibly_leaked_expression (expr.right);
                }
+
+               public override void visit_assignment (Assignment! a) {
+                       if (a.left.static_type.is_lvalue_ref) {
+                               visit_possibly_missing_copy_expression (a.right);
+                       } else {
+                               visit_possibly_leaked_expression (a.right);
+                       }
+               }
        }
 }
index b20221edbc38d4ad3b1c2694f0b3105cfba523dc..cd91e0d4f362e2e05d6f1257bd8b410edc6622a1 100644 (file)
@@ -48,24 +48,24 @@ namespace Vala {
                        context.accept (this);
                }
                
-               public override void visit_begin_source_file (SourceFile file) {
+               public override void visit_begin_source_file (SourceFile! file) {
                        current_source_file = file;
                        current_using_directives = file.get_using_directives ();
                }
 
-               public override void visit_end_source_file (SourceFile file) {
+               public override void visit_end_source_file (SourceFile! file) {
                        current_using_directives = null;
                }
 
-               public override void visit_begin_namespace (Namespace ns) {
+               public override void visit_begin_namespace (Namespace! ns) {
                        current_symbol = ns.symbol;
                }
 
-               public override void visit_end_namespace (Namespace ns) {
+               public override void visit_end_namespace (Namespace! ns) {
                        current_symbol = current_symbol.parent_symbol;
                }
 
-               public override void visit_begin_class (Class cl) {
+               public override void visit_begin_class (Class! cl) {
                        current_symbol = cl.symbol;
                        
                        if (cl.base_class != null) {
@@ -73,19 +73,19 @@ namespace Vala {
                        }
                }
 
-               public override void visit_end_class (Class cl) {
+               public override void visit_end_class (Class! cl) {
                        current_symbol = current_symbol.parent_symbol;
                }
 
-               public override void visit_begin_struct (Struct st) {
+               public override void visit_begin_struct (Struct! st) {
                        current_symbol = st.symbol;
                }
 
-               public override void visit_end_struct (Struct st) {
+               public override void visit_end_struct (Struct! st) {
                        current_symbol = current_symbol.parent_symbol;
                }
 
-               public override void visit_field (Field f) {
+               public override void visit_field (Field! f) {
                        if (f.access == MemberAccessibility.PUBLIC) {
                                if (f.type_reference.type != null) {
                                        /* is null if it references a type parameter */
@@ -99,7 +99,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_begin_method (Method m) {
+               public override void visit_begin_method (Method! m) {
                        current_symbol = m.symbol;
                        
                        if (m.return_type.type != null) {
@@ -108,7 +108,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_end_method (Method m) {
+               public override void visit_end_method (Method! m) {
                        current_symbol = current_symbol.parent_symbol;
                        
                        if (m.is_virtual || m.is_override) {
@@ -135,7 +135,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_formal_parameter (FormalParameter p) {
+               public override void visit_formal_parameter (FormalParameter! p) {
                        if (!p.ellipsis) {
                                if (p.type_reference.type != null) {
                                        /* is null if it references a type parameter */
@@ -145,7 +145,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_end_property (Property prop) {
+               public override void visit_end_property (Property! prop) {
                        if (prop.type_reference.type != null) {
                                /* is null if it references a type parameter */
                                current_source_file.add_symbol_dependency (prop.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW);
@@ -153,37 +153,39 @@ namespace Vala {
                        }
                }
 
-               public override void visit_begin_constructor (Constructor c) {
+               public override void visit_begin_constructor (Constructor! c) {
                        current_symbol = c.symbol;
                }
 
-               public override void visit_end_constructor (Constructor c) {
+               public override void visit_end_constructor (Constructor! c) {
                        current_symbol = current_symbol.parent_symbol;
                }
 
-               public override void visit_begin_destructor (Destructor d) {
+               public override void visit_begin_destructor (Destructor! d) {
                        current_symbol = d.symbol;
                }
 
-               public override void visit_end_destructor (Destructor d) {
+               public override void visit_end_destructor (Destructor! d) {
                        current_symbol = current_symbol.parent_symbol;
                }
 
-               public override void visit_named_argument (NamedArgument n) {
+               public override void visit_named_argument (NamedArgument! n) {
                }
 
-               public override void visit_begin_block (Block b) {
+               public override void visit_begin_block (Block! b) {
                        current_symbol = b.symbol;
                }
 
-               public override void visit_end_block (Block b) {
+               public override void visit_end_block (Block! b) {
                        current_symbol = current_symbol.parent_symbol;
                }
 
-               public override void visit_variable_declarator (VariableDeclarator decl) {
+               public override void visit_variable_declarator (VariableDeclarator! decl) {
                        if (decl.type_reference == null) {
                                /* var type */
-                               decl.type_reference = decl.initializer.static_type;
+                               decl.type_reference = decl.initializer.static_type.copy ();
+                               decl.type_reference.is_lvalue_ref = decl.type_reference.is_ref;
+                               decl.type_reference.is_ref = false;
                        }
                        
                        if (decl.type_reference.type != null) {
@@ -194,7 +196,7 @@ namespace Vala {
                        current_symbol.add (decl.name, decl.symbol);
                }
 
-               public override void visit_expression_statement (ExpressionStatement stmt) {
+               public override void visit_expression_statement (ExpressionStatement! stmt) {
                        if (stmt.expression.static_type != null &&
                            stmt.expression.static_type.is_ref) {
                                Report.warning (stmt.source_reference, "Short-living reference");
@@ -202,7 +204,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_begin_foreach_statement (ForeachStatement stmt) {
+               public override void visit_begin_foreach_statement (ForeachStatement! stmt) {
                        if (stmt.type_reference.type != null) {
                                current_source_file.add_symbol_dependency (stmt.type_reference.type.symbol, SourceFileDependencyType.SOURCE);
                        }
@@ -214,40 +216,40 @@ namespace Vala {
                        current_symbol.add (stmt.variable_name, stmt.symbol);
                }
 
-               public override void visit_boolean_literal (BooleanLiteral expr) {
+               public override void visit_boolean_literal (BooleanLiteral! expr) {
                        expr.static_type = bool_type;
                }
 
-               public override void visit_character_literal (CharacterLiteral expr) {
+               public override void visit_character_literal (CharacterLiteral! expr) {
                        expr.static_type = new TypeReference ();
                        expr.static_type.type = (Type_) root_symbol.lookup ("char").node;
                }
 
-               public override void visit_integer_literal (IntegerLiteral expr) {
+               public override void visit_integer_literal (IntegerLiteral! expr) {
                        expr.static_type = new TypeReference ();
                        expr.static_type.type = (Type_) root_symbol.lookup ("int").node;
                }
 
-               public override void visit_real_literal (IntegerLiteral expr) {
+               public override void visit_real_literal (IntegerLiteral! expr) {
                        expr.static_type = new TypeReference ();
                        expr.static_type.type = (Type_) root_symbol.lookup ("double").node;
                }
 
-               public override void visit_string_literal (StringLiteral expr) {
+               public override void visit_string_literal (StringLiteral! expr) {
                        expr.static_type = string_type;
                }
 
-               public override void visit_null_literal (NullLiteral expr) {
+               public override void visit_null_literal (NullLiteral! expr) {
                        /* empty TypeReference represents null */
                        
                        expr.static_type = new TypeReference ();
                }
 
-               public override void visit_literal_expression (LiteralExpression expr) {
+               public override void visit_literal_expression (LiteralExpression! expr) {
                        expr.static_type = expr.literal.static_type;
                }
                
-               TypeReference get_static_type_for_node (CodeNode node) {
+               TypeReference get_static_type_for_node (CodeNode! node) {
                        if (node is Field) {
                                var f = (Field) node;
                                return f.type_reference;
@@ -273,7 +275,7 @@ namespace Vala {
                        return null;
                }
                
-               Symbol symbol_lookup_inherited (Symbol sym, string name) {
+               Symbol symbol_lookup_inherited (Symbol! sym, string! name) {
                        var result = sym.lookup (name);
                        if (result == null && sym.node is Class) {
                                var cl = (Class) sym.node;
@@ -284,7 +286,7 @@ namespace Vala {
                        return result;
                }
 
-               public override void visit_simple_name (SimpleName expr) {
+               public override void visit_simple_name (SimpleName! expr) {
                        var sym = current_symbol;
                        while (sym != null && expr.symbol_reference == null) {
                                expr.symbol_reference = symbol_lookup_inherited (sym, expr.name);
@@ -314,11 +316,11 @@ namespace Vala {
                        expr.static_type = get_static_type_for_node (expr.symbol_reference.node);
                }
 
-               public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
+               public override void visit_parenthesized_expression (ParenthesizedExpression! expr) {
                        expr.static_type = expr.inner.static_type;
                }
 
-               public override void visit_member_access (MemberAccess expr) {
+               public override void visit_member_access (MemberAccess! expr) {
                        if (expr.inner.static_type == null
                            && expr.inner.symbol_reference == null) {
                                /* if there was an error in the inner expression, skip this check */
@@ -349,7 +351,7 @@ namespace Vala {
                        expr.static_type = get_static_type_for_node (expr.symbol_reference.node);
                }
                
-               private bool is_type_compatible (TypeReference expression_type, TypeReference expected_type) {
+               private bool is_type_compatible (TypeReference! expression_type, TypeReference! expected_type) {
                        /* null can be casted to any reference or array type */
                        if (expression_type.type == null && (expected_type.type.is_reference_type () || expected_type.array)) {
                                return true;
@@ -400,7 +402,7 @@ namespace Vala {
                        return false;
                }
 
-               public override void visit_invocation_expression (InvocationExpression expr) {
+               public override void visit_invocation_expression (InvocationExpression! expr) {
                        if (expr.call.symbol_reference == null) {
                                /* if method resolving didn't succeed, skip this check */
                                return;
@@ -450,7 +452,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_object_creation_expression (ObjectCreationExpression expr) {
+               public override void visit_object_creation_expression (ObjectCreationExpression! expr) {
                        if (expr.type_reference.type == null) {
                                /* if type resolving didn't succeed, skip this check */
                                return;
@@ -462,7 +464,7 @@ namespace Vala {
                        expr.static_type.is_ref = true;
                }
 
-               public override void visit_unary_expression (UnaryExpression expr) {
+               public override void visit_unary_expression (UnaryExpression! expr) {
                        if (expr.inner.static_type == null) {
                                /* if there was an error in the inner expression, skip type check */
                                return;
@@ -493,7 +495,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_cast_expression (CastExpression expr) {
+               public override void visit_cast_expression (CastExpression! expr) {
                        if (expr.type_reference.type == null) {
                                /* if type resolving didn't succeed, skip this check */
                                return;
@@ -504,7 +506,7 @@ namespace Vala {
                        expr.static_type = expr.type_reference;
                }
                
-               private bool check_binary_type (BinaryExpression expr, string operation) {
+               private bool check_binary_type (BinaryExpression! expr, string! operation) {
                        if (!is_type_compatible (expr.right.static_type, expr.left.static_type)) {
                                Report.error (expr.source_reference, "%s: Cannot convert from `%s' to `%s'".printf (operation, expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
                                return false;
@@ -513,7 +515,7 @@ namespace Vala {
                        return true;
                }
                
-               public override void visit_binary_expression (BinaryExpression expr) {
+               public override void visit_binary_expression (BinaryExpression! expr) {
                        if (expr.left.static_type == null
                            || expr.right.static_type == null) {
                                /* if there were any errors in inner expressions, skip type check */
@@ -614,7 +616,7 @@ namespace Vala {
                        }
                }
 
-               public override void visit_type_check (TypeCheck expr) {
+               public override void visit_type_check (TypeCheck! expr) {
                        if (expr.type_reference.type == null) {
                                /* if type resolving didn't succeed, skip this check */
                                return;
@@ -625,7 +627,7 @@ namespace Vala {
                        expr.static_type = bool_type;
                }
 
-               public override void visit_assignment (Assignment a) {
+               public override void visit_assignment (Assignment! a) {
                        if (a.left.symbol_reference.node is Signal) {
                                var sig = (Signal) a.left.symbol_reference.node;
                        } else if (a.left.symbol_reference.node is Property) {
@@ -649,7 +651,7 @@ namespace Vala {
                                                                Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
                                                        }
                                                        
-                                                       a.left.static_type.is_ref = true;
+                                                       a.left.static_type.is_lvalue_ref = true;
                                                }
                                        } else if (a.left.static_type.is_lvalue_ref) {
                                                /* lhs wants to own the value
@@ -659,6 +661,8 @@ namespace Vala {
                                        }
                                }
                        }
+                       
+                       a.static_type = a.left.static_type;
                }
        }
 }
index 44bc23fe53bcd5d05dd0f3914fd6abf8633af09a..55dcdc20d2ee92cb067ea2ddefbbac3495255694 100644 (file)
@@ -30,23 +30,24 @@ namespace Vala {
                List<Method> methods;
                
                public string cname;
+               public string ref_function;
                public string lower_case_csuffix;
                bool reference_type;
                
-               public static ref Struct new (string name, SourceReference source) {
+               public static ref Struct new (string! name, SourceReference source) {
                        return (new Struct (name = name, source_reference = source));
                }
 
-               public void add_type_parameter (TypeParameter p) {
+               public void add_type_parameter (TypeParameter! p) {
                        type_parameters.append (p);
                        p.type = this;
                }
                
-               public void add_constant (Constant c) {
+               public void add_constant (Constant! c) {
                        constants.append (c);
                }
                
-               public void add_field (Field f) {
+               public void add_field (Field! f) {
                        fields.append (f);
                }
                
@@ -54,7 +55,7 @@ namespace Vala {
                        return fields.copy ();
                }
                
-               public void add_method (Method m) {
+               public void add_method (Method! m) {
                        return_if_fail (m != null);
                        
                        methods.append (m);
@@ -64,7 +65,7 @@ namespace Vala {
                        return methods.copy ();
                }
                
-               public override void accept (CodeVisitor visitor) {
+               public override void accept (CodeVisitor! visitor) {
                        visitor.visit_begin_struct (this);
                        
                        foreach (TypeParameter p in type_parameters) {
@@ -93,7 +94,7 @@ namespace Vala {
                        return cname;
                }
                
-               public void set_cname (string cname) {
+               public void set_cname (string! cname) {
                        this.cname = cname;
                }
                
@@ -104,7 +105,7 @@ namespace Vala {
                        return lower_case_csuffix;
                }
                
-               public void set_lower_case_csuffix (string csuffix) {
+               public void set_lower_case_csuffix (string! csuffix) {
                        this.lower_case_csuffix = csuffix;
                }
                
@@ -123,7 +124,7 @@ namespace Vala {
                        return reference_type;
                }
                
-               void process_ccode_attribute (Attribute a) {
+               private void process_ccode_attribute (Attribute! a) {
                        foreach (NamedArgument arg in a.args) {
                                if (arg.name == "cname") {
                                        /* this will already be checked during semantic analysis */
@@ -148,12 +149,27 @@ namespace Vala {
                        }
                }
                
+               private void process_ref_type_attribute (Attribute! a) {
+                       reference_type = true;
+                       foreach (NamedArgument arg in a.args) {
+                               if (arg.name == "ref_function") {
+                                       /* this will already be checked during semantic analysis */
+                                       if (arg.argument is LiteralExpression) {
+                                               var lit = ((LiteralExpression) arg.argument).literal;
+                                               if (lit is StringLiteral) {
+                                                       set_ref_function (((StringLiteral) lit).eval ());
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
                public void process_attributes () {
                        foreach (Attribute a in attributes) {
                                if (a.name == "CCode") {
                                        process_ccode_attribute (a);
                                } else if (a.name == "ReferenceType") {
-                                       reference_type = true;
+                                       process_ref_type_attribute (a);
                                }
                        }
                }
@@ -162,6 +178,18 @@ namespace Vala {
                        return false;
                }
                
+               public override string get_ref_function () {
+                       if (ref_function == null) {
+                               Report.warning (source_reference, "type foo is missing a copy/reference increment function");
+                               ref_function = "g_strdup";
+                       }
+                       return ref_function;
+               }
+               
+               public void set_ref_function (string! name) {
+                       this.ref_function = name;
+               }
+               
                public override string get_free_function () {
                        return "g_free";
                }
index dc55c547d7e668c57ac8260efd411424e44ce2fa..d4ac3c74bea9248eec030f9fa360bf5e2bfed5d9 100644 (file)
@@ -102,11 +102,13 @@ namespace Vala {
                                if (sym == null) {
                                        foreach (NamespaceReference ns in current_using_directives) {
                                                var local_sym = ns.namespace_symbol.lookup (type.type_name);
-                                               if (sym != null && local_sym != null) {
-                                                       Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ()));
-                                                       return;
+                                               if (local_sym != null) {
+                                                       if (sym != null) {
+                                                               Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ()));
+                                                               return;
+                                                       }
+                                                       sym = local_sym;
                                                }
-                                               sym = local_sym;
                                        }
                                }
                                if (sym == null) {
@@ -132,6 +134,13 @@ namespace Vala {
                                }
                                type.type = (Type_) sym.node;
                        }
+                       
+                       if (type.type != null && !type.type.is_reference_type ()) {
+                               /* reset is_lvalue_ref for contexts where types
+                                * are ref by default (field declarations)
+                                */
+                               type.is_lvalue_ref = false;
+                       }
                }
        }
 }
index c6960c74cfe50a99f34a9faea2cf6744d9cea1c0..63001267c3ffbaaffe89e847a42d75f94c659df4 100644 (file)
@@ -35,7 +35,7 @@ namespace Vala {
                public abstract string get_ref_function ();
                public abstract string get_free_function ();
                
-               public abstract string get_upper_case_cname (string infix);
+               public abstract ref string get_upper_case_cname (string infix);
                public abstract string get_lower_case_cname (string infix);
                
                public List<string> cheader_filenames;
index f2de50b042f45cc71a79de08c7dcab0c413dcb82..a4ad46f75d99d142f0b1da763c3d691d8bc03577 100644 (file)
@@ -124,5 +124,20 @@ namespace Vala {
                                return "null";
                        }
                }
+               
+               public ref TypeReference copy () {
+                       var result = new TypeReference ();
+                       result.is_ref = is_ref;
+                       result.is_lvalue_ref = is_lvalue_ref;
+                       result.is_weak = is_weak;
+                       result.is_out = is_out;
+                       result.array = array;
+                       result.array_own = array_own;
+                       result.non_null = non_null;
+                       result.type = type;
+                       result.type_parameter = type_parameter;
+                       
+                       return result;
+               }
        }
 }
index 519de1ae4ad43b69751637e3a22e95c139dff8ae..f99a520e5ab7b419c17a7f7fd899ed520f63adb7 100644 (file)
@@ -112,7 +112,7 @@ public struct unichar {
        public unichar tolower ();
 }
 
-[ReferenceType ()]
+[ReferenceType (ref_function = "g_strdup")]
 [CCode (cname = "char", cheader_filename = "string.h,glib.h")]
 public struct string {
        [CCode (cname = "g_str_has_suffix")]
@@ -292,14 +292,14 @@ namespace GLib {
                string arg_description;
        }
        
-       [ReferenceType ()]
+       [ReferenceType (ref_function = "g_list_copy")]
        public struct List<G> {
                [ReturnsModifiedPointer ()]
-               public void append (G data);
+               public void append (ref G data);
                [ReturnsModifiedPointer ()]
-               public void prepend (G data);
+               public void prepend (ref G data);
                [ReturnsModifiedPointer ()]
-               public void insert (G data, int position);
+               public void insert (ref G data, int position);
                [ReturnsModifiedPointer ()]
                public void insert_before (List<G> sibling, G data);
                [ReturnsModifiedPointer ()]
@@ -343,7 +343,7 @@ namespace GLib {
        [ReferenceType ()]
        public struct HashTable<K,V> {
                public static ref HashTable new (HashFunc hash_func, EqualFunc key_equal_func);
-               public void insert (K key, V value);
+               public void insert (ref K key, ref V value);
                public V lookup (K key);
        }