Skip to content

Commit 64dd349

Browse files
committed
Merge pull request #213 from ChaiScript/fix_binary_literal_sizing
Fix binary literal sizing
2 parents 9d18360 + 1add4c4 commit 64dd349

4 files changed

Lines changed: 125 additions & 133 deletions

File tree

include/chaiscript/dispatchkit/bootstrap.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,8 @@ namespace chaiscript
509509
bootstrap_pod_type<long>("long", m);
510510
bootstrap_pod_type<unsigned int>("unsigned_int", m);
511511
bootstrap_pod_type<unsigned long>("unsigned_long", m);
512+
bootstrap_pod_type<long long>("long_long", m);
513+
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
512514
bootstrap_pod_type<size_t>("size_t", m);
513515
bootstrap_pod_type<char>("char", m);
514516
bootstrap_pod_type<wchar_t>("wchar_t", m);

include/chaiscript/language/chaiscript_parser.hpp

Lines changed: 86 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@
1717
#include <cstring>
1818

1919

20+
2021
#include "../dispatchkit/boxed_value.hpp"
2122
#include "chaiscript_common.hpp"
2223

24+
25+
#if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min)
26+
#pragma push_macro("max") // Why Microsoft? why? This is worse than bad
27+
#undef max
28+
#pragma push_macro("min")
29+
#undef min
30+
#endif
31+
32+
2333
namespace chaiscript
2434
{
2535
/// \brief Classes and functions used during the parsing process.
@@ -621,8 +631,7 @@ namespace chaiscript
621631

622632

623633

624-
template<typename IntType>
625-
static Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
634+
static Boxed_Value buildInt(const int base, const std::string &t_val, const bool prefixed)
626635
{
627636
bool unsigned_ = false;
628637
bool long_ = false;
@@ -649,94 +658,47 @@ namespace chaiscript
649658
}
650659
}
651660

652-
std::stringstream ss(t_val.substr(0, i));
653-
ss >> t_type;
654-
655-
std::stringstream testu(t_val.substr(0, i));
656-
uint64_t u;
657-
testu >> t_type >> u;
658-
659-
bool unsignedrequired = false;
660-
661-
if ((u >> (sizeof(int) * 8)) > 0)
662-
{
663-
//requires something bigger than int
664-
long_ = true;
665-
}
666-
667-
static_assert(sizeof(long) == sizeof(uint64_t) || sizeof(long) * 2 == sizeof(uint64_t), "Unexpected sizing of integer types");
661+
const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val;
668662

669-
if ((sizeof(long) < sizeof(uint64_t))
670-
&& (u >> ((sizeof(uint64_t) - sizeof(long)) * 8)) > 0)
671-
{
672-
//requires something bigger than long
673-
longlong_ = true;
674-
}
663+
try {
664+
auto u = std::stoll(val,nullptr,base);
675665

666+
#ifdef __GNUC__
667+
#pragma GCC diagnostic push
668+
#pragma GCC diagnostic ignored "-Wsign-compare"
669+
#endif
676670

677-
const size_t size = [&]()->size_t{
678-
if (longlong_)
679-
{
680-
return sizeof(int64_t) * 8;
681-
} else if (long_) {
682-
return sizeof(long) * 8;
671+
if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
672+
return const_var(static_cast<int>(u));
673+
} else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits<unsigned int>::min() && u <= std::numeric_limits<unsigned int>::max()) {
674+
return const_var(static_cast<unsigned int>(u));
675+
} else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long>::min() && u <= std::numeric_limits<long>::max()) {
676+
return const_var(static_cast<long>(u));
677+
} else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
678+
return const_var(static_cast<unsigned long>(u));
679+
} else if (!unsigned_ && u >= std::numeric_limits<long long>::min() && u <= std::numeric_limits<long long>::max()) {
680+
return const_var(static_cast<long long>(u));
683681
} else {
684-
return sizeof(int) * 8;
682+
return const_var(static_cast<unsigned long long>(u));
685683
}
686-
}();
687684

688-
if ( (u >> (size - 1)) > 0)
689-
{
690-
unsignedrequired = true;
691-
}
685+
#ifdef __GNUC__
686+
#pragma GCC diagnostic pop
687+
#endif
692688

693-
if (unsignedrequired && !unsigned_)
694-
{
695-
if (t_type == &std::hex || t_type == &std::oct)
696-
{
697-
// with hex and octal we are happy to just make it unsigned
698-
unsigned_ = true;
699-
} else {
700-
// with decimal we must bump it up to the next size
701-
if (long_)
702-
{
703-
longlong_ = true;
704-
} else if (!long_ && !longlong_) {
705-
long_ = true;
706-
}
707-
}
708-
}
689+
} catch (const std::out_of_range &) {
690+
// too big to be signed
691+
try {
692+
auto u = std::stoull(val,nullptr,base);
709693

710-
if (unsigned_)
711-
{
712-
if (longlong_)
713-
{
714-
uint64_t val;
715-
ss >> val;
716-
return const_var(val);
717-
} else if (long_) {
718-
unsigned long val;
719-
ss >> val;
720-
return const_var(val);
721-
} else {
722-
unsigned int val;
723-
ss >> val;
724-
return const_var(val);
725-
}
726-
} else {
727-
if (longlong_)
728-
{
729-
int64_t val;
730-
ss >> val;
731-
return const_var(val);
732-
} else if (long_) {
733-
long val;
734-
ss >> val;
735-
return const_var(val);
736-
} else {
737-
int val;
738-
ss >> val;
739-
return const_var(val);
694+
if (u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
695+
return const_var(static_cast<unsigned long>(u));
696+
} else {
697+
return const_var(static_cast<unsigned long long>(u));
698+
}
699+
} catch (const std::out_of_range &) {
700+
// it's just simply too big
701+
return const_var(std::numeric_limits<long long>::max());
740702
}
741703
}
742704
}
@@ -756,59 +718,44 @@ namespace chaiscript
756718
} else {
757719
const auto start = m_position;
758720
if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) {
759-
if (Hex_()) {
760-
auto match = Position::str(start, m_position);
761-
auto bv = buildInt(std::hex, match);
762-
m_match_stack.emplace_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
763-
return true;
764-
}
765-
766-
if (Binary_()) {
767-
auto match = Position::str(start, m_position);
768-
int64_t temp_int = 0;
769-
size_t pos = 0;
770-
const auto end = match.length();
771-
772-
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
773-
temp_int <<= 1;
774-
if (match[pos] == '1') {
775-
temp_int += 1;
776-
}
777-
++pos;
721+
try {
722+
if (Hex_()) {
723+
auto match = Position::str(start, m_position);
724+
auto bv = buildInt(16, match, true);
725+
m_match_stack.emplace_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
726+
return true;
778727
}
779728

780-
Boxed_Value i = [&]()->Boxed_Value{
781-
if (match.length() <= sizeof(int) * 8)
782-
{
783-
return const_var(static_cast<int>(temp_int));
784-
} else {
785-
return const_var(temp_int);
786-
}
787-
}();
788-
789-
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(i)));
790-
return true;
791-
}
792-
if (Float_()) {
793-
auto match = Position::str(start, m_position);
794-
auto bv = buildFloat(match);
795-
m_match_stack.push_back(make_node<eval::Float_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
796-
return true;
797-
}
798-
else {
799-
IntSuffix_();
800-
auto match = Position::str(start, m_position);
801-
if (!match.empty() && (match[0] == '0')) {
802-
auto bv = buildInt(std::oct, match);
729+
if (Binary_()) {
730+
auto match = Position::str(start, m_position);
731+
auto bv = buildInt(2, match, true);
803732
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
733+
return true;
804734
}
805-
else if (!match.empty()) {
806-
auto bv = buildInt(std::dec, match);
807-
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
808-
} else {
809-
return false;
735+
if (Float_()) {
736+
auto match = Position::str(start, m_position);
737+
auto bv = buildFloat(match);
738+
m_match_stack.push_back(make_node<eval::Float_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
739+
return true;
810740
}
811-
return true;
741+
else {
742+
IntSuffix_();
743+
auto match = Position::str(start, m_position);
744+
if (!match.empty() && (match[0] == '0')) {
745+
auto bv = buildInt(8, match, false);
746+
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
747+
}
748+
else if (!match.empty()) {
749+
auto bv = buildInt(10, match, false);
750+
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
751+
} else {
752+
return false;
753+
}
754+
return true;
755+
}
756+
} catch (const std::invalid_argument &) {
757+
// error parsing number passed in to buildFloat/buildInt
758+
return false;
812759
}
813760
}
814761
else {
@@ -975,6 +922,8 @@ namespace chaiscript
975922
{
976923
}
977924

925+
Char_Parser &operator=(const Char_Parser &) = delete;
926+
978927
~Char_Parser(){
979928
if (is_octal) {
980929
process_octal();
@@ -2456,5 +2405,12 @@ namespace chaiscript
24562405
}
24572406
}
24582407

2408+
2409+
#ifdef CHAISCRIPT_MSVC
2410+
#pragma pop_macro("min")
2411+
#pragma pop_macro("max")
2412+
#endif
2413+
2414+
24592415
#endif /* CHAISCRIPT_PARSER_HPP_ */
24602416

unittests/integer_literal_test.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
template<typename T>
66
bool test_literal(T val, const std::string &str)
77
{
8+
std::cout << "Comparing : " << val;
89
chaiscript::ChaiScript chai;
910
T val2 = chai.eval<T>(str);
10-
std::cout << "Comparing : " << val << " " << val2 << '\n';
11+
std::cout << " " << val2 << '\n';
1112
return val == val2;
1213
}
1314

@@ -74,6 +75,39 @@ int main()
7475
&& TEST_LITERAL(177777777777777777)
7576
&& TEST_LITERAL(1777777777777777777)
7677

78+
&& test_literal(0xF, "0b1111")
79+
&& test_literal(0xFF, "0b11111111")
80+
&& test_literal(0xFFF, "0b111111111111")
81+
&& test_literal(0xFFFF, "0b1111111111111111")
82+
&& test_literal(0xFFFFF, "0b11111111111111111111")
83+
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
84+
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
85+
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
86+
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
87+
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
88+
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
89+
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
90+
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
91+
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
92+
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
93+
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
94+
95+
&& test_literal(0x7, "0b111")
96+
&& test_literal(0x7F, "0b1111111")
97+
&& test_literal(0x7FF, "0b11111111111")
98+
&& test_literal(0x7FFF, "0b111111111111111")
99+
&& test_literal(0x7FFFF, "0b1111111111111111111")
100+
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
101+
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
102+
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
103+
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
104+
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
105+
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
106+
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
107+
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
108+
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
109+
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
110+
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
77111
)
78112
{
79113
return EXIT_SUCCESS;

unittests/number_suffixes.chai

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ assert_equal(true, int_type.bare_equal(1.get_type_info()))
22
assert_equal(true, unsigned_int_type.bare_equal(1u.get_type_info()))
33
assert_equal(true, unsigned_long_type.bare_equal(1lu.get_type_info()))
44
assert_equal(true, long_type.bare_equal(1l.get_type_info()))
5-
assert_equal(true, int64_t_type.bare_equal(1ll.get_type_info()))
6-
assert_equal(true, uint64_t_type.bare_equal(1ull.get_type_info()))
5+
assert_equal(true, long_long_type.bare_equal(1ll.get_type_info()))
6+
assert_equal(true, unsigned_long_long_type.bare_equal(1ull.get_type_info()))
77

88
assert_equal(true, double_type.bare_equal(1.6.get_type_info()))
99
assert_equal(true, float_type.bare_equal(1.6f.get_type_info()))

0 commit comments

Comments
 (0)