support temporary variables in initializers and iterators of for
authorJürg Billeter <j@bitron.ch>
Thu, 5 Apr 2007 11:49:49 +0000 (11:49 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 5 Apr 2007 11:49:49 +0000 (11:49 +0000)
2007-04-05  Jürg Billeter  <j@bitron.ch>

* vala/valacodegenerator.vala, vala/valaforstatement.vala: support
  temporary variables in initializers and iterators of for statements
* vala/valacodegenerator.vala: support freeing generic types
* vala/parser.y, vala/valacodevisitor.vala,
  vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala,
  vala/valareferencetransferexpression.vala: add reference transfer
  expressions, e.g. `#var'
* vala/vala.h, vala/Makefile.am: update

svn path=/trunk/; revision=281

vala/ChangeLog
vala/vala/Makefile.am
vala/vala/parser.y
vala/vala/vala.h
vala/vala/valacodegenerator.vala
vala/vala/valacodevisitor.vala
vala/vala/valaforstatement.vala
vala/vala/valareferencetransferexpression.vala [new file with mode: 0644]
vala/vala/valasemanticanalyzer.vala

index ca32dd6..a42ceab 100644 (file)
@@ -1,5 +1,16 @@
 2007-04-05  Jürg Billeter  <j@bitron.ch>
 
+       * vala/valacodegenerator.vala, vala/valaforstatement.vala: support
+         temporary variables in initializers and iterators of for statements
+       * vala/valacodegenerator.vala: support freeing generic types
+       * vala/parser.y, vala/valacodevisitor.vala,
+         vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala,
+         vala/valareferencetransferexpression.vala: add reference transfer
+         expressions, e.g. `#var'
+       * vala/vala.h, vala/Makefile.am: update
+
+2007-04-05  Jürg Billeter  <j@bitron.ch>
+
        * vala/valacodegenerator.vala: generate properties for destroy function
          pointers in generic types
 
index 7ff4eaa..f9a1fb1 100644 (file)
@@ -247,6 +247,9 @@ libvala_la_SOURCES = \
        valarealliteral.c \
        valarealliteral.h \
        valarealliteral.vala \
+       valareferencetransferexpression.c \
+       valareferencetransferexpression.h \
+       valareferencetransferexpression.vala \
        valareport.c \
        valareport.h \
        valareport.vala \
@@ -406,6 +409,7 @@ valainclude_HEADERS = \
        valapropertyaccessor.h \
        valaproperty.h \
        valarealliteral.h \
+       valareferencetransferexpression.h \
        valareport.h \
        valareturnstatement.h \
        valasemanticanalyzer.h \
index 5e65199..229683c 100644 (file)
@@ -908,6 +908,13 @@ unary_expression
                g_object_unref (src);
                g_object_unref ($2);
          }
+       | HASH unary_expression
+         {
+               ValaSourceReference *src = src(@1);
+               $$ = VALA_EXPRESSION (vala_reference_transfer_expression_new ($2, src));
+               g_object_unref (src);
+               g_object_unref ($2);
+         }
        | cast_expression
        | pointer_indirection_expression
        | addressof_expression
index d68c473..9b66faa 100644 (file)
@@ -56,6 +56,7 @@
 #include <vala/valaproperty.h>
 #include <vala/valapropertyaccessor.h>
 #include <vala/valarealliteral.h>
+#include <vala/valareferencetransferexpression.h>
 #include <vala/valareport.h>
 #include <vala/valareturnstatement.h>
 #include <vala/valasignal.h>
index 6eb27ba..2034963 100644 (file)
@@ -2086,7 +2086,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                
                if (memory_management) {
                        foreach (VariableDeclarator decl in local_vars) {
-                               if (decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) {
+                               if (decl.type_reference.takes_ownership) {
                                        cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference)));
                                }
                        }
@@ -2244,11 +2244,12 @@ public class Vala.CodeGenerator : CodeVisitor {
                                unref_function = type.data_type.get_free_function ();
                        }
                        return new CCodeIdentifier (unref_function);
-               } else if (type.type_parameter != null) {
-                       // TODO add support for type parameters
+               } else if (type.type_parameter != null && current_class != null) {
+                       string func_name = "%s_destroy_func".printf (type.type_parameter.name.down ());
+                       return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+               } else {
                        return new CCodeConstant ("NULL");
                }
-               Report.error (null, "internal error: destroy function requested for unknown type %s".printf (type.to_string ()));
        }
 
        private ref CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type) {
@@ -2260,6 +2261,15 @@ public class Vala.CodeGenerator : CodeVisitor {
                 */
 
                var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL"));
+               if (type.data_type == null) {
+                       if (current_class == null) {
+                               return new CCodeConstant ("NULL");
+                       }
+
+                       // unref functions are optional for type parameters
+                       var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL"));
+                       cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull);
+               }
 
                var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
                ccall.add_argument (cvar);
@@ -2516,17 +2526,18 @@ public class Vala.CodeGenerator : CodeVisitor {
 
        public override void visit_for_statement (ForStatement! stmt) {
                var cfor = new CCodeForStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
+               stmt.ccodenode = cfor;
                
                foreach (Expression init_expr in stmt.get_initializer ()) {
                        cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
+                       create_temp_decl (stmt, init_expr.temp_vars);
                }
                
                foreach (Expression it_expr in stmt.get_iterator ()) {
                        cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
+                       create_temp_decl (stmt, it_expr.temp_vars);
                }
-               
-               stmt.ccodenode = cfor;
-               
+
                create_temp_decl (stmt, stmt.condition.temp_vars);
        }
 
@@ -3719,7 +3730,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                        op = CCodeUnaryOperator.ADDRESS_OF;
                }
                expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode);
-               
+
                visit_expression (expr);
        }
 
@@ -3730,7 +3741,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                } else {
                        expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
                }
-               
+
                visit_expression (expr);
        }
        
@@ -3742,6 +3753,21 @@ public class Vala.CodeGenerator : CodeVisitor {
                expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
        }
 
+       public override void visit_reference_transfer_expression (ReferenceTransferExpression! expr) {
+               /* (tmp = var, var = null, tmp) */
+               var ccomma = new CCodeCommaExpression ();
+               var temp_decl = get_temp_variable_declarator (expr.static_type);
+               temp_vars.prepend (temp_decl);
+               var cvar = new CCodeIdentifier (temp_decl.name);
+
+               ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode));
+               ccomma.append_expression (new CCodeAssignment ((CCodeExpression) expr.inner.ccodenode, new CCodeConstant ("NULL")));
+               ccomma.append_expression (cvar);
+               expr.ccodenode = ccomma;
+
+               visit_expression (expr);
+       }
+
        public override void visit_binary_expression (BinaryExpression! expr) {
                CCodeBinaryOperator op;
                if (expr.operator == BinaryOperator.PLUS) {
index 690748a..e5624f5 100644 (file)
@@ -765,6 +765,14 @@ public abstract class Vala.CodeVisitor {
        }
 
        /**
+        * Visit operation called for reference transfer expressions.
+        *
+        * @param expr a reference transfer expression
+        */
+       public virtual void visit_reference_transfer_expression (ReferenceTransferExpression! expr) {
+       }
+
+       /**
         * Visit operation called for binary expressions.
         *
         * @param expr a binary expression
index 7e5b8ab..e7d7238 100644 (file)
@@ -1,6 +1,6 @@
 /* valaforstatement.vala
  *
- * Copyright (C) 2006  Jürg Billeter
+ * Copyright (C) 2006-2007  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
@@ -104,6 +104,7 @@ public class Vala.ForStatement : Statement {
        public override void accept (CodeVisitor! visitor) {
                foreach (Expression init_expr in initializer) {
                        init_expr.accept (visitor);
+                       visitor.visit_end_full_expression (init_expr);
                }
 
                condition.accept (visitor);
@@ -112,6 +113,7 @@ public class Vala.ForStatement : Statement {
 
                foreach (Expression it_expr in iterator) {
                        it_expr.accept (visitor);
+                       visitor.visit_end_full_expression (it_expr);
                }
                
                body.accept (visitor);
diff --git a/vala/vala/valareferencetransferexpression.vala b/vala/vala/valareferencetransferexpression.vala
new file mode 100644 (file)
index 0000000..ec6000d
--- /dev/null
@@ -0,0 +1,64 @@
+/* valareferencetransferexpression.vala
+ *
+ * Copyright (C) 2007  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;
+
+/**
+ * Represents a reference transfer expression in the source code, e.g. `#foo'.
+ */
+public class Vala.ReferenceTransferExpression : Expression {
+       /**
+        * The variable whose reference is to be transferred.
+        */
+       public Expression! inner {
+               get {
+                       return _inner;
+               }
+               set construct {
+                       _inner = value;
+                       _inner.parent_node = this;
+               }
+       }
+       
+       private Expression! _inner;
+
+       /**
+        * Creates a new reference transfer expression.
+        *
+        * @param inner variable whose reference is to be transferred
+        * @return      newly created reference transfer expression
+        */
+       public ReferenceTransferExpression (construct Expression! inner, construct SourceReference source_reference = null) {
+       }
+       
+       public override void accept (CodeVisitor! visitor) {
+               inner.accept (visitor);
+
+               visitor.visit_reference_transfer_expression (this);
+       }
+
+       public override void replace (CodeNode! old_node, CodeNode! new_node) {
+               if (inner == old_node) {
+                       inner = (Expression) new_node;
+               }
+       }
+}
index ae8956a..f889668 100644 (file)
@@ -1681,6 +1681,30 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                expr.static_type.takes_ownership = expr.inner.static_type.takes_ownership;
        }
 
+       public override void visit_reference_transfer_expression (ReferenceTransferExpression! expr) {
+               if (expr.inner.error) {
+                       /* if there was an error in the inner expression, skip type check */
+                       expr.error = true;
+                       return;
+               }
+
+               if (!(expr.inner is MemberAccess || expr.inner is ElementAccess)) {
+                       expr.error = true;
+                       Report.error (expr.source_reference, "Reference transfer not supported for this expression");
+                       return;
+               }
+
+               if (!expr.inner.static_type.takes_ownership) {
+                       expr.error = true;
+                       Report.error (expr.source_reference, "No reference to be transferred");
+                       return;
+               }
+
+               expr.static_type = expr.inner.static_type.copy ();
+               expr.static_type.transfers_ownership = true;
+               expr.static_type.takes_ownership = false;
+       }
+
        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 ()));