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 : }
|