ChaiScript
boxed_number.hpp
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::exception {
29  struct arithmetic_error : std::runtime_error {
30  explicit arithmetic_error(const std::string &reason)
31  : std::runtime_error("Arithmetic error: " + reason) {
32  }
33  arithmetic_error(const arithmetic_error &) = default;
34  ~arithmetic_error() noexcept override = default;
35  };
36 } // namespace chaiscript::exception
37 
38 namespace chaiscript {
39 // Due to the nature of generating every possible arithmetic operation, there
40 // are going to be warnings generated on every platform regarding size and sign,
41 // this is OK, so we're disabling size/and sign type warnings
42 #ifdef CHAISCRIPT_MSVC
43 #pragma warning(push)
44 #pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
45 #endif
46 
47 #ifdef __GNUC__
48 #pragma GCC diagnostic push
49 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
50 #pragma GCC diagnostic ignored "-Wpragmas"
51 #pragma GCC diagnostic ignored "-Wsign-compare"
52 #pragma GCC diagnostic ignored "-Wfloat-equal"
53 #pragma GCC diagnostic ignored "-Wconversion"
54 #pragma GCC diagnostic ignored "-Wsign-conversion"
55 #pragma GCC diagnostic ignored "-Wfloat-conversion"
56 #pragma GCC diagnostic ignored "-Wswitch"
57 #endif
58 
60  class Boxed_Number {
61  private:
62  enum class Common_Types {
63  t_int32,
64  t_double,
65  t_uint8,
66  t_int8,
67  t_uint16,
68  t_int16,
69  t_uint32,
70  t_uint64,
71  t_int64,
72  t_float,
73  t_long_double
74  };
75 
76  template<typename T>
77  constexpr static inline void check_divide_by_zero([[maybe_unused]] T t) {
78 #ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
79  if constexpr (!std::is_floating_point<T>::value) {
80  if (t == 0) {
81  throw chaiscript::exception::arithmetic_error("divide by zero");
82  }
83  }
84 #endif
85  }
86 
87  constexpr static Common_Types get_common_type(size_t t_size, bool t_signed) noexcept {
88  return (t_size == 1 && t_signed) ? (Common_Types::t_int8)
89  : (t_size == 1) ? (Common_Types::t_uint8)
90  : (t_size == 2 && t_signed) ? (Common_Types::t_int16)
91  : (t_size == 2) ? (Common_Types::t_uint16)
92  : (t_size == 4 && t_signed) ? (Common_Types::t_int32)
93  : (t_size == 4) ? (Common_Types::t_uint32)
94  : (t_size == 8 && t_signed) ? (Common_Types::t_int64)
95  : (Common_Types::t_uint64);
96  }
97 
98  static Common_Types get_common_type(const Boxed_Value &t_bv) {
99  const Type_Info &inp_ = t_bv.get_type_info();
100 
101  if (inp_ == user_type<int>()) {
102  return get_common_type(sizeof(int), true);
103  } else if (inp_ == user_type<double>()) {
104  return Common_Types::t_double;
105  } else if (inp_ == user_type<long double>()) {
106  return Common_Types::t_long_double;
107  } else if (inp_ == user_type<float>()) {
108  return Common_Types::t_float;
109  } else if (inp_ == user_type<char>()) {
110  return get_common_type(sizeof(char), std::is_signed<char>::value);
111  } else if (inp_ == user_type<unsigned char>()) {
112  return get_common_type(sizeof(unsigned char), false);
113  } else if (inp_ == user_type<unsigned int>()) {
114  return get_common_type(sizeof(unsigned int), false);
115  } else if (inp_ == user_type<long>()) {
116  return get_common_type(sizeof(long), true);
117  } else if (inp_ == user_type<long long>()) {
118  return get_common_type(sizeof(long long), true);
119  } else if (inp_ == user_type<unsigned long>()) {
120  return get_common_type(sizeof(unsigned long), false);
121  } else if (inp_ == user_type<unsigned long long>()) {
122  return get_common_type(sizeof(unsigned long long), false);
123  } else if (inp_ == user_type<std::int8_t>()) {
124  return Common_Types::t_int8;
125  } else if (inp_ == user_type<std::int16_t>()) {
126  return Common_Types::t_int16;
127  } else if (inp_ == user_type<std::int32_t>()) {
128  return Common_Types::t_int32;
129  } else if (inp_ == user_type<std::int64_t>()) {
130  return Common_Types::t_int64;
131  } else if (inp_ == user_type<std::uint8_t>()) {
132  return Common_Types::t_uint8;
133  } else if (inp_ == user_type<std::uint16_t>()) {
134  return Common_Types::t_uint16;
135  } else if (inp_ == user_type<std::uint32_t>()) {
136  return Common_Types::t_uint32;
137  } else if (inp_ == user_type<std::uint64_t>()) {
138  return Common_Types::t_uint64;
139  } else if (inp_ == user_type<wchar_t>()) {
140  return get_common_type(sizeof(wchar_t), std::is_signed<wchar_t>::value);
141  } else if (inp_ == user_type<char16_t>()) {
142  return get_common_type(sizeof(char16_t), std::is_signed<char16_t>::value);
143  } else if (inp_ == user_type<char32_t>()) {
144  return get_common_type(sizeof(char32_t), std::is_signed<char32_t>::value);
145  } else {
147  }
148  }
149 
150  template<typename LHS, typename RHS>
151  static auto go(Operators::Opers t_oper, const Boxed_Value &t_bv, LHS *t_lhs, const LHS &c_lhs, const RHS &c_rhs) {
152  switch (t_oper) {
153  case Operators::Opers::equals:
154  return const_var(c_lhs == c_rhs);
155  case Operators::Opers::less_than:
156  return const_var(c_lhs < c_rhs);
157  case Operators::Opers::greater_than:
158  return const_var(c_lhs > c_rhs);
159  case Operators::Opers::less_than_equal:
160  return const_var(c_lhs <= c_rhs);
161  case Operators::Opers::greater_than_equal:
162  return const_var(c_lhs >= c_rhs);
163  case Operators::Opers::not_equal:
164  return const_var(c_lhs != c_rhs);
165  case Operators::Opers::sum:
166  return const_var(c_lhs + c_rhs);
167  case Operators::Opers::quotient:
168  check_divide_by_zero(c_rhs);
169  return const_var(c_lhs / c_rhs);
170  case Operators::Opers::product:
171  return const_var(c_lhs * c_rhs);
172  case Operators::Opers::difference:
173  return const_var(c_lhs - c_rhs);
174  default:
175  break;
176  }
177 
178  if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
179  switch (t_oper) {
180  case Operators::Opers::shift_left:
181  return const_var(c_lhs << c_rhs);
182  case Operators::Opers::shift_right:
183  return const_var(c_lhs >> c_rhs);
184  case Operators::Opers::remainder:
185  check_divide_by_zero(c_rhs);
186  return const_var(c_lhs % c_rhs);
187  case Operators::Opers::bitwise_and:
188  return const_var(c_lhs & c_rhs);
189  case Operators::Opers::bitwise_or:
190  return const_var(c_lhs | c_rhs);
191  case Operators::Opers::bitwise_xor:
192  return const_var(c_lhs ^ c_rhs);
193  default:
194  break;
195  }
196  }
197 
198  if (t_lhs) {
199  switch (t_oper) {
200  case Operators::Opers::assign:
201  *t_lhs = c_rhs;
202  return t_bv;
203  case Operators::Opers::assign_product:
204  *t_lhs *= c_rhs;
205  return t_bv;
206  case Operators::Opers::assign_sum:
207  *t_lhs += c_rhs;
208  return t_bv;
209  case Operators::Opers::assign_quotient:
210  check_divide_by_zero(c_rhs);
211  *t_lhs /= c_rhs;
212  return t_bv;
213  case Operators::Opers::assign_difference:
214  *t_lhs -= c_rhs;
215  return t_bv;
216  default:
217  break;
218  }
219 
220  if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
221  switch (t_oper) {
222  case Operators::Opers::assign_bitwise_and:
223  check_divide_by_zero(c_rhs);
224  *t_lhs &= c_rhs;
225  return t_bv;
226  case Operators::Opers::assign_bitwise_or:
227  *t_lhs |= c_rhs;
228  return t_bv;
229  case Operators::Opers::assign_shift_left:
230  *t_lhs <<= c_rhs;
231  return t_bv;
232  case Operators::Opers::assign_shift_right:
233  *t_lhs >>= c_rhs;
234  return t_bv;
235  case Operators::Opers::assign_remainder:
236  *t_lhs %= c_rhs;
237  return t_bv;
238  case Operators::Opers::assign_bitwise_xor:
239  *t_lhs ^= c_rhs;
240  return t_bv;
241  default:
242  break;
243  }
244  }
245  }
246 
248  }
249 
250  template<typename Callable>
251  inline static auto visit(const Boxed_Value &bv, Callable &&callable) {
252  switch (get_common_type(bv)) {
253  case Common_Types::t_int32:
254  return callable(*static_cast<const std::int32_t *>(bv.get_const_ptr()));
255  case Common_Types::t_uint8:
256  return callable(*static_cast<const std::uint8_t *>(bv.get_const_ptr()));
257  case Common_Types::t_int8:
258  return callable(*static_cast<const std::int8_t *>(bv.get_const_ptr()));
259  case Common_Types::t_uint16:
260  return callable(*static_cast<const std::uint16_t *>(bv.get_const_ptr()));
261  case Common_Types::t_int16:
262  return callable(*static_cast<const std::int16_t *>(bv.get_const_ptr()));
263  case Common_Types::t_uint32:
264  return callable(*static_cast<const std::uint32_t *>(bv.get_const_ptr()));
265  case Common_Types::t_uint64:
266  return callable(*static_cast<const std::uint64_t *>(bv.get_const_ptr()));
267  case Common_Types::t_int64:
268  return callable(*static_cast<const std::int64_t *>(bv.get_const_ptr()));
269  case Common_Types::t_double:
270  return callable(*static_cast<const double *>(bv.get_const_ptr()));
271  case Common_Types::t_float:
272  return callable(*static_cast<const float *>(bv.get_const_ptr()));
273  case Common_Types::t_long_double:
274  return callable(*static_cast<const long double *>(bv.get_const_ptr()));
275  }
277  }
278 
279  inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) {
280  auto unary_operator = [t_oper, &t_lhs](const auto &c_lhs) {
281  auto *lhs = static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
282 
283  if (lhs) {
284  switch (t_oper) {
285  case Operators::Opers::pre_increment:
286  ++(*lhs);
287  return t_lhs;
288  case Operators::Opers::pre_decrement:
289  --(*lhs);
290  return t_lhs;
291  default:
292  break;
293  }
294  }
295 
296  switch (t_oper) {
297  case Operators::Opers::unary_minus:
298  return const_var(-c_lhs);
299  case Operators::Opers::unary_plus:
300  return const_var(+c_lhs);
301  default:
302  break;
303  }
304 
305  if constexpr (!std::is_floating_point_v<std::decay_t<decltype(c_lhs)>>) {
306  switch (t_oper) {
307  case Operators::Opers::bitwise_complement:
308  return const_var(~c_lhs);
309  default:
310  break;
311  }
312  }
313 
315  };
316 
317  return visit(t_lhs, unary_operator);
318  }
319 
320  inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) {
321  auto lhs_visit = [t_oper, &t_lhs, &t_rhs](const auto &c_lhs) {
322  auto *lhs = t_lhs.is_return_value() ? nullptr : static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
323 
324  auto rhs_visit = [t_oper, &t_lhs, lhs, &c_lhs](const auto &c_rhs) { return go(t_oper, t_lhs, lhs, c_lhs, c_rhs); };
325 
326  return visit(t_rhs, rhs_visit);
327  };
328 
329  return visit(t_lhs, lhs_visit);
330  }
331 
332  template<typename Target, typename Source>
333  static inline Target get_as_aux(const Boxed_Value &t_bv) {
334  return static_cast<Target>(*static_cast<const Source *>(t_bv.get_const_ptr()));
335  }
336 
337  template<typename Source>
338  static std::string to_string_aux(const Boxed_Value &v) {
339  std::ostringstream oss;
340  oss << *static_cast<const Source *>(v.get_const_ptr());
341  return oss.str();
342  }
343 
344  public:
345  Boxed_Number()
346  : bv(Boxed_Value(0)) {
347  }
348 
349  explicit Boxed_Number(Boxed_Value v)
350  : bv(std::move(v)) {
351  validate_boxed_number(bv);
352  }
353 
354  Boxed_Number(const Boxed_Number &) = default;
355  Boxed_Number(Boxed_Number &&) = default;
356  Boxed_Number &operator=(Boxed_Number &&) = default;
357 
358  template<typename T>
359  explicit Boxed_Number(T t)
360  : bv(Boxed_Value(t)) {
361  validate_boxed_number(bv);
362  }
363 
364  static Boxed_Value clone(const Boxed_Value &t_bv) { return Boxed_Number(t_bv).get_as(t_bv.get_type_info()).bv; }
365 
366  static bool is_floating_point(const Boxed_Value &t_bv) {
367  const Type_Info &inp_ = t_bv.get_type_info();
368 
369  if (inp_ == user_type<double>()) {
370  return true;
371  } else if (inp_ == user_type<long double>()) {
372  return true;
373  } else if (inp_ == user_type<float>()) {
374  return true;
375  } else {
376  return false;
377  }
378  }
379 
380  Boxed_Number get_as(const Type_Info &inp_) const {
381  if (inp_.bare_equal(user_type<int>())) {
382  return Boxed_Number(get_as<int>());
383  } else if (inp_.bare_equal(user_type<double>())) {
384  return Boxed_Number(get_as<double>());
385  } else if (inp_.bare_equal(user_type<float>())) {
386  return Boxed_Number(get_as<float>());
387  } else if (inp_.bare_equal(user_type<long double>())) {
388  return Boxed_Number(get_as<long double>());
389  } else if (inp_.bare_equal(user_type<char>())) {
390  return Boxed_Number(get_as<char>());
391  } else if (inp_.bare_equal(user_type<unsigned char>())) {
392  return Boxed_Number(get_as<unsigned char>());
393  } else if (inp_.bare_equal(user_type<wchar_t>())) {
394  return Boxed_Number(get_as<wchar_t>());
395  } else if (inp_.bare_equal(user_type<char16_t>())) {
396  return Boxed_Number(get_as<char16_t>());
397  } else if (inp_.bare_equal(user_type<char32_t>())) {
398  return Boxed_Number(get_as<char32_t>());
399  } else if (inp_.bare_equal(user_type<unsigned int>())) {
400  return Boxed_Number(get_as<unsigned int>());
401  } else if (inp_.bare_equal(user_type<long>())) {
402  return Boxed_Number(get_as<long>());
403  } else if (inp_.bare_equal(user_type<long long>())) {
404  return Boxed_Number(get_as<long long>());
405  } else if (inp_.bare_equal(user_type<unsigned long>())) {
406  return Boxed_Number(get_as<unsigned long>());
407  } else if (inp_.bare_equal(user_type<unsigned long long>())) {
408  return Boxed_Number(get_as<unsigned long long>());
409  } else if (inp_.bare_equal(user_type<int8_t>())) {
410  return Boxed_Number(get_as<int8_t>());
411  } else if (inp_.bare_equal(user_type<int16_t>())) {
412  return Boxed_Number(get_as<int16_t>());
413  } else if (inp_.bare_equal(user_type<int32_t>())) {
414  return Boxed_Number(get_as<int32_t>());
415  } else if (inp_.bare_equal(user_type<int64_t>())) {
416  return Boxed_Number(get_as<int64_t>());
417  } else if (inp_.bare_equal(user_type<uint8_t>())) {
418  return Boxed_Number(get_as<uint8_t>());
419  } else if (inp_.bare_equal(user_type<uint16_t>())) {
420  return Boxed_Number(get_as<uint16_t>());
421  } else if (inp_.bare_equal(user_type<uint32_t>())) {
422  return Boxed_Number(get_as<uint32_t>());
423  } else if (inp_.bare_equal(user_type<uint64_t>())) {
424  return Boxed_Number(get_as<uint64_t>());
425  } else {
427  }
428  }
429 
430  template<typename Source, typename Target>
431  static void check_type() {
432 #ifdef CHAISCRIPT_MSVC
433 // MSVC complains about this being redundant / tautologica l
434 #pragma warning(push)
435 #pragma warning(disable : 4127 6287)
436 #endif
437  if (sizeof(Source) != sizeof(Target) || std::is_signed<Source>() != std::is_signed<Target>()
438  || std::is_floating_point<Source>() != std::is_floating_point<Target>()) {
440  }
441 #ifdef CHAISCRIPT_MSVC
442 #pragma warning(pop)
443 #endif
444  }
445 
446  template<typename Target>
447  Target get_as_checked() const {
448  switch (get_common_type(bv)) {
449  case Common_Types::t_int32:
450  check_type<int32_t, Target>();
451  return get_as_aux<Target, int32_t>(bv);
452  case Common_Types::t_uint8:
453  check_type<uint8_t, Target>();
454  return get_as_aux<Target, uint8_t>(bv);
455  case Common_Types::t_int8:
456  check_type<int8_t, Target>();
457  return get_as_aux<Target, int8_t>(bv);
458  case Common_Types::t_uint16:
459  check_type<uint16_t, Target>();
460  return get_as_aux<Target, uint16_t>(bv);
461  case Common_Types::t_int16:
462  check_type<int16_t, Target>();
463  return get_as_aux<Target, int16_t>(bv);
464  case Common_Types::t_uint32:
465  check_type<uint32_t, Target>();
466  return get_as_aux<Target, uint32_t>(bv);
467  case Common_Types::t_uint64:
468  check_type<uint64_t, Target>();
469  return get_as_aux<Target, uint64_t>(bv);
470  case Common_Types::t_int64:
471  check_type<int64_t, Target>();
472  return get_as_aux<Target, int64_t>(bv);
473  case Common_Types::t_double:
474  check_type<double, Target>();
475  return get_as_aux<Target, double>(bv);
476  case Common_Types::t_float:
477  check_type<float, Target>();
478  return get_as_aux<Target, float>(bv);
479  case Common_Types::t_long_double:
480  check_type<long double, Target>();
481  return get_as_aux<Target, long double>(bv);
482  }
483 
485  }
486 
487  template<typename Target>
488  Target get_as() const {
489  switch (get_common_type(bv)) {
490  case Common_Types::t_int32:
491  return get_as_aux<Target, int32_t>(bv);
492  case Common_Types::t_uint8:
493  return get_as_aux<Target, uint8_t>(bv);
494  case Common_Types::t_int8:
495  return get_as_aux<Target, int8_t>(bv);
496  case Common_Types::t_uint16:
497  return get_as_aux<Target, uint16_t>(bv);
498  case Common_Types::t_int16:
499  return get_as_aux<Target, int16_t>(bv);
500  case Common_Types::t_uint32:
501  return get_as_aux<Target, uint32_t>(bv);
502  case Common_Types::t_uint64:
503  return get_as_aux<Target, uint64_t>(bv);
504  case Common_Types::t_int64:
505  return get_as_aux<Target, int64_t>(bv);
506  case Common_Types::t_double:
507  return get_as_aux<Target, double>(bv);
508  case Common_Types::t_float:
509  return get_as_aux<Target, float>(bv);
510  case Common_Types::t_long_double:
511  return get_as_aux<Target, long double>(bv);
512  }
513 
515  }
516 
517  std::string to_string() const {
518  switch (get_common_type(bv)) {
519  case Common_Types::t_int32:
520  return std::to_string(get_as<int32_t>());
521  case Common_Types::t_uint8:
522  return std::to_string(get_as<uint32_t>());
523  case Common_Types::t_int8:
524  return std::to_string(get_as<int32_t>());
525  case Common_Types::t_uint16:
526  return std::to_string(get_as<uint16_t>());
527  case Common_Types::t_int16:
528  return std::to_string(get_as<int16_t>());
529  case Common_Types::t_uint32:
530  return std::to_string(get_as<uint32_t>());
531  case Common_Types::t_uint64:
532  return std::to_string(get_as<uint64_t>());
533  case Common_Types::t_int64:
534  return std::to_string(get_as<int64_t>());
535  case Common_Types::t_double:
536  return to_string_aux<double>(bv);
537  case Common_Types::t_float:
538  return to_string_aux<float>(bv);
539  case Common_Types::t_long_double:
540  return to_string_aux<long double>(bv);
541  }
542 
544  }
545 
546  static void validate_boxed_number(const Boxed_Value &v) {
547  const Type_Info &inp_ = v.get_type_info();
548  if (inp_ == user_type<bool>()) {
550  }
551 
552  if (!inp_.is_arithmetic()) {
554  }
555  }
556 
557  static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
558  return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
559  }
560 
561  static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
562  return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
563  }
564 
565  static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
566  return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
567  }
568 
569  static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
570  return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
571  }
572 
573  static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
574  return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
575  }
576 
577  static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
578  return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
579  }
580 
581  static Boxed_Number pre_decrement(Boxed_Number t_lhs) { return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv)); }
582 
583  static Boxed_Number pre_increment(Boxed_Number t_lhs) { return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv)); }
584 
585  static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
586  return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
587  }
588 
589  static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv)); }
590 
591  static const Boxed_Number unary_minus(const Boxed_Number &t_lhs) { return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv)); }
592 
593  static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
594  return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
595  }
596 
597  static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
598  return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
599  }
600 
601  static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
602  return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
603  }
604 
605  static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
606  return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
607  }
608 
609  static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
610  return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
611  }
612 
613  static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
614  return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
615  }
616 
617  static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
618  return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
619  }
620 
621  static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
622  return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
623  }
624 
625  static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
626  return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
627  }
628 
629  static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs) {
630  return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
631  }
632 
633  static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
634  return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
635  }
636 
637  static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
638  return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
639  }
640 
641  static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
642  return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
643  }
644 
645  static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
646  return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
647  }
648 
649  static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
650  return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
651  }
652  static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs) {
653  return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
654  }
655 
656  static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
657  return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
658  }
659 
660  static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
661  return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
662  }
663 
664  static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
665  return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
666  }
667 
668  static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
669  return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
670  }
671 
672  static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) {
673  return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
674  }
675 
676  static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) {
677  return oper(t_oper, t_lhs, t_rhs);
678  }
679 
680  static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) { return oper(t_oper, t_lhs); }
681 
682  Boxed_Value bv;
683  };
684 
685  namespace detail {
687  template<>
689  static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *) { return Boxed_Number(ob); }
690  };
691 
693  template<>
695  };
696 
698  template<>
699  struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number> {
700  };
701  } // namespace detail
702 
703 #ifdef __GNUC__
704 #pragma GCC diagnostic pop
705 #endif
706 
707 #ifdef CHAISCRIPT_MSVC
708 #pragma warning(pop)
709 #endif
710 
711 } // namespace chaiscript
712 
713 #endif
Compile time deduced information about a type.
Definition: type_info.hpp:27
Boxed_Value const_var(const T &t)
Takes an object and returns an immutable Boxed_Value.
Definition: boxed_value.hpp:336
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions=nullptr)
Function for extracting a value stored in a Boxed_Value object.
Definition: boxed_cast.hpp:71
Definition: type_conversions.hpp:417
Namespace chaiscript contains every API call that the average user will be concerned with...
A wrapper for holding any valid C++ type.
Definition: boxed_value.hpp:24
Cast_Helper for converting from Boxed_Value to Boxed_Number.
Definition: boxed_number.hpp:688
Classes which may be thrown during error cases when ChaiScript is executing.
Definition: bad_boxed_cast.hpp:25
Thrown in the event that an Any cannot be cast to the desired type.
Definition: any.hpp:20
Represents any numeric type, generically. Used internally for generic operations between POD values...
Definition: boxed_number.hpp:60
Definition: boxed_number.hpp:29
The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner.
Definition: boxed_cast_helper.hpp:251