From e5b8ea46c49adf0e540b618a1c111b9404fb89ac Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Thu, 7 Feb 2008 21:35:50 +0000 Subject: [PATCH] Support delete operator for pointers, fixes bug 512868 2008-02-07 Juerg Billeter * 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 --- ChangeLog | 12 +++++ gobject/valaccodegenerator.vala | 27 +++++++--- vala/Makefile.am | 1 + vala/parser.y | 115 ++++++++++++++++++++++++++++++++++------ vala/scanner.l | 1 + vala/valacodecontext.vala | 6 +++ vala/valacodegenerator.vala | 4 ++ vala/valacodevisitor.vala | 8 +++ vala/valadeletestatement.vala | 46 ++++++++++++++++ vala/valainterfacewriter.vala | 9 ++-- vala/valasemanticanalyzer.vala | 19 +++++-- vapi/gio-2.0.vapi | 2 +- vapi/gtk+-2.0.vapi | 2 +- 13 files changed, 218 insertions(+), 34 deletions(-) create mode 100644 vala/valadeletestatement.vala diff --git a/ChangeLog b/ChangeLog index d3f9268..c209029 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2008-02-07 Jürg Billeter + * 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 + * vala/valasemanticanalyzer.vala: allow pointer arithmetic 2008-02-07 Jürg Billeter diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index b386911..642160b 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -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); } diff --git a/vala/Makefile.am b/vala/Makefile.am index d10e4dd..97c2052 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -52,6 +52,7 @@ libvalacore_la_VALASOURCES = \ valadeclarationstatement.vala \ valadelegate.vala \ valadelegatetype.vala \ + valadeletestatement.vala \ valadestructor.vala \ valadostatement.vala \ valaelementaccess.vala \ diff --git a/vala/parser.y b/vala/parser.y index 821af95..ad73feb 100644 --- a/vala/parser.y +++ b/vala/parser.y @@ -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 comment %type identifier +%type identifier_or_keyword %type literal %type boolean_literal %type stars @@ -329,6 +331,7 @@ static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src); %type opt_finally_clause %type finally_clause %type lock_statement +%type delete_statement %type opt_name_specifier %type name_specifier %type 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 diff --git a/vala/scanner.l b/vala/scanner.l index 9838dc8..4565e0a 100644 --- a/vala/scanner.l +++ b/vala/scanner.l @@ -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; } diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index 0b557e0..2f45f01 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -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); diff --git a/vala/valacodegenerator.vala b/vala/valacodegenerator.vala index facf920..58330fc 100644 --- a/vala/valacodegenerator.vala +++ b/vala/valacodegenerator.vala @@ -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; } diff --git a/vala/valacodevisitor.vala b/vala/valacodevisitor.vala index b39e2f3..1514ca4 100644 --- a/vala/valacodevisitor.vala +++ b/vala/valacodevisitor.vala @@ -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 index 0000000..59c7001 --- /dev/null +++ b/vala/valadeletestatement.vala @@ -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 + */ + +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); + } +} diff --git a/vala/valainterfacewriter.vala b/vala/valainterfacewriter.vala index ede7732..74dc79a 100644 --- a/vala/valainterfacewriter.vala +++ b/vala/valainterfacewriter.vala @@ -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); diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 89b21e0..32e47bc 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -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! sl) { var init = new LiteralExpression (new IntegerLiteral (il.size.to_string (), il.source_reference), il.source_reference); init.accept (this); diff --git a/vapi/gio-2.0.vapi b/vapi/gio-2.0.vapi index 78dcf28..320abb6 100644 --- a/vapi/gio-2.0.vapi +++ b/vapi/gio-2.0.vapi @@ -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); diff --git a/vapi/gtk+-2.0.vapi b/vapi/gtk+-2.0.vapi index 6184f8d..30ef955 100644 --- a/vapi/gtk+-2.0.vapi +++ b/vapi/gtk+-2.0.vapi @@ -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); -- 2.7.4