Support delete operator for pointers, fixes bug 512868
authorJuerg Billeter <j@bitron.ch>
Thu, 7 Feb 2008 21:35:50 +0000 (21:35 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 7 Feb 2008 21:35:50 +0000 (21:35 +0000)
2008-02-07  Juerg Billeter  <j@bitron.ch>

* vala/Makefile.am, vala/parser.y, vala/scanner.l,
  vala/valacodecontext.vala, vala/valacodegenerator.vala,
  vala/valacodevisitor.vala, vala/valadeletestatement.vala,
  vala/valainterfacewriter.vala, vala/valasemanticanalyzer.vala,
  gobject/valaccodegenerator.vala:

  Support delete operator for pointers, fixes bug 512868

* vapi/gio-2.0.vapi, vapi/gtk+-2.0.vapi: regenerated

svn path=/trunk/; revision=992

13 files changed:
ChangeLog
gobject/valaccodegenerator.vala
vala/Makefile.am
vala/parser.y
vala/scanner.l
vala/valacodecontext.vala
vala/valacodegenerator.vala
vala/valacodevisitor.vala
vala/valadeletestatement.vala [new file with mode: 0644]
vala/valainterfacewriter.vala
vala/valasemanticanalyzer.vala
vapi/gio-2.0.vapi
vapi/gtk+-2.0.vapi

index d3f9268..c209029 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2008-02-07  Jürg Billeter  <j@bitron.ch>
 
+       * vala/Makefile.am, vala/parser.y, vala/scanner.l,
+         vala/valacodecontext.vala, vala/valacodegenerator.vala,
+         vala/valacodevisitor.vala, vala/valadeletestatement.vala,
+         vala/valainterfacewriter.vala, vala/valasemanticanalyzer.vala,
+         gobject/valaccodegenerator.vala:
+
+         Support delete operator for pointers, fixes bug 512868
+
+       * vapi/gio-2.0.vapi, vapi/gtk+-2.0.vapi: regenerated
+
+2008-02-07  Jürg Billeter  <j@bitron.ch>
+
        * vala/valasemanticanalyzer.vala: allow pointer arithmetic
 
 2008-02-07  Jürg Billeter  <j@bitron.ch>
index b386911..642160b 100644 (file)
@@ -1082,6 +1082,8 @@ public class Vala.CCodeGenerator : CodeGenerator {
                } else if (type.type_parameter != null && current_type_symbol is Class) {
                        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 if (type is PointerType) {
+                       return new CCodeIdentifier ("g_free");
                } else {
                        return new CCodeConstant ("NULL");
                }
@@ -2090,12 +2092,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
        private string get_symbol_lock_name (Symbol! sym) {
                return "__lock_%s".printf (sym.name);
        }
-       
-       /**
-        * Visit operation called for lock statements.
-        *
-        * @param stmt a lock statement
-        */
+
        public override void visit_lock_statement (LockStatement! stmt) {
                var cn = new CCodeFragment ();
                CCodeExpression l = null;
@@ -2124,6 +2121,20 @@ public class Vala.CCodeGenerator : CodeGenerator {
                stmt.ccodenode = cn;
        }
 
+       public override void visit_delete_statement (DeleteStatement stmt) {
+               stmt.accept_children (this);
+
+               var pointer_type = (PointerType) stmt.expression.static_type;
+               DataType type = pointer_type;
+               if (pointer_type.base_type.data_type != null && pointer_type.base_type.data_type.is_reference_type ()) {
+                       type = pointer_type.base_type;
+               }
+
+               var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
+               ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode);
+               stmt.ccodenode = new CCodeExpressionStatement (ccall);
+       }
+
        public override void visit_array_creation_expression (ArrayCreationExpression! expr) {
                expr.code_binding.emit ();
        }
@@ -3404,6 +3415,10 @@ public class Vala.CCodeGenerator : CodeGenerator {
                return null;
        }
 
+       public override CodeBinding create_delete_statement_binding (DeleteStatement node) {
+               return null;
+       }
+
        public override CodeBinding create_array_creation_expression_binding (ArrayCreationExpression! node) {
                return new CCodeArrayCreationExpressionBinding (this, node);
        }
index d10e4dd..97c2052 100644 (file)
@@ -52,6 +52,7 @@ libvalacore_la_VALASOURCES = \
        valadeclarationstatement.vala \
        valadelegate.vala \
        valadelegatetype.vala \
+       valadeletestatement.vala \
        valadestructor.vala \
        valadostatement.vala \
        valaelementaccess.vala \
index 821af95..ad73feb 100644 (file)
@@ -168,6 +168,7 @@ static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src);
 %token CONTINUE "continue"
 %token DEFAULT "default"
 %token DELEGATE "delegate"
+%token DELETE "delete"
 %token DO "do"
 %token ELSE "else"
 %token ENSURES "ensures"
@@ -223,6 +224,7 @@ static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src);
 
 %type <str> comment
 %type <str> identifier
+%type <str> identifier_or_keyword
 %type <literal> literal
 %type <literal> boolean_literal
 %type <num> stars
@@ -329,6 +331,7 @@ static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src);
 %type <block> opt_finally_clause
 %type <block> finally_clause
 %type <statement> lock_statement
+%type <statement> delete_statement
 %type <str> opt_name_specifier
 %type <str> name_specifier
 %type <num> opt_access_modifier
@@ -408,22 +411,74 @@ opt_comma
 /* identifiers never conflict with context-specific keywords get, set, requires, or ensures */
 identifier
        : IDENTIFIER
-       | GET
-         {
-               $$ = g_strdup ("get");
-         }
-       | SET
-         {
-               $$ = g_strdup ("set");
-         }
-       | REQUIRES
-         {
-               $$ = g_strdup ("requires");
-         }
-       | ENSURES
-         {
-               $$ = g_strdup ("ensures");
-         }
+       | GET { $$ = g_strdup ("get"); }
+       | SET { $$ = g_strdup ("set"); }
+       | REQUIRES { $$ = g_strdup ("requires"); }
+       | ENSURES { $$ = g_strdup ("ensures"); }
+       ;
+
+/* identifiers never conflict with context-specific keywords get, set, requires, or ensures */
+identifier_or_keyword
+       : IDENTIFIER
+       | ABSTRACT { $$ = g_strdup ("abstract"); }
+       | AS { $$ = g_strdup ("as"); }
+       | BASE { $$ = g_strdup ("base"); }
+       | BREAK { $$ = g_strdup ("break"); }
+       | CASE { $$ = g_strdup ("case"); }
+       | CATCH { $$ = g_strdup ("catch"); }
+       | CLASS { $$ = g_strdup ("class"); }
+       | CONST { $$ = g_strdup ("const"); }
+       | CONSTRUCT { $$ = g_strdup ("construct"); }
+       | CONTINUE { $$ = g_strdup ("continue"); }
+       | DEFAULT { $$ = g_strdup ("default"); }
+       | DELEGATE { $$ = g_strdup ("delegate"); }
+       | DELETE { $$ = g_strdup ("delete"); }
+       | DO { $$ = g_strdup ("do"); }
+       | ELSE { $$ = g_strdup ("else"); }
+       | ENSURES { $$ = g_strdup ("ensures"); }
+       | ENUM { $$ = g_strdup ("enum"); }
+       | ERRORDOMAIN { $$ = g_strdup ("errordomain"); }
+       | VALA_FALSE { $$ = g_strdup ("false"); }
+       | FINALLY { $$ = g_strdup ("finally"); }
+       | FOR { $$ = g_strdup ("for"); }
+       | FOREACH { $$ = g_strdup ("foreach"); }
+       | GET { $$ = g_strdup ("get"); }
+       | IF { $$ = g_strdup ("if"); }
+       | IN { $$ = g_strdup ("in"); }
+       | INLINE { $$ = g_strdup ("inline"); }
+       | INTERFACE { $$ = g_strdup ("interface"); }
+       | IS { $$ = g_strdup ("is"); }
+       | LOCK { $$ = g_strdup ("lock"); }
+       | NAMESPACE { $$ = g_strdup ("namespace"); }
+       | NEW { $$ = g_strdup ("new"); }
+       | VALA_NULL { $$ = g_strdup ("null"); }
+       | OUT { $$ = g_strdup ("out"); }
+       | OVERRIDE { $$ = g_strdup ("override"); }
+       | PRIVATE { $$ = g_strdup ("private"); }
+       | PROTECTED { $$ = g_strdup ("protected"); }
+       | PUBLIC { $$ = g_strdup ("public"); }
+       | REF { $$ = g_strdup ("ref"); }
+       | REQUIRES { $$ = g_strdup ("requires"); }
+       | RETURN { $$ = g_strdup ("return"); }
+       | SET { $$ = g_strdup ("set"); }
+       | SIGNAL { $$ = g_strdup ("signal"); }
+       | SIZEOF { $$ = g_strdup ("sizeof"); }
+       | STATIC { $$ = g_strdup ("static"); }
+       | STRUCT { $$ = g_strdup ("struct"); }
+       | SWITCH { $$ = g_strdup ("switch"); }
+       | THIS { $$ = g_strdup ("this"); }
+       | THROW { $$ = g_strdup ("throw"); }
+       | THROWS { $$ = g_strdup ("throws"); }
+       | VALA_TRUE { $$ = g_strdup ("true"); }
+       | TRY { $$ = g_strdup ("try"); }
+       | TYPEOF { $$ = g_strdup ("typeof"); }
+       | USING { $$ = g_strdup ("using"); }
+       | VAR { $$ = g_strdup ("var"); }
+       | VIRTUAL { $$ = g_strdup ("virtual"); }
+       | VOID { $$ = g_strdup ("void"); }
+       | VOLATILE { $$ = g_strdup ("volatile"); }
+       | WEAK { $$ = g_strdup ("weak"); }
+       | WHILE { $$ = g_strdup ("while"); }
        ;
 
 literal
@@ -791,7 +846,7 @@ parenthesized_expression
        ;
 
 member_access
-       : primary_expression DOT identifier opt_type_argument_list
+       : primary_expression DOT identifier_or_keyword opt_type_argument_list
          {
                ValaSourceReference *src = src(@3);
                $$ = VALA_EXPRESSION (vala_code_context_create_member_access (context, $1, $3, src));
@@ -1715,6 +1770,7 @@ statement
        | jump_statement
        | try_statement
        | lock_statement
+       | delete_statement
        ;
 
 embedded_statement
@@ -1810,6 +1866,19 @@ embedded_statement
                        g_object_unref (src);
                }
          }
+       | delete_statement
+         {
+               ValaSourceReference *src = src(@1);
+               if ($1 == NULL) {
+                       // error in subexpression
+                       $$ = NULL;
+               } else {
+                       $$ = vala_code_context_create_block (context, src);
+                       vala_block_add_statement ($$, $1);
+                       g_object_unref ($1);
+                       g_object_unref (src);
+               }
+         }
        ;
 
 block
@@ -2424,6 +2493,7 @@ general_catch_clause
                g_object_unref (src);
          }
        ;
+
 opt_finally_clause
        : /* empty */
          {
@@ -2449,6 +2519,17 @@ lock_statement
                g_object_unref ($4);
                g_object_unref ($6);
          }
+       ;
+
+delete_statement
+       : comment DELETE expression SEMICOLON
+         {
+               ValaSourceReference *src = src_com(@2, $1);
+               $$ = VALA_STATEMENT (vala_code_context_create_delete_statement (context, $3, src));
+               g_object_unref (src);
+               g_object_unref ($3);
+         }
+       ;
 
 namespace_declaration
        : comment opt_attributes NAMESPACE identifier
index 9838dc8..4565e0a 100644 (file)
@@ -147,6 +147,7 @@ generic_type                        {type_name}("<"{space}{type_name}("?"|"*"+)?(","{space}{type_name
 "continue"     { uploc; return CONTINUE; }
 "default"      { uploc; return DEFAULT; }
 "delegate"     { uploc; return DELEGATE; }
+"delete"       { uploc; return DELETE; }
 "do"           { uploc; return DO; }
 "else"         { uploc; return ELSE; }
 "ensures"      { uploc; return ENSURES; }
index 0b557e0..2f45f01 100644 (file)
@@ -697,6 +697,12 @@ public class Vala.CodeContext : Object {
                return node;
        }
 
+       public DeleteStatement create_delete_statement (Expression expression, SourceReference source_reference = null) {
+               var node = new DeleteStatement (expression, source_reference);
+               node.code_binding = codegen.create_delete_statement_binding (node);
+               return node;
+       }
+
        public ArrayCreationExpression! create_array_creation_expression (DataType element_type, int rank, InitializerList initializer_list, SourceReference source_reference) {
                var node = new ArrayCreationExpression (element_type, rank, initializer_list, source_reference);
                node.code_binding = codegen.create_array_creation_expression_binding (node);
index facf920..58330fc 100644 (file)
@@ -202,6 +202,10 @@ public class Vala.CodeGenerator : CodeVisitor {
                return null;
        }
 
+       public virtual CodeBinding create_delete_statement_binding (DeleteStatement node) {
+               return null;
+       }
+
        public virtual CodeBinding create_array_creation_expression_binding (ArrayCreationExpression! node) {
                return null;
        }
index b39e2f3..1514ca4 100644 (file)
@@ -404,6 +404,14 @@ public abstract class Vala.CodeVisitor : Object {
        }
 
        /**
+        * Visit operation called for delete statements.
+        *
+        * @param stmt a delete statement
+        */
+       public virtual void visit_delete_statement (DeleteStatement stmt) {
+       }
+
+       /**
         * Visit operations called for array creation expresions.
         *
         * @param expr an array creation expression
diff --git a/vala/valadeletestatement.vala b/vala/valadeletestatement.vala
new file mode 100644 (file)
index 0000000..59c7001
--- /dev/null
@@ -0,0 +1,46 @@
+/* valadeletestatement.vala
+ *
+ * Copyright (C) 2008  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.1 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 delete statement e.g. "delete a".
+ */
+public class Vala.DeleteStatement : CodeNode, Statement {
+       /**
+        * Expression representing the instance to be freed.
+        */
+       public Expression expression { get; set; }
+
+       public DeleteStatement (Expression expression, SourceReference source_reference = null) {
+               this.expression = expression;
+               this.source_reference = source_reference;
+       }
+
+       public override void accept (CodeVisitor! visitor) {
+               visitor.visit_delete_statement (this);
+       }
+
+       public override void accept_children (CodeVisitor! visitor) {
+               expression.accept (visitor);
+       }
+}
index ede7732..74dc79a 100644 (file)
@@ -720,10 +720,11 @@ public class Vala.InterfaceWriter : CodeVisitor {
        
        private void write_identifier (string! s) {
                if (s == "base" || s == "break" || s == "class" ||
-                   s == "construct" || s == "delegate" || s == "do" ||
-                   s == "foreach" || s == "in" || s == "interface" ||
-                   s == "lock" || s == "namespace" || s == "new" ||
-                   s == "out" || s == "ref" || s == "signal") {
+                   s == "construct" || s == "delegate" || s == "delete" ||
+                   s == "do" || s == "foreach" || s == "in" ||
+                   s == "interface" || s == "lock" || s == "namespace" ||
+                   s == "new" || s == "out" || s == "ref" ||
+                   s == "signal") {
                        stream.putc ('@');
                }
                write_string (s);
index 89b21e0..32e47bc 100644 (file)
@@ -1087,11 +1087,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                clause.accept_children (this);
        }
 
-       /**
-        * Visit operation called for lock statements.
-        *
-        * @param stmt a lock statement
-        */
        public override void visit_lock_statement (LockStatement! stmt) {
                /* resource must be a member access and denote a Lockable */
                if (!(stmt.resource is MemberAccess && stmt.resource.symbol_reference is Lockable)) {
@@ -1111,6 +1106,20 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                ((Lockable) stmt.resource.symbol_reference).set_lock_used (true);
        }
 
+       public override void visit_delete_statement (DeleteStatement stmt) {
+               stmt.accept_children (this);
+
+               if (stmt.expression.error) {
+                       // if there was an error in the inner expression, skip this check
+                       return;
+               }
+
+               if (!(stmt.expression.static_type is PointerType)) {
+                       stmt.error = true;
+                       Report.error (stmt.source_reference, "delete operator not supported for `%s'".printf (stmt.expression.static_type.to_string ()));
+               }
+       }
+
        private int create_sizes_from_initializer_list (InitializerList! il, int rank, Gee.List<LiteralExpression>! sl) {
                var init = new LiteralExpression (new IntegerLiteral (il.size.to_string (), il.source_reference), il.source_reference);
                init.accept (this);
index 78dcf28..320abb6 100644 (file)
@@ -650,7 +650,7 @@ namespace GLib {
        [CCode (cheader_filename = "gio/gio.h")]
        public interface File : GLib.Object {
                public bool copy_attributes (GLib.File destination, GLib.FileCopyFlags flags, GLib.Cancellable cancellable) throws GLib.Error;
-               public bool delete (GLib.Cancellable cancellable) throws GLib.Error;
+               public bool @delete (GLib.Cancellable cancellable) throws GLib.Error;
                public weak GLib.File get_child (string name);
                public bool load_contents (GLib.Cancellable cancellable, out weak string contents, ulong length, out weak string etag_out) throws GLib.Error;
                public void load_contents_async (GLib.Cancellable cancellable, GLib.AsyncReadyCallback callback, pointer user_data);
index 6184f8d..30ef955 100644 (file)
@@ -4700,7 +4700,7 @@ namespace Gtk {
                public weak Gtk.TextMark create_mark (string mark_name, Gtk.TextIter where, bool left_gravity);
                public weak Gtk.TextTag create_tag (string tag_name, ...);
                public void cut_clipboard (Gtk.Clipboard clipboard, bool default_editable);
-               public void delete (Gtk.TextIter start, Gtk.TextIter end);
+               public void @delete (Gtk.TextIter start, Gtk.TextIter end);
                public bool delete_interactive (Gtk.TextIter start_iter, Gtk.TextIter end_iter, bool default_editable);
                public void delete_mark (Gtk.TextMark mark);
                public void delete_mark_by_name (string name);