Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-12 08:32:00

0001 /*=============================================================================
0002     Boost.Wave: A Standard compliant C++ preprocessor library
0003 
0004     http://www.boost.org/
0005 
0006     Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
0007     Software License, Version 1.0. (See accompanying file
0008     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 =============================================================================*/
0010 
0011 #if !defined(BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)
0012 #define BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED
0013 
0014 #if defined (BOOST_SPIRIT_DEBUG)
0015 #include <iostream>
0016 #endif // defined(BOOST_SPIRIT_DEBUG)
0017 
0018 #include <limits>
0019 
0020 #include <boost/wave/wave_config.hpp>
0021 #include <boost/wave/grammars/cpp_value_error.hpp> // value_error
0022 
0023 // this must occur after all of the includes and before any code appears
0024 #ifdef BOOST_HAS_ABI_HEADERS
0025 #include BOOST_ABI_PREFIX
0026 #endif
0027 
0028 ///////////////////////////////////////////////////////////////////////////////
0029 namespace boost {
0030 namespace wave {
0031 namespace grammars {
0032 namespace closures {
0033 
0034 class closure_value;
0035 inline bool as_bool(closure_value const& v);
0036 
0037 ///////////////////////////////////////////////////////////////////////////////
0038 //
0039 //  The closure_value class represents the closure type, which is used for the
0040 //  expression grammar.
0041 //
0042 //      This class was introduced to allow the expression grammar to respect
0043 //      the numeric type of a numeric literal or expression result.
0044 //
0045 ///////////////////////////////////////////////////////////////////////////////
0046 class closure_value {
0047 public:
0048 
0049     enum value_type {
0050         is_int = 1,
0051         is_uint = 2,
0052         is_bool = 3
0053     };
0054 
0055     closure_value(value_error valid_ = error_noerror)
0056     : type(is_int), valid(valid_)
0057     { value.i = 0; }
0058     explicit closure_value(int i, value_error valid_ = error_noerror)
0059     : type(is_int), valid(valid_)
0060     { value.i = i; }
0061     explicit closure_value(unsigned int ui, value_error valid_ = error_noerror)
0062     : type(is_uint), valid(valid_)
0063     { value.ui = ui; }
0064     explicit closure_value(int_literal_type i, value_error valid_ = error_noerror)
0065     : type(is_int), valid(valid_)
0066     { value.i = i; }
0067     explicit closure_value(uint_literal_type ui, value_error valid_ = error_noerror)
0068     : type(is_uint), valid(valid_)
0069     { value.ui = ui; }
0070     explicit closure_value(bool b, value_error valid_ = error_noerror)
0071     : type(is_bool), valid(valid_)
0072     { value.b = b; }
0073 
0074     value_type get_type() const { return type; }
0075     value_error is_valid() const { return valid; }
0076 
0077     // explicit conversion
0078     friend int_literal_type as_int(closure_value const& v)
0079     {
0080         switch (v.type) {
0081         case is_uint:   return v.value.ui;
0082         case is_bool:   return v.value.b ? 1 : 0;
0083         case is_int:    break;
0084         }
0085         return v.value.i;
0086     }
0087     friend uint_literal_type as_uint(closure_value const& v)
0088     {
0089         switch (v.type) {
0090         case is_uint:   return v.value.ui;
0091         case is_bool:   return v.value.b ? 1 : 0;
0092         case is_int:    break;
0093         }
0094         return v.value.i;
0095     }
0096     friend int_literal_type as_long(closure_value const& v)
0097     {
0098         switch (v.type) {
0099         case is_uint:   return v.value.ui;
0100         case is_bool:   return v.value.b ? 1 : 0;
0101         case is_int:    break;
0102         }
0103         return v.value.i;
0104     }
0105     friend uint_literal_type as_ulong(closure_value const& v)
0106     {
0107         switch (v.type) {
0108         case is_uint:   return v.value.ui;
0109         case is_bool:   return v.value.b ? 1 : 0;
0110         case is_int:    break;
0111         }
0112         return v.value.i;
0113     }
0114     friend bool as_bool(closure_value const& v)
0115     {
0116         switch (v.type) {
0117         case is_uint:   return v.value.ui != 0;
0118         case is_bool:   return v.value.b;
0119         case is_int:    break;
0120         }
0121         return v.value.i != 0.0;
0122     }
0123 
0124     // assignment
0125     closure_value &operator= (closure_value const &rhs)
0126     {
0127         switch (rhs.get_type()) {
0128         case is_int:
0129             value.i = as_long(rhs);
0130             type = is_int;
0131             break;
0132 
0133         case is_uint:
0134             value.ui = as_ulong(rhs);
0135             type = is_uint;
0136             break;
0137 
0138         case is_bool:
0139             value.b = as_bool(rhs);
0140             type = is_bool;
0141             break;
0142         }
0143         valid = rhs.valid;
0144         return *this;
0145     }
0146     closure_value &operator= (int rhs)
0147     {
0148         type = is_int;
0149         value.i = rhs;
0150         valid = error_noerror;
0151         return *this;
0152     }
0153     closure_value &operator= (unsigned int rhs)
0154     {
0155         type = is_uint;
0156         value.ui = rhs;
0157         valid = error_noerror;
0158         return *this;
0159     }
0160     closure_value &operator= (int_literal_type rhs)
0161     {
0162         type = is_int;
0163         value.i = rhs;
0164         valid = error_noerror;
0165         return *this;
0166     }
0167     closure_value &operator= (uint_literal_type rhs)
0168     {
0169         type = is_uint;
0170         value.ui = rhs;
0171         valid = error_noerror;
0172         return *this;
0173     }
0174     closure_value &operator= (bool rhs)
0175     {
0176         type = is_bool;
0177         value.b = rhs;
0178         valid = error_noerror;
0179         return *this;
0180     }
0181 
0182     // arithmetics
0183     closure_value &operator+= (closure_value const &rhs)
0184     {
0185         switch (type) {
0186         case is_int:
0187             switch(rhs.type) {
0188             case is_bool:
0189                 {
0190                     // bool is either 0 or 1
0191                     if (((std::numeric_limits<int_literal_type>::max)() - as_long(rhs)) < value.i)
0192                     {
0193                         // signed overflow will occur if addition performed
0194                         valid = error_integer_overflow;
0195                     }
0196                     else {
0197                         value.i += as_long(rhs);
0198                     }
0199                 }
0200                 break;
0201 
0202             case is_int:
0203                 {
0204                     if (((rhs.value.i > 0) &&
0205                          (((std::numeric_limits<int_literal_type>::max)() - rhs.value.i) < value.i)) ||
0206                         ((rhs.value.i < 0) &&
0207                          (((std::numeric_limits<int_literal_type>::min)() - rhs.value.i) > value.i)))
0208                     {
0209                         // signed overflow will occur if addition performed
0210                         valid = error_integer_overflow;
0211                     }
0212                     else {
0213                         value.i += rhs.value.i;
0214                     }
0215                 }
0216                 break;
0217 
0218             case is_uint:
0219                 {
0220                     uint_literal_type result = value.ui + rhs.value.ui;
0221                     if (result < value.ui) {
0222                         valid = error_integer_overflow;
0223                     }
0224                     else {
0225                         value.ui = result;
0226                         type = is_uint;
0227                     }
0228                 }
0229                 break;
0230             }
0231             break;
0232 
0233         case is_uint:
0234             {
0235                 uint_literal_type result = value.ui + as_ulong(rhs);
0236                 if (result < value.ui) {
0237                     valid = error_integer_overflow;
0238                 }
0239                 else {
0240                     value.ui = result;
0241                 }
0242             }
0243             break;
0244 
0245         case is_bool:
0246             value.i = value.b + as_bool(rhs);
0247             type = is_int;
0248         }
0249         valid = (value_error)(valid | rhs.valid);
0250         return *this;
0251     }
0252     closure_value &operator-= (closure_value const &rhs)
0253     {
0254         switch (type) {
0255         case is_int:
0256             switch(rhs.type) {
0257             case is_bool:
0258                 {
0259                     if (((std::numeric_limits<int_literal_type>::min)() + as_long(rhs)) > value.i)
0260                     {
0261                         // signed overflow will occur if subtraction performed
0262                         valid = error_integer_overflow;
0263                     }
0264                     else {
0265                         value.i -= as_long(rhs);
0266                     }
0267                 }
0268                 break;
0269 
0270             case is_int:
0271                 {
0272                     if (((rhs.value.i < 0) &&
0273                          (((std::numeric_limits<int_literal_type>::max)() + rhs.value.i) < value.i)) ||
0274                         ((rhs.value.i > 0) &&
0275                          (((std::numeric_limits<int_literal_type>::min)() + rhs.value.i) > value.i)))
0276                     {
0277                         // signed overflow will occur if subtraction performed
0278                         valid = error_integer_overflow;
0279                     }
0280                     else {
0281                         value.i -= rhs.value.i;
0282                     }
0283                 }
0284                 break;
0285 
0286             case is_uint:
0287                 {
0288                     uint_literal_type result = value.ui - rhs.value.ui;
0289                     if (result > value.ui) {
0290                         valid = error_integer_overflow;
0291                     }
0292                     else {
0293                         value.ui = result;
0294                         type = is_uint;
0295                     }
0296                 }
0297                 break;
0298             }
0299             break;
0300 
0301         case is_uint:
0302             switch(rhs.type) {
0303             case is_bool:
0304                 {
0305                     uint_literal_type result = value.ui - as_ulong(rhs);
0306                     if (result > value.ui)
0307                     {
0308                         valid = error_integer_overflow;
0309                     }
0310                     else {
0311                         value.ui = result;
0312                     }
0313                 }
0314                 break;
0315 
0316             case is_int:
0317                 {
0318                     uint_literal_type result = value.ui - rhs.value.i;
0319                     if ((rhs.value.i > 0L && result > value.ui) ||
0320                         (rhs.value.i < 0L && result < value.ui))
0321                     {
0322                         valid = error_integer_overflow;
0323                     }
0324                     else {
0325                         value.ui = result;
0326                     }
0327                 }
0328                 break;
0329 
0330             case is_uint:
0331                 {
0332                     uint_literal_type result = value.ui - rhs.value.ui;
0333                     if (result > value.ui) {
0334                         valid = error_integer_overflow;
0335                     }
0336                     else {
0337                         value.ui = result;
0338                     }
0339                 }
0340                 break;
0341             }
0342             break;
0343 
0344         case is_bool:
0345             value.i = value.b - as_bool(rhs);
0346             type = is_int;
0347         }
0348         valid = (value_error)(valid | rhs.valid);
0349         return *this;
0350     }
0351     closure_value &operator*= (closure_value const &rhs)
0352     {
0353         switch (type) {
0354         case is_int:
0355             switch(rhs.type) {
0356             case is_bool:   value.i *= as_long(rhs); break;
0357             case is_int:
0358                 {
0359                     // overflow tests for signed multiplication taken from
0360                     // Warren, Hacker's Delight, 2nd Ed. p32
0361                     int_literal_type mx = (std::numeric_limits<int_literal_type>::max)();
0362                     int_literal_type mn = (std::numeric_limits<int_literal_type>::min)();
0363 
0364                     bool ovflw =
0365                         (value.i > 0) ? ((rhs.value.i > 0) ? (value.i > (mx / rhs.value.i))
0366                                                            : (rhs.value.i < (mn / value.i)))
0367                                       : ((rhs.value.i > 0) ? (value.i < (mn / rhs.value.i))
0368                                                            : ((value.i != 0) && (rhs.value.i < (mx / value.i))));
0369                     if (ovflw)
0370                     {
0371                         valid = error_integer_overflow;
0372                     }
0373                     else {
0374                         value.i *= rhs.value.i;
0375                     }
0376                 }
0377                 break;
0378 
0379             case is_uint:
0380                 {
0381                     uint_literal_type result = value.ui * rhs.value.ui;
0382                     if (0 != value.ui && 0 != rhs.value.ui &&
0383                         (result / value.ui != rhs.value.ui ||
0384                          result / rhs.value.ui != value.ui)
0385                        )
0386                     {
0387                         valid = error_integer_overflow;
0388                     }
0389                     else {
0390                         value.ui = result;
0391                         type = is_uint;
0392                     }
0393                 }
0394                 break;
0395             }
0396             break;
0397 
0398         case is_uint:
0399             {
0400                 uint_literal_type rhs_val = as_ulong(rhs);
0401                 uint_literal_type result = value.ui * rhs_val;
0402                 if (0 != value.ui && 0 != rhs_val &&
0403                     (result / value.ui != rhs_val ||
0404                       result / rhs_val != value.ui)
0405                     )
0406                 {
0407                     valid = error_integer_overflow;
0408                 }
0409                 else {
0410                     value.ui = result;
0411                     type = is_uint;
0412                 }
0413             }
0414             break;
0415 
0416         case is_bool:
0417             switch (rhs.type) {
0418             case is_int:
0419                 value.i = (value.b ? 1 : 0) * rhs.value.i;
0420                 type = is_int;
0421                 break;
0422 
0423             case is_uint:
0424                 value.ui = (value.b ? 1 : 0) * rhs.value.ui;
0425                 type = is_uint;
0426                 break;
0427 
0428             case is_bool:
0429                 value.b = 0 != ((value.b ? 1 : 0) * (rhs.value.b ? 1 : 0));
0430                 break;
0431             }
0432         }
0433         valid = (value_error)(valid | rhs.valid);
0434         return *this;
0435     }
0436     closure_value &operator/= (closure_value const &rhs)
0437     {
0438         switch (type) {
0439         case is_int:
0440             switch(rhs.type) {
0441             case is_bool:
0442             case is_int:
0443                 if (as_long(rhs) != 0) {
0444                     if (std::numeric_limits<int_literal_type>::min() == value.i &&
0445                         -1 == rhs.value.i) {
0446                         // LONG_MIN / -1 on two's complement
0447                         valid = error_integer_overflow;
0448                     }
0449                     else {
0450                         value.i /= as_long(rhs);
0451                     }
0452                 }
0453                 else {
0454                     valid = error_division_by_zero;   // division by zero
0455                 }
0456                 break;
0457 
0458             case is_uint:
0459                 if (rhs.value.ui != 0) {
0460                     value.ui /= rhs.value.ui;
0461                     type = is_uint;
0462                 }
0463                 else {
0464                     valid = error_division_by_zero;      // division by zero
0465                 }
0466                 break;
0467             }
0468             break;
0469 
0470         case is_uint:
0471             if (as_ulong(rhs) != 0)
0472                 value.ui /= as_ulong(rhs);
0473             else
0474                 valid = error_division_by_zero;         // division by zero
0475             break;
0476 
0477         case is_bool:
0478             if (as_bool(rhs)) {
0479                 switch(rhs.type) {
0480                 case is_int:
0481                     value.i = (value.b ? 1 : 0) / rhs.value.i;
0482                     type = is_int;
0483                     break;
0484 
0485                 case is_uint:
0486                     value.i = (value.b ? 1 : 0) / rhs.value.ui;
0487                     type = is_int;
0488                     break;
0489 
0490                 case is_bool:
0491                     break;
0492                 }
0493             }
0494             else {
0495                 valid = error_division_by_zero;         // division by zero
0496             }
0497         }
0498         return *this;
0499     }
0500     closure_value &operator%= (closure_value const &rhs)
0501     {
0502         switch (type) {
0503         case is_int:
0504             switch(rhs.type) {
0505             case is_bool:
0506             case is_int:
0507                 if (as_long(rhs) != 0) {
0508                     if (value.i == -value.i && -1 == rhs.value.i) {
0509                         // LONG_MIN % -1 on two's complement
0510                         valid = error_integer_overflow;
0511                     }
0512                     else {
0513                         value.i %= as_long(rhs);
0514                     }
0515                 }
0516                 else {
0517                     valid = error_division_by_zero;      // division by zero
0518                 }
0519                 break;
0520 
0521             case is_uint:
0522                 if (rhs.value.ui != 0) {
0523                     value.ui %= rhs.value.ui;
0524                     type = is_uint;
0525                 }
0526                 else {
0527                     valid = error_division_by_zero;      // division by zero
0528                 }
0529                 break;
0530             }
0531             break;
0532 
0533         case is_uint:
0534             if (as_ulong(rhs) != 0)
0535                 value.ui %= as_ulong(rhs);
0536             else
0537                 valid = error_division_by_zero;      // division by zero
0538             break;
0539 
0540         case is_bool:
0541             if (as_bool(rhs)) {
0542                 switch(rhs.type) {
0543                 case is_int:
0544                     value.i = (value.b ? 1 : 0) % rhs.value.i;
0545                     type = is_int;
0546                     break;
0547 
0548                 case is_uint:
0549                     value.i = (value.b ? 1 : 0) % rhs.value.ui;
0550                     type = is_int;
0551                     break;
0552 
0553                 case is_bool:
0554                     break;
0555                 }
0556             }
0557             else {
0558                 valid = error_division_by_zero;      // division by zero
0559             }
0560         }
0561         return *this;
0562     }
0563 
0564     friend closure_value
0565     operator- (closure_value const &rhs)
0566     {
0567         switch (rhs.type) {
0568         case is_int:
0569             {
0570                 int_literal_type value = as_long(rhs);
0571                 if (value != 0 && value == -value)
0572                     return closure_value(-value, error_integer_overflow);
0573                 return closure_value(-value, rhs.valid);
0574             }
0575 
0576         case is_bool:   return closure_value(-as_long(rhs), rhs.valid);
0577         case is_uint:   break;
0578         }
0579 
0580         int_literal_type value = as_ulong(rhs);
0581         if (value != 0 && value == -value)
0582             return closure_value(-value, error_integer_overflow);
0583         return closure_value(-value, rhs.valid);
0584     }
0585     friend closure_value
0586     operator~ (closure_value const &rhs)
0587     {
0588         return closure_value(~as_ulong(rhs), rhs.valid);
0589     }
0590     friend closure_value
0591     operator! (closure_value const &rhs)
0592     {
0593         switch (rhs.type) {
0594         case is_int:    return closure_value(!as_long(rhs), rhs.valid);
0595         case is_bool:   return closure_value(!as_bool(rhs), rhs.valid);
0596         case is_uint:   break;
0597         }
0598         return closure_value(!as_ulong(rhs), rhs.valid);
0599     }
0600 
0601     // comparison
0602     friend closure_value
0603     operator== (closure_value const &lhs, closure_value const &rhs)
0604     {
0605         bool cmp = false;
0606         switch (lhs.type) {
0607         case is_int:
0608             switch(rhs.type) {
0609             case is_bool:   cmp = as_bool(lhs) == rhs.value.b; break;
0610             case is_int:    cmp = lhs.value.i == rhs.value.i; break;
0611             case is_uint:   cmp = lhs.value.ui == rhs.value.ui; break;
0612             }
0613             break;
0614 
0615         case is_uint:   cmp = lhs.value.ui == as_ulong(rhs); break;
0616         case is_bool:   cmp = lhs.value.b == as_bool(rhs); break;
0617         }
0618         return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
0619     }
0620     friend closure_value
0621     operator!= (closure_value const &lhs, closure_value const &rhs)
0622     {
0623         return closure_value(!as_bool(lhs == rhs), (value_error)(lhs.valid | rhs.valid));
0624     }
0625     friend closure_value
0626     operator> (closure_value const &lhs, closure_value const &rhs)
0627     {
0628         bool cmp = false;
0629         switch (lhs.type) {
0630         case is_int:
0631             switch(rhs.type) {
0632             case is_bool:   cmp = lhs.value.i > as_long(rhs); break;
0633             case is_int:    cmp = lhs.value.i > rhs.value.i; break;
0634             case is_uint:   cmp = lhs.value.ui > rhs.value.ui; break;
0635             }
0636             break;
0637 
0638         case is_uint:   cmp = lhs.value.ui > as_ulong(rhs); break;
0639         case is_bool:   cmp = lhs.value.b > as_bool(rhs); break;
0640         }
0641         return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
0642     }
0643     friend closure_value
0644     operator< (closure_value const &lhs, closure_value const &rhs)
0645     {
0646         bool cmp = false;
0647         switch (lhs.type) {
0648         case is_int:
0649             switch(rhs.type) {
0650             case is_bool:   cmp = lhs.value.i < as_long(rhs); break;
0651             case is_int:    cmp = lhs.value.i < rhs.value.i; break;
0652             case is_uint:   cmp = lhs.value.ui < rhs.value.ui; break;
0653             }
0654             break;
0655 
0656         case is_uint:   cmp = lhs.value.ui < as_ulong(rhs); break;
0657         case is_bool:   cmp = as_bool(lhs) < as_bool(rhs); break;
0658         }
0659         return closure_value(cmp, (value_error)(lhs.valid | rhs.valid));
0660     }
0661     friend closure_value
0662     operator<= (closure_value const &lhs, closure_value const &rhs)
0663     {
0664         return closure_value(!as_bool(lhs > rhs), (value_error)(lhs.valid | rhs.valid));
0665     }
0666     friend closure_value
0667     operator>= (closure_value const &lhs, closure_value const &rhs)
0668     {
0669         return closure_value(!as_bool(lhs < rhs), (value_error)(lhs.valid | rhs.valid));
0670     }
0671 
0672     closure_value &
0673     operator<<= (closure_value const &rhs)
0674     {
0675         switch (type) {
0676         case is_bool:
0677         case is_int:
0678             switch (rhs.type) {
0679             case is_bool:
0680             case is_int:
0681                 {
0682                 int_literal_type shift_by = as_long(rhs);
0683 
0684                     if (shift_by > 64)
0685                         shift_by = 64;
0686                     else if (shift_by < -64)
0687                         shift_by = -64;
0688                     value.i <<= shift_by;
0689                 }
0690                 break;
0691 
0692             case is_uint:
0693                 {
0694                 uint_literal_type shift_by = as_ulong(rhs);
0695 
0696                     if (shift_by > 64)
0697                         shift_by = 64;
0698                     value.ui <<= shift_by;
0699 
0700                 // Note: The usual arithmetic conversions are not performed on
0701                 //       bit shift operations.
0702                 }
0703                 break;
0704             }
0705             break;
0706 
0707         case is_uint:
0708             switch (rhs.type) {
0709             case is_bool:
0710             case is_int:
0711                 {
0712                 int_literal_type shift_by = as_long(rhs);
0713 
0714                     if (shift_by > 64)
0715                         shift_by = 64;
0716                     else if (shift_by < -64)
0717                         shift_by = -64;
0718                     value.ui <<= shift_by;
0719                 }
0720                 break;
0721 
0722             case is_uint:
0723                 {
0724                 uint_literal_type shift_by = as_ulong(rhs);
0725 
0726                     if (shift_by > 64)
0727                         shift_by = 64;
0728                     value.ui <<= shift_by;
0729                 }
0730                 break;
0731             }
0732         }
0733         valid = (value_error)(valid | rhs.valid);
0734         return *this;
0735     }
0736 
0737     closure_value &
0738     operator>>= (closure_value const &rhs)
0739     {
0740         switch (type) {
0741         case is_bool:
0742         case is_int:
0743             switch (rhs.type) {
0744             case is_bool:
0745             case is_int:
0746                 {
0747                 int_literal_type shift_by = as_long(rhs);
0748 
0749                     if (shift_by > 64)
0750                         shift_by = 64;
0751                     else if (shift_by < -64)
0752                         shift_by = -64;
0753                     value.i >>= shift_by;
0754                 }
0755                 break;
0756 
0757             case is_uint:
0758                 {
0759                 uint_literal_type shift_by = as_ulong(rhs);
0760 
0761                     if (shift_by > 64)
0762                         shift_by = 64;
0763                     value.ui >>= shift_by;
0764 
0765                 // Note: The usual arithmetic conversions are not performed on
0766                 //       bit shift operations.
0767                 }
0768                 break;
0769             }
0770             break;
0771 
0772         case is_uint:
0773             switch (rhs.type) {
0774             case is_bool:
0775             case is_int:
0776                 {
0777                 int_literal_type shift_by = as_long(rhs);
0778 
0779                     if (shift_by > 64)
0780                         shift_by = 64;
0781                     else if (shift_by < -64)
0782                         shift_by = -64;
0783                     value.ui >>= shift_by;
0784                 }
0785                 break;
0786 
0787             case is_uint:
0788                 {
0789                 uint_literal_type shift_by = as_ulong(rhs);
0790 
0791                     if (shift_by > 64)
0792                         shift_by = 64;
0793                     value.ui >>= shift_by;
0794                 }
0795                 break;
0796             }
0797             break;
0798         }
0799         valid = (value_error)(valid | rhs.valid);
0800         return *this;
0801     }
0802 
0803     friend closure_value
0804     operator|| (closure_value const &lhs, closure_value const &rhs)
0805     {
0806         bool result = as_bool(lhs) || as_bool(rhs);
0807         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0808     }
0809 
0810     friend closure_value
0811     operator&& (closure_value const &lhs, closure_value const &rhs)
0812     {
0813         bool result = as_bool(lhs) && as_bool(rhs);
0814         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0815     }
0816 
0817     friend closure_value
0818     operator| (closure_value const &lhs, closure_value const &rhs)
0819     {
0820         uint_literal_type result = as_ulong(lhs) | as_ulong(rhs);
0821         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0822     }
0823 
0824     friend closure_value
0825     operator& (closure_value const &lhs, closure_value const &rhs)
0826     {
0827         uint_literal_type result = as_ulong(lhs) & as_ulong(rhs);
0828         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0829     }
0830 
0831     friend closure_value
0832     operator^ (closure_value const &lhs, closure_value const &rhs)
0833     {
0834         uint_literal_type result = as_ulong(lhs) ^ as_ulong(rhs);
0835         return closure_value(result, (value_error)(lhs.valid | rhs.valid));
0836     }
0837 
0838     // handle the ?: operator
0839     closure_value &
0840     handle_questionmark(closure_value const &cond, closure_value const &val2)
0841     {
0842         switch (type) {
0843         case is_int:
0844             switch (val2.type) {
0845             case is_bool: value.b = as_bool(cond) ? value.b : as_bool(val2); break;
0846             case is_int:  value.i = as_bool(cond) ? value.i : as_long(val2); break;
0847             case is_uint:
0848                 value.ui = as_bool(cond) ? value.ui : as_ulong(val2);
0849                 type = is_uint;   // changing type!
0850                 break;
0851             }
0852             break;
0853 
0854         case is_uint:   value.ui = as_bool(cond) ? value.ui : as_ulong(val2); break;
0855         case is_bool:   value.b = as_bool(cond) ? value.b : as_bool(val2); break;
0856         }
0857         valid = as_bool(cond) ? valid : val2.valid;
0858         return *this;
0859     }
0860 
0861 #if defined (BOOST_SPIRIT_DEBUG)
0862     friend std::ostream&
0863     operator<< (std::ostream &o, closure_value const &val)
0864     {
0865         switch (val.type) {
0866         case is_int:    o << "int(" << as_long(val) << ")"; break;
0867         case is_uint:   o << "unsigned int(" << as_ulong(val) << ")"; break;
0868         case is_bool:   o << "bool(" << as_bool(val) << ")"; break;
0869         }
0870         return o;
0871     }
0872 #endif // defined(BOOST_SPIRIT_DEBUG)
0873 
0874 private:
0875     value_type type;
0876     union {
0877         int_literal_type i;
0878         uint_literal_type ui;
0879         bool b;
0880     } value;
0881     value_error valid;
0882 };
0883 
0884 ///////////////////////////////////////////////////////////////////////////////
0885 }   // namespace closures
0886 }   // namespace grammars
0887 }   // namespace wave
0888 }   // namespace boost
0889 
0890 // the suffix header occurs after all of the code
0891 #ifdef BOOST_HAS_ABI_HEADERS
0892 #include BOOST_ABI_SUFFIX
0893 #endif
0894 
0895 #endif // !defined(BOOST_CPP_EXPRESSION_VALUE_HPP_452FE66D_8754_4107_AF1E_E42255A0C18A_INCLUDED)