Commit cb55d7ec authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

support temporary variables in initializers and iterators of for

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
parent 08974624
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
......
......@@ -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 \
......
......@@ -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
......
......@@ -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>
......
......@@ -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) {
......
......@@ -764,6 +764,14 @@ public abstract class Vala.CodeVisitor {
public virtual void visit_addressof_expression (AddressofExpression! expr) {
}
/**
* 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.
*
......
/* 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);
......
/* 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;
}
}
}
......@@ -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 ()));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment