LCOV - code coverage report
Current view: top level - vala - valaarraycreationexpression.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 72.1 % 183 132
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valaarraycreationexpression.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       6              :  * This library is free software; you can redistribute it and/or
       7              :  * modify it under the terms of the GNU Lesser General Public
       8              :  * License as published by the Free Software Foundation; either
       9              :  * version 2.1 of the License, or (at your option) any later version.
      10              : 
      11              :  * This library is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              : 
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this library; if not, write to the Free Software
      18              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      19              :  *
      20              :  * Author:
      21              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      22              :  *      Jürg Billeter <j@bitron.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27              : /**
      28              :  * Represents an array creation expression.
      29              :  *
      30              :  * {{{ new int[] { 1, 2, 3 } }}}
      31              :  */
      32        18299 : public class Vala.ArrayCreationExpression : Expression {
      33              :         /**
      34              :          * The type of the elements of the array.
      35              :          */
      36              :         public DataType element_type {
      37        88025 :                 get { return _element_type; }
      38        15653 :                 private set {
      39        39661 :                         _element_type = value;
      40        15653 :                         _element_type.parent_node = this;
      41              :                 }
      42              :         }
      43              : 
      44              :         /**
      45              :          * The length type.
      46              :          */
      47              :         public DataType? length_type {
      48        55609 :                 get { return _length_type; }
      49         7817 :                 set {
      50        15634 :                         _length_type = value;
      51         7817 :                         if (_length_type != null) {
      52         7817 :                                 _length_type.parent_node = this;
      53              :                         }
      54              :                 }
      55              :         }
      56              : 
      57              :         /**
      58              :          * The rank of the array.
      59              :          */
      60         8987 :         public int rank { get; private set; }
      61              : 
      62              :         /**
      63              :          * The size for each dimension ascending from left to right.
      64              :          */
      65        16762 :         private List<Expression> sizes = new ArrayList<Expression> ();
      66              : 
      67              :         /**
      68              :          * The root array initializer list.
      69              :          */
      70              :         public InitializerList? initializer_list {
      71        46163 :                 get { return _initializer_list; }
      72         8381 :                 private set {
      73         9000 :                         _initializer_list = value;
      74         8381 :                         if (_initializer_list != null) {
      75          619 :                                 _initializer_list.parent_node = this;
      76              :                         }
      77              :                 }
      78              :         }
      79              : 
      80         8381 :         private DataType _element_type;
      81         8381 :         private DataType _length_type;
      82         8381 :         private InitializerList? _initializer_list;
      83              : 
      84              :         /**
      85              :          * Add a size expression.
      86              :          */
      87         8400 :         public void append_size (Expression size) {
      88         8400 :                 sizes.add (size);
      89         8400 :                 if (size != null) {
      90         8400 :                         size.parent_node = this;
      91              :                 }
      92              :         }
      93              : 
      94              :         /**
      95              :          * Get the sizes for all dimensions ascending from left to right.
      96              :          */
      97         8480 :         public unowned List<Expression> get_sizes () {
      98         8480 :                 return sizes;
      99              :         }
     100              : 
     101        25143 :         public ArrayCreationExpression (DataType element_type, int rank, InitializerList? initializer_list, SourceReference? source_reference = null) {
     102         8381 :                 this.element_type = element_type;
     103         8381 :                 this.rank = rank;
     104         8381 :                 this.initializer_list = initializer_list;
     105         8381 :                 this.source_reference = source_reference;
     106              :         }
     107              : 
     108        19542 :         public override void accept_children (CodeVisitor visitor) {
     109        19542 :                 if (element_type != null) {
     110        19542 :                         element_type.accept (visitor);
     111              :                 }
     112              : 
     113        19542 :                 if (length_type != null) {
     114        10828 :                         length_type.accept (visitor);
     115              :                 }
     116              : 
     117        57500 :                 foreach (Expression e in sizes) {
     118        18979 :                         e.accept (visitor);
     119              :                 }
     120              : 
     121        19542 :                 if (initializer_list != null) {
     122         1699 :                         initializer_list.accept (visitor);
     123              :                 }
     124              :         }
     125              : 
     126        19542 :         public override void accept (CodeVisitor visitor) {
     127        19542 :                 visitor.visit_array_creation_expression (this);
     128              : 
     129        19542 :                 visitor.visit_expression (this);
     130              :         }
     131              : 
     132            0 :         public override bool is_pure () {
     133            0 :                 return false;
     134              :         }
     135              : 
     136            0 :         public override bool is_accessible (Symbol sym) {
     137            0 :                 if (element_type != null && !element_type.is_accessible (sym)) {
     138            0 :                         return false;
     139              :                 }
     140              : 
     141            0 :                 if (length_type != null && !length_type.is_accessible (sym)) {
     142            0 :                         return false;
     143              :                 }
     144              : 
     145            0 :                 foreach (Expression e in sizes) {
     146            0 :                         if (!e.is_accessible (sym)) {
     147            0 :                                 return false;
     148              :                         }
     149              :                 }
     150              : 
     151            0 :                 if (initializer_list != null) {
     152            0 :                         return initializer_list.is_accessible (sym);
     153              :                 }
     154              : 
     155            0 :                 return true;
     156              :         }
     157              : 
     158            0 :         public override string to_string () {
     159            0 :                 var builder = new StringBuilder ("new ");
     160            0 :                 builder.append_printf ("%s[", element_type.to_string ());
     161            0 :                 bool first = true;
     162            0 :                 foreach (var size in sizes) {
     163            0 :                         if (first) {
     164            0 :                                 builder.append (size.to_string ());
     165            0 :                                 first = false;
     166              :                         } else {
     167            0 :                                 builder.append_printf (", %s", size.to_string ());
     168              :                         }
     169              :                 }
     170            0 :                 var length_str = length_type.to_string ();
     171            0 :                 if (length_str != "int") {
     172            0 :                         builder.append_printf (":%s", length_str);
     173              :                 }
     174            0 :                 builder.append_c (']');
     175            0 :                 if (initializer_list != null) {
     176            0 :                         builder.append (initializer_list.to_string ());
     177              :                 }
     178            0 :                 return builder.str;
     179              :         }
     180              : 
     181            0 :         public override void replace_expression (Expression old_node, Expression new_node) {
     182            0 :                 for (int i = 0; i < sizes.size; i++) {
     183            0 :                         if (sizes[i] == old_node) {
     184            0 :                                 sizes[i] = new_node;
     185            0 :                                 new_node.parent_node = this;
     186            0 :                                 return;
     187              :                         }
     188              :                 }
     189              :         }
     190              : 
     191         7281 :         public override void replace_type (DataType old_type, DataType new_type) {
     192         7281 :                 if (element_type == old_type) {
     193         7272 :                         element_type = new_type;
     194              :                 }
     195         7281 :                 if (length_type == old_type) {
     196            9 :                         length_type = new_type;
     197              :                 }
     198              :         }
     199              : 
     200          668 :         private int create_sizes_from_initializer_list (CodeContext context, InitializerList il, int rank, List<Literal> sl) {
     201         1305 :                 if (sl.size == (this.rank - rank)) {
     202              :                         // only add size if this is the first initializer list of the current dimension
     203          637 :                         var init = new IntegerLiteral (il.size.to_string (), il.source_reference);
     204          637 :                         init.check (context);
     205          637 :                         sl.add (init);
     206              :                 }
     207              : 
     208          668 :                 int subsize = -1;
     209         3898 :                 foreach (Expression e in il.get_initializers ()) {
     210         1616 :                         if (e is InitializerList && e.target_type is ArrayType) {
     211           51 :                                 if (rank == 1) {
     212            0 :                                         il.error = true;
     213            0 :                                         e.error = true;
     214            0 :                                         Report.error (e.source_reference, "Expected array element, got array initializer list");
     215            0 :                                         return -1;
     216              :                                 }
     217           51 :                                 int size = create_sizes_from_initializer_list (context, (InitializerList) e, rank - 1, sl);
     218           51 :                                 if (size == -1) {
     219            0 :                                         return -1;
     220              :                                 }
     221           51 :                                 if (subsize >= 0 && subsize != size) {
     222            0 :                                         il.error = true;
     223            0 :                                         Report.error (il.source_reference, "Expected initializer list of size %d, got size %d", subsize, size);
     224            0 :                                         return -1;
     225              :                                 } else {
     226              :                                         subsize = size;
     227              :                                 }
     228              :                         } else {
     229         1565 :                                 if (rank != 1) {
     230            1 :                                         il.error = true;
     231            1 :                                         e.error = true;
     232            1 :                                         Report.error (e.source_reference, "Expected array initializer list, got array element");
     233            1 :                                         return -1;
     234              :                                 }
     235              :                         }
     236              :                 }
     237          667 :                 return il.size;
     238              :         }
     239              : 
     240         7810 :         public override bool check (CodeContext context) {
     241         7810 :                 if (checked) {
     242            0 :                         return !error;
     243              :                 }
     244              : 
     245         7810 :                 checked = true;
     246              : 
     247         7810 :                 List<Expression> sizes = get_sizes ();
     248         7810 :                 var initlist = initializer_list;
     249              : 
     250         7810 :                 if (element_type != null) {
     251         7810 :                         element_type.check (context);
     252              : 
     253              :                         // check whether there is the expected amount of type-arguments
     254         7810 :                         if (!element_type.check_type_arguments (context, true)) {
     255            2 :                                 error = true;
     256            2 :                                 return false;
     257              :                         }
     258              :                 }
     259              : 
     260         7808 :                 if (length_type == null) {
     261              :                         // Make sure that "int" is still picked up as default
     262         7232 :                         length_type = context.analyzer.int_type.copy ();
     263              :                 } else {
     264          576 :                         length_type.check (context);
     265          576 :                         if (!(length_type is IntegerType) || length_type.nullable) {
     266            2 :                                 error = true;
     267            2 :                                 Report.error (length_type.source_reference, "Expected integer type as length type of array");
     268              :                         }
     269              :                 }
     270              : 
     271        22198 :                 foreach (Expression e in sizes) {
     272         7195 :                         e.check (context);
     273              :                 }
     274              : 
     275         7808 :                 var calc_sizes = new ArrayList<Literal> ();
     276         7808 :                 if (initlist != null) {
     277          617 :                         initlist.target_type = new ArrayType (element_type, rank, source_reference);
     278          617 :                         ((ArrayType) initlist.target_type).length_type = length_type.copy ();
     279              : 
     280          617 :                         if (!initlist.check (context)) {
     281            2 :                                 error = true;
     282              :                         }
     283              : 
     284          617 :                         var ret = create_sizes_from_initializer_list (context, initlist, rank, calc_sizes);
     285          617 :                         if (ret == -1) {
     286            1 :                                 error = true;
     287              :                         }
     288              : 
     289          619 :                         if (calc_sizes.size != rank) {
     290            2 :                                 error = true;
     291            2 :                                 var actual_type = new ArrayType (element_type, calc_sizes.size, source_reference);
     292            2 :                                 ((ArrayType) actual_type).length_type = length_type;
     293            2 :                                 Report.error (initlist.source_reference, "Expected initializer for `%s' but got `%s'", target_type.to_string (), actual_type.to_string ());
     294              :                         }
     295              :                 }
     296              : 
     297         7808 :                 if (sizes.size > 0) {
     298              :                         /* check for errors in the size list */
     299        21583 :                         foreach (Expression e in sizes) {
     300         7195 :                                 if (e.value_type == null) {
     301              :                                         /* return on previous error */
     302            0 :                                         return false;
     303         7195 :                                 } else if (!(e.value_type is IntegerType || e.value_type is EnumValueType)) {
     304            1 :                                         error = true;
     305            1 :                                         Report.error (e.source_reference, "Expression of integer type expected");
     306              :                                 }
     307              :                         }
     308              :                 } else {
     309          615 :                         if (initlist == null) {
     310            0 :                                 error = true;
     311              :                                 /* this is an internal error because it is already handled by the parser */
     312            0 :                                 Report.error (source_reference, "internal error: initializer list expected");
     313              :                         } else {
     314         1885 :                                 foreach (Expression size in calc_sizes) {
     315          635 :                                         append_size (size);
     316              :                                 }
     317              :                         }
     318              :                 }
     319              : 
     320         7808 :                 if (error) {
     321            6 :                         return false;
     322              :                 }
     323              : 
     324              :                 /* check for wrong elements inside the initializer */
     325         7802 :                 if (initializer_list != null && initializer_list.value_type == null) {
     326            0 :                         return false;
     327              :                 }
     328              : 
     329              :                 /* try to construct the type of the array */
     330         7802 :                 if (element_type == null) {
     331            0 :                         error = true;
     332            0 :                         Report.error (source_reference, "Cannot determine the element type of the created array");
     333            0 :                         return false;
     334              :                 }
     335              : 
     336         7802 :                 value_type = new ArrayType (element_type, rank, source_reference);
     337         7802 :                 ((ArrayType) value_type).length_type = length_type.copy ();
     338         7802 :                 if (formal_target_type is ArrayType) {
     339         1855 :                         ((ArrayType) value_type).fixed_length = ((ArrayType) formal_target_type).fixed_length;
     340         1855 :                         ((ArrayType) value_type).inline_allocated = ((ArrayType) formal_target_type).inline_allocated;
     341              :                 }
     342         7802 :                 value_type.value_owned = true;
     343              : 
     344         7802 :                 if (!value_type.check (context)) {
     345            1 :                         return false;
     346              :                 }
     347              : 
     348         7801 :                 return !error;
     349              :         }
     350              : 
     351          697 :         public override void emit (CodeGenerator codegen) {
     352         2133 :                 foreach (Expression e in sizes) {
     353          718 :                         e.emit (codegen);
     354              :                 }
     355              : 
     356          697 :                 if (initializer_list != null) {
     357          606 :                         initializer_list.emit (codegen);
     358              :                 }
     359              : 
     360          697 :                 codegen.visit_array_creation_expression (this);
     361              : 
     362          697 :                 codegen.visit_expression (this);
     363              :         }
     364              : 
     365         5506 :         public override void get_used_variables (Collection<Variable> collection) {
     366        16560 :                 foreach (Expression e in sizes) {
     367         5527 :                         e.get_used_variables (collection);
     368              :                 }
     369              : 
     370         5506 :                 if (initializer_list != null) {
     371          589 :                         initializer_list.get_used_variables (collection);
     372              :                 }
     373              :         }
     374              : }
        

Generated by: LCOV version 2.0-1