Commit 8cbc51a1 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

Support += to efficiently append elements to arrays, fixes part of bug

2009-01-04  Jürg Billeter  <j@bitron.ch>

	* vala/valabinaryexpression.vala:
	* gobject/valaccodearraymodule.vala:
	* gobject/valaccodeassignmentmodule.vala:
	* gobject/valaccodebasemodule.vala:
	* gobject/valaccodemodule.vala:

	Support += to efficiently append elements to arrays,
	fixes part of bug 566425

svn path=/trunk/; revision=2264
parent 28f092fb
2009-01-04 Jürg Billeter <j@bitron.ch>
* vala/valabinaryexpression.vala:
* gobject/valaccodearraymodule.vala:
* gobject/valaccodeassignmentmodule.vala:
* gobject/valaccodebasemodule.vala:
* gobject/valaccodemodule.vala:
Support += to efficiently append elements to arrays,
fixes part of bug 566425
2009-01-04 Jürg Billeter <j@bitron.ch>
* gobject/valaccodebasemodule.vala:
......
/* valaccodearraymodule.vala
*
* Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
* Copyright (C) 2006-2009 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -21,14 +22,11 @@
* Raffaele Sandrini <raffaele@sandrini.ch>
*/
using GLib;
using Gee;
/**
* The link between an assignment and generated code.
*/
public class Vala.CCodeArrayModule : CCodeMethodCallModule {
private int next_array_dup_id = 0;
int next_array_dup_id = 0;
int next_array_add_id = 0;
public CCodeArrayModule (CCodeGenerator codegen, CCodeModule? next) {
base (codegen, next);
......@@ -227,6 +225,48 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
}
}
public override string get_array_size_cname (string array_cname) {
return "%s_size".printf (array_cname);
}
public override CCodeExpression get_array_size_cexpression (Expression array_expr) {
if (array_expr.symbol_reference is LocalVariable) {
var local = (LocalVariable) array_expr.symbol_reference;
return get_variable_cexpression (get_array_size_cname (get_variable_cname (local.name)));
} else if (array_expr.symbol_reference is Field) {
var field = (Field) array_expr.symbol_reference;
var ma = (MemberAccess) array_expr;
CCodeExpression size_expr = null;
if (field.binding == MemberBinding.INSTANCE) {
var cl = field.parent_symbol as Class;
bool is_gtypeinstance = (cl != null && !cl.is_compact);
string size_cname = get_array_size_cname (field.name);
CCodeExpression typed_inst = (CCodeExpression) get_ccodenode (ma.inner);
CCodeExpression inst;
if (is_gtypeinstance && field.access == SymbolAccessibility.PRIVATE) {
inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
} else {
inst = typed_inst;
}
if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
size_expr = new CCodeMemberAccess.pointer (inst, size_cname);
} else {
size_expr = new CCodeMemberAccess (inst, size_cname);
}
} else {
size_expr = new CCodeIdentifier (get_array_size_cname (field.get_cname ()));
}
return size_expr;
}
assert_not_reached ();
}
public override void visit_element_access (ElementAccess expr) {
expr.accept_children (codegen);
......@@ -480,6 +520,68 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
return dup_func;
}
string generate_array_add_wrapper (ArrayType array_type) {
string add_func = "_vala_array_add%d".printf (++next_array_add_id);
if (!add_wrapper (add_func)) {
// wrapper already defined
return add_func;
}
// declaration
var function = new CCodeFunction (add_func, "void");
function.modifiers = CCodeModifiers.STATIC;
function.add_parameter (new CCodeFormalParameter ("array", array_type.get_cname () + "*"));
function.add_parameter (new CCodeFormalParameter ("length", "int*"));
function.add_parameter (new CCodeFormalParameter ("size", "int*"));
string typename = array_type.element_type.get_cname ();
CCodeExpression value = new CCodeIdentifier ("value");
if (array_type.element_type.is_real_struct_type ()) {
if (!array_type.element_type.nullable || !array_type.element_type.value_owned) {
typename = "const " + typename;
}
if (!array_type.element_type.nullable) {
typename += "*";
value = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, value);
}
}
function.add_parameter (new CCodeFormalParameter ("value", typename));
var array = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("array"));
var length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("length"));
var size = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("size"));
// definition
var block = new CCodeBlock ();
var renew_call = new CCodeFunctionCall (new CCodeIdentifier ("g_renew"));
renew_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
renew_call.add_argument (array);
renew_call.add_argument (size);
var resize_block = new CCodeBlock ();
resize_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (size, new CCodeConditionalExpression (size, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("2"), size), new CCodeConstant ("4")))));
resize_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (array, renew_call)));
var csizecheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, length, size);
block.add_statement (new CCodeIfStatement (csizecheck, resize_block));
block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (array, new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, length)), value)));
// append to file
source_type_member_declaration.append (function.copy ());
function.block = block;
source_type_member_definition.append (function);
return add_func;
}
public override void visit_method_call (MethodCall expr) {
base.visit_method_call (expr);
......@@ -500,4 +602,44 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
ccall.insert_argument (1, new CCodeIdentifier (element_type.get_cname ()));
}
bool is_array_add (Assignment assignment) {
var binary = assignment.right as BinaryExpression;
if (binary != null && binary.left.value_type is ArrayType) {
if (binary.operator == BinaryOperator.PLUS) {
if (assignment.left.symbol_reference == binary.left.symbol_reference) {
return true;
}
}
}
return false;
}
public override void visit_assignment (Assignment assignment) {
if (!is_array_add (assignment)) {
base.visit_assignment (assignment);
return;
}
var binary = assignment.right as BinaryExpression;
var array = binary.left;
var array_type = (ArrayType) array.value_type;
var element = binary.right;
array.accept (codegen);
element.target_type = array_type.element_type.copy ();
element.accept (codegen);
var value_param = new FormalParameter ("value", element.target_type);
var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_add_wrapper (array_type)));
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) array.ccodenode));
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_length_cexpression (array)));
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_size_cexpression (array)));
ccall.add_argument (handle_struct_argument (value_param, element, (CCodeExpression) element.ccodenode));
assignment.ccodenode = ccall;
}
}
/* valaccodeassignmentmodule.vala
*
* Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
* Copyright (C) 2006-2009 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -168,6 +169,16 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
var rhs_array_len = head.get_array_length_cexpression (assignment.right, dim);
ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
}
if (array_type.rank == 1) {
var array_var = assignment.left.symbol_reference;
if (array_var != null && array_var.is_internal_symbol ()
&& (assignment.left.symbol_reference is LocalVariable
|| assignment.left.symbol_reference is Field)) {
var lhs_array_size = head.get_array_size_cexpression (assignment.left);
var rhs_array_len = head.get_array_length_cexpression (assignment.left, 1);
ccomma.append_expression (new CCodeAssignment (lhs_array_size, rhs_array_len));
}
}
} else if (instance_delegate) {
var lhs_delegate_target = get_delegate_target_cexpression (assignment.left);
var rhs_delegate_target = get_delegate_target_cexpression (assignment.right);
......
/* valaccodebasemodule.vala
*
* Copyright (C) 2006-2009 Jürg Billeter, Raffaele Sandrini
* Copyright (C) 2006-2009 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -819,12 +820,15 @@ public class Vala.CCodeBaseModule : CCodeModule {
if (f.field_type is ArrayType && !f.no_array_length) {
// create fields to store array dimensions
var array_type = (ArrayType) f.field_type;
var len_type = int_type.copy ();
for (int dim = 1; dim <= array_type.rank; dim++) {
var len_type = int_type.copy ();
st.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
}
if (array_type.rank == 1 && f.is_internal_symbol ()) {
st.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
}
} else if (f.field_type is DelegateType) {
var delegate_type = (DelegateType) f.field_type;
if (delegate_type.delegate_symbol.has_target) {
......@@ -940,6 +944,15 @@ public class Vala.CCodeBaseModule : CCodeModule {
}
source_type_member_declaration.append (len_def);
}
if (array_type.rank == 1 && f.is_internal_symbol ()) {
var len_type = int_type.copy ();
var cdecl = new CCodeDeclaration (len_type.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_size_cname (f.get_cname ()), new CCodeConstant ("0")));
cdecl.modifiers = CCodeModifiers.STATIC;
source_type_member_declaration.append (cdecl);
}
} else if (f.field_type is DelegateType) {
var delegate_type = (DelegateType) f.field_type;
if (delegate_type.delegate_symbol.has_target) {
......@@ -1400,6 +1413,11 @@ public class Vala.CCodeBaseModule : CCodeModule {
var len_var = new LocalVariable (int_type.copy (), head.get_array_length_cname (get_variable_cname (local.name), dim));
temp_vars.insert (0, len_var);
}
if (array_type.rank == 1) {
var size_var = new LocalVariable (int_type.copy (), head.get_array_size_cname (get_variable_cname (local.name)));
temp_vars.insert (0, size_var);
}
} else if (local.variable_type is DelegateType) {
var deleg_type = (DelegateType) local.variable_type;
var d = deleg_type.delegate_symbol;
......@@ -1428,6 +1446,11 @@ public class Vala.CCodeBaseModule : CCodeModule {
var rhs_array_len = head.get_array_length_cexpression (local.initializer, dim);
ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
}
if (array_type.rank == 1) {
var lhs_array_size = get_variable_cexpression (head.get_array_size_cname (get_variable_cname (local.name)));
var rhs_array_len = get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), 1));
ccomma.append_expression (new CCodeAssignment (lhs_array_size, rhs_array_len));
}
ccomma.append_expression (get_variable_cexpression (temp_var.name));
......
/* valaccodemodule.vala
*
* Copyright (C) 2008 Jürg Billeter
* Copyright (C) 2008-2009 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
......@@ -404,6 +404,14 @@ public abstract class Vala.CCodeModule {
return next.get_array_length_cexpression (array_expr, dim);
}
public virtual string get_array_size_cname (string array_cname) {
return next.get_array_size_cname (array_cname);
}
public virtual CCodeExpression get_array_size_cexpression (Expression array_expr) {
return next.get_array_size_cexpression (array_expr);
}
public virtual void add_simple_check (CodeNode node, CCodeFragment cfrag) {
next.add_simple_check (node, cfrag);
}
......
......@@ -229,6 +229,19 @@ public class Vala.BinaryExpression : Expression {
} else {
value_type.value_owned = true;
}
} else if (left.value_type is ArrayType && operator == BinaryOperator.PLUS) {
// array concatenation
var array_type = (ArrayType) left.value_type;
if (right.value_type == null || !right.value_type.compatible (array_type.element_type)) {
error = true;
Report.error (source_reference, "Incompatible operand");
return false;
}
value_type = array_type.copy ();
value_type.value_owned = true;
} else if (operator == BinaryOperator.PLUS
|| operator == BinaryOperator.MINUS
|| operator == BinaryOperator.MUL
......
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