1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
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 =============================================================================*/
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
14 #if defined (BOOST_SPIRIT_DEBUG)
16 #endif // defined(BOOST_SPIRIT_DEBUG)
18 #include <boost/wave/wave_config.hpp>
19 #include <boost/wave/grammars/cpp_value_error.hpp> // value_error
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
26 ///////////////////////////////////////////////////////////////////////////////
33 inline bool as_bool(closure_value const& v);
35 ///////////////////////////////////////////////////////////////////////////////
37 // The closure_value class represents the closure type, which is used for the
38 // expression grammar.
40 // This class was introduced to allow the expression grammar to respect
41 // the numeric type of a numeric literal or expression result.
43 ///////////////////////////////////////////////////////////////////////////////
53 closure_value(value_error valid_ = error_noerror)
54 : type(is_int), valid(valid_)
56 explicit closure_value(int i, value_error valid_ = error_noerror)
57 : type(is_int), valid(valid_)
59 explicit closure_value(unsigned int ui, value_error valid_ = error_noerror)
60 : type(is_uint), valid(valid_)
62 explicit closure_value(int_literal_type i, value_error valid_ = error_noerror)
63 : type(is_int), valid(valid_)
65 explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror)
66 : type(is_uint), valid(valid_)
68 explicit closure_value(bool b, value_error valid_ = error_noerror)
69 : type(is_bool), valid(valid_)
72 value_type get_type() const { return type; }
73 value_error is_valid() const { return valid; }
75 // explicit conversion
76 friend int_literal_type as_int(closure_value const& v)
79 case is_uint: return v.value.ui;
80 case is_bool: return v.value.b ? 1 : 0;
85 friend uint_literal_type as_uint(closure_value const& v)
88 case is_uint: return v.value.ui;
89 case is_bool: return v.value.b ? 1 : 0;
94 friend int_literal_type as_long(closure_value const& v)
97 case is_uint: return v.value.ui;
98 case is_bool: return v.value.b ? 1 : 0;
103 friend uint_literal_type as_ulong(closure_value const& v)
106 case is_uint: return v.value.ui;
107 case is_bool: return v.value.b ? 1 : 0;
112 friend bool as_bool(closure_value const& v)
115 case is_uint: return v.value.ui != 0;
116 case is_bool: return v.value.b;
119 return v.value.i != 0.0;
123 closure_value &operator= (closure_value const &rhs)
125 switch (rhs.get_type()) {
127 value.i = as_long(rhs);
132 value.ui = as_ulong(rhs);
137 value.b = as_bool(rhs);
144 closure_value &operator= (int rhs)
148 valid = error_noerror;
151 closure_value &operator= (unsigned int rhs)
155 valid = error_noerror;
158 closure_value &operator= (int_literal_type rhs)
162 valid = error_noerror;
165 closure_value &operator= (uint_literal_type rhs)
169 valid = error_noerror;
172 closure_value &operator= (bool rhs)
176 valid = error_noerror;
181 closure_value &operator+= (closure_value const &rhs)
188 int_literal_type result = value.i + as_long(rhs);
189 if ((rhs.value.i > 0L && value.i > result) ||
190 (rhs.value.i < 0L && value.i < result))
192 valid = error_integer_overflow;
202 int_literal_type result = value.i + rhs.value.i;
203 if ((rhs.value.i > 0L && value.i > result) ||
204 (rhs.value.i < 0L && value.i < result))
206 valid = error_integer_overflow;
216 uint_literal_type result = value.ui + rhs.value.ui;
217 if (result < value.ui) {
218 valid = error_integer_overflow;
231 uint_literal_type result = value.ui + as_ulong(rhs);
232 if (result < value.ui) {
233 valid = error_integer_overflow;
242 value.i = value.b + as_bool(rhs);
245 valid = (value_error)(valid | rhs.valid);
248 closure_value &operator-= (closure_value const &rhs)
255 int_literal_type result = value.i - as_long(rhs);
256 if ((rhs.value.i > 0L && result > value.i) ||
257 (rhs.value.i < 0L && result < value.i))
259 valid = error_integer_overflow;
269 int_literal_type result = value.i - rhs.value.i;
270 if ((rhs.value.i > 0L && result > value.i) ||
271 (rhs.value.i < 0L && result < value.i))
273 valid = error_integer_overflow;
283 uint_literal_type result = value.ui - rhs.value.ui;
284 if (result > value.ui) {
285 valid = error_integer_overflow;
300 uint_literal_type result = value.ui - as_ulong(rhs);
301 if (result > value.ui)
303 valid = error_integer_overflow;
313 uint_literal_type result = value.ui - rhs.value.i;
314 if ((rhs.value.i > 0L && result > value.ui) ||
315 (rhs.value.i < 0L && result < value.ui))
317 valid = error_integer_overflow;
327 uint_literal_type result = value.ui - rhs.value.ui;
328 if (result > value.ui) {
329 valid = error_integer_overflow;
340 value.i = value.b - as_bool(rhs);
343 valid = (value_error)(valid | rhs.valid);
346 closure_value &operator*= (closure_value const &rhs)
351 case is_bool: value.i *= as_long(rhs); break;
354 int_literal_type result = value.i * rhs.value.i;
355 if (0 != value.i && 0 != rhs.value.i &&
356 (result / value.i != rhs.value.i ||
357 result / rhs.value.i != value.i)
360 valid = error_integer_overflow;
370 uint_literal_type result = value.ui * rhs.value.ui;
371 if (0 != value.ui && 0 != rhs.value.ui &&
372 (result / value.ui != rhs.value.ui ||
373 result / rhs.value.ui != value.ui)
376 valid = error_integer_overflow;
389 uint_literal_type rhs_val = as_ulong(rhs);
390 uint_literal_type result = value.ui * rhs_val;
391 if (0 != value.ui && 0 != rhs_val &&
392 (result / value.ui != rhs_val ||
393 result / rhs_val != value.ui)
396 valid = error_integer_overflow;
408 value.i = (value.b ? 1 : 0) * rhs.value.i;
413 value.ui = (value.b ? 1 : 0) * rhs.value.ui;
418 value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0));
422 valid = (value_error)(valid | rhs.valid);
425 closure_value &operator/= (closure_value const &rhs)
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;
438 value.i /= as_long(rhs);
442 valid = error_division_by_zero; // division by zero
447 if (rhs.value.ui != 0) {
448 value.ui /= rhs.value.ui;
452 valid = error_division_by_zero; // division by zero
459 if (as_ulong(rhs) != 0)
460 value.ui /= as_ulong(rhs);
462 valid = error_division_by_zero; // division by zero
469 value.i = (value.b ? 1 : 0) / rhs.value.i;
474 value.i = (value.b ? 1 : 0) / rhs.value.ui;
483 valid = error_division_by_zero; // division by zero
488 closure_value &operator%= (closure_value const &rhs)
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;
501 value.i %= as_long(rhs);
505 valid = error_division_by_zero; // division by zero
510 if (rhs.value.ui != 0) {
511 value.ui %= rhs.value.ui;
515 valid = error_division_by_zero; // division by zero
522 if (as_ulong(rhs) != 0)
523 value.ui %= as_ulong(rhs);
525 valid = error_division_by_zero; // division by zero
532 value.i = (value.b ? 1 : 0) % rhs.value.i;
537 value.i = (value.b ? 1 : 0) % rhs.value.ui;
546 valid = error_division_by_zero; // division by zero
553 operator- (closure_value const &rhs)
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);
564 case is_bool: return closure_value(-as_long(rhs), rhs.valid);
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);
574 operator~ (closure_value const &rhs)
576 return closure_value(~as_ulong(rhs), rhs.valid);
579 operator! (closure_value const &rhs)
582 case is_int: return closure_value(!as_long(rhs), rhs.valid);
583 case is_bool: return closure_value(!as_bool(rhs), rhs.valid);
586 return closure_value(!as_ulong(rhs), rhs.valid);
591 operator== (closure_value const &lhs, closure_value const &rhs)
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;
603 case is_uint: cmp = lhs.value.ui == as_ulong(rhs); break;
604 case is_bool: cmp = lhs.value.b == as_bool(rhs); break;
606 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
609 operator!= (closure_value const &lhs, closure_value const &rhs)
611 return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid));
614 operator> (closure_value const &lhs, closure_value const &rhs)
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;
626 case is_uint: cmp = lhs.value.ui > as_ulong(rhs); break;
627 case is_bool: cmp = lhs.value.b > as_bool(rhs); break;
629 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
632 operator< (closure_value const &lhs, closure_value const &rhs)
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;
644 case is_uint: cmp = lhs.value.ui < as_ulong(rhs); break;
645 case is_bool: cmp = as_bool(lhs) < as_bool(rhs); break;
647 return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
650 operator<= (closure_value const &lhs, closure_value const &rhs)
652 return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid));
655 operator>= (closure_value const &lhs, closure_value const &rhs)
657 return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid));
661 operator<<= (closure_value const &rhs)
670 int_literal_type shift_by = as_long(rhs);
674 else if (shift_by < -64)
676 value.i <<= shift_by;
682 uint_literal_type shift_by = as_ulong(rhs);
686 value.ui <<= shift_by;
688 // Note: The usual arithmetic conversions are not performed on
689 // bit shift operations.
700 int_literal_type shift_by = as_long(rhs);
704 else if (shift_by < -64)
706 value.ui <<= shift_by;
712 uint_literal_type shift_by = as_ulong(rhs);
716 value.ui <<= shift_by;
721 valid = (value_error)(valid | rhs.valid);
726 operator>>= (closure_value const &rhs)
735 int_literal_type shift_by = as_long(rhs);
739 else if (shift_by < -64)
741 value.i >>= shift_by;
747 uint_literal_type shift_by = as_ulong(rhs);
751 value.ui >>= shift_by;
753 // Note: The usual arithmetic conversions are not performed on
754 // bit shift operations.
765 int_literal_type shift_by = as_long(rhs);
769 else if (shift_by < -64)
771 value.ui >>= shift_by;
777 uint_literal_type shift_by = as_ulong(rhs);
781 value.ui >>= shift_by;
787 valid = (value_error)(valid | rhs.valid);
792 operator|| (closure_value const &lhs, closure_value const &rhs)
794 bool result = as_bool(lhs) || as_bool(rhs);
795 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
799 operator&& (closure_value const &lhs, closure_value const &rhs)
801 bool result = as_bool(lhs) && as_bool(rhs);
802 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
806 operator| (closure_value const &lhs, closure_value const &rhs)
808 uint_literal_type result = as_ulong(lhs) | as_ulong(rhs);
809 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
813 operator& (closure_value const &lhs, closure_value const &rhs)
815 uint_literal_type result = as_ulong(lhs) & as_ulong(rhs);
816 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
820 operator^ (closure_value const &lhs, closure_value const &rhs)
822 uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs);
823 return closure_value(result, (value_error)(lhs.valid | rhs.valid));
826 // handle the ?: operator
828 handle_questionmark(closure_value const &cond, closure_value const &val2)
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;
836 value.ui = as_bool(cond) ? value.ui : as_ulong(val2);
837 type = is_uint; // changing type!
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;
845 valid = as_bool(cond) ? valid : val2.valid;
849 #if defined (BOOST_SPIRIT_DEBUG)
851 operator<< (std::ostream &o, closure_value const &val)
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;
860 #endif // defined(BOOST_SPIRIT_DEBUG)
866 uint_literal_type ui;
872 ///////////////////////////////////////////////////////////////////////////////
873 } // namespace closures
874 } // namespace grammars
878 // the suffix header occurs after all of the code
879 #ifdef BOOST_HAS_ABI_HEADERS
880 #include BOOST_ABI_SUFFIX
883 #endif // !defined(CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)