Merge pull request #213 from ChaiScript/fix_binary_literal_sizing

Fix binary literal sizing
This commit is contained in:
Jason Turner 2015-10-04 20:38:37 -06:00
commit 64dd349e32
4 changed files with 125 additions and 133 deletions

View File

@ -509,6 +509,8 @@ namespace chaiscript
bootstrap_pod_type<long>("long", m); bootstrap_pod_type<long>("long", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m); bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m); bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<long long>("long_long", m);
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
bootstrap_pod_type<size_t>("size_t", m); bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m); bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<wchar_t>("wchar_t", m); bootstrap_pod_type<wchar_t>("wchar_t", m);

View File

@ -17,9 +17,19 @@
#include <cstring> #include <cstring>
#include "../dispatchkit/boxed_value.hpp" #include "../dispatchkit/boxed_value.hpp"
#include "chaiscript_common.hpp" #include "chaiscript_common.hpp"
#if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min)
#pragma push_macro("max") // Why Microsoft? why? This is worse than bad
#undef max
#pragma push_macro("min")
#undef min
#endif
namespace chaiscript namespace chaiscript
{ {
/// \brief Classes and functions used during the parsing process. /// \brief Classes and functions used during the parsing process.
@ -621,8 +631,7 @@ namespace chaiscript
template<typename IntType> static Boxed_Value buildInt(const int base, const std::string &t_val, const bool prefixed)
static Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
{ {
bool unsigned_ = false; bool unsigned_ = false;
bool long_ = false; bool long_ = false;
@ -649,94 +658,47 @@ namespace chaiscript
} }
} }
std::stringstream ss(t_val.substr(0, i)); const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val;
ss >> t_type;
std::stringstream testu(t_val.substr(0, i)); try {
uint64_t u; auto u = std::stoll(val,nullptr,base);
testu >> t_type >> u;
bool unsignedrequired = false; #ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#endif
if ((u >> (sizeof(int) * 8)) > 0) if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
{ return const_var(static_cast<int>(u));
//requires something bigger than int } else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits<unsigned int>::min() && u <= std::numeric_limits<unsigned int>::max()) {
long_ = true; return const_var(static_cast<unsigned int>(u));
} } else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long>::min() && u <= std::numeric_limits<long>::max()) {
return const_var(static_cast<long>(u));
static_assert(sizeof(long) == sizeof(uint64_t) || sizeof(long) * 2 == sizeof(uint64_t), "Unexpected sizing of integer types"); } else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
return const_var(static_cast<unsigned long>(u));
if ((sizeof(long) < sizeof(uint64_t)) } else if (!unsigned_ && u >= std::numeric_limits<long long>::min() && u <= std::numeric_limits<long long>::max()) {
&& (u >> ((sizeof(uint64_t) - sizeof(long)) * 8)) > 0) return const_var(static_cast<long long>(u));
{
//requires something bigger than long
longlong_ = true;
}
const size_t size = [&]()->size_t{
if (longlong_)
{
return sizeof(int64_t) * 8;
} else if (long_) {
return sizeof(long) * 8;
} else { } else {
return sizeof(int) * 8; return const_var(static_cast<unsigned long long>(u));
} }
}();
if ( (u >> (size - 1)) > 0) #ifdef __GNUC__
{ #pragma GCC diagnostic pop
unsignedrequired = true; #endif
}
if (unsignedrequired && !unsigned_) } catch (const std::out_of_range &) {
{ // too big to be signed
if (t_type == &std::hex || t_type == &std::oct) try {
{ auto u = std::stoull(val,nullptr,base);
// with hex and octal we are happy to just make it unsigned
unsigned_ = true; if (u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
} else { return const_var(static_cast<unsigned long>(u));
// with decimal we must bump it up to the next size } else {
if (long_) return const_var(static_cast<unsigned long long>(u));
{
longlong_ = true;
} else if (!long_ && !longlong_) {
long_ = true;
} }
} } catch (const std::out_of_range &) {
} // it's just simply too big
return const_var(std::numeric_limits<long long>::max());
if (unsigned_)
{
if (longlong_)
{
uint64_t val;
ss >> val;
return const_var(val);
} else if (long_) {
unsigned long val;
ss >> val;
return const_var(val);
} else {
unsigned int val;
ss >> val;
return const_var(val);
}
} else {
if (longlong_)
{
int64_t val;
ss >> val;
return const_var(val);
} else if (long_) {
long val;
ss >> val;
return const_var(val);
} else {
int val;
ss >> val;
return const_var(val);
} }
} }
} }
@ -756,59 +718,44 @@ namespace chaiscript
} else { } else {
const auto start = m_position; const auto start = m_position;
if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) { if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) {
if (Hex_()) { try {
auto match = Position::str(start, m_position); if (Hex_()) {
auto bv = buildInt(std::hex, match); auto match = Position::str(start, m_position);
m_match_stack.emplace_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv))); auto bv = buildInt(16, match, true);
return true; m_match_stack.emplace_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
} return true;
if (Binary_()) {
auto match = Position::str(start, m_position);
int64_t temp_int = 0;
size_t pos = 0;
const auto end = match.length();
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
temp_int <<= 1;
if (match[pos] == '1') {
temp_int += 1;
}
++pos;
} }
Boxed_Value i = [&]()->Boxed_Value{ if (Binary_()) {
if (match.length() <= sizeof(int) * 8) auto match = Position::str(start, m_position);
{ auto bv = buildInt(2, match, true);
return const_var(static_cast<int>(temp_int)); m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
return true;
}
if (Float_()) {
auto match = Position::str(start, m_position);
auto bv = buildFloat(match);
m_match_stack.push_back(make_node<eval::Float_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
return true;
}
else {
IntSuffix_();
auto match = Position::str(start, m_position);
if (!match.empty() && (match[0] == '0')) {
auto bv = buildInt(8, match, false);
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
}
else if (!match.empty()) {
auto bv = buildInt(10, match, false);
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
} else { } else {
return const_var(temp_int); return false;
} }
}(); return true;
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(i)));
return true;
}
if (Float_()) {
auto match = Position::str(start, m_position);
auto bv = buildFloat(match);
m_match_stack.push_back(make_node<eval::Float_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
return true;
}
else {
IntSuffix_();
auto match = Position::str(start, m_position);
if (!match.empty() && (match[0] == '0')) {
auto bv = buildInt(std::oct, match);
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
} }
else if (!match.empty()) { } catch (const std::invalid_argument &) {
auto bv = buildInt(std::dec, match); // error parsing number passed in to buildFloat/buildInt
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv))); return false;
} else {
return false;
}
return true;
} }
} }
else { else {
@ -975,6 +922,8 @@ namespace chaiscript
{ {
} }
Char_Parser &operator=(const Char_Parser &) = delete;
~Char_Parser(){ ~Char_Parser(){
if (is_octal) { if (is_octal) {
process_octal(); process_octal();
@ -2456,5 +2405,12 @@ namespace chaiscript
} }
} }
#ifdef CHAISCRIPT_MSVC
#pragma pop_macro("min")
#pragma pop_macro("max")
#endif
#endif /* CHAISCRIPT_PARSER_HPP_ */ #endif /* CHAISCRIPT_PARSER_HPP_ */

View File

@ -5,9 +5,10 @@
template<typename T> template<typename T>
bool test_literal(T val, const std::string &str) bool test_literal(T val, const std::string &str)
{ {
std::cout << "Comparing : " << val;
chaiscript::ChaiScript chai; chaiscript::ChaiScript chai;
T val2 = chai.eval<T>(str); T val2 = chai.eval<T>(str);
std::cout << "Comparing : " << val << " " << val2 << '\n'; std::cout << " " << val2 << '\n';
return val == val2; return val == val2;
} }
@ -74,6 +75,39 @@ int main()
&& TEST_LITERAL(177777777777777777) && TEST_LITERAL(177777777777777777)
&& TEST_LITERAL(1777777777777777777) && TEST_LITERAL(1777777777777777777)
&& test_literal(0xF, "0b1111")
&& test_literal(0xFF, "0b11111111")
&& test_literal(0xFFF, "0b111111111111")
&& test_literal(0xFFFF, "0b1111111111111111")
&& test_literal(0xFFFFF, "0b11111111111111111111")
&& test_literal(0xFFFFFF, "0b111111111111111111111111")
&& test_literal(0xFFFFFFF, "0b1111111111111111111111111111")
&& test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111")
&& test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7, "0b111")
&& test_literal(0x7F, "0b1111111")
&& test_literal(0x7FF, "0b11111111111")
&& test_literal(0x7FFF, "0b111111111111111")
&& test_literal(0x7FFFF, "0b1111111111111111111")
&& test_literal(0x7FFFFF, "0b11111111111111111111111")
&& test_literal(0x7FFFFFF, "0b111111111111111111111111111")
&& test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111")
&& test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111")
&& test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111")
) )
{ {
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -2,8 +2,8 @@ assert_equal(true, int_type.bare_equal(1.get_type_info()))
assert_equal(true, unsigned_int_type.bare_equal(1u.get_type_info())) assert_equal(true, unsigned_int_type.bare_equal(1u.get_type_info()))
assert_equal(true, unsigned_long_type.bare_equal(1lu.get_type_info())) assert_equal(true, unsigned_long_type.bare_equal(1lu.get_type_info()))
assert_equal(true, long_type.bare_equal(1l.get_type_info())) assert_equal(true, long_type.bare_equal(1l.get_type_info()))
assert_equal(true, int64_t_type.bare_equal(1ll.get_type_info())) assert_equal(true, long_long_type.bare_equal(1ll.get_type_info()))
assert_equal(true, uint64_t_type.bare_equal(1ull.get_type_info())) assert_equal(true, unsigned_long_long_type.bare_equal(1ull.get_type_info()))
assert_equal(true, double_type.bare_equal(1.6.get_type_info())) assert_equal(true, double_type.bare_equal(1.6.get_type_info()))
assert_equal(true, float_type.bare_equal(1.6f.get_type_info())) assert_equal(true, float_type.bare_equal(1.6f.get_type_info()))