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
valarealliteral.c \
valarealliteral.h \
valarealliteral.vala \
+ valareferencetransferexpression.c \
+ valareferencetransferexpression.h \
+ valareferencetransferexpression.vala \
valareport.c \
valareport.h \
valareport.vala \
valapropertyaccessor.h \
valaproperty.h \
valarealliteral.h \
+ valareferencetransferexpression.h \
valareport.h \
valareturnstatement.h \
valasemanticanalyzer.h \
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
#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>
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)));
}
}
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) {
*/
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);
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);
}
op = CCodeUnaryOperator.ADDRESS_OF;
}
expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode);
-
+
visit_expression (expr);
}
} else {
expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
}
-
+
visit_expression (expr);
}
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) {
}
/**
+ * 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
/* 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
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);
foreach (Expression it_expr in iterator) {
it_expr.accept (visitor);
+ visitor.visit_end_full_expression (it_expr);
}
body.accept (visitor);
--- /dev/null
+/* 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;
+ }
+ }
+}
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 ()));