]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | http://www.boost.org/ | |
5 | ||
6 | Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost | |
7 | Software License, Version 1.0. (See accompanying file | |
8 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | =============================================================================*/ | |
10 | ||
11 | #if !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) | |
12 | #define CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED | |
13 | ||
14 | #if defined (BOOST_SPIRIT_DEBUG) | |
15 | #include <iostream> | |
16 | #endif // defined(BOOST_SPIRIT_DEBUG) | |
17 | ||
18 | #include <boost/wave/wave_config.hpp> | |
19 | #include <boost/wave/grammars/cpp_value_error.hpp> // value_error | |
20 | ||
21 | // this must occur after all of the includes and before any code appears | |
22 | #ifdef BOOST_HAS_ABI_HEADERS | |
23 | #include BOOST_ABI_PREFIX | |
24 | #endif | |
25 | ||
26 | /////////////////////////////////////////////////////////////////////////////// | |
27 | namespace boost { | |
28 | namespace wave { | |
29 | namespace grammars { | |
30 | namespace closures { | |
31 | ||
32 | class closure_value; | |
33 | inline bool as_bool(closure_value const& v); | |
34 | ||
35 | /////////////////////////////////////////////////////////////////////////////// | |
36 | // | |
b32b8144 FG |
37 | // The closure_value class represents the closure type, which is used for the |
38 | // expression grammar. | |
7c673cae | 39 | // |
b32b8144 | 40 | // This class was introduced to allow the expression grammar to respect |
7c673cae FG |
41 | // the numeric type of a numeric literal or expression result. |
42 | // | |
43 | /////////////////////////////////////////////////////////////////////////////// | |
44 | class closure_value { | |
45 | public: | |
46 | ||
47 | enum value_type { | |
48 | is_int = 1, | |
49 | is_uint = 2, | |
50 | is_bool = 3 | |
51 | }; | |
b32b8144 FG |
52 | |
53 | closure_value(value_error valid_ = error_noerror) | |
54 | : type(is_int), valid(valid_) | |
7c673cae | 55 | { value.i = 0; } |
b32b8144 FG |
56 | explicit closure_value(int i, value_error valid_ = error_noerror) |
57 | : type(is_int), valid(valid_) | |
7c673cae | 58 | { value.i = i; } |
b32b8144 FG |
59 | explicit closure_value(unsigned int ui, value_error valid_ = error_noerror) |
60 | : type(is_uint), valid(valid_) | |
7c673cae | 61 | { value.ui = ui; } |
b32b8144 FG |
62 | explicit closure_value(int_literal_type i, value_error valid_ = error_noerror) |
63 | : type(is_int), valid(valid_) | |
7c673cae | 64 | { value.i = i; } |
b32b8144 FG |
65 | explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror) |
66 | : type(is_uint), valid(valid_) | |
7c673cae | 67 | { value.ui = ui; } |
b32b8144 FG |
68 | explicit closure_value(bool b, value_error valid_ = error_noerror) |
69 | : type(is_bool), valid(valid_) | |
7c673cae FG |
70 | { value.b = b; } |
71 | ||
72 | value_type get_type() const { return type; } | |
73 | value_error is_valid() const { return valid; } | |
b32b8144 | 74 | |
7c673cae FG |
75 | // explicit conversion |
76 | friend int_literal_type as_int(closure_value const& v) | |
77 | { | |
78 | switch (v.type) { | |
79 | case is_uint: return v.value.ui; | |
80 | case is_bool: return v.value.b ? 1 : 0; | |
81 | case is_int: break; | |
82 | } | |
83 | return v.value.i; | |
84 | } | |
85 | friend uint_literal_type as_uint(closure_value const& v) | |
86 | { | |
87 | switch (v.type) { | |
88 | case is_uint: return v.value.ui; | |
89 | case is_bool: return v.value.b ? 1 : 0; | |
90 | case is_int: break; | |
91 | } | |
92 | return v.value.i; | |
93 | } | |
b32b8144 | 94 | friend int_literal_type as_long(closure_value const& v) |
7c673cae FG |
95 | { |
96 | switch (v.type) { | |
97 | case is_uint: return v.value.ui; | |
98 | case is_bool: return v.value.b ? 1 : 0; | |
99 | case is_int: break; | |
100 | } | |
101 | return v.value.i; | |
102 | } | |
103 | friend uint_literal_type as_ulong(closure_value const& v) | |
104 | { | |
105 | switch (v.type) { | |
106 | case is_uint: return v.value.ui; | |
107 | case is_bool: return v.value.b ? 1 : 0; | |
108 | case is_int: break; | |
109 | } | |
110 | return v.value.i; | |
111 | } | |
112 | friend bool as_bool(closure_value const& v) | |
113 | { | |
114 | switch (v.type) { | |
115 | case is_uint: return v.value.ui != 0; | |
116 | case is_bool: return v.value.b; | |
117 | case is_int: break; | |
118 | } | |
119 | return v.value.i != 0.0; | |
120 | } | |
121 | ||
b32b8144 | 122 | // assignment |
7c673cae FG |
123 | closure_value &operator= (closure_value const &rhs) |
124 | { | |
125 | switch (rhs.get_type()) { | |
b32b8144 FG |
126 | case is_int: |
127 | value.i = as_long(rhs); | |
7c673cae FG |
128 | type = is_int; |
129 | break; | |
b32b8144 FG |
130 | |
131 | case is_uint: | |
132 | value.ui = as_ulong(rhs); | |
7c673cae FG |
133 | type = is_uint; |
134 | break; | |
b32b8144 FG |
135 | |
136 | case is_bool: | |
7c673cae FG |
137 | value.b = as_bool(rhs); |
138 | type = is_bool; | |
139 | break; | |
140 | } | |
141 | valid = rhs.valid; | |
142 | return *this; | |
143 | } | |
144 | closure_value &operator= (int rhs) | |
145 | { | |
146 | type = is_int; | |
147 | value.i = rhs; | |
148 | valid = error_noerror; | |
149 | return *this; | |
150 | } | |
151 | closure_value &operator= (unsigned int rhs) | |
152 | { | |
153 | type = is_uint; | |
154 | value.ui = rhs; | |
155 | valid = error_noerror; | |
156 | return *this; | |
157 | } | |
158 | closure_value &operator= (int_literal_type rhs) | |
159 | { | |
160 | type = is_int; | |
161 | value.i = rhs; | |
162 | valid = error_noerror; | |
163 | return *this; | |
164 | } | |
165 | closure_value &operator= (uint_literal_type rhs) | |
166 | { | |
167 | type = is_uint; | |
168 | value.ui = rhs; | |
169 | valid = error_noerror; | |
170 | return *this; | |
171 | } | |
172 | closure_value &operator= (bool rhs) | |
173 | { | |
174 | type = is_bool; | |
175 | value.b = rhs; | |
176 | valid = error_noerror; | |
177 | return *this; | |
178 | } | |
179 | ||
180 | // arithmetics | |
181 | closure_value &operator+= (closure_value const &rhs) | |
182 | { | |
183 | switch (type) { | |
b32b8144 | 184 | case is_int: |
7c673cae FG |
185 | switch(rhs.type) { |
186 | case is_bool: | |
187 | { | |
b32b8144 FG |
188 | int_literal_type result = value.i + as_long(rhs); |
189 | if ((rhs.value.i > 0L && value.i > result) || | |
7c673cae FG |
190 | (rhs.value.i < 0L && value.i < result)) |
191 | { | |
192 | valid = error_integer_overflow; | |
193 | } | |
194 | else { | |
195 | value.i = result; | |
196 | } | |
197 | } | |
198 | break; | |
b32b8144 | 199 | |
7c673cae FG |
200 | case is_int: |
201 | { | |
202 | int_literal_type result = value.i + rhs.value.i; | |
b32b8144 | 203 | if ((rhs.value.i > 0L && value.i > result) || |
7c673cae FG |
204 | (rhs.value.i < 0L && value.i < result)) |
205 | { | |
206 | valid = error_integer_overflow; | |
207 | } | |
208 | else { | |
209 | value.i = result; | |
210 | } | |
211 | } | |
212 | break; | |
b32b8144 | 213 | |
7c673cae FG |
214 | case is_uint: |
215 | { | |
b32b8144 | 216 | uint_literal_type result = value.ui + rhs.value.ui; |
7c673cae FG |
217 | if (result < value.ui) { |
218 | valid = error_integer_overflow; | |
219 | } | |
220 | else { | |
221 | value.ui = result; | |
b32b8144 | 222 | type = is_uint; |
7c673cae FG |
223 | } |
224 | } | |
225 | break; | |
226 | } | |
227 | break; | |
b32b8144 | 228 | |
7c673cae FG |
229 | case is_uint: |
230 | { | |
b32b8144 | 231 | uint_literal_type result = value.ui + as_ulong(rhs); |
7c673cae FG |
232 | if (result < value.ui) { |
233 | valid = error_integer_overflow; | |
234 | } | |
235 | else { | |
236 | value.ui = result; | |
237 | } | |
238 | } | |
239 | break; | |
b32b8144 FG |
240 | |
241 | case is_bool: | |
7c673cae FG |
242 | value.i = value.b + as_bool(rhs); |
243 | type = is_int; | |
244 | } | |
245 | valid = (value_error)(valid | rhs.valid); | |
246 | return *this; | |
247 | } | |
248 | closure_value &operator-= (closure_value const &rhs) | |
249 | { | |
250 | switch (type) { | |
251 | case is_int: | |
252 | switch(rhs.type) { | |
253 | case is_bool: | |
254 | { | |
b32b8144 FG |
255 | int_literal_type result = value.i - as_long(rhs); |
256 | if ((rhs.value.i > 0L && result > value.i) || | |
7c673cae FG |
257 | (rhs.value.i < 0L && result < value.i)) |
258 | { | |
259 | valid = error_integer_overflow; | |
260 | } | |
261 | else { | |
262 | value.i = result; | |
263 | } | |
264 | } | |
265 | break; | |
266 | ||
267 | case is_int: | |
268 | { | |
269 | int_literal_type result = value.i - rhs.value.i; | |
b32b8144 | 270 | if ((rhs.value.i > 0L && result > value.i) || |
7c673cae FG |
271 | (rhs.value.i < 0L && result < value.i)) |
272 | { | |
273 | valid = error_integer_overflow; | |
274 | } | |
275 | else { | |
276 | value.i = result; | |
277 | } | |
278 | } | |
279 | break; | |
b32b8144 | 280 | |
7c673cae FG |
281 | case is_uint: |
282 | { | |
b32b8144 | 283 | uint_literal_type result = value.ui - rhs.value.ui; |
7c673cae FG |
284 | if (result > value.ui) { |
285 | valid = error_integer_overflow; | |
286 | } | |
287 | else { | |
288 | value.ui = result; | |
b32b8144 | 289 | type = is_uint; |
7c673cae FG |
290 | } |
291 | } | |
292 | break; | |
293 | } | |
294 | break; | |
b32b8144 | 295 | |
7c673cae FG |
296 | case is_uint: |
297 | switch(rhs.type) { | |
298 | case is_bool: | |
299 | { | |
b32b8144 | 300 | uint_literal_type result = value.ui - as_ulong(rhs); |
7c673cae FG |
301 | if (result > value.ui) |
302 | { | |
303 | valid = error_integer_overflow; | |
304 | } | |
305 | else { | |
306 | value.ui = result; | |
307 | } | |
308 | } | |
309 | break; | |
310 | ||
311 | case is_int: | |
312 | { | |
313 | uint_literal_type result = value.ui - rhs.value.i; | |
b32b8144 | 314 | if ((rhs.value.i > 0L && result > value.ui) || |
7c673cae FG |
315 | (rhs.value.i < 0L && result < value.ui)) |
316 | { | |
317 | valid = error_integer_overflow; | |
318 | } | |
319 | else { | |
320 | value.ui = result; | |
321 | } | |
322 | } | |
323 | break; | |
b32b8144 | 324 | |
7c673cae FG |
325 | case is_uint: |
326 | { | |
b32b8144 | 327 | uint_literal_type result = value.ui - rhs.value.ui; |
7c673cae FG |
328 | if (result > value.ui) { |
329 | valid = error_integer_overflow; | |
330 | } | |
331 | else { | |
332 | value.ui = result; | |
333 | } | |
334 | } | |
335 | break; | |
336 | } | |
337 | break; | |
338 | ||
b32b8144 | 339 | case is_bool: |
7c673cae FG |
340 | value.i = value.b - as_bool(rhs); |
341 | type = is_int; | |
342 | } | |
343 | valid = (value_error)(valid | rhs.valid); | |
344 | return *this; | |
345 | } | |
346 | closure_value &operator*= (closure_value const &rhs) | |
347 | { | |
348 | switch (type) { | |
b32b8144 | 349 | case is_int: |
7c673cae FG |
350 | switch(rhs.type) { |
351 | case is_bool: value.i *= as_long(rhs); break; | |
352 | case is_int: | |
353 | { | |
b32b8144 | 354 | int_literal_type result = value.i * rhs.value.i; |
7c673cae FG |
355 | if (0 != value.i && 0 != rhs.value.i && |
356 | (result / value.i != rhs.value.i || | |
357 | result / rhs.value.i != value.i) | |
358 | ) | |
359 | { | |
360 | valid = error_integer_overflow; | |
361 | } | |
362 | else { | |
363 | value.i = result; | |
364 | } | |
365 | } | |
366 | break; | |
b32b8144 | 367 | |
7c673cae FG |
368 | case is_uint: |
369 | { | |
b32b8144 | 370 | uint_literal_type result = value.ui * rhs.value.ui; |
7c673cae FG |
371 | if (0 != value.ui && 0 != rhs.value.ui && |
372 | (result / value.ui != rhs.value.ui || | |
373 | result / rhs.value.ui != value.ui) | |
374 | ) | |
375 | { | |
376 | valid = error_integer_overflow; | |
377 | } | |
378 | else { | |
379 | value.ui = result; | |
b32b8144 | 380 | type = is_uint; |
7c673cae FG |
381 | } |
382 | } | |
383 | break; | |
384 | } | |
385 | break; | |
b32b8144 | 386 | |
7c673cae FG |
387 | case is_uint: |
388 | { | |
389 | uint_literal_type rhs_val = as_ulong(rhs); | |
b32b8144 | 390 | uint_literal_type result = value.ui * rhs_val; |
7c673cae FG |
391 | if (0 != value.ui && 0 != rhs_val && |
392 | (result / value.ui != rhs_val || | |
393 | result / rhs_val != value.ui) | |
394 | ) | |
395 | { | |
396 | valid = error_integer_overflow; | |
397 | } | |
398 | else { | |
399 | value.ui = result; | |
b32b8144 | 400 | type = is_uint; |
7c673cae FG |
401 | } |
402 | } | |
403 | break; | |
b32b8144 | 404 | |
7c673cae FG |
405 | case is_bool: |
406 | switch (rhs.type) { | |
407 | case is_int: | |
b32b8144 FG |
408 | value.i = (value.b ? 1 : 0) * rhs.value.i; |
409 | type = is_int; | |
7c673cae | 410 | break; |
b32b8144 | 411 | |
7c673cae | 412 | case is_uint: |
b32b8144 FG |
413 | value.ui = (value.b ? 1 : 0) * rhs.value.ui; |
414 | type = is_uint; | |
7c673cae | 415 | break; |
b32b8144 | 416 | |
7c673cae FG |
417 | case is_bool: |
418 | value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0)); | |
419 | break; | |
420 | } | |
421 | } | |
422 | valid = (value_error)(valid | rhs.valid); | |
423 | return *this; | |
424 | } | |
425 | closure_value &operator/= (closure_value const &rhs) | |
426 | { | |
427 | switch (type) { | |
b32b8144 | 428 | case is_int: |
7c673cae | 429 | switch(rhs.type) { |
b32b8144 | 430 | case is_bool: |
7c673cae FG |
431 | case is_int: |
432 | if (as_long(rhs) != 0) { | |
433 | if (value.i == -value.i && -1 == rhs.value.i) { | |
434 | // LONG_MIN / -1 on two's complement | |
435 | valid = error_integer_overflow; | |
436 | } | |
437 | else { | |
b32b8144 | 438 | value.i /= as_long(rhs); |
7c673cae FG |
439 | } |
440 | } | |
441 | else { | |
442 | valid = error_division_by_zero; // division by zero | |
443 | } | |
444 | break; | |
b32b8144 | 445 | |
7c673cae FG |
446 | case is_uint: |
447 | if (rhs.value.ui != 0) { | |
b32b8144 FG |
448 | value.ui /= rhs.value.ui; |
449 | type = is_uint; | |
7c673cae FG |
450 | } |
451 | else { | |
452 | valid = error_division_by_zero; // division by zero | |
453 | } | |
454 | break; | |
455 | } | |
456 | break; | |
b32b8144 FG |
457 | |
458 | case is_uint: | |
459 | if (as_ulong(rhs) != 0) | |
460 | value.ui /= as_ulong(rhs); | |
7c673cae FG |
461 | else |
462 | valid = error_division_by_zero; // division by zero | |
463 | break; | |
464 | ||
b32b8144 | 465 | case is_bool: |
7c673cae FG |
466 | if (as_bool(rhs)) { |
467 | switch(rhs.type) { | |
468 | case is_int: | |
469 | value.i = (value.b ? 1 : 0) / rhs.value.i; | |
470 | type = is_int; | |
471 | break; | |
b32b8144 | 472 | |
7c673cae FG |
473 | case is_uint: |
474 | value.i = (value.b ? 1 : 0) / rhs.value.ui; | |
475 | type = is_int; | |
476 | break; | |
b32b8144 | 477 | |
7c673cae FG |
478 | case is_bool: |
479 | break; | |
480 | } | |
481 | } | |
482 | else { | |
483 | valid = error_division_by_zero; // division by zero | |
484 | } | |
485 | } | |
486 | return *this; | |
487 | } | |
488 | closure_value &operator%= (closure_value const &rhs) | |
489 | { | |
490 | switch (type) { | |
b32b8144 | 491 | case is_int: |
7c673cae | 492 | switch(rhs.type) { |
b32b8144 | 493 | case is_bool: |
7c673cae FG |
494 | case is_int: |
495 | if (as_long(rhs) != 0) { | |
496 | if (value.i == -value.i && -1 == rhs.value.i) { | |
497 | // LONG_MIN % -1 on two's complement | |
498 | valid = error_integer_overflow; | |
499 | } | |
500 | else { | |
b32b8144 | 501 | value.i %= as_long(rhs); |
7c673cae FG |
502 | } |
503 | } | |
504 | else { | |
505 | valid = error_division_by_zero; // division by zero | |
506 | } | |
507 | break; | |
b32b8144 | 508 | |
7c673cae FG |
509 | case is_uint: |
510 | if (rhs.value.ui != 0) { | |
b32b8144 FG |
511 | value.ui %= rhs.value.ui; |
512 | type = is_uint; | |
7c673cae FG |
513 | } |
514 | else { | |
515 | valid = error_division_by_zero; // division by zero | |
516 | } | |
517 | break; | |
518 | } | |
519 | break; | |
b32b8144 FG |
520 | |
521 | case is_uint: | |
522 | if (as_ulong(rhs) != 0) | |
523 | value.ui %= as_ulong(rhs); | |
7c673cae FG |
524 | else |
525 | valid = error_division_by_zero; // division by zero | |
526 | break; | |
527 | ||
b32b8144 | 528 | case is_bool: |
7c673cae FG |
529 | if (as_bool(rhs)) { |
530 | switch(rhs.type) { | |
531 | case is_int: | |
532 | value.i = (value.b ? 1 : 0) % rhs.value.i; | |
533 | type = is_int; | |
534 | break; | |
b32b8144 | 535 | |
7c673cae FG |
536 | case is_uint: |
537 | value.i = (value.b ? 1 : 0) % rhs.value.ui; | |
538 | type = is_int; | |
539 | break; | |
b32b8144 | 540 | |
7c673cae FG |
541 | case is_bool: |
542 | break; | |
b32b8144 | 543 | } |
7c673cae FG |
544 | } |
545 | else { | |
546 | valid = error_division_by_zero; // division by zero | |
547 | } | |
548 | } | |
549 | return *this; | |
550 | } | |
551 | ||
b32b8144 | 552 | friend closure_value |
7c673cae FG |
553 | operator- (closure_value const &rhs) |
554 | { | |
555 | switch (rhs.type) { | |
556 | case is_int: | |
557 | { | |
558 | int_literal_type value = as_long(rhs); | |
559 | if (value != 0 && value == -value) | |
560 | return closure_value(-value, error_integer_overflow); | |
561 | return closure_value(-value, rhs.valid); | |
562 | } | |
b32b8144 FG |
563 | |
564 | case is_bool: return closure_value(-as_long(rhs), rhs.valid); | |
7c673cae FG |
565 | case is_uint: break; |
566 | } | |
567 | ||
568 | int_literal_type value = as_ulong(rhs); | |
569 | if (value != 0 && value == -value) | |
570 | return closure_value(-value, error_integer_overflow); | |
571 | return closure_value(-value, rhs.valid); | |
572 | } | |
b32b8144 | 573 | friend closure_value |
7c673cae FG |
574 | operator~ (closure_value const &rhs) |
575 | { | |
b32b8144 | 576 | return closure_value(~as_ulong(rhs), rhs.valid); |
7c673cae | 577 | } |
b32b8144 | 578 | friend closure_value |
7c673cae FG |
579 | operator! (closure_value const &rhs) |
580 | { | |
581 | switch (rhs.type) { | |
582 | case is_int: return closure_value(!as_long(rhs), rhs.valid); | |
b32b8144 | 583 | case is_bool: return closure_value(!as_bool(rhs), rhs.valid); |
7c673cae FG |
584 | case is_uint: break; |
585 | } | |
586 | return closure_value(!as_ulong(rhs), rhs.valid); | |
587 | } | |
b32b8144 | 588 | |
7c673cae | 589 | // comparison |
b32b8144 | 590 | friend closure_value |
7c673cae FG |
591 | operator== (closure_value const &lhs, closure_value const &rhs) |
592 | { | |
593 | bool cmp = false; | |
594 | switch (lhs.type) { | |
595 | case is_int: | |
596 | switch(rhs.type) { | |
597 | case is_bool: cmp = as_bool(lhs) == rhs.value.b; break; | |
598 | case is_int: cmp = lhs.value.i == rhs.value.i; break; | |
599 | case is_uint: cmp = lhs.value.ui == rhs.value.ui; break; | |
600 | } | |
601 | break; | |
b32b8144 | 602 | |
7c673cae FG |
603 | case is_uint: cmp = lhs.value.ui == as_ulong(rhs); break; |
604 | case is_bool: cmp = lhs.value.b == as_bool(rhs); break; | |
605 | } | |
606 | return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); | |
607 | } | |
b32b8144 | 608 | friend closure_value |
7c673cae FG |
609 | operator!= (closure_value const &lhs, closure_value const &rhs) |
610 | { | |
611 | return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid)); | |
612 | } | |
b32b8144 | 613 | friend closure_value |
7c673cae FG |
614 | operator> (closure_value const &lhs, closure_value const &rhs) |
615 | { | |
616 | bool cmp = false; | |
617 | switch (lhs.type) { | |
618 | case is_int: | |
619 | switch(rhs.type) { | |
620 | case is_bool: cmp = lhs.value.i > as_long(rhs); break; | |
621 | case is_int: cmp = lhs.value.i > rhs.value.i; break; | |
622 | case is_uint: cmp = lhs.value.ui > rhs.value.ui; break; | |
623 | } | |
624 | break; | |
b32b8144 | 625 | |
7c673cae FG |
626 | case is_uint: cmp = lhs.value.ui > as_ulong(rhs); break; |
627 | case is_bool: cmp = lhs.value.b > as_bool(rhs); break; | |
628 | } | |
629 | return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); | |
630 | } | |
b32b8144 | 631 | friend closure_value |
7c673cae FG |
632 | operator< (closure_value const &lhs, closure_value const &rhs) |
633 | { | |
634 | bool cmp = false; | |
635 | switch (lhs.type) { | |
636 | case is_int: | |
637 | switch(rhs.type) { | |
638 | case is_bool: cmp = lhs.value.i < as_long(rhs); break; | |
639 | case is_int: cmp = lhs.value.i < rhs.value.i; break; | |
640 | case is_uint: cmp = lhs.value.ui < rhs.value.ui; break; | |
641 | } | |
642 | break; | |
b32b8144 | 643 | |
7c673cae FG |
644 | case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break; |
645 | case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break; | |
646 | } | |
647 | return closure_value(cmp, (value_error)(lhs.valid | rhs.valid)); | |
648 | } | |
b32b8144 | 649 | friend closure_value |
7c673cae FG |
650 | operator<= (closure_value const &lhs, closure_value const &rhs) |
651 | { | |
652 | return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid)); | |
653 | } | |
b32b8144 | 654 | friend closure_value |
7c673cae FG |
655 | operator>= (closure_value const &lhs, closure_value const &rhs) |
656 | { | |
657 | return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid)); | |
658 | } | |
659 | ||
660 | closure_value & | |
661 | operator<<= (closure_value const &rhs) | |
662 | { | |
663 | switch (type) { | |
664 | case is_bool: | |
665 | case is_int: | |
666 | switch (rhs.type) { | |
667 | case is_bool: | |
668 | case is_int: | |
669 | { | |
670 | int_literal_type shift_by = as_long(rhs); | |
b32b8144 FG |
671 | |
672 | if (shift_by > 64) | |
7c673cae FG |
673 | shift_by = 64; |
674 | else if (shift_by < -64) | |
675 | shift_by = -64; | |
b32b8144 | 676 | value.i <<= shift_by; |
7c673cae FG |
677 | } |
678 | break; | |
b32b8144 | 679 | |
7c673cae FG |
680 | case is_uint: |
681 | { | |
682 | uint_literal_type shift_by = as_ulong(rhs); | |
b32b8144 FG |
683 | |
684 | if (shift_by > 64) | |
7c673cae | 685 | shift_by = 64; |
b32b8144 FG |
686 | value.ui <<= shift_by; |
687 | ||
688 | // Note: The usual arithmetic conversions are not performed on | |
7c673cae FG |
689 | // bit shift operations. |
690 | } | |
691 | break; | |
692 | } | |
693 | break; | |
694 | ||
695 | case is_uint: | |
696 | switch (rhs.type) { | |
697 | case is_bool: | |
698 | case is_int: | |
699 | { | |
700 | int_literal_type shift_by = as_long(rhs); | |
b32b8144 FG |
701 | |
702 | if (shift_by > 64) | |
7c673cae FG |
703 | shift_by = 64; |
704 | else if (shift_by < -64) | |
705 | shift_by = -64; | |
b32b8144 | 706 | value.ui <<= shift_by; |
7c673cae FG |
707 | } |
708 | break; | |
b32b8144 | 709 | |
7c673cae FG |
710 | case is_uint: |
711 | { | |
712 | uint_literal_type shift_by = as_ulong(rhs); | |
b32b8144 FG |
713 | |
714 | if (shift_by > 64) | |
7c673cae | 715 | shift_by = 64; |
b32b8144 | 716 | value.ui <<= shift_by; |
7c673cae FG |
717 | } |
718 | break; | |
719 | } | |
720 | } | |
721 | valid = (value_error)(valid | rhs.valid); | |
722 | return *this; | |
723 | } | |
724 | ||
725 | closure_value & | |
726 | operator>>= (closure_value const &rhs) | |
727 | { | |
728 | switch (type) { | |
729 | case is_bool: | |
730 | case is_int: | |
731 | switch (rhs.type) { | |
732 | case is_bool: | |
733 | case is_int: | |
734 | { | |
735 | int_literal_type shift_by = as_long(rhs); | |
b32b8144 FG |
736 | |
737 | if (shift_by > 64) | |
7c673cae FG |
738 | shift_by = 64; |
739 | else if (shift_by < -64) | |
740 | shift_by = -64; | |
b32b8144 | 741 | value.i >>= shift_by; |
7c673cae FG |
742 | } |
743 | break; | |
b32b8144 | 744 | |
7c673cae FG |
745 | case is_uint: |
746 | { | |
747 | uint_literal_type shift_by = as_ulong(rhs); | |
b32b8144 FG |
748 | |
749 | if (shift_by > 64) | |
7c673cae | 750 | shift_by = 64; |
b32b8144 FG |
751 | value.ui >>= shift_by; |
752 | ||
753 | // Note: The usual arithmetic conversions are not performed on | |
7c673cae FG |
754 | // bit shift operations. |
755 | } | |
756 | break; | |
757 | } | |
758 | break; | |
b32b8144 | 759 | |
7c673cae FG |
760 | case is_uint: |
761 | switch (rhs.type) { | |
762 | case is_bool: | |
763 | case is_int: | |
764 | { | |
765 | int_literal_type shift_by = as_long(rhs); | |
b32b8144 FG |
766 | |
767 | if (shift_by > 64) | |
7c673cae FG |
768 | shift_by = 64; |
769 | else if (shift_by < -64) | |
770 | shift_by = -64; | |
b32b8144 | 771 | value.ui >>= shift_by; |
7c673cae FG |
772 | } |
773 | break; | |
b32b8144 | 774 | |
7c673cae FG |
775 | case is_uint: |
776 | { | |
777 | uint_literal_type shift_by = as_ulong(rhs); | |
b32b8144 FG |
778 | |
779 | if (shift_by > 64) | |
7c673cae | 780 | shift_by = 64; |
b32b8144 | 781 | value.ui >>= shift_by; |
7c673cae FG |
782 | } |
783 | break; | |
784 | } | |
785 | break; | |
786 | } | |
787 | valid = (value_error)(valid | rhs.valid); | |
788 | return *this; | |
789 | } | |
790 | ||
b32b8144 | 791 | friend closure_value |
7c673cae FG |
792 | operator|| (closure_value const &lhs, closure_value const &rhs) |
793 | { | |
794 | bool result = as_bool(lhs) || as_bool(rhs); | |
795 | return closure_value(result, (value_error)(lhs.valid | rhs.valid)); | |
796 | } | |
b32b8144 FG |
797 | |
798 | friend closure_value | |
7c673cae FG |
799 | operator&& (closure_value const &lhs, closure_value const &rhs) |
800 | { | |
801 | bool result = as_bool(lhs) && as_bool(rhs); | |
802 | return closure_value(result, (value_error)(lhs.valid | rhs.valid)); | |
803 | } | |
804 | ||
b32b8144 | 805 | friend closure_value |
7c673cae FG |
806 | operator| (closure_value const &lhs, closure_value const &rhs) |
807 | { | |
808 | uint_literal_type result = as_ulong(lhs) | as_ulong(rhs); | |
809 | return closure_value(result, (value_error)(lhs.valid | rhs.valid)); | |
810 | } | |
b32b8144 FG |
811 | |
812 | friend closure_value | |
7c673cae FG |
813 | operator& (closure_value const &lhs, closure_value const &rhs) |
814 | { | |
815 | uint_literal_type result = as_ulong(lhs) & as_ulong(rhs); | |
816 | return closure_value(result, (value_error)(lhs.valid | rhs.valid)); | |
817 | } | |
818 | ||
b32b8144 | 819 | friend closure_value |
7c673cae FG |
820 | operator^ (closure_value const &lhs, closure_value const &rhs) |
821 | { | |
822 | uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs); | |
823 | return closure_value(result, (value_error)(lhs.valid | rhs.valid)); | |
824 | } | |
b32b8144 | 825 | |
7c673cae FG |
826 | // handle the ?: operator |
827 | closure_value & | |
828 | handle_questionmark(closure_value const &cond, closure_value const &val2) | |
829 | { | |
830 | switch (type) { | |
831 | case is_int: | |
832 | switch (val2.type) { | |
833 | case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break; | |
834 | case is_int: value.i = as_bool(cond) ? value.i : as_long(val2); break; | |
b32b8144 FG |
835 | case is_uint: |
836 | value.ui = as_bool(cond) ? value.ui : as_ulong(val2); | |
7c673cae FG |
837 | type = is_uint; // changing type! |
838 | break; | |
839 | } | |
840 | break; | |
b32b8144 | 841 | |
7c673cae FG |
842 | case is_uint: value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break; |
843 | case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break; | |
844 | } | |
845 | valid = as_bool(cond) ? valid : val2.valid; | |
846 | return *this; | |
847 | } | |
b32b8144 | 848 | |
7c673cae FG |
849 | #if defined (BOOST_SPIRIT_DEBUG) |
850 | friend std::ostream& | |
851 | operator<< (std::ostream &o, closure_value const &val) | |
852 | { | |
853 | switch (val.type) { | |
854 | case is_int: o << "int(" << as_long(val) << ")"; break; | |
855 | case is_uint: o << "unsigned int(" << as_ulong(val) << ")"; break; | |
856 | case is_bool: o << "bool(" << as_bool(val) << ")"; break; | |
857 | } | |
858 | return o; | |
859 | } | |
860 | #endif // defined(BOOST_SPIRIT_DEBUG) | |
861 | ||
862 | private: | |
863 | value_type type; | |
864 | union { | |
865 | int_literal_type i; | |
866 | uint_literal_type ui; | |
867 | bool b; | |
868 | } value; | |
869 | value_error valid; | |
870 | }; | |
871 | ||
872 | /////////////////////////////////////////////////////////////////////////////// | |
873 | } // namespace closures | |
874 | } // namespace grammars | |
875 | } // namespace wave | |
876 | } // namespace boost | |
877 | ||
878 | // the suffix header occurs after all of the code | |
879 | #ifdef BOOST_HAS_ABI_HEADERS | |
880 | #include BOOST_ABI_SUFFIX | |
881 | #endif | |
882 | ||
883 | #endif // !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED) |