ChaiScript / ChaiScript
1
// This file is distributed under the BSD License.
2
// See "license.txt" for details.
3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5
// http://www.chaiscript.com
6

7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9

10
#ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
11
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
12

13
#include <cstdint>
14
#include <sstream>
15
#include <string>
16

17
#include "../language/chaiscript_algebraic.hpp"
18
#include "any.hpp"
19
#include "boxed_cast.hpp"
20
#include "boxed_cast_helper.hpp"
21
#include "boxed_value.hpp"
22
#include "type_info.hpp"
23

24
namespace chaiscript {
25
class Type_Conversions;
26
}  // namespace chaiscript
27

28
namespace chaiscript
29
{
30
  namespace exception
31
  {
32
    struct arithmetic_error : std::runtime_error
33
    {
34 1
      explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
35
      arithmetic_error(const arithmetic_error &) = default;
36 1
      ~arithmetic_error() noexcept override = default;
37
    };
38
  }
39
}
40

41
namespace chaiscript 
42
{
43

44
// Due to the nature of generating every possible arithmetic operation, there
45
// are going to be warnings generated on every platform regarding size and sign,
46
// this is OK, so we're disabling size/and sign type warnings
47
#ifdef CHAISCRIPT_MSVC
48
#pragma warning(push)
49
#pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
50
#endif
51

52

53
#ifdef __GNUC__
54
#pragma GCC diagnostic push
55
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
56
#pragma GCC diagnostic ignored "-Wpragmas"
57
#pragma GCC diagnostic ignored "-Wsign-compare"
58
#pragma GCC diagnostic ignored "-Wfloat-equal"
59
#pragma GCC diagnostic ignored "-Wconversion"
60
#pragma GCC diagnostic ignored "-Wsign-conversion"
61
#pragma GCC diagnostic ignored "-Wfloat-conversion"
62
#pragma GCC diagnostic ignored "-Wswitch"
63
#endif
64

65
  /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
66
  class Boxed_Number
67
  {
68
    private:
69
      enum class Common_Types {
70
        t_int32,
71
        t_double,
72
        t_uint8,
73
        t_int8,
74
        t_uint16,
75
        t_int16,
76
        t_uint32,
77
        t_uint64,
78
        t_int64,
79
        t_float,
80
        t_long_double
81
      };
82

83
      template<typename T>
84 1
      constexpr static inline void check_divide_by_zero([[maybe_unused]] T t)
85
      {
86
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
87
        if constexpr (!std::is_floating_point<T>::value) {
88 1
          if (t == 0) {
89 1
            throw chaiscript::exception::arithmetic_error("divide by zero");
90
          }
91
        }
92
#endif
93
      }
94

95 1
      constexpr static Common_Types get_common_type(size_t t_size, bool t_signed) noexcept
96
      {
97 1
        return   (t_size == 1 && t_signed)?(Common_Types::t_int8)
98 1
                :(t_size == 1)?(Common_Types::t_uint8)
99 0
                :(t_size == 2 && t_signed)?(Common_Types::t_int16)
100 0
                :(t_size == 2)?(Common_Types::t_uint16)
101 1
                :(t_size == 4 && t_signed)?(Common_Types::t_int32)
102 1
                :(t_size == 4)?(Common_Types::t_uint32)
103 1
                :(t_size == 8 && t_signed)?(Common_Types::t_int64)
104 1
                :(Common_Types::t_uint64);
105
      }
106

107

108 1
      static Common_Types get_common_type(const Boxed_Value &t_bv)
109
      {
110 1
        const Type_Info &inp_ = t_bv.get_type_info();
111

112 1
        if (inp_ == user_type<int>()) {
113 1
          return get_common_type(sizeof(int), true);
114 1
        } else if (inp_ == user_type<double>()) {
115 1
          return Common_Types::t_double;
116 1
        } else if (inp_ == user_type<long double>()) {
117 1
          return Common_Types::t_long_double;
118 1
        } else if (inp_ == user_type<float>()) {
119 1
          return Common_Types::t_float;
120 1
        } else if (inp_ == user_type<char>()) {
121 1
          return get_common_type(sizeof(char), std::is_signed<char>::value);
122 1
        } else if (inp_ == user_type<unsigned char>()) {
123 1
          return get_common_type(sizeof(unsigned char), false);
124 1
        } else if (inp_ == user_type<unsigned int>()) {
125 1
          return get_common_type(sizeof(unsigned int), false);
126 1
        } else if (inp_ == user_type<long>()) {
127 1
          return get_common_type(sizeof(long), true);
128 1
        } else if (inp_ == user_type<long long>()) {
129 1
          return get_common_type(sizeof(long long), true);
130 1
        } else if (inp_ == user_type<unsigned long>()) {
131 1
          return get_common_type(sizeof(unsigned long), false);
132 1
        } else if (inp_ == user_type<unsigned long long>()) {
133 1
          return get_common_type(sizeof(unsigned long long), false);
134 1
        } else if (inp_ == user_type<std::int8_t>()) {
135 1
          return Common_Types::t_int8;
136 1
        } else if (inp_ == user_type<std::int16_t>()) {
137 1
          return Common_Types::t_int16;
138 1
        } else if (inp_ == user_type<std::int32_t>()) {
139 0
          return Common_Types::t_int32;
140 1
        } else if (inp_ == user_type<std::int64_t>()) {
141 0
          return Common_Types::t_int64;
142 1
        } else if (inp_ == user_type<std::uint8_t>()) {
143 0
          return Common_Types::t_uint8;
144 1
        } else if (inp_ == user_type<std::uint16_t>()) {
145 1
          return Common_Types::t_uint16;
146 0
        } else if (inp_ == user_type<std::uint32_t>()) {
147 0
          return Common_Types::t_uint32;
148 0
        } else if (inp_ == user_type<std::uint64_t>()) {
149 0
          return Common_Types::t_uint64;
150 0
        } else if (inp_ == user_type<wchar_t>()) {
151 0
          return get_common_type(sizeof(wchar_t), std::is_signed<wchar_t>::value);
152 0
        } else if (inp_ == user_type<char16_t>()) {
153 0
          return get_common_type(sizeof(char16_t), std::is_signed<char16_t>::value);
154 0
        } else if (inp_ == user_type<char32_t>()) {
155 0
          return get_common_type(sizeof(char32_t), std::is_signed<char32_t>::value);
156
        } else  {
157 0
          throw chaiscript::detail::exception::bad_any_cast();
158
        }
159
      }
160

161
  
162

163
      template<typename LHS, typename RHS>
164 1
      static auto go(Operators::Opers t_oper, const Boxed_Value &t_bv, LHS *t_lhs, const LHS &c_lhs, const RHS &c_rhs)
165
      {
166 1
        switch (t_oper) {
167 1
          case Operators::Opers::equals:
168 1
            return const_var(c_lhs == c_rhs);
169 1
          case Operators::Opers::less_than:
170 1
            return const_var(c_lhs < c_rhs);
171 1
          case Operators::Opers::greater_than:
172 1
            return const_var(c_lhs > c_rhs);
173 1
          case Operators::Opers::less_than_equal:
174 1
            return const_var(c_lhs <= c_rhs);
175 1
          case Operators::Opers::greater_than_equal:
176 1
            return const_var(c_lhs >= c_rhs);
177 1
          case Operators::Opers::not_equal:
178 1
            return const_var(c_lhs != c_rhs);
179 1
          case Operators::Opers::sum:
180 1
            return const_var(c_lhs + c_rhs);
181 1
          case Operators::Opers::quotient:
182 1
            check_divide_by_zero(c_rhs);
183 1
            return const_var(c_lhs / c_rhs);
184 1
          case Operators::Opers::product:
185 1
            return const_var(c_lhs * c_rhs);
186 1
          case Operators::Opers::difference:
187 1
            return const_var(c_lhs - c_rhs);
188 1
          default:
189 1
            break;
190
          }
191

192

193
        if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
194 1
          switch (t_oper) {
195 1
            case Operators::Opers::shift_left:
196 1
              return const_var(c_lhs << c_rhs);
197 1
            case Operators::Opers::shift_right:
198 1
              return const_var(c_lhs >> c_rhs);
199 1
            case Operators::Opers::remainder:
200 1
              check_divide_by_zero(c_rhs);
201 1
              return const_var(c_lhs % c_rhs);
202 1
            case Operators::Opers::bitwise_and:
203 1
              return const_var(c_lhs & c_rhs);
204 1
            case Operators::Opers::bitwise_or:
205 1
              return const_var(c_lhs | c_rhs);
206 1
            case Operators::Opers::bitwise_xor:
207 1
              return const_var(c_lhs ^ c_rhs);
208 1
            default:
209 1
              break;
210
            }
211
        }
212

213 1
        if (t_lhs) {
214 1
          switch (t_oper) {
215 1
            case Operators::Opers::assign:
216 1
              *t_lhs = c_rhs;
217 1
              return t_bv;
218 1
            case Operators::Opers::assign_product:
219 1
              *t_lhs *= c_rhs;
220 1
              return t_bv;
221 1
            case Operators::Opers::assign_sum:
222 1
              *t_lhs += c_rhs;
223 1
              return t_bv;
224 1
            case Operators::Opers::assign_quotient:
225 1
              check_divide_by_zero(c_rhs);
226 1
              *t_lhs /= c_rhs;
227 1
              return t_bv;
228 1
            case Operators::Opers::assign_difference:
229 1
              *t_lhs -= c_rhs;
230 1
              return t_bv;
231 1
            default:
232 1
              break;
233
            }
234

235
          if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
236 1
            switch (t_oper) {
237 1
              case Operators::Opers::assign_bitwise_and:
238 1
                check_divide_by_zero(c_rhs);
239 1
                *t_lhs &= c_rhs;
240 1
                return t_bv;
241 1
              case Operators::Opers::assign_bitwise_or:
242 1
                *t_lhs |= c_rhs;
243 1
                return t_bv;
244 1
              case Operators::Opers::assign_shift_left:
245 1
                *t_lhs <<= c_rhs;
246 1
                return t_bv;
247 1
              case Operators::Opers::assign_shift_right:
248 1
                *t_lhs >>= c_rhs;
249 1
                return t_bv;
250 1
              case Operators::Opers::assign_remainder:
251 1
                *t_lhs %= c_rhs;
252 1
                return t_bv;
253 1
              case Operators::Opers::assign_bitwise_xor:
254 1
                *t_lhs ^= c_rhs;
255 1
                return t_bv;
256 0
              default:
257 0
                break;
258
              }
259
          }
260
        }
261

262 1
        throw chaiscript::detail::exception::bad_any_cast();
263
      }
264

265
      template<typename Callable>
266 1
        inline static auto visit(const Boxed_Value &bv, Callable &&callable)
267
        {
268 1
          switch (get_common_type(bv)) {
269 1
            case Common_Types::t_int32:
270 1
              return callable(*static_cast<const std::int32_t *>(bv.get_const_ptr()));
271 1
            case Common_Types::t_uint8:
272 1
              return callable(*static_cast<const std::uint8_t *>(bv.get_const_ptr()));
273 1
            case Common_Types::t_int8:
274 1
              return callable(*static_cast<const std::int8_t *>(bv.get_const_ptr()));
275 1
            case Common_Types::t_uint16:
276 1
              return callable(*static_cast<const std::uint16_t *>(bv.get_const_ptr()));
277 1
            case Common_Types::t_int16:
278 1
              return callable(*static_cast<const std::int16_t *>(bv.get_const_ptr()));
279 1
            case Common_Types::t_uint32:
280 1
              return callable(*static_cast<const std::uint32_t *>(bv.get_const_ptr()));
281 1
            case Common_Types::t_uint64:
282 1
              return callable(*static_cast<const std::uint64_t *>(bv.get_const_ptr()));
283 1
            case Common_Types::t_int64:
284 1
              return callable(*static_cast<const std::int64_t *>(bv.get_const_ptr()));
285 1
            case Common_Types::t_double:
286 1
              return callable(*static_cast<const double *>(bv.get_const_ptr()));
287 1
            case Common_Types::t_float:
288 1
              return callable(*static_cast<const float *>(bv.get_const_ptr()));
289 1
            case Common_Types::t_long_double:
290 1
              return callable(*static_cast<const long double *>(bv.get_const_ptr()));
291 0
            default:
292 0
              throw chaiscript::detail::exception::bad_any_cast();
293

294
          }
295
        }
296

297 1
        inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
298
        {
299
          auto unary_operator = [t_oper, &t_lhs](const auto &c_lhs){
300
            auto *lhs = static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
301

302
            if (lhs) {
303
              switch (t_oper) {
304
                case Operators::Opers::pre_increment:
305
                  ++(*lhs);
306
                  return t_lhs;
307
                case Operators::Opers::pre_decrement:
308
                  --(*lhs);
309
                  return t_lhs;
310
                default:
311
                  break;
312
                }
313
            }
314

315
            switch (t_oper) {
316
              case Operators::Opers::unary_minus:
317
                return const_var(-c_lhs);
318
              case Operators::Opers::unary_plus:
319
                return const_var(+c_lhs);
320
              default:
321
                break;
322
              }
323

324
            if constexpr (!std::is_floating_point_v<std::decay_t<decltype(c_lhs)>>) {
325
              switch (t_oper) {
326
                case Operators::Opers::bitwise_complement:
327
                  return const_var(~c_lhs);
328
                default:
329
                  break;
330
                }
331
            }
332

333
            throw chaiscript::detail::exception::bad_any_cast();
334 1
          };
335

336 1
          return visit(t_lhs, unary_operator);
337
        }
338

339

340 1
        inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
341
        {
342

343
          auto lhs_visit = [t_oper, &t_lhs, &t_rhs](const auto &c_lhs){
344
            auto *lhs = t_lhs.is_return_value()?nullptr:static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
345

346
            auto rhs_visit = [t_oper, &t_lhs, lhs, &c_lhs](const auto &c_rhs) {
347
              return go(t_oper, t_lhs, lhs, c_lhs, c_rhs);
348
            };
349

350
            return visit(t_rhs, rhs_visit);
351 1
          };
352

353 1
          return visit(t_lhs, lhs_visit);
354
        }
355

356
        template<typename Target, typename Source>
357 1
          static inline Target get_as_aux(const Boxed_Value &t_bv)
358
          {
359 1
            return static_cast<Target>(*static_cast<const Source *>(t_bv.get_const_ptr()));
360
          }
361

362
        template<typename Source>
363 1
         static std::string to_string_aux(const Boxed_Value &v)
364
        {
365 1
          std::ostringstream oss;
366 1
          oss << *static_cast<const Source *>(v.get_const_ptr());
367 1
          return oss.str();
368
        }
369

370
    public:
371
      Boxed_Number()
372
        : bv(Boxed_Value(0))
373
      {
374
      }
375

376 1
      explicit Boxed_Number(Boxed_Value v)
377 1
        : bv(std::move(v))
378
      {
379 1
        validate_boxed_number(bv);
380
      }
381

382 1
      Boxed_Number(const Boxed_Number &) = default;
383
      Boxed_Number(Boxed_Number &&) = default;
384
      Boxed_Number& operator=(Boxed_Number &&) = default;
385

386 1
      template<typename T> explicit Boxed_Number(T t)
387 1
        : bv(Boxed_Value(t))
388
      {
389 1
        validate_boxed_number(bv);
390
      }
391

392 1
      static Boxed_Value clone(const Boxed_Value &t_bv) {
393 1
        return Boxed_Number(t_bv).get_as(t_bv.get_type_info()).bv;
394
      }
395

396 1
      static bool is_floating_point(const Boxed_Value &t_bv)
397
      {
398 1
        const Type_Info &inp_ = t_bv.get_type_info();
399

400 1
        if (inp_ == user_type<double>()) {
401 1
          return true;
402 1
        } else if (inp_ == user_type<long double>()) {
403 0
          return true;
404 1
        } else if (inp_ == user_type<float>()) {
405 0
          return true;
406
        } else {
407 1
          return false;
408
        }
409
      }
410

411 1
      Boxed_Number get_as(const Type_Info &inp_) const
412
      {
413 1
        if (inp_.bare_equal(user_type<int>())) {
414 1
          return Boxed_Number(get_as<int>());
415 1
        } else if (inp_.bare_equal(user_type<double>())) {
416 1
          return Boxed_Number(get_as<double>());
417 1
        } else if (inp_.bare_equal(user_type<float>())) {
418 1
          return Boxed_Number(get_as<float>());
419 1
        } else if (inp_.bare_equal(user_type<long double>())) {
420 1
          return Boxed_Number(get_as<long double>());
421 1
        } else if (inp_.bare_equal(user_type<char>())) {
422 0
          return Boxed_Number(get_as<char>());
423 1
        } else if (inp_.bare_equal(user_type<unsigned char>())) {
424 1
          return Boxed_Number(get_as<unsigned char>());
425 1
        } else if (inp_.bare_equal(user_type<wchar_t>())) {
426 0
          return Boxed_Number(get_as<wchar_t>());
427 1
        } else if (inp_.bare_equal(user_type<char16_t>())) {
428 0
          return Boxed_Number(get_as<char16_t>());
429 1
        } else if (inp_.bare_equal(user_type<char32_t>())) {
430 0
          return Boxed_Number(get_as<char32_t>());
431 1
        } else if (inp_.bare_equal(user_type<unsigned int>())) {
432 1
          return Boxed_Number(get_as<unsigned int>());
433 1
        } else if (inp_.bare_equal(user_type<long>())) {
434 1
          return Boxed_Number(get_as<long>());
435 1
        } else if (inp_.bare_equal(user_type<long long>())) {
436 1
          return Boxed_Number(get_as<long long>());
437 1
        } else if (inp_.bare_equal(user_type<unsigned long>())) {
438 1
          return Boxed_Number(get_as<unsigned long>());
439 1
        } else if (inp_.bare_equal(user_type<unsigned long long>())) {
440 1
          return Boxed_Number(get_as<unsigned long long>());
441 1
        } else if (inp_.bare_equal(user_type<int8_t>())) {
442 1
          return Boxed_Number(get_as<int8_t>());
443 1
        } else if (inp_.bare_equal(user_type<int16_t>())) {
444 1
          return Boxed_Number(get_as<int16_t>());
445 1
        } else if (inp_.bare_equal(user_type<int32_t>())) {
446 0
          return Boxed_Number(get_as<int32_t>());
447 1
        } else if (inp_.bare_equal(user_type<int64_t>())) {
448 0
          return Boxed_Number(get_as<int64_t>());
449 1
        } else if (inp_.bare_equal(user_type<uint8_t>())) {
450 0
          return Boxed_Number(get_as<uint8_t>());
451 1
        } else if (inp_.bare_equal(user_type<uint16_t>())) {
452 1
          return Boxed_Number(get_as<uint16_t>());
453 0
        } else if (inp_.bare_equal(user_type<uint32_t>())) {
454 0
          return Boxed_Number(get_as<uint32_t>());
455 0
        } else if (inp_.bare_equal(user_type<uint64_t>())) {
456 0
          return Boxed_Number(get_as<uint64_t>());
457
        } else {
458 0
          throw chaiscript::detail::exception::bad_any_cast();
459
        }
460

461
      }
462

463
      template<typename Source, typename Target> 
464 1
      static void check_type()
465
      {
466
#ifdef CHAISCRIPT_MSVC
467
// MSVC complains about this being redundant / tautologica l
468
#pragma warning(push)
469
#pragma warning(disable : 4127 6287)
470
#endif
471 1
        if (sizeof(Source) != sizeof(Target)
472 1
            || std::is_signed<Source>() != std::is_signed<Target>()
473 0
            || std::is_floating_point<Source>() != std::is_floating_point<Target>())
474
        {
475 0
          throw chaiscript::detail::exception::bad_any_cast();
476
        }
477
#ifdef CHAISCRIPT_MSVC
478
#pragma warning(pop)
479
#endif
480
      }
481

482 1
      template<typename Target> Target get_as_checked() const
483
      {
484 1
        switch (get_common_type(bv)) {
485 1
          case Common_Types::t_int32:
486 1
            check_type<int32_t, Target>();
487 1
            return get_as_aux<Target, int32_t>(bv);
488 0
          case Common_Types::t_uint8:
489 0
            check_type<uint8_t, Target>();
490 0
            return get_as_aux<Target, uint8_t>(bv);
491 0
          case Common_Types::t_int8:
492 0
            check_type<int8_t, Target>();
493 0
            return get_as_aux<Target, int8_t>(bv);
494 0
          case Common_Types::t_uint16:
495 0
            check_type<uint16_t, Target>();
496 0
            return get_as_aux<Target, uint16_t>(bv);
497 0
          case Common_Types::t_int16:
498 0
            check_type<int16_t, Target>();
499 0
            return get_as_aux<Target, int16_t>(bv);
500 1
          case Common_Types::t_uint32:
501 1
            check_type<uint32_t, Target>();
502 1
            return get_as_aux<Target, uint32_t>(bv);
503 1
          case Common_Types::t_uint64:
504 1
            check_type<uint64_t, Target>();
505 1
            return get_as_aux<Target, uint64_t>(bv);
506 1
          case Common_Types::t_int64:
507 1
            check_type<int64_t, Target>();
508 1
            return get_as_aux<Target, int64_t>(bv);
509 0
          case Common_Types::t_double:
510 0
            check_type<double, Target>();
511 0
            return get_as_aux<Target, double>(bv);
512 0
          case Common_Types::t_float:
513 0
            check_type<float, Target>();
514 0
            return get_as_aux<Target, float>(bv);
515 0
          case Common_Types::t_long_double:
516 0
            check_type<long double, Target>();
517 0
            return get_as_aux<Target, long double>(bv);
518
        }
519

520 0
        throw chaiscript::detail::exception::bad_any_cast();
521
      }
522

523

524 1
      template<typename Target> Target get_as() const
525
      {
526 1
        switch (get_common_type(bv)) {
527 1
          case Common_Types::t_int32:
528 1
            return get_as_aux<Target, int32_t>(bv);
529 0
          case Common_Types::t_uint8:
530 0
            return get_as_aux<Target, uint8_t>(bv);
531 1
          case Common_Types::t_int8:
532 1
            return get_as_aux<Target, int8_t>(bv);
533 0
          case Common_Types::t_uint16:
534 0
            return get_as_aux<Target, uint16_t>(bv);
535 0
          case Common_Types::t_int16:
536 0
            return get_as_aux<Target, int16_t>(bv);
537 1
          case Common_Types::t_uint32:
538 1
            return get_as_aux<Target, uint32_t>(bv);
539 1
          case Common_Types::t_uint64:
540 1
            return get_as_aux<Target, uint64_t>(bv);
541 1
          case Common_Types::t_int64:
542 1
            return get_as_aux<Target, int64_t>(bv);
543 1
          case Common_Types::t_double:
544 1
            return get_as_aux<Target, double>(bv);
545 1
          case Common_Types::t_float:
546 1
            return get_as_aux<Target, float>(bv);
547 1
          case Common_Types::t_long_double:
548 1
            return get_as_aux<Target, long double>(bv);
549
        }
550

551 0
        throw chaiscript::detail::exception::bad_any_cast();
552
      }
553

554 1
      std::string to_string() const
555
      {
556 1
        switch (get_common_type(bv)) {
557 1
          case Common_Types::t_int32:
558 1
            return std::to_string(get_as<int32_t>());
559 0
          case Common_Types::t_uint8:
560 0
            return std::to_string(get_as<uint32_t>());
561 0
          case Common_Types::t_int8:
562 0
            return std::to_string(get_as<int32_t>());
563 0
          case Common_Types::t_uint16:
564 0
            return std::to_string(get_as<uint16_t>());
565 0
          case Common_Types::t_int16:
566 0
            return std::to_string(get_as<int16_t>());
567 1
          case Common_Types::t_uint32:
568 1
            return std::to_string(get_as<uint32_t>());
569 1
          case Common_Types::t_uint64:
570 1
            return std::to_string(get_as<uint64_t>());
571 1
          case Common_Types::t_int64:
572 1
            return std::to_string(get_as<int64_t>());
573 1
          case Common_Types::t_double:
574 1
            return to_string_aux<double>(bv);
575 1
          case Common_Types::t_float:
576 1
            return to_string_aux<float>(bv);
577 1
          case Common_Types::t_long_double:
578 1
            return to_string_aux<long double>(bv);
579
        }
580

581 0
        throw chaiscript::detail::exception::bad_any_cast();
582
      }
583

584 1
      static void validate_boxed_number(const Boxed_Value &v)
585
      {
586 1
        const Type_Info &inp_ = v.get_type_info();
587 1
        if (inp_ == user_type<bool>())
588
        {
589 1
          throw chaiscript::detail::exception::bad_any_cast();
590
        }
591

592 1
        if (!inp_.is_arithmetic())
593
        {
594 1
          throw chaiscript::detail::exception::bad_any_cast();
595
        }
596
      }
597

598

599

600 1
      static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
601
      {
602 1
        return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
603
      }
604

605 1
      static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
606
      {
607 1
        return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
608
      }
609

610 0
      static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) 
611
      {
612 0
        return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
613
      }
614

615 0
      static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
616
      {
617 0
        return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
618
      }
619

620 0
      static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
621
      {
622 0
        return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
623
      }
624

625 0
      static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) 
626
      {
627 0
        return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
628
      }
629

630 0
      static Boxed_Number pre_decrement(Boxed_Number t_lhs)
631
      {
632 0
        return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv));
633
      }
634

635 0
      static Boxed_Number pre_increment(Boxed_Number t_lhs) 
636
      {
637 0
        return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv));
638
      }
639

640 1
      static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) 
641
      {
642 1
        return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
643
      }
644

645 1
      static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) 
646
      {
647 1
        return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv));
648
      }
649

650 1
      static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
651
      {
652 1
        return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv));
653
      }
654

655 1
      static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) 
656
      {
657 1
        return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
658
      }
659

660 0
      static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
661
      {
662 0
        return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
663
      }
664

665 0
      static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs) 
666
      {
667 0
        return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
668
      }
669

670 0
      static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
671
      {
672 0
        return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
673
      }
674

675 0
      static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
676
      {
677 0
        return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
678
      }
679

680 0
      static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
681
      {
682 0
        return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
683
      }
684

685 0
      static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
686
      {
687 0
        return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
688
      }
689

690 0
      static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
691
      {
692 0
        return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
693
      }
694

695 0
      static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
696
      {
697 0
        return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
698
      }
699

700 0
      static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
701
      {
702 0
        return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
703
      }
704

705 0
      static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
706
      {
707 0
        return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
708
      }
709

710 0
      static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
711
      {
712 0
        return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
713
      }
714

715 0
      static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs) 
716
      {
717 0
        return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
718
      }
719

720 1
      static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
721
      {
722 1
        return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
723
      }
724

725 0
      static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
726
      {
727 0
        return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
728
      }
729 0
      static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
730
      {
731 0
        return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
732
      }
733

734 0
      static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) 
735
      {
736 0
        return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
737
      }
738

739 0
      static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
740
      {
741 0
        return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
742
      }
743

744 1
      static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
745
      {
746 1
        return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
747
      }
748

749 0
      static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
750
      {
751 0
        return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
752
      }
753

754 0
      static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
755
      {
756 0
        return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
757
      }
758

759

760

761 1
      static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
762
      {
763 1
        return oper(t_oper, t_lhs, t_rhs);
764
      }
765

766 1
      static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
767
      {
768 1
        return oper(t_oper, t_lhs);
769
      }
770

771

772

773
      Boxed_Value bv;
774
  };
775

776
  namespace detail
777
  {
778
    /// Cast_Helper for converting from Boxed_Value to Boxed_Number
779
    template<>
780
      struct Cast_Helper<Boxed_Number>
781
      {
782
        static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
783
        {
784
          return Boxed_Number(ob);
785
        }
786
      };
787

788
    /// Cast_Helper for converting from Boxed_Value to Boxed_Number
789
    template<>
790
      struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
791
      {
792
      };
793

794
    /// Cast_Helper for converting from Boxed_Value to Boxed_Number
795
    template<>
796
      struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
797
      {
798
      };
799
  }
800

801
#ifdef __GNUC__
802
#pragma GCC diagnostic pop
803
#endif
804

805
#ifdef CHAISCRIPT_MSVC
806
#pragma warning(pop)
807
#endif
808

809
}
810

811

812

813
#endif
814

Read our documentation on viewing source code .

Loading