From: Jürg Billeter Date: Thu, 5 Apr 2007 11:49:49 +0000 (+0000) Subject: support temporary variables in initializers and iterators of for X-Git-Tag: VALA_0_0_9~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cb55d7ec9e5c533f424924095d2d8bea34cdfa83;p=platform%2Fupstream%2Fvala.git support temporary variables in initializers and iterators of for 2007-04-05 Jürg Billeter * 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 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index ca32dd6..a42ceab 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,5 +1,16 @@ 2007-04-05 Jürg Billeter + * 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 + * vala/valacodegenerator.vala: generate properties for destroy function pointers in generic types diff --git a/vala/vala/Makefile.am b/vala/vala/Makefile.am index 7ff4eaa..f9a1fb1 100644 --- a/vala/vala/Makefile.am +++ b/vala/vala/Makefile.am @@ -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 \ diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 5e65199..229683c 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -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 diff --git a/vala/vala/vala.h b/vala/vala/vala.h index d68c473..9b66faa 100644 --- a/vala/vala/vala.h +++ b/vala/vala/vala.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 6eb27ba..2034963 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -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) { diff --git a/vala/vala/valacodevisitor.vala b/vala/vala/valacodevisitor.vala index 690748a..e5624f5 100644 --- a/vala/vala/valacodevisitor.vala +++ b/vala/vala/valacodevisitor.vala @@ -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 diff --git a/vala/vala/valaforstatement.vala b/vala/vala/valaforstatement.vala index 7e5b8ab..e7d7238 100644 --- a/vala/vala/valaforstatement.vala +++ b/vala/vala/valaforstatement.vala @@ -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 index 0000000..ec6000d --- /dev/null +++ b/vala/vala/valareferencetransferexpression.vala @@ -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 + */ + +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; + } + } +} diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index ae8956a..f889668 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -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 ()));