]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/wave/grammars/cpp_expression_value.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / wave / grammars / cpp_expression_value.hpp
CommitLineData
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///////////////////////////////////////////////////////////////////////////////
27namespace boost {
28namespace wave {
29namespace grammars {
30namespace closures {
31
32class closure_value;
33inline 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///////////////////////////////////////////////////////////////////////////////
44class closure_value {
45public:
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
862private:
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)