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

            Line data    Source code
       1              : /* valaarraytype.vala
       2              :  *
       3              :  * Copyright (C) 2007-2012  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23              : using GLib;
      24              : 
      25              : /**
      26              :  * An array type.
      27              :  */
      28       764086 : public class Vala.ArrayType : ReferenceType {
      29              :         /**
      30              :          * The element type.
      31              :          */
      32              :         public DataType element_type {
      33      6150274 :                 get { return _element_type; }
      34      1308635 :                 private set {
      35      1996060 :                         _element_type = value;
      36      1308635 :                         _element_type.parent_node = this;
      37              :                 }
      38              :         }
      39              : 
      40              :         /**
      41              :          * The length type.
      42              :          */
      43              :         public DataType? length_type {
      44      5439523 :                 get { return _length_type; }
      45       666864 :                 set {
      46      1333728 :                         _length_type = value;
      47       666864 :                         if (_length_type != null) {
      48       666864 :                                 _length_type.parent_node = this;
      49              :                         }
      50              :                 }
      51              :         }
      52              : 
      53       751205 :         public bool invalid_syntax { get; set; }
      54              : 
      55       655923 :         public bool inline_allocated { get; set; }
      56              : 
      57        47628 :         public bool fixed_length { get; set; }
      58              : 
      59              :         /**
      60              :          * The length of this fixed-length array.
      61              :          */
      62              :         public Expression? length {
      63        13979 :                 get { return _length; }
      64         3190 :                 set {
      65         6345 :                         _length = value;
      66         3190 :                         if (_length != null) {
      67         3155 :                                 _length.parent_node = this;
      68              :                         }
      69              :                 }
      70              :         }
      71              : 
      72              :         /**
      73              :          * The rank of this array.
      74              :          */
      75       861729 :         public int rank { get; set; }
      76              : 
      77       762549 :         private DataType _element_type;
      78       762549 :         private DataType _length_type;
      79       762549 :         private Expression _length;
      80              : 
      81       762549 :         private ArrayLengthField length_field;
      82       762549 :         private ArrayResizeMethod resize_method;
      83       762549 :         private ArrayMoveMethod move_method;
      84       762549 :         private ArrayCopyMethod copy_method;
      85              : 
      86      2287647 :         public ArrayType (DataType element_type, int rank, SourceReference? source_reference = null) {
      87       762549 :                 base (null, source_reference);
      88       762549 :                 this.element_type = element_type;
      89       762549 :                 this.rank = rank;
      90              :         }
      91              : 
      92        18845 :         public override Symbol? get_member (string member_name) {
      93        18845 :                 if (member_name == "length") {
      94        34640 :                         return get_length_field ();
      95         1525 :                 } else if (member_name == "move") {
      96            4 :                         return get_move_method ();
      97         1523 :                 } else if (member_name == "resize") {
      98           18 :                         if (rank > 1) {
      99         1503 :                                 return null;
     100              :                         }
     101           36 :                         return get_resize_method ();
     102         1505 :                 } else if (member_name == "copy") {
     103            4 :                         return get_copy_method ();
     104              :                 }
     105        18845 :                 return null;
     106              :         }
     107              : 
     108        17320 :         unowned ArrayLengthField get_length_field () {
     109        17320 :                 if (length_field == null) {
     110        17318 :                         length_field = new ArrayLengthField (source_reference);
     111              : 
     112        17318 :                         length_field.access = SymbolAccessibility.PUBLIC;
     113              : 
     114        17318 :                         if (rank > 1) {
     115              :                                 // length is an int[] containing the dimensions of the array, starting at 0
     116           50 :                                 length_field.variable_type = new ArrayType (length_type.copy (), 1, source_reference);
     117              :                         } else {
     118        17268 :                                 length_field.variable_type = length_type.copy ();
     119              :                         }
     120              : 
     121              :                 }
     122        17320 :                 return length_field;
     123              :         }
     124              : 
     125           18 :         unowned ArrayResizeMethod get_resize_method () {
     126           18 :                 if (resize_method == null) {
     127           18 :                         resize_method = new ArrayResizeMethod (source_reference);
     128              : 
     129           18 :                         resize_method.return_type = new VoidType ();
     130           18 :                         resize_method.access = SymbolAccessibility.PUBLIC;
     131              : 
     132           18 :                         if (CodeContext.get ().profile == Profile.POSIX) {
     133            1 :                                 resize_method.set_attribute_string ("CCode", "cname", "realloc");
     134              :                         } else {
     135           17 :                                 resize_method.set_attribute_string ("CCode", "cname", "g_renew");
     136              :                         }
     137              : 
     138           18 :                         resize_method.add_parameter (new Parameter ("length", length_type));
     139              : 
     140           18 :                         resize_method.returns_modified_pointer = true;
     141              :                 }
     142           18 :                 return resize_method;
     143              :         }
     144              : 
     145            2 :         unowned ArrayMoveMethod get_move_method () {
     146            2 :                 if (move_method == null) {
     147            2 :                         move_method = new ArrayMoveMethod (source_reference);
     148              : 
     149            2 :                         move_method.return_type = new VoidType ();
     150            2 :                         move_method.access = SymbolAccessibility.PUBLIC;
     151              : 
     152            2 :                         move_method.set_attribute_string ("CCode", "cname", "_vala_array_move");
     153              : 
     154            2 :                         move_method.add_parameter (new Parameter ("src", length_type));
     155            2 :                         move_method.add_parameter (new Parameter ("dest", length_type));
     156            2 :                         move_method.add_parameter (new Parameter ("length", length_type));
     157              :                 }
     158            2 :                 return move_method;
     159              :         }
     160              : 
     161            2 :         unowned ArrayCopyMethod get_copy_method () {
     162            2 :                 if (copy_method == null) {
     163            2 :                         copy_method = new ArrayCopyMethod (source_reference);
     164              : 
     165            2 :                         copy_method.return_type = this.copy ();
     166            2 :                         copy_method.return_type.value_owned = true;
     167            2 :                         copy_method.access = SymbolAccessibility.PUBLIC;
     168              : 
     169            2 :                         copy_method.set_attribute_string ("CCode", "cname", "_vala_array_copy");
     170              :                 }
     171            2 :                 return copy_method;
     172              :         }
     173              : 
     174       185765 :         public override DataType copy () {
     175       185765 :                 var result = new ArrayType (element_type.copy (), rank, source_reference);
     176       185765 :                 if (length_type != null) {
     177       120162 :                         result.length_type = length_type.copy ();
     178              :                 }
     179              : 
     180       185765 :                 result.value_owned = value_owned;
     181       185765 :                 result.nullable = nullable;
     182       185765 :                 result.floating_reference = floating_reference;
     183              : 
     184       185765 :                 result.inline_allocated = inline_allocated;
     185       185765 :                 if (fixed_length) {
     186          714 :                         result.fixed_length = true;
     187          714 :                         result.length = length;
     188              :                 }
     189              : 
     190       185765 :                 result.invalid_syntax = invalid_syntax;
     191              : 
     192       185765 :                 return result;
     193              :         }
     194              : 
     195          430 :         public override string to_qualified_string (Scope? scope) {
     196          430 :                 var elem_str = element_type.to_qualified_string (scope);
     197          430 :                 if (element_type.is_weak () && !(parent_node is Constant)) {
     198            3 :                         elem_str = "(unowned %s)".printf (elem_str);
     199              :                 }
     200              : 
     201          430 :                 if (!fixed_length) {
     202          418 :                         var length_str = length_type == null ? "int" : length_type.to_qualified_string (scope);
     203          418 :                         if (length_str != "int") {
     204            3 :                                 length_str = ":%s".printf (length_str);
     205              :                         } else {
     206          415 :                                 length_str = "";
     207              :                         }
     208          418 :                         return "%s[%s%s]%s".printf (elem_str, string.nfill (rank - 1, ','), length_str, nullable ? "?" : "");
     209              :                 } else {
     210          430 :                         return elem_str;
     211              :                 }
     212              :         }
     213              : 
     214        25725 :         public override bool compatible (DataType target_type) {
     215        25725 :                 var context = CodeContext.get ();
     216              : 
     217        25725 :                 if (context.profile == Profile.GOBJECT && target_type.type_symbol != null) {
     218          134 :                         if (target_type.type_symbol.is_subtype_of (context.analyzer.gvalue_type.type_symbol) && element_type.type_symbol == context.analyzer.string_type.type_symbol) {
     219              :                                 // allow implicit conversion from string[] to GValue
     220            1 :                                 return true;
     221              :                         }
     222              : 
     223          133 :                         if (target_type.type_symbol.is_subtype_of (context.analyzer.gvariant_type.type_symbol)) {
     224              :                                 // allow implicit conversion to GVariant
     225           11 :                                 return true;
     226              :                         }
     227              :                 }
     228              : 
     229        25713 :                 if (target_type is PointerType || (target_type.type_symbol != null && target_type.type_symbol.get_attribute ("PointerType") != null)) {
     230              :                         /* any array type can be cast to a generic pointer */
     231         4245 :                         return true;
     232              :                 }
     233              : 
     234              :                 /* temporarily ignore type parameters */
     235        21468 :                 if (target_type is GenericType) {
     236            0 :                         return true;
     237              :                 }
     238              : 
     239        21468 :                 unowned ArrayType? target_array_type = target_type as ArrayType;
     240        21468 :                 if (target_array_type == null) {
     241          131 :                         return false;
     242              :                 }
     243              : 
     244        21337 :                 if (target_array_type.rank != rank) {
     245            0 :                         return false;
     246              :                 }
     247              : 
     248        21337 :                 if (element_type is ValueType && element_type.nullable != target_array_type.element_type.nullable) {
     249            0 :                         return false;
     250              :                 }
     251              : 
     252        21337 :                 if (!length_type.compatible (target_array_type.length_type)) {
     253            0 :                         return false;
     254              :                 }
     255              : 
     256        42672 :                 if (element_type.compatible (target_array_type.element_type)
     257        21335 :                     && target_array_type.element_type.compatible (element_type)) {
     258        21329 :                         return true;
     259            8 :                 } else if (element_type.type_symbol is Class) {
     260            7 :                         unowned Class cl = (Class) element_type.type_symbol;
     261           14 :                         if ((!cl.is_compact || cl == context.analyzer.string_type.type_symbol)
     262            7 :                             && element_type.compatible (target_array_type.element_type)) {
     263            6 :                                 return true;
     264              :                         }
     265              :                 }
     266              : 
     267            2 :                 return false;
     268              :         }
     269              : 
     270        10708 :         public override bool is_reference_type_or_type_parameter () {
     271        10708 :                 return true;
     272              :         }
     273              : 
     274       955175 :         public override void accept_children (CodeVisitor visitor) {
     275       955175 :                 element_type.accept (visitor);
     276       955175 :                 if (length_type != null) {
     277       409029 :                         length_type.accept (visitor);
     278              :                 }
     279              :         }
     280              : 
     281       540422 :         public override void replace_type (DataType old_type, DataType new_type) {
     282       540422 :                 if (element_type == old_type) {
     283       540397 :                         element_type = new_type;
     284              :                 }
     285       540422 :                 if (length_type == old_type) {
     286           25 :                         length_type = new_type;
     287              :                 }
     288              :         }
     289              : 
     290       506611 :         public override bool is_accessible (Symbol sym) {
     291       506611 :                 if (length_type != null && !length_type.is_accessible (sym)) {
     292            0 :                         return false;
     293              :                 }
     294       506611 :                 return element_type.is_accessible (sym);
     295              :         }
     296              : 
     297       936812 :         public override bool check (CodeContext context) {
     298       936812 :                 if (invalid_syntax) {
     299            4 :                         Report.error (source_reference, "syntax error, no expression allowed between array brackets");
     300            4 :                         error = true;
     301            4 :                         return false;
     302              :                 }
     303              : 
     304       936808 :                 if (fixed_length && length != null) {
     305         2535 :                         length.check (context);
     306              : 
     307         2535 :                         if (length.value_type == null || !(length.value_type is IntegerType || length.value_type is EnumValueType)
     308         2535 :                             || !length.is_constant ()) {
     309            1 :                                 error = true;
     310            1 :                                 Report.error (length.source_reference, "Expression of constant integer type expected");
     311            1 :                                 return false;
     312              :                         }
     313              :                 }
     314              : 
     315       936807 :                 if (element_type is ArrayType) {
     316            1 :                         error = true;
     317            1 :                         Report.error (source_reference, "Stacked arrays are not supported");
     318            1 :                         return false;
     319       936834 :                 } else if (element_type is DelegateType) {
     320           29 :                         var delegate_type = (DelegateType) element_type;
     321           29 :                         if (delegate_type.delegate_symbol.has_target) {
     322            1 :                                 error = true;
     323            1 :                                 Report.error (source_reference, "Delegates with target are not supported as array element type");
     324            1 :                                 return false;
     325              :                         }
     326              :                 }
     327              : 
     328       936805 :                 if (length_type == null) {
     329              :                         // Make sure that "int" is still picked up as default
     330       538231 :                         length_type = context.analyzer.int_type.copy ();
     331              :                 } else {
     332       398574 :                         length_type.check (context);
     333       398574 :                         if (!(length_type is IntegerType) || length_type.nullable) {
     334            1 :                                 error = true;
     335            1 :                                 Report.error (length_type.source_reference, "Expected integer type as length type of array");
     336            1 :                                 return false;
     337              :                         }
     338              :                 }
     339              : 
     340       936804 :                 if (!element_type.check (context)) {
     341            1 :                         error = true;
     342            1 :                         return false;
     343              :                 }
     344              : 
     345              :                 // check whether there is the expected amount of type-arguments
     346       936803 :                 if (!element_type.check_type_arguments (context, true)) {
     347            0 :                         error = true;
     348            0 :                         return false;
     349              :                 }
     350              : 
     351       936812 :                 return true;
     352              :         }
     353              : 
     354        14456 :         public override DataType get_actual_type (DataType? derived_instance_type, List<DataType>? method_type_arguments, CodeNode? node_reference) {
     355        14456 :                 ArrayType result = (ArrayType) this.copy ();
     356              : 
     357        14456 :                 if (derived_instance_type == null && method_type_arguments == null) {
     358              :                         return result;
     359              :                 }
     360              : 
     361        14426 :                 if (element_type is GenericType || element_type.has_type_arguments ()) {
     362         5689 :                         result.element_type = result.element_type.get_actual_type (derived_instance_type, method_type_arguments, node_reference);
     363              :                 }
     364              : 
     365              :                 return result;
     366              :         }
     367              : 
     368            1 :         public override DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
     369            1 :                 unowned ArrayType? array_type = value_type as ArrayType;
     370            1 :                 if (array_type != null) {
     371            1 :                         return element_type.infer_type_argument (type_param, array_type.element_type);
     372              :                 }
     373              : 
     374            1 :                 return null;
     375              :         }
     376              : 
     377        29502 :         public override bool is_disposable () {
     378        29502 :                 if (fixed_length) {
     379          746 :                         return element_type.is_disposable ();
     380              :                 } else {
     381        28756 :                         return base.is_disposable ();
     382              :                 }
     383              :         }
     384              : }
        

Generated by: LCOV version 2.0-1