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

            Line data    Source code
       1              : /* valaintegerliteral.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  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              :  * Represents an integer literal in the source code.
      27              :  */
      28         1538 : public class Vala.IntegerLiteral : Literal {
      29              :         /**
      30              :          * The literal value.
      31              :          */
      32      1126136 :         public string value { get; private set; }
      33              : 
      34       849692 :         public string type_suffix { get; private set; }
      35              : 
      36              :         /**
      37              :          * Creates a new integer literal.
      38              :          *
      39              :          * @param i      literal value
      40              :          * @param source reference to source code
      41              :          * @return       newly created integer literal
      42              :          */
      43      1033905 :         public IntegerLiteral (string i, SourceReference? source = null) {
      44       344635 :                 value = i;
      45       344635 :                 source_reference = source;
      46              :         }
      47              : 
      48       608172 :         public override void accept (CodeVisitor visitor) {
      49       608172 :                 visitor.visit_integer_literal (this);
      50              : 
      51       608172 :                 visitor.visit_expression (this);
      52              :         }
      53              : 
      54           38 :         public override string to_string () {
      55           38 :                 return value;
      56              :         }
      57              : 
      58            0 :         public override bool is_pure () {
      59            0 :                 return true;
      60              :         }
      61              : 
      62       297609 :         public override bool check (CodeContext context) {
      63       297609 :                 if (checked) {
      64        49881 :                         return !error;
      65              :                 }
      66              : 
      67       247728 :                 checked = true;
      68              : 
      69       247728 :                 int l = 0;
      70       247793 :                 while (value.has_suffix ("l") || value.has_suffix ("L")) {
      71           65 :                         l++;
      72           65 :                         value = value.substring (0, value.length - 1);
      73              :                 }
      74              : 
      75       247728 :                 bool u = false;
      76       247728 :                 if (value.has_suffix ("u") || value.has_suffix ("U")) {
      77         4301 :                         u = true;
      78         4301 :                         value = value.substring (0, value.length - 1);
      79              :                 }
      80              : 
      81       247728 :                 bool negative = value.has_prefix ("-");
      82       247728 :                 if (negative && u) {
      83            1 :                         Report.error (source_reference, "unsigned integer literal cannot be negative");
      84            1 :                         error = true;
      85              :                 }
      86              : 
      87       247728 :                 int64 n = 0LL;
      88       247728 :                 uint64 un = 0ULL;
      89              : 
      90       247728 :                 errno = 0;
      91       247737 :                 if (value.has_prefix ("0b") || value.has_prefix ("0B")
      92       247721 :                     || value.has_prefix ("-0b") || value.has_prefix ("-0B")) {
      93              :                         string v;
      94            9 :                         if (negative) {
      95            2 :                                 v = "-" + value.substring (3);
      96              :                         } else {
      97            7 :                                 v = value.substring (2);
      98              :                         }
      99              :                         string unparsed;
     100            9 :                         if (negative) {
     101            2 :                                 int64.try_parse (v, out n, out unparsed, 2);
     102            2 :                                 value = n.to_string ();
     103              :                         } else {
     104            7 :                                 uint64.try_parse (v, out un, out unparsed, 2);
     105            7 :                                 value = un.to_string ();
     106              :                         }
     107            9 :                         if (unparsed != "") {
     108            1 :                                 Report.error (source_reference, "invalid digit '%c' in binary literal", unparsed[0]);
     109            1 :                                 error = true;
     110              :                         }
     111       249162 :                 } else if ((value[0] == '0' && value.length > 1
     112         7163 :                     && (value[1] == 'o' || value[1] == 'O' || value[1].isdigit ()))
     113       246278 :                     || (value.has_prefix ("-0") && value.length > 3
     114            5 :                     && (value[2] == 'o' || value[2] == 'O' || value[2].isdigit ()))) {
     115         1443 :                         if (negative) {
     116            2 :                                 if (!value[2].isdigit ()) {
     117            2 :                                         value = "-0" + value.substring (3);
     118              :                                 }
     119              :                         } else {
     120         1441 :                                 if (!value[1].isdigit ()) {
     121            8 :                                         value = "0" + value.substring (2);
     122              :                                 }
     123              :                         }
     124              :                         string unparsed;
     125         1443 :                         if (negative) {
     126            4 :                                 int64.try_parse (value, out n, out unparsed, 8);
     127              :                         } else {
     128         2882 :                                 uint64.try_parse (value, out un, out unparsed, 8);
     129              :                         }
     130         1443 :                         if (unparsed != "") {
     131            1 :                                 Report.error (source_reference, "invalid digit '%c' in octal literal", unparsed[0]);
     132            1 :                                 error = true;
     133              :                         }
     134              :                 } else {
     135              :                         // hexademical and decimal literal
     136       246276 :                         if (negative) {
     137        68293 :                                 n = int64.parse (value);
     138              :                         } else {
     139       177983 :                                 un = uint64.parse (value);
     140              :                         }
     141              :                 }
     142              : 
     143       247728 :                 if (errno == ERANGE) {
     144            5 :                         Report.error (source_reference, "integer literal is too large for its type");
     145            5 :                         error = true;
     146       247723 :                 } else if (errno == EINVAL) {
     147            0 :                         Report.error (source_reference, "invalid integer literal");
     148            0 :                         error = true;
     149              :                 }
     150              : 
     151       247728 :                 if (un > int64.MAX) {
     152              :                         // value doesn't fit into signed 64-bit
     153              :                         u = true;
     154              :                         l = 2;
     155       247718 :                 } else if (!negative) {
     156       179421 :                         n = (int64) un;
     157              :                 }
     158       247728 :                 if (!u && (n > int.MAX || n < int.MIN)) {
     159              :                         // value doesn't fit into signed 32-bit
     160              :                         l = 2;
     161       247703 :                 } else if (u && n > uint.MAX) {
     162              :                         // value doesn't fit into unsigned 32-bit
     163              :                         l = 2;
     164              :                 }
     165              : 
     166              :                 string type_name;
     167       247703 :                 if (l == 0) {
     168       247672 :                         if (u) {
     169         4295 :                                 type_suffix = "U";
     170         4295 :                                 type_name = "uint";
     171              :                         } else {
     172       243377 :                                 type_suffix = "";
     173       243377 :                                 type_name = "int";
     174              :                         }
     175           56 :                 } else if (l == 1) {
     176            5 :                         if (u) {
     177            3 :                                 type_suffix = "UL";
     178            3 :                                 type_name = "ulong";
     179              :                         } else {
     180            2 :                                 type_suffix = "L";
     181            2 :                                 type_name = "long";
     182              :                         }
     183              :                 } else {
     184           51 :                         if (u) {
     185           13 :                                 type_suffix = "ULL";
     186           13 :                                 type_name = "uint64";
     187              :                         } else {
     188           38 :                                 type_suffix = "LL";
     189           38 :                                 type_name = "int64";
     190              :                         }
     191              :                 }
     192              : 
     193       247728 :                 var st = (Struct) context.root.scope.lookup (type_name);
     194              :                 // ensure attributes are already processed
     195       247728 :                 st.check (context);
     196              : 
     197       247728 :                 value_type = new IntegerType (st, value, type_name);
     198              : 
     199       247728 :                 return !error;
     200              :         }
     201              : 
     202         9601 :         public override void emit (CodeGenerator codegen) {
     203         9601 :                 codegen.visit_integer_literal (this);
     204              : 
     205         9601 :                 codegen.visit_expression (this);
     206              :         }
     207              : }
        

Generated by: LCOV version 2.0-1