boxed_number.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. // This file is distributed under the BSD License.
  2. // See "license.txt" for details.
  3. // Copyright 2009-2012, Jonathan Turner ([email protected])
  4. // Copyright 2009-2017, Jason Turner ([email protected])
  5. // http://www.chaiscript.com
  6. // This is an open source non-commercial project. Dear PVS-Studio, please check it.
  7. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
  8. #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_
  9. #define CHAISCRIPT_BOXED_NUMERIC_HPP_
  10. #include <cstdint>
  11. #include <sstream>
  12. #include <string>
  13. #include "../language/chaiscript_algebraic.hpp"
  14. #include "any.hpp"
  15. #include "boxed_cast.hpp"
  16. #include "boxed_cast_helper.hpp"
  17. #include "boxed_value.hpp"
  18. #include "type_info.hpp"
  19. namespace chaiscript {
  20. class Type_Conversions;
  21. } // namespace chaiscript
  22. namespace chaiscript
  23. {
  24. namespace exception
  25. {
  26. struct arithmetic_error : std::runtime_error
  27. {
  28. explicit arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
  29. arithmetic_error(const arithmetic_error &) = default;
  30. ~arithmetic_error() noexcept override = default;
  31. };
  32. }
  33. }
  34. namespace chaiscript
  35. {
  36. // Due to the nature of generating every possible arithmetic operation, there
  37. // are going to be warnings generated on every platform regarding size and sign,
  38. // this is OK, so we're disabling size/and sign type warnings
  39. #ifdef CHAISCRIPT_MSVC
  40. #pragma warning(push)
  41. #pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242)
  42. #endif
  43. #ifdef __GNUC__
  44. #pragma GCC diagnostic push
  45. #pragma GCC diagnostic ignored "-Wunknown-pragmas"
  46. #pragma GCC diagnostic ignored "-Wpragmas"
  47. #pragma GCC diagnostic ignored "-Wsign-compare"
  48. #pragma GCC diagnostic ignored "-Wfloat-equal"
  49. #pragma GCC diagnostic ignored "-Wconversion"
  50. #pragma GCC diagnostic ignored "-Wsign-conversion"
  51. #pragma GCC diagnostic ignored "-Wfloat-conversion"
  52. #endif
  53. /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
  54. class Boxed_Number
  55. {
  56. private:
  57. enum class Common_Types {
  58. t_int32,
  59. t_double,
  60. t_uint8,
  61. t_int8,
  62. t_uint16,
  63. t_int16,
  64. t_uint32,
  65. t_uint64,
  66. t_int64,
  67. t_float,
  68. t_long_double
  69. };
  70. template<typename T>
  71. static inline void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr)
  72. {
  73. #ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
  74. if (t == 0) {
  75. throw chaiscript::exception::arithmetic_error("divide by zero");
  76. }
  77. #endif
  78. }
  79. template<typename T>
  80. static inline void check_divide_by_zero(T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr)
  81. {
  82. }
  83. static constexpr Common_Types get_common_type(size_t t_size, bool t_signed)
  84. {
  85. return (t_size == 1 && t_signed)?(Common_Types::t_int8)
  86. :(t_size == 1)?(Common_Types::t_uint8)
  87. :(t_size == 2 && t_signed)?(Common_Types::t_int16)
  88. :(t_size == 2)?(Common_Types::t_uint16)
  89. :(t_size == 4 && t_signed)?(Common_Types::t_int32)
  90. :(t_size == 4)?(Common_Types::t_uint32)
  91. :(t_size == 8 && t_signed)?(Common_Types::t_int64)
  92. :(Common_Types::t_uint64);
  93. }
  94. static Common_Types get_common_type(const Boxed_Value &t_bv)
  95. {
  96. const Type_Info &inp_ = t_bv.get_type_info();
  97. if (inp_ == typeid(int)) {
  98. return get_common_type(sizeof(int), true);
  99. } else if (inp_ == typeid(double)) {
  100. return Common_Types::t_double;
  101. } else if (inp_ == typeid(long double)) {
  102. return Common_Types::t_long_double;
  103. } else if (inp_ == typeid(float)) {
  104. return Common_Types::t_float;
  105. } else if (inp_ == typeid(char)) {
  106. return get_common_type(sizeof(char), std::is_signed<char>::value);
  107. } else if (inp_ == typeid(unsigned char)) {
  108. return get_common_type(sizeof(unsigned char), false);
  109. } else if (inp_ == typeid(unsigned int)) {
  110. return get_common_type(sizeof(unsigned int), false);
  111. } else if (inp_ == typeid(long)) {
  112. return get_common_type(sizeof(long), true);
  113. } else if (inp_ == typeid(long long)) {
  114. return get_common_type(sizeof(long long), true);
  115. } else if (inp_ == typeid(unsigned long)) {
  116. return get_common_type(sizeof(unsigned long), false);
  117. } else if (inp_ == typeid(unsigned long long)) {
  118. return get_common_type(sizeof(unsigned long long), false);
  119. } else if (inp_ == typeid(std::int8_t)) {
  120. return Common_Types::t_int8;
  121. } else if (inp_ == typeid(std::int16_t)) {
  122. return Common_Types::t_int16;
  123. } else if (inp_ == typeid(std::int32_t)) {
  124. return Common_Types::t_int32;
  125. } else if (inp_ == typeid(std::int64_t)) {
  126. return Common_Types::t_int64;
  127. } else if (inp_ == typeid(std::uint8_t)) {
  128. return Common_Types::t_uint8;
  129. } else if (inp_ == typeid(std::uint16_t)) {
  130. return Common_Types::t_uint16;
  131. } else if (inp_ == typeid(std::uint32_t)) {
  132. return Common_Types::t_uint32;
  133. } else if (inp_ == typeid(std::uint64_t)) {
  134. return Common_Types::t_uint64;
  135. } else if (inp_ == typeid(wchar_t)) {
  136. return get_common_type(sizeof(wchar_t), std::is_signed<wchar_t>::value);
  137. } else if (inp_ == typeid(char16_t)) {
  138. return get_common_type(sizeof(char16_t), std::is_signed<char16_t>::value);
  139. } else if (inp_ == typeid(char32_t)) {
  140. return get_common_type(sizeof(char32_t), std::is_signed<char32_t>::value);
  141. } else {
  142. throw chaiscript::detail::exception::bad_any_cast();
  143. }
  144. }
  145. template<typename T>
  146. static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const T &u)
  147. {
  148. switch (t_oper)
  149. {
  150. case Operators::Opers::equals:
  151. return const_var(t == u);
  152. case Operators::Opers::less_than:
  153. return const_var(t < u);
  154. case Operators::Opers::greater_than:
  155. return const_var(t > u);
  156. case Operators::Opers::less_than_equal:
  157. return const_var(t <= u);
  158. case Operators::Opers::greater_than_equal:
  159. return const_var(t >= u);
  160. case Operators::Opers::not_equal:
  161. return const_var(t != u);
  162. default:
  163. throw chaiscript::detail::exception::bad_any_cast();
  164. }
  165. }
  166. template<typename T>
  167. static Boxed_Value unary_go(Operators::Opers t_oper, T &t, const Boxed_Value &t_lhs)
  168. {
  169. switch (t_oper)
  170. {
  171. case Operators::Opers::pre_increment:
  172. ++t;
  173. break;
  174. case Operators::Opers::pre_decrement:
  175. --t;
  176. break;
  177. default:
  178. throw chaiscript::detail::exception::bad_any_cast();
  179. }
  180. return t_lhs;
  181. }
  182. template<typename T, typename U>
  183. static Boxed_Value binary_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
  184. {
  185. switch (t_oper)
  186. {
  187. case Operators::Opers::assign:
  188. t = u;
  189. break;
  190. case Operators::Opers::assign_product:
  191. t *= u;
  192. break;
  193. case Operators::Opers::assign_sum:
  194. t += u;
  195. break;
  196. case Operators::Opers::assign_quotient:
  197. check_divide_by_zero(u);
  198. t /= u;
  199. break;
  200. case Operators::Opers::assign_difference:
  201. t -= u;
  202. break;
  203. default:
  204. throw chaiscript::detail::exception::bad_any_cast();
  205. }
  206. return t_lhs;
  207. }
  208. template<typename T, typename U>
  209. static Boxed_Value binary_int_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
  210. {
  211. switch (t_oper)
  212. {
  213. case Operators::Opers::assign_bitwise_and:
  214. t &= u;
  215. break;
  216. case Operators::Opers::assign_bitwise_or:
  217. t |= u;
  218. break;
  219. case Operators::Opers::assign_shift_left:
  220. t <<= u;
  221. break;
  222. case Operators::Opers::assign_shift_right:
  223. t >>= u;
  224. break;
  225. case Operators::Opers::assign_remainder:
  226. check_divide_by_zero(u);
  227. t %= u;
  228. break;
  229. case Operators::Opers::assign_bitwise_xor:
  230. t ^= u;
  231. break;
  232. default:
  233. throw chaiscript::detail::exception::bad_any_cast();
  234. }
  235. return t_lhs;
  236. }
  237. template<typename T>
  238. static Boxed_Value const_unary_int_go(Operators::Opers t_oper, const T &t)
  239. {
  240. switch (t_oper)
  241. {
  242. case Operators::Opers::bitwise_complement:
  243. return const_var(~t);
  244. default:
  245. throw chaiscript::detail::exception::bad_any_cast();
  246. }
  247. }
  248. template<typename T>
  249. static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const T &u)
  250. {
  251. switch (t_oper)
  252. {
  253. case Operators::Opers::shift_left:
  254. return const_var(t << u);
  255. case Operators::Opers::shift_right:
  256. return const_var(t >> u);
  257. case Operators::Opers::remainder:
  258. check_divide_by_zero(u);
  259. return const_var(t % u);
  260. case Operators::Opers::bitwise_and:
  261. return const_var(t & u);
  262. case Operators::Opers::bitwise_or:
  263. return const_var(t | u);
  264. case Operators::Opers::bitwise_xor:
  265. return const_var(t ^ u);
  266. default:
  267. throw chaiscript::detail::exception::bad_any_cast();
  268. }
  269. }
  270. template<typename T>
  271. static Boxed_Value const_unary_go(Operators::Opers t_oper, const T &t)
  272. {
  273. switch (t_oper)
  274. {
  275. case Operators::Opers::unary_minus:
  276. return const_var(-t);
  277. case Operators::Opers::unary_plus:
  278. return const_var(+t);
  279. default:
  280. throw chaiscript::detail::exception::bad_any_cast();
  281. }
  282. }
  283. template<typename T>
  284. static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const T &u)
  285. {
  286. switch (t_oper)
  287. {
  288. case Operators::Opers::sum:
  289. return const_var(t + u);
  290. case Operators::Opers::quotient:
  291. check_divide_by_zero(u);
  292. return const_var(t / u);
  293. case Operators::Opers::product:
  294. return const_var(t * u);
  295. case Operators::Opers::difference:
  296. return const_var(t - u);
  297. default:
  298. throw chaiscript::detail::exception::bad_any_cast();
  299. }
  300. }
  301. template<typename LHS, typename RHS>
  302. static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
  303. -> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
  304. {
  305. typedef typename std::common_type<LHS, RHS>::type common_type;
  306. if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
  307. {
  308. return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
  309. } else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
  310. return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
  311. } else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
  312. return binary_int_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
  313. } else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
  314. return const_binary_int_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
  315. } else if (t_oper > Operators::Opers::const_flag) {
  316. return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
  317. } else {
  318. throw chaiscript::detail::exception::bad_any_cast();
  319. }
  320. }
  321. template<typename LHS, typename RHS>
  322. static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
  323. -> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
  324. {
  325. typedef typename std::common_type<LHS, RHS>::type common_type;
  326. if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
  327. {
  328. return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
  329. } else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
  330. return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
  331. } else if (t_oper > Operators::Opers::const_flag) {
  332. return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
  333. } else {
  334. throw chaiscript::detail::exception::bad_any_cast();
  335. }
  336. }
  337. // Unary
  338. template<typename LHS>
  339. static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
  340. -> typename std::enable_if<!std::is_floating_point<LHS>::value, Boxed_Value>::type
  341. {
  342. if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
  343. return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
  344. } else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
  345. return const_unary_int_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
  346. } else if (t_oper > Operators::Opers::const_flag) {
  347. return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
  348. } else {
  349. throw chaiscript::detail::exception::bad_any_cast();
  350. }
  351. }
  352. template<typename LHS>
  353. static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
  354. -> typename std::enable_if<std::is_floating_point<LHS>::value, Boxed_Value>::type
  355. {
  356. if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
  357. return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
  358. } else if (t_oper > Operators::Opers::const_flag) {
  359. return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
  360. } else {
  361. throw chaiscript::detail::exception::bad_any_cast();
  362. }
  363. }
  364. template<typename LHS>
  365. inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
  366. {
  367. switch (get_common_type(t_rhs)) {
  368. case Common_Types::t_int32:
  369. return go<LHS, int32_t>(t_oper, t_lhs, t_rhs);
  370. case Common_Types::t_uint8:
  371. return go<LHS, uint8_t>(t_oper, t_lhs, t_rhs);
  372. case Common_Types::t_int8:
  373. return go<LHS, int8_t>(t_oper, t_lhs, t_rhs);
  374. case Common_Types::t_uint16:
  375. return go<LHS, uint16_t>(t_oper, t_lhs, t_rhs);
  376. case Common_Types::t_int16:
  377. return go<LHS, int16_t>(t_oper, t_lhs, t_rhs);
  378. case Common_Types::t_uint32:
  379. return go<LHS, uint32_t>(t_oper, t_lhs, t_rhs);
  380. case Common_Types::t_uint64:
  381. return go<LHS, uint64_t>(t_oper, t_lhs, t_rhs);
  382. case Common_Types::t_int64:
  383. return go<LHS, int64_t>(t_oper, t_lhs, t_rhs);
  384. case Common_Types::t_double:
  385. return go<LHS, double>(t_oper, t_lhs, t_rhs);
  386. case Common_Types::t_float:
  387. return go<LHS, float>(t_oper, t_lhs, t_rhs);
  388. case Common_Types::t_long_double:
  389. return go<LHS, long double>(t_oper, t_lhs, t_rhs);
  390. }
  391. throw chaiscript::detail::exception::bad_any_cast();
  392. }
  393. inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
  394. {
  395. switch (get_common_type(t_lhs)) {
  396. case Common_Types::t_int32:
  397. return go<int32_t>(t_oper, t_lhs);
  398. case Common_Types::t_uint8:
  399. return go<uint8_t>(t_oper, t_lhs);
  400. case Common_Types::t_int8:
  401. return go<int8_t>(t_oper, t_lhs);
  402. case Common_Types::t_uint16:
  403. return go<uint16_t>(t_oper, t_lhs);
  404. case Common_Types::t_int16:
  405. return go<int16_t>(t_oper, t_lhs);
  406. case Common_Types::t_uint32:
  407. return go<uint32_t>(t_oper, t_lhs);
  408. case Common_Types::t_uint64:
  409. return go<uint64_t>(t_oper, t_lhs);
  410. case Common_Types::t_int64:
  411. return go<int64_t>(t_oper, t_lhs);
  412. case Common_Types::t_double:
  413. return go<double>(t_oper, t_lhs);
  414. case Common_Types::t_float:
  415. return go<float>(t_oper, t_lhs);
  416. case Common_Types::t_long_double:
  417. return go<long double>(t_oper, t_lhs);
  418. }
  419. throw chaiscript::detail::exception::bad_any_cast();
  420. }
  421. inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
  422. {
  423. switch (get_common_type(t_lhs)) {
  424. case Common_Types::t_int32:
  425. return oper_rhs<int32_t>(t_oper, t_lhs, t_rhs);
  426. case Common_Types::t_uint8:
  427. return oper_rhs<uint8_t>(t_oper, t_lhs, t_rhs);
  428. case Common_Types::t_int8:
  429. return oper_rhs<int8_t>(t_oper, t_lhs, t_rhs);
  430. case Common_Types::t_uint16:
  431. return oper_rhs<uint16_t>(t_oper, t_lhs, t_rhs);
  432. case Common_Types::t_int16:
  433. return oper_rhs<int16_t>(t_oper, t_lhs, t_rhs);
  434. case Common_Types::t_uint32:
  435. return oper_rhs<uint32_t>(t_oper, t_lhs, t_rhs);
  436. case Common_Types::t_uint64:
  437. return oper_rhs<uint64_t>(t_oper, t_lhs, t_rhs);
  438. case Common_Types::t_int64:
  439. return oper_rhs<int64_t>(t_oper, t_lhs, t_rhs);
  440. case Common_Types::t_double:
  441. return oper_rhs<double>(t_oper, t_lhs, t_rhs);
  442. case Common_Types::t_float:
  443. return oper_rhs<float>(t_oper, t_lhs, t_rhs);
  444. case Common_Types::t_long_double:
  445. return oper_rhs<long double>(t_oper, t_lhs, t_rhs);
  446. }
  447. throw chaiscript::detail::exception::bad_any_cast();
  448. }
  449. template<typename Target, typename Source>
  450. static inline Target get_as_aux(const Boxed_Value &t_bv)
  451. {
  452. return static_cast<Target>(*static_cast<const Source *>(t_bv.get_const_ptr()));
  453. }
  454. template<typename Source>
  455. static std::string to_string_aux(const Boxed_Value &v)
  456. {
  457. std::ostringstream oss;
  458. oss << *static_cast<const Source *>(v.get_const_ptr());
  459. return oss.str();
  460. }
  461. public:
  462. Boxed_Number()
  463. : bv(Boxed_Value(0))
  464. {
  465. }
  466. explicit Boxed_Number(Boxed_Value v)
  467. : bv(std::move(v))
  468. {
  469. validate_boxed_number(bv);
  470. }
  471. Boxed_Number(const Boxed_Number &) = default;
  472. Boxed_Number(Boxed_Number &&) = default;
  473. Boxed_Number& operator=(Boxed_Number &&) = default;
  474. template<typename T> explicit Boxed_Number(T t)
  475. : bv(Boxed_Value(t))
  476. {
  477. validate_boxed_number(bv);
  478. }
  479. static bool is_floating_point(const Boxed_Value &t_bv)
  480. {
  481. const Type_Info &inp_ = t_bv.get_type_info();
  482. if (inp_ == typeid(double)) {
  483. return true;
  484. } else if (inp_ == typeid(long double)) {
  485. return true;
  486. } else if (inp_ == typeid(float)) {
  487. return true;
  488. } else {
  489. return false;
  490. }
  491. }
  492. Boxed_Number get_as(const Type_Info &inp_) const
  493. {
  494. if (inp_.bare_equal_type_info(typeid(int))) {
  495. return Boxed_Number(get_as<int>());
  496. } else if (inp_.bare_equal_type_info(typeid(double))) {
  497. return Boxed_Number(get_as<double>());
  498. } else if (inp_.bare_equal_type_info(typeid(float))) {
  499. return Boxed_Number(get_as<float>());
  500. } else if (inp_.bare_equal_type_info(typeid(long double))) {
  501. return Boxed_Number(get_as<long double>());
  502. } else if (inp_.bare_equal_type_info(typeid(char))) {
  503. return Boxed_Number(get_as<char>());
  504. } else if (inp_.bare_equal_type_info(typeid(unsigned char))) {
  505. return Boxed_Number(get_as<unsigned char>());
  506. } else if (inp_.bare_equal_type_info(typeid(wchar_t))) {
  507. return Boxed_Number(get_as<wchar_t>());
  508. } else if (inp_.bare_equal_type_info(typeid(char16_t))) {
  509. return Boxed_Number(get_as<char16_t>());
  510. } else if (inp_.bare_equal_type_info(typeid(char32_t))) {
  511. return Boxed_Number(get_as<char32_t>());
  512. } else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
  513. return Boxed_Number(get_as<unsigned int>());
  514. } else if (inp_.bare_equal_type_info(typeid(long))) {
  515. return Boxed_Number(get_as<long>());
  516. } else if (inp_.bare_equal_type_info(typeid(long long))) {
  517. return Boxed_Number(get_as<long long>());
  518. } else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
  519. return Boxed_Number(get_as<unsigned long>());
  520. } else if (inp_.bare_equal_type_info(typeid(unsigned long long))) {
  521. return Boxed_Number(get_as<unsigned long long>());
  522. } else if (inp_.bare_equal_type_info(typeid(int8_t))) {
  523. return Boxed_Number(get_as<int8_t>());
  524. } else if (inp_.bare_equal_type_info(typeid(int16_t))) {
  525. return Boxed_Number(get_as<int16_t>());
  526. } else if (inp_.bare_equal_type_info(typeid(int32_t))) {
  527. return Boxed_Number(get_as<int32_t>());
  528. } else if (inp_.bare_equal_type_info(typeid(int64_t))) {
  529. return Boxed_Number(get_as<int64_t>());
  530. } else if (inp_.bare_equal_type_info(typeid(uint8_t))) {
  531. return Boxed_Number(get_as<uint8_t>());
  532. } else if (inp_.bare_equal_type_info(typeid(uint16_t))) {
  533. return Boxed_Number(get_as<uint16_t>());
  534. } else if (inp_.bare_equal_type_info(typeid(uint32_t))) {
  535. return Boxed_Number(get_as<uint32_t>());
  536. } else if (inp_.bare_equal_type_info(typeid(uint64_t))) {
  537. return Boxed_Number(get_as<uint64_t>());
  538. } else {
  539. throw chaiscript::detail::exception::bad_any_cast();
  540. }
  541. }
  542. template<typename Source, typename Target>
  543. static void check_type()
  544. {
  545. #ifdef CHAISCRIPT_MSVC
  546. // MSVC complains about this being redundant / tautologica l
  547. #pragma warning(push)
  548. #pragma warning(disable : 4127 6287)
  549. #endif
  550. if (sizeof(Source) != sizeof(Target)
  551. || std::is_signed<Source>() != std::is_signed<Target>()
  552. || std::is_floating_point<Source>() != std::is_floating_point<Target>())
  553. {
  554. throw chaiscript::detail::exception::bad_any_cast();
  555. }
  556. #ifdef CHAISCRIPT_MSVC
  557. #pragma warning(pop)
  558. #endif
  559. }
  560. template<typename Target> Target get_as_checked() const
  561. {
  562. switch (get_common_type(bv)) {
  563. case Common_Types::t_int32:
  564. check_type<int32_t, Target>();
  565. return get_as_aux<Target, int32_t>(bv);
  566. case Common_Types::t_uint8:
  567. check_type<uint8_t, Target>();
  568. return get_as_aux<Target, uint8_t>(bv);
  569. case Common_Types::t_int8:
  570. check_type<int8_t, Target>();
  571. return get_as_aux<Target, int8_t>(bv);
  572. case Common_Types::t_uint16:
  573. check_type<uint16_t, Target>();
  574. return get_as_aux<Target, uint16_t>(bv);
  575. case Common_Types::t_int16:
  576. check_type<int16_t, Target>();
  577. return get_as_aux<Target, int16_t>(bv);
  578. case Common_Types::t_uint32:
  579. check_type<uint32_t, Target>();
  580. return get_as_aux<Target, uint32_t>(bv);
  581. case Common_Types::t_uint64:
  582. check_type<uint64_t, Target>();
  583. return get_as_aux<Target, uint64_t>(bv);
  584. case Common_Types::t_int64:
  585. check_type<int64_t, Target>();
  586. return get_as_aux<Target, int64_t>(bv);
  587. case Common_Types::t_double:
  588. check_type<double, Target>();
  589. return get_as_aux<Target, double>(bv);
  590. case Common_Types::t_float:
  591. check_type<float, Target>();
  592. return get_as_aux<Target, float>(bv);
  593. case Common_Types::t_long_double:
  594. check_type<long double, Target>();
  595. return get_as_aux<Target, long double>(bv);
  596. }
  597. throw chaiscript::detail::exception::bad_any_cast();
  598. }
  599. template<typename Target> Target get_as() const
  600. {
  601. switch (get_common_type(bv)) {
  602. case Common_Types::t_int32:
  603. return get_as_aux<Target, int32_t>(bv);
  604. case Common_Types::t_uint8:
  605. return get_as_aux<Target, uint8_t>(bv);
  606. case Common_Types::t_int8:
  607. return get_as_aux<Target, int8_t>(bv);
  608. case Common_Types::t_uint16:
  609. return get_as_aux<Target, uint16_t>(bv);
  610. case Common_Types::t_int16:
  611. return get_as_aux<Target, int16_t>(bv);
  612. case Common_Types::t_uint32:
  613. return get_as_aux<Target, uint32_t>(bv);
  614. case Common_Types::t_uint64:
  615. return get_as_aux<Target, uint64_t>(bv);
  616. case Common_Types::t_int64:
  617. return get_as_aux<Target, int64_t>(bv);
  618. case Common_Types::t_double:
  619. return get_as_aux<Target, double>(bv);
  620. case Common_Types::t_float:
  621. return get_as_aux<Target, float>(bv);
  622. case Common_Types::t_long_double:
  623. return get_as_aux<Target, long double>(bv);
  624. }
  625. throw chaiscript::detail::exception::bad_any_cast();
  626. }
  627. std::string to_string() const
  628. {
  629. switch (get_common_type(bv)) {
  630. case Common_Types::t_int32:
  631. return std::to_string(get_as<int32_t>());
  632. case Common_Types::t_uint8:
  633. return std::to_string(get_as<uint32_t>());
  634. case Common_Types::t_int8:
  635. return std::to_string(get_as<int32_t>());
  636. case Common_Types::t_uint16:
  637. return std::to_string(get_as<uint16_t>());
  638. case Common_Types::t_int16:
  639. return std::to_string(get_as<int16_t>());
  640. case Common_Types::t_uint32:
  641. return std::to_string(get_as<uint32_t>());
  642. case Common_Types::t_uint64:
  643. return std::to_string(get_as<uint64_t>());
  644. case Common_Types::t_int64:
  645. return std::to_string(get_as<int64_t>());
  646. case Common_Types::t_double:
  647. return to_string_aux<double>(bv);
  648. case Common_Types::t_float:
  649. return to_string_aux<float>(bv);
  650. case Common_Types::t_long_double:
  651. return to_string_aux<long double>(bv);
  652. }
  653. throw chaiscript::detail::exception::bad_any_cast();
  654. }
  655. static void validate_boxed_number(const Boxed_Value &v)
  656. {
  657. const Type_Info &inp_ = v.get_type_info();
  658. if (inp_ == typeid(bool))
  659. {
  660. throw chaiscript::detail::exception::bad_any_cast();
  661. }
  662. if (!inp_.is_arithmetic())
  663. {
  664. throw chaiscript::detail::exception::bad_any_cast();
  665. }
  666. }
  667. static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  668. {
  669. return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
  670. }
  671. static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  672. {
  673. return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
  674. }
  675. static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  676. {
  677. return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
  678. }
  679. static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  680. {
  681. return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
  682. }
  683. static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  684. {
  685. return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
  686. }
  687. static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  688. {
  689. return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
  690. }
  691. static Boxed_Number pre_decrement(Boxed_Number t_lhs)
  692. {
  693. return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv));
  694. }
  695. static Boxed_Number pre_increment(Boxed_Number t_lhs)
  696. {
  697. return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv));
  698. }
  699. static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  700. {
  701. return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
  702. }
  703. static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
  704. {
  705. return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv));
  706. }
  707. static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
  708. {
  709. return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv));
  710. }
  711. static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  712. {
  713. return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
  714. }
  715. static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  716. {
  717. return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
  718. }
  719. static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  720. {
  721. return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
  722. }
  723. static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  724. {
  725. return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
  726. }
  727. static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  728. {
  729. return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
  730. }
  731. static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  732. {
  733. return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
  734. }
  735. static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  736. {
  737. return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
  738. }
  739. static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  740. {
  741. return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
  742. }
  743. static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  744. {
  745. return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
  746. }
  747. static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
  748. {
  749. return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
  750. }
  751. static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  752. {
  753. return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
  754. }
  755. static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  756. {
  757. return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
  758. }
  759. static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  760. {
  761. return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
  762. }
  763. static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  764. {
  765. return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
  766. }
  767. static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  768. {
  769. return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
  770. }
  771. static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
  772. {
  773. return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
  774. }
  775. static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  776. {
  777. return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
  778. }
  779. static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  780. {
  781. return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
  782. }
  783. static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  784. {
  785. return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
  786. }
  787. static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  788. {
  789. return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
  790. }
  791. static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
  792. {
  793. return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
  794. }
  795. static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
  796. {
  797. return oper(t_oper, t_lhs, t_rhs);
  798. }
  799. static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
  800. {
  801. return oper(t_oper, t_lhs);
  802. }
  803. Boxed_Value bv;
  804. };
  805. namespace detail
  806. {
  807. /// Cast_Helper for converting from Boxed_Value to Boxed_Number
  808. template<>
  809. struct Cast_Helper<Boxed_Number>
  810. {
  811. static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
  812. {
  813. return Boxed_Number(ob);
  814. }
  815. };
  816. /// Cast_Helper for converting from Boxed_Value to Boxed_Number
  817. template<>
  818. struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
  819. {
  820. };
  821. /// Cast_Helper for converting from Boxed_Value to Boxed_Number
  822. template<>
  823. struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
  824. {
  825. };
  826. }
  827. #ifdef __GNUC__
  828. #pragma GCC diagnostic pop
  829. #endif
  830. #ifdef CHAISCRIPT_MSVC
  831. #pragma warning(pop)
  832. #endif
  833. }
  834. #endif