#include <chaiscript/chaiscript_basic.hpp>
#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"


#ifdef CHAISCRIPT_MSVC
// ignore errors about negative unsigned integer literals
#pragma warning(push)
#pragma warning(disable : 4146)
#endif


#define TEST_LITERAL(v) test_literal(v, #v)
#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true)

template<typename T>
bool test_literal(T val, const std::string &str, bool use_boxed_number = false)
{
  std::cout << '(' << str << ") Comparing : C++ '" << val;
  chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());

  // Note, after applying the `-` it's possible that chaiscript has internally converted
  // between two equivalently sized types (ie, unsigned long and unsigned long long on a 64bit system)
  // so we're going to allow some leeway with the signed tests
  T val2 = [&](){
    if (!use_boxed_number) {
      return chai.eval<T>(str);
    } else {
      return chai.eval<chaiscript::Boxed_Number>(str).get_as_checked<T>();
    }
  }();

  std::cout << "' chai '" << val2 << "'\n";
  return val == val2;
}

int main()
{
  if( 
      TEST_LITERAL(0xF)
      && TEST_LITERAL(0xFF)
      && TEST_LITERAL(0xFFF)
      && TEST_LITERAL(0xFFFF)
      && TEST_LITERAL(0xFFFFF)
      && TEST_LITERAL(0xFFFFFF)
      && TEST_LITERAL(0xFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFFFFFFF)
      && TEST_LITERAL(0xFFFFFFFFFFFFFFFF) 


      && TEST_LITERAL(01)
      && TEST_LITERAL(017)
      && TEST_LITERAL(0177)
      && TEST_LITERAL(01777)
      && TEST_LITERAL(017777)
      && TEST_LITERAL(0177777)
      && TEST_LITERAL(01777777)
      && TEST_LITERAL(017777777)
      && TEST_LITERAL(0177777777)
      && TEST_LITERAL(01777777777)
      && TEST_LITERAL(017777777777)
      && TEST_LITERAL(0177777777777)
      && TEST_LITERAL(01777777777777)
      && TEST_LITERAL(017777777777777)
      && TEST_LITERAL(0177777777777777)
      && TEST_LITERAL(01777777777777777)
      && TEST_LITERAL(017777777777777777)
      && TEST_LITERAL(0177777777777777777)
      && TEST_LITERAL(01777777777777777777)
      && TEST_LITERAL(017777777777777777777)
      && TEST_LITERAL(0177777777777777777777)
      && TEST_LITERAL(01777777777777777777777)

      && TEST_LITERAL(1)
      && TEST_LITERAL(17)
      && TEST_LITERAL(177)
      && TEST_LITERAL(1777)
      && TEST_LITERAL(17777)
      && TEST_LITERAL(177777)
      && TEST_LITERAL(1777777)
      && TEST_LITERAL(17777777)
      && TEST_LITERAL(177777777)
      && TEST_LITERAL(1777777777)
      && TEST_LITERAL(17777777777)
      && TEST_LITERAL(177777777777)
      && TEST_LITERAL(1777777777777)
      && TEST_LITERAL(17777777777777)
      && TEST_LITERAL(177777777777777)
      && TEST_LITERAL(1777777777777777)
      && TEST_LITERAL(17777777777777777)
      && TEST_LITERAL(177777777777777777)
      && 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")


      && TEST_LITERAL_SIGNED(-0xF)
      && TEST_LITERAL_SIGNED(-0xFF)
      && TEST_LITERAL_SIGNED(-0xFFF)
      && TEST_LITERAL_SIGNED(-0xFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFF)
      && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFFF) 


      && TEST_LITERAL_SIGNED(-01)
      && TEST_LITERAL_SIGNED(-017)
      && TEST_LITERAL_SIGNED(-0177)
      && TEST_LITERAL_SIGNED(-01777)
      && TEST_LITERAL_SIGNED(-017777)
      && TEST_LITERAL_SIGNED(-0177777)
      && TEST_LITERAL_SIGNED(-01777777)
      && TEST_LITERAL_SIGNED(-017777777)
      && TEST_LITERAL_SIGNED(-0177777777)
      && TEST_LITERAL_SIGNED(-01777777777)
      && TEST_LITERAL_SIGNED(-017777777777)
      && TEST_LITERAL_SIGNED(-0177777777777)
      && TEST_LITERAL_SIGNED(-01777777777777)
      && TEST_LITERAL_SIGNED(-017777777777777)
      && TEST_LITERAL_SIGNED(-0177777777777777)
      && TEST_LITERAL_SIGNED(-01777777777777777)
      && TEST_LITERAL_SIGNED(-017777777777777777)
      && TEST_LITERAL_SIGNED(-0177777777777777777)
      && TEST_LITERAL_SIGNED(-01777777777777777777)
      && TEST_LITERAL_SIGNED(-017777777777777777777)
      && TEST_LITERAL_SIGNED(-0177777777777777777777)
      && TEST_LITERAL_SIGNED(-01777777777777777777777)

      && TEST_LITERAL_SIGNED(-1)
      && TEST_LITERAL_SIGNED(-17)
      && TEST_LITERAL_SIGNED(-177)
      && TEST_LITERAL_SIGNED(-1777)
      && TEST_LITERAL_SIGNED(-17777)
      && TEST_LITERAL_SIGNED(-177777)
      && TEST_LITERAL_SIGNED(-1777777)
      && TEST_LITERAL_SIGNED(-17777777)
      && TEST_LITERAL_SIGNED(-177777777)
      && TEST_LITERAL_SIGNED(-1777777777)
      && TEST_LITERAL_SIGNED(-17777777777)
      && TEST_LITERAL_SIGNED(-177777777777)
      && TEST_LITERAL_SIGNED(-1777777777777)
      && TEST_LITERAL_SIGNED(-17777777777777)
      && TEST_LITERAL_SIGNED(-177777777777777)
      && TEST_LITERAL_SIGNED(-1777777777777777)
      && TEST_LITERAL_SIGNED(-17777777777777777)
      && TEST_LITERAL_SIGNED(-177777777777777777)
      && TEST_LITERAL_SIGNED(-1777777777777777777)

      // Test 8/16/24/32 bit boundaries for various types

      && TEST_LITERAL(255)
      && TEST_LITERAL(65535)
      && TEST_LITERAL(16777215)
#ifndef CHAISCRIPT_MSVC
        // bug in cl.exe causes this to be incorrectly parsed as an unsigned
        && TEST_LITERAL(4294967295)
#endif

      && TEST_LITERAL_SIGNED(-255)
      && TEST_LITERAL_SIGNED(-65535)
      && TEST_LITERAL_SIGNED(-16777215)
#ifndef CHAISCRIPT_MSVC
        // bug in cl.exe causes this to be incorrectly parsed as an unsigned
        && TEST_LITERAL_SIGNED(-4294967295)
#endif

      && TEST_LITERAL(255u)
      && TEST_LITERAL(65535u)
      && TEST_LITERAL(16777215u)
      && TEST_LITERAL(4294967295u)

      && TEST_LITERAL_SIGNED(-255u)
      && TEST_LITERAL_SIGNED(-65535u)
      && TEST_LITERAL_SIGNED(-16777215u)
      && TEST_LITERAL_SIGNED(-4294967295u)

      && TEST_LITERAL(255l)
      && TEST_LITERAL(65535l)
      && TEST_LITERAL(16777215l)
#ifndef CHAISCRIPT_MSVC
        // bug in cl.exe causes this to be incorrectly parsed as an unsigned
        && TEST_LITERAL(4294967295l)
#endif

      && TEST_LITERAL_SIGNED(-255l)
      && TEST_LITERAL_SIGNED(-65535l)
      && TEST_LITERAL_SIGNED(-16777215l)
#ifndef CHAISCRIPT_MSVC
        // bug in cl.exe causes this to be incorrectly parsed as an unsigned
        && TEST_LITERAL_SIGNED(-4294967295l)
#endif

      && TEST_LITERAL(255ul)
      && TEST_LITERAL(65535ul)
      && TEST_LITERAL(16777215ul)
      && TEST_LITERAL(4294967295ul)

      && TEST_LITERAL_SIGNED(-255ul)
      && TEST_LITERAL_SIGNED(-65535ul)
      && TEST_LITERAL_SIGNED(-16777215ul)
      && TEST_LITERAL_SIGNED(-4294967295ul)

      && TEST_LITERAL(255ull)
      && TEST_LITERAL(65535ull)
      && TEST_LITERAL(16777215ull)
      && TEST_LITERAL(4294967295ull)

      && TEST_LITERAL_SIGNED(-255ull)
      && TEST_LITERAL_SIGNED(-65535ull)
      && TEST_LITERAL_SIGNED(-16777215ull)
      && TEST_LITERAL_SIGNED(-4294967295ull)

      && TEST_LITERAL(255ll)
      && TEST_LITERAL(65535ll)
      && TEST_LITERAL(16777215ll)
      && TEST_LITERAL(4294967295ll)

      && TEST_LITERAL_SIGNED(-255ll)
      && TEST_LITERAL_SIGNED(-65535ll)
      && TEST_LITERAL_SIGNED(-16777215ll)
      && TEST_LITERAL_SIGNED(-4294967295ll)


      )
  {
    return EXIT_SUCCESS;
  } else {
    return EXIT_FAILURE;
  }

}


#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
