diff --git a/include/scratchcpp/value.h b/include/scratchcpp/value.h index df4db60e..96c781f3 100644 --- a/include/scratchcpp/value.h +++ b/include/scratchcpp/value.h @@ -22,38 +22,18 @@ class LIBSCRATCHCPP_EXPORT Value { public: /*! Constructs a number Value. */ - Value(float numberValue) - { - value_init(&m_data); - value_assign_float(&m_data, numberValue); - } - - /*! Constructs a number Value. */ - Value(double numberValue) + Value(double numberValue = 0.0) { value_init(&m_data); value_assign_double(&m_data, numberValue); } /*! Constructs a number Value. */ - Value(int numberValue = 0) - { - value_init(&m_data); - value_assign_int(&m_data, numberValue); - } - - /*! Constructs a number Value. */ - Value(size_t numberValue) - { - value_init(&m_data); - value_assign_size_t(&m_data, numberValue); - } - - /*! Constructs a number Value. */ - Value(long numberValue) + template::value>> + Value(T numberValue) { value_init(&m_data); - value_assign_long(&m_data, numberValue); + value_assign_double(&m_data, numberValue); } /*! Constructs a boolean Value. */ @@ -77,13 +57,6 @@ class LIBSCRATCHCPP_EXPORT Value value_assign_cstring(&m_data, stringValue); } - /*! Constructs a special Value. */ - Value(SpecialValue specialValue) - { - value_init(&m_data); - value_assign_special(&m_data, specialValue); - } - /*! Constructs value from ValueData. */ Value(const ValueData &v) { @@ -181,27 +154,16 @@ class LIBSCRATCHCPP_EXPORT Value /*! Replaces the value with modulo of the value and the given value. */ void mod(const Value &v) { value_mod(&m_data, &v.m_data, &m_data); } - const Value &operator=(float v) - { - value_assign_float(&m_data, v); - return *this; - } - const Value &operator=(double v) { value_assign_double(&m_data, v); return *this; } - const Value &operator=(int v) + template::value>> + const Value &operator=(T v) { - value_assign_int(&m_data, v); - return *this; - } - - const Value &operator=(long v) - { - value_assign_long(&m_data, v); + value_assign_double(&m_data, v); return *this; } diff --git a/include/scratchcpp/value_functions.h b/include/scratchcpp/value_functions.h index 5ff2c1e4..d4409a0b 100644 --- a/include/scratchcpp/value_functions.h +++ b/include/scratchcpp/value_functions.h @@ -11,15 +11,10 @@ extern "C" LIBSCRATCHCPP_EXPORT void value_init(ValueData *v); - LIBSCRATCHCPP_EXPORT void value_assign_float(ValueData *v, float numberValue); LIBSCRATCHCPP_EXPORT void value_assign_double(ValueData *v, double numberValue); - LIBSCRATCHCPP_EXPORT void value_assign_int(ValueData *v, int numberValue); - LIBSCRATCHCPP_EXPORT void value_assign_size_t(ValueData *v, size_t numberValue); - LIBSCRATCHCPP_EXPORT void value_assign_long(ValueData *v, long numberValue); LIBSCRATCHCPP_EXPORT void value_assign_bool(ValueData *v, bool boolValue); LIBSCRATCHCPP_EXPORT void value_assign_string(ValueData *v, const std::string &stringValue); LIBSCRATCHCPP_EXPORT void value_assign_cstring(ValueData *v, const char *stringValue); - LIBSCRATCHCPP_EXPORT void value_assign_special(ValueData *v, SpecialValue specialValue); LIBSCRATCHCPP_EXPORT void value_assign_copy(ValueData *v, const ValueData *another); LIBSCRATCHCPP_EXPORT bool value_isInfinity(const ValueData *v); diff --git a/include/scratchcpp/valuedata.h b/include/scratchcpp/valuedata.h index b3af3e1d..571928ca 100644 --- a/include/scratchcpp/valuedata.h +++ b/include/scratchcpp/valuedata.h @@ -9,21 +9,11 @@ namespace libscratchcpp { -enum class LIBSCRATCHCPP_EXPORT SpecialValue -{ - Infinity, - NegativeInfinity, - NaN -}; - enum class LIBSCRATCHCPP_EXPORT ValueType { Number = 0, Bool = 1, - String = 2, - Infinity = -1, - NegativeInfinity = -2, - NaN = -3 + String = 2 }; extern "C" diff --git a/src/blocks/operatorblocks.cpp b/src/blocks/operatorblocks.cpp index cd200ad6..376ae27a 100644 --- a/src/blocks/operatorblocks.cpp +++ b/src/blocks/operatorblocks.cpp @@ -261,9 +261,9 @@ unsigned int OperatorBlocks::op_ln(VirtualMachine *vm) { const Value &v = *vm->getInput(0, 1); if (v < 0) - vm->replaceReturnValue(Value(SpecialValue::NaN), 1); + vm->replaceReturnValue(std::numeric_limits::quiet_NaN(), 1); else if (v == 0 || v.isNaN()) - vm->replaceReturnValue(Value(SpecialValue::NegativeInfinity), 1); + vm->replaceReturnValue(-std::numeric_limits::infinity(), 1); else if (!v.isInfinity()) vm->replaceReturnValue(std::log(v.toDouble()), 1); return 0; @@ -273,9 +273,9 @@ unsigned int OperatorBlocks::op_log(VirtualMachine *vm) { const Value &v = *vm->getInput(0, 1); if (v < 0) - vm->replaceReturnValue(Value(SpecialValue::NaN), 1); + vm->replaceReturnValue(std::numeric_limits::quiet_NaN(), 1); else if (v == 0 || v.isNaN()) - vm->replaceReturnValue(Value(SpecialValue::NegativeInfinity), 1); + vm->replaceReturnValue(-std::numeric_limits::infinity(), 1); else if (!v.isInfinity()) vm->replaceReturnValue(std::log10(v.toDouble()), 1); return 0; @@ -284,7 +284,9 @@ unsigned int OperatorBlocks::op_log(VirtualMachine *vm) unsigned int OperatorBlocks::op_eexp(VirtualMachine *vm) { const Value *v = vm->getInput(0, 1); - if (v->isNegativeInfinity()) + if (v->isNaN()) + vm->replaceReturnValue(1, 1); + else if (v->isNegativeInfinity()) vm->replaceReturnValue(0, 1); else if (!v->isInfinity()) vm->replaceReturnValue(std::exp(v->toDouble()), 1); @@ -294,7 +296,9 @@ unsigned int OperatorBlocks::op_eexp(VirtualMachine *vm) unsigned int OperatorBlocks::op_10exp(VirtualMachine *vm) { const Value *v = vm->getInput(0, 1); - if (v->isNegativeInfinity()) + if (v->isNaN()) + vm->replaceReturnValue(1, 1); + else if (v->isNegativeInfinity()) vm->replaceReturnValue(0, 1); else if (!v->isInfinity()) vm->replaceReturnValue(std::pow(10, v->toDouble()), 1); diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 70b60963..54abde95 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -10,11 +10,8 @@ using namespace libscratchcpp; -static std::unordered_map TYPE_MAP = { - { ValueType::Number, Compiler::StaticType::Number }, { ValueType::Bool, Compiler::StaticType::Bool }, - { ValueType::String, Compiler::StaticType::String }, { ValueType::Infinity, Compiler::StaticType::Number }, - { ValueType::NegativeInfinity, Compiler::StaticType::Number }, { ValueType::NaN, Compiler::StaticType::Number } -}; +static std::unordered_map + TYPE_MAP = { { ValueType::Number, Compiler::StaticType::Number }, { ValueType::Bool, Compiler::StaticType::Bool }, { ValueType::String, Compiler::StaticType::String } }; LLVMCodeBuilder::LLVMCodeBuilder(const std::string &id, bool warp) : m_id(id), diff --git a/src/engine/virtualmachine_p.cpp b/src/engine/virtualmachine_p.cpp index 558d7b76..6addee35 100644 --- a/src/engine/virtualmachine_p.cpp +++ b/src/engine/virtualmachine_p.cpp @@ -461,7 +461,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value *v = READ_REG(0, 1); if (v->isNegativeInfinity()) - REPLACE_RET_VALUE(Value(SpecialValue::Infinity), 1); + REPLACE_RET_VALUE(std::numeric_limits::infinity(), 1); else if (!v->isInfinity()) REPLACE_RET_VALUE(std::abs(v->toDouble()), 1); DISPATCH(); @@ -487,7 +487,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value &v = *READ_REG(0, 1); if (v < 0) - REPLACE_RET_VALUE(Value(SpecialValue::NaN), 1); + REPLACE_RET_VALUE(std::numeric_limits::quiet_NaN(), 1); else if (!v.isInfinity()) REPLACE_RET_VALUE(std::sqrt(v.toDouble()), 1); DISPATCH(); @@ -497,7 +497,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value *v = READ_REG(0, 1); if (v->isInfinity() || v->isNegativeInfinity()) - REPLACE_RET_VALUE(Value(SpecialValue::NaN), 1); + REPLACE_RET_VALUE(std::numeric_limits::quiet_NaN(), 1); else REPLACE_RET_VALUE(std::sin(v->toDouble() * pi / 180), 1); DISPATCH(); @@ -507,7 +507,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value *v = READ_REG(0, 1); if (v->isInfinity() || v->isNegativeInfinity()) - REPLACE_RET_VALUE(Value(SpecialValue::NaN), 1); + REPLACE_RET_VALUE(std::numeric_limits::quiet_NaN(), 1); else REPLACE_RET_VALUE(std::cos(v->toDouble() * pi / 180), 1); DISPATCH(); @@ -517,7 +517,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value *v = READ_REG(0, 1); if (v->isInfinity() || v->isNegativeInfinity()) - REPLACE_RET_VALUE(Value(SpecialValue::NaN), 1); + REPLACE_RET_VALUE(std::numeric_limits::quiet_NaN(), 1); else { long mod; if (v->toLong() < 0) @@ -525,9 +525,9 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) else mod = v->toLong() % 360; if (mod == 90) - REPLACE_RET_VALUE(Value(SpecialValue::Infinity), 1); + REPLACE_RET_VALUE(std::numeric_limits::infinity(), 1); else if (mod == 270) - REPLACE_RET_VALUE(Value(SpecialValue::NegativeInfinity), 1); + REPLACE_RET_VALUE(-std::numeric_limits::infinity(), 1); else REPLACE_RET_VALUE(std::tan(v->toDouble() * pi / 180), 1); } @@ -538,7 +538,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value &v = *READ_REG(0, 1); if (v < -1 || v > 1) - REPLACE_RET_VALUE(Value(SpecialValue::NaN), 1); + REPLACE_RET_VALUE(std::numeric_limits::quiet_NaN(), 1); else REPLACE_RET_VALUE(std::asin(v.toDouble()) * 180 / pi, 1); DISPATCH(); @@ -548,7 +548,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) { const Value &v = *READ_REG(0, 1); if (v < -1 || v > 1) - REPLACE_RET_VALUE(Value(SpecialValue::NaN), 1); + REPLACE_RET_VALUE(std::numeric_limits::quiet_NaN(), 1); else REPLACE_RET_VALUE(std::acos(v.toDouble()) * 180 / pi, 1); DISPATCH(); diff --git a/src/scratch/inputvalue.cpp b/src/scratch/inputvalue.cpp index 9b6b732d..2d66269d 100644 --- a/src/scratch/inputvalue.cpp +++ b/src/scratch/inputvalue.cpp @@ -17,11 +17,8 @@ using namespace libscratchcpp; -static const std::map VALUE_TYPE_MAP = { - { ValueType::Number, InputValue::Type::Number }, { ValueType::Bool, InputValue::Type::String }, - { ValueType::String, InputValue::Type::String }, { ValueType::Infinity, InputValue::Type::String }, - { ValueType::NegativeInfinity, InputValue::Type::String }, { ValueType::NaN, InputValue::Type::String } -}; +static const std::map + VALUE_TYPE_MAP = { { ValueType::Number, InputValue::Type::Number }, { ValueType::Bool, InputValue::Type::String }, { ValueType::String, InputValue::Type::String } }; /*! Constructs InputValue with the given type. */ InputValue::InputValue(Type type) : diff --git a/src/scratch/value_functions.cpp b/src/scratch/value_functions.cpp index 4a5f6a8b..d13264d0 100644 --- a/src/scratch/value_functions.cpp +++ b/src/scratch/value_functions.cpp @@ -33,63 +33,11 @@ extern "C" /* assign */ - /*! Assigns number of type 'float' to the given value. */ - void value_assign_float(ValueData *v, float numberValue) - { - value_free(v); - - if (value_isInf(numberValue)) - v->type = ValueType::Infinity; - else if (value_isNegativeInf(numberValue)) - v->type = ValueType::NegativeInfinity; - else if (std::isnan(numberValue)) - v->type = ValueType::NaN; - else { - v->type = ValueType::Number; - v->numberValue = value_floatToDouble(numberValue); - } - } - /*! Assigns number of type 'double' to the given value. */ void value_assign_double(ValueData *v, double numberValue) { value_free(v); - if (value_isInf(numberValue)) - v->type = ValueType::Infinity; - else if (value_isNegativeInf(numberValue)) - v->type = ValueType::NegativeInfinity; - else if (std::isnan(numberValue)) - v->type = ValueType::NaN; - else { - v->type = ValueType::Number; - v->numberValue = numberValue; - } - } - - /*! Assigns number of type 'int' to the given value. */ - void value_assign_int(ValueData *v, int numberValue) - { - value_free(v); - - v->type = ValueType::Number; - v->numberValue = numberValue; - } - - /*! Assigns number of type 'size_t' to the given value. */ - void value_assign_size_t(ValueData *v, size_t numberValue) - { - value_free(v); - - v->type = ValueType::Number; - v->numberValue = numberValue; - } - - /*! Assigns number of type 'long' to the given value. */ - void value_assign_long(ValueData *v, long numberValue) - { - value_free(v); - v->type = ValueType::Number; v->numberValue = numberValue; } @@ -112,16 +60,7 @@ extern "C" /*! Assigns C string to the given value. */ void value_assign_cstring(ValueData *v, const char *stringValue) { - if (strcmp(stringValue, "Infinity") == 0) { - value_free(v); - v->type = ValueType::Infinity; - } else if (strcmp(stringValue, "-Infinity") == 0) { - value_free(v); - v->type = ValueType::NegativeInfinity; - } else if (strcmp(stringValue, "NaN") == 0) { - value_free(v); - v->type = ValueType::NaN; - } else if (v->type == ValueType::String) { + if (v->type == ValueType::String) { value_replaceStr(v, stringValue); } else { value_free(v); @@ -129,23 +68,6 @@ extern "C" } } - /*! Assigns special value to the given value. */ - void value_assign_special(ValueData *v, SpecialValue specialValue) - { - value_free(v); - - if (specialValue == SpecialValue::Infinity) - v->type = ValueType::Infinity; - else if (specialValue == SpecialValue::NegativeInfinity) - v->type = ValueType::NegativeInfinity; - else if (specialValue == SpecialValue::NaN) - v->type = ValueType::NaN; - else { - v->type = ValueType::Number; - v->numberValue = 0; - } - } - /*! Assigns another value to the given value. */ void value_assign_copy(ValueData *v, const libscratchcpp::ValueData *another) { @@ -173,8 +95,6 @@ extern "C" bool value_isInfinity(const libscratchcpp::ValueData *v) { switch (v->type) { - case ValueType::Infinity: - return true; case ValueType::Number: return value_isInf(v->numberValue); case ValueType::String: @@ -188,10 +108,8 @@ extern "C" bool value_isNegativeInfinity(const libscratchcpp::ValueData *v) { switch (v->type) { - case ValueType::NegativeInfinity: - return true; case ValueType::Number: - return value_isNegativeInf(-v->numberValue); + return value_isNegativeInf(v->numberValue); case ValueType::String: return strcmp(v->stringValue, "-Infinity") == 0; default: @@ -203,10 +121,7 @@ extern "C" bool value_isNaN(const libscratchcpp::ValueData *v) { switch (v->type) { - case ValueType::NaN: - return true; case ValueType::Number: - assert(!std::isnan(v->numberValue)); return std::isnan(v->numberValue); case ValueType::String: return strcmp(v->stringValue, "NaN") == 0; @@ -230,8 +145,6 @@ extern "C" if (value_isInfinity(v) || value_isNegativeInfinity(v)) return true; - assert(v->type != ValueType::Infinity && v->type != ValueType::NegativeInfinity); - switch (v->type) { case ValueType::Number: case ValueType::Bool: @@ -249,11 +162,12 @@ extern "C" // https://github.com/scratchfoundation/scratch-vm/blob/112989da0e7306eeb405a5c52616e41c2164af24/src/util/cast.js#L157-L181 switch (v->type) { case ValueType::Bool: - case ValueType::Infinity: - case ValueType::NegativeInfinity: - case ValueType::NaN: return true; + case ValueType::Number: { + if (std::isinf(v->numberValue) || std::isnan(v->numberValue)) + return true; + double intpart; std::modf(v->numberValue, &intpart); return v->numberValue == intpart; @@ -282,9 +196,9 @@ extern "C" /*! Returns the long representation of the given value. */ long value_toLong(const libscratchcpp::ValueData *v) { - if (v->type == ValueType::Number) + if (v->type == ValueType::Number) { return v->numberValue; - else if (v->type == ValueType::Bool) + } else if (v->type == ValueType::Bool) return v->boolValue; else if (v->type == ValueType::String) return value_stringToLong(v->stringValue); @@ -314,10 +228,6 @@ extern "C" return v->boolValue; else if (v->type == ValueType::String) return value_stringToDouble(v->stringValue); - else if (v->type == ValueType::Infinity) - return std::numeric_limits::infinity(); - else if (v->type == ValueType::NegativeInfinity) - return -std::numeric_limits::infinity(); else return 0; } @@ -331,10 +241,6 @@ extern "C" return v->numberValue != 0; } else if (v->type == ValueType::String) { return value_stringToBool(v->stringValue); - } else if (v->type == ValueType::Infinity || v->type == ValueType::NegativeInfinity) { - return true; - } else if (v->type == ValueType::NaN) { - return false; } else { return false; } @@ -349,12 +255,6 @@ extern "C" value_doubleToString(v->numberValue, dst); else if (v->type == ValueType::Bool) dst->assign(v->boolValue ? "true" : "false"); - else if (v->type == ValueType::Infinity) - dst->assign("Infinity"); - else if (v->type == ValueType::NegativeInfinity) - dst->assign("-Infinity"); - else if (v->type == ValueType::NaN) - dst->assign("NaN"); else dst->clear(); } @@ -430,122 +330,36 @@ extern "C" /*! Adds the given values and writes the result to dst. */ void value_add(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { - if (v1->type == ValueType::Number && v2->type == ValueType::Number) { - value_assign_double(dst, v1->numberValue + v2->numberValue); - return; - } else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) { - value_assign_long(dst, v1->boolValue + v2->boolValue); - return; - } else if ((static_cast(v1->type) < 0) || (static_cast(v2->type) < 0)) { - if ((v1->type == ValueType::Infinity && v2->type == ValueType::NegativeInfinity) || (v1->type == ValueType::NegativeInfinity && v2->type == ValueType::Infinity)) { - value_assign_special(dst, SpecialValue::NaN); - return; - } else if (v1->type == ValueType::Infinity || v2->type == ValueType::Infinity) { - value_assign_special(dst, SpecialValue::Infinity); - return; - } else if (v1->type == ValueType::NegativeInfinity || v2->type == ValueType::NegativeInfinity) { - value_assign_special(dst, SpecialValue::NegativeInfinity); - return; - } - } - value_assign_double(dst, value_toDouble(v1) + value_toDouble(v2)); } /*! Subtracts the given values and writes the result to dst. */ void value_subtract(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { - if (v1->type == ValueType::Number && v2->type == ValueType::Number) { - value_assign_double(dst, v1->numberValue - v2->numberValue); - return; - } else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) { - value_assign_long(dst, v1->boolValue - v2->boolValue); - return; - } else if ((static_cast(v1->type) < 0) || (static_cast(v2->type) < 0)) { - if ((v1->type == ValueType::Infinity && v2->type == ValueType::Infinity) || (v1->type == ValueType::NegativeInfinity && v2->type == ValueType::NegativeInfinity)) { - value_assign_special(dst, SpecialValue::NaN); - return; - } else if (v1->type == ValueType::Infinity || v2->type == ValueType::NegativeInfinity) { - value_assign_special(dst, SpecialValue::Infinity); - return; - } else if (v1->type == ValueType::NegativeInfinity || v2->type == ValueType::Infinity) { - value_assign_special(dst, SpecialValue::NegativeInfinity); - return; - } - } - value_assign_double(dst, value_toDouble(v1) - value_toDouble(v2)); } /*! Multiplies the given values and writes the result to dst. */ void value_multiply(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { - - if (v1->type == ValueType::Number && v2->type == ValueType::Number) - value_assign_double(dst, v1->numberValue * v2->numberValue); - else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) - value_assign_long(dst, v1->boolValue * v2->boolValue); - else { - const ValueType t1 = v1->type, t2 = v2->type; - - if ((static_cast(t1) < 0 && t1 != ValueType::NaN) || (static_cast(t2) < 0 && t2 != ValueType::NaN)) { - if (t1 == ValueType::Infinity || t1 == ValueType::NegativeInfinity || t2 == ValueType::Infinity || t2 == ValueType::NegativeInfinity) { - bool mode = (t1 == ValueType::Infinity || t2 == ValueType::Infinity); - const ValueData *value; - - if ((t1 == ValueType::Infinity && (t2 == ValueType::Infinity || t2 == ValueType::NegativeInfinity)) || (t2 != ValueType::Infinity && t2 != ValueType::NegativeInfinity)) - value = v2; - else - value = v1; - - if (value_isPositive(value)) - value_assign_special(dst, mode ? SpecialValue::Infinity : SpecialValue::NegativeInfinity); - else if (value_isNegative(value)) - value_assign_special(dst, mode ? SpecialValue::NegativeInfinity : SpecialValue::Infinity); - else - value_assign_special(dst, SpecialValue::NaN); - } - } else - value_assign_double(dst, value_toDouble(v1) * value_toDouble(v2)); - } + value_assign_double(dst, value_toDouble(v1) * value_toDouble(v2)); } /*! Divides the given values and writes the result to dst. */ void value_divide(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { - if (value_isZero(v1) && value_isZero(v2)) - value_assign_special(dst, SpecialValue::NaN); - else if (value_toDouble(v2) == 0) { - if (value_isPositive(v1)) - value_assign_special(dst, SpecialValue::Infinity); - else - value_assign_special(dst, SpecialValue::NegativeInfinity); - } else if ((v1->type == ValueType::Infinity || v1->type == ValueType::NegativeInfinity) && (v2->type == ValueType::Infinity || v2->type == ValueType::NegativeInfinity)) { - value_assign_special(dst, SpecialValue::NaN); - } else if (v1->type == ValueType::Infinity || v1->type == ValueType::NegativeInfinity) { - if (value_toDouble(v2) < 0) { - if (v1->type == ValueType::Infinity) - value_assign_special(dst, SpecialValue::NegativeInfinity); - else - value_assign_special(dst, SpecialValue::Infinity); - } else { - if (v1->type == ValueType::Infinity) - value_assign_special(dst, SpecialValue::Infinity); - else - value_assign_special(dst, SpecialValue::NegativeInfinity); - } - } else if (v2->type == ValueType::Infinity || v2->type == ValueType::NegativeInfinity) { - value_assign_long(dst, 0); - } else - value_assign_double(dst, value_toDouble(v1) / value_toDouble(v2)); + value_assign_double(dst, value_toDouble(v1) / value_toDouble(v2)); } /*! Calculates the modulo the given values and writes the result to dst. */ void value_mod(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { - if ((v2 == 0) || (v1->type == ValueType::Infinity || v1->type == ValueType::NegativeInfinity)) - value_assign_special(dst, SpecialValue::NaN); - else if (v2->type == ValueType::Infinity || v2->type == ValueType::NegativeInfinity) + double a = value_toDouble(v1); + double b = value_toDouble(v2); + + if ((b == 0) || std::isinf(a)) + value_assign_double(dst, std::numeric_limits::quiet_NaN()); + else if (std::isinf(b)) value_assign_double(dst, value_toDouble(v1)); else if (value_isNegative(v1) || value_isNegative(v2)) value_assign_double(dst, fmod(value_toDouble(v2) + fmod(value_toDouble(v1), -value_toDouble(v2)), value_toDouble(v2))); @@ -561,9 +375,12 @@ extern "C" // https://github.com/scratchfoundation/scratch-vm/blob/112989da0e7306eeb405a5c52616e41c2164af24/src/util/cast.js#L121-L150 assert(v1 && v2); - if (v1->type == ValueType::Number && v2->type == ValueType::Number) + if (v1->type == ValueType::Number && v2->type == ValueType::Number) { + if (std::isnan(v1->numberValue) && std::isnan(v2->numberValue)) + return true; + return v1->numberValue == v2->numberValue; - else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) + } else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) return v1->boolValue == v2->boolValue; bool ok; @@ -584,8 +401,8 @@ extern "C" // Handle the special case of Infinity if ((static_cast(v1->type) < 0) && (static_cast(v2->type) < 0)) { - assert(v1->type != ValueType::NaN); - assert(v2->type != ValueType::NaN); + assert(!value_isNaN(v1)); + assert(!value_isNaN(v2)); return v1->type == v2->type; } @@ -602,16 +419,6 @@ extern "C" return v1->numberValue > v2->numberValue; else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) return v1->boolValue > v2->boolValue; - else if ((static_cast(v1->type) < 0) || (static_cast(v2->type) < 0)) { - if (v1->type == ValueType::Infinity) { - return v2->type != ValueType::Infinity; - } else if (v1->type == ValueType::NegativeInfinity) - return false; - else if (v2->type == ValueType::Infinity) - return false; - else if (v2->type == ValueType::NegativeInfinity) - return true; - } double n1, n2; @@ -637,16 +444,6 @@ extern "C" return v1->numberValue < v2->numberValue; else if (v1->type == ValueType::Bool && v2->type == ValueType::Bool) return v1->boolValue < v2->boolValue; - else if ((static_cast(v1->type) < 0) || (static_cast(v2->type) < 0)) { - if (v1->type == ValueType::Infinity) { - return false; - } else if (v1->type == ValueType::NegativeInfinity) - return v2->type != ValueType::NegativeInfinity; - else if (v2->type == ValueType::Infinity) - return v1->type != ValueType::Infinity; - else if (v2->type == ValueType::NegativeInfinity) - return false; - } return value_toDouble(v1) < value_toDouble(v2); double n1, n2; diff --git a/src/scratch/value_functions_p.h b/src/scratch/value_functions_p.h index e41c8a0a..cffe2ab7 100644 --- a/src/scratch/value_functions_p.h +++ b/src/scratch/value_functions_p.h @@ -38,20 +38,17 @@ inline unsigned int value_digitCount(T v) return i + j; } -template -inline bool value_isInf(T v) -{ - return v > 0 && std::isinf(v); -} - -template -inline bool value_isNegativeInf(T v) -{ - return v < 0 && std::isinf(v); -} - extern "C" { + inline bool value_isInf(double v) + { + return v > 0 && std::isinf(v); + } + + inline bool value_isNegativeInf(double v) + { + return v < 0 && std::isinf(v); + } inline long value_convert_int_str(const char *str, int n, bool *ok) { @@ -369,22 +366,17 @@ extern "C" *ok = true; return ret; - } else - return 0; + } // Special values - if (strncmp(s, "Infinity", len) == 0) { + if (value_stringsEqual(s, "Infinity")) { if (ok) *ok = true; return std::numeric_limits::infinity(); - } else if (strncmp(s, "-Infinity", len) == 0) { + } else if (value_stringsEqual(s, "-Infinity")) { if (ok) *ok = true; return -std::numeric_limits::infinity(); - } else if (strncmp(s, "NaN", len) == 0) { - if (ok) - *ok = true; - return std::numeric_limits::quiet_NaN(); } return 0; @@ -392,7 +384,12 @@ extern "C" inline long value_stringToLong(const char *s, bool *ok = nullptr) { - return value_stringToDoubleImpl(s, ok); + const double ret = value_stringToDoubleImpl(s, ok); + + if (std::isinf(ret)) + return 0; + + return ret; } inline bool value_stringIsInt(const char *s, int n) @@ -412,6 +409,18 @@ extern "C" inline void value_doubleToString(double v, std::string *dst) { + if (std::isinf(v)) { + if (v > 0) + dst->assign("Infinity"); + else + dst->assign("-Infinity"); + + return; + } else if (std::isnan(v)) { + dst->assign("NaN"); + return; + } + std::stringstream stream; if (v != 0) { @@ -472,18 +481,14 @@ extern "C" // we can optimize by prioritizing the other types here. if (v->type == ValueType::String) return value_stringToDoubleImpl(v->stringValue, ok); - else if (v->type == ValueType::Infinity) - return std::numeric_limits::infinity(); - else if (v->type == ValueType::NegativeInfinity) - return -std::numeric_limits::infinity(); - else if (v->type == ValueType::NaN) { - if (ok) + else if (v->type == ValueType::Number) { + if (std::isnan(v->numberValue)) { *ok = false; + return 0; + } - return 0; - } else if (v->type == ValueType::Number) return v->numberValue; - else if (v->type == ValueType::Bool) + } else if (v->type == ValueType::Bool) return v->boolValue; else { assert(false); // this should never happen @@ -500,12 +505,6 @@ extern "C" return v->numberValue > 0; else if (v->type == ValueType::Bool) return v->boolValue; - else if (static_cast(v->type) < 0) { - if (v->type == ValueType::Infinity) - return true; - else - return false; - } return value_toDouble(v) > 0; } @@ -516,12 +515,6 @@ extern "C" return v->numberValue < 0; else if (v->type == ValueType::Bool) return false; - else if (static_cast(v->type) < 0) { - if (v->type == ValueType::NegativeInfinity) - return true; - else - return false; - } return value_toDouble(v) < 0; } diff --git a/test/blocks/list_blocks_test.cpp b/test/blocks/list_blocks_test.cpp index 90577da8..adafc8b6 100644 --- a/test/blocks/list_blocks_test.cpp +++ b/test/blocks/list_blocks_test.cpp @@ -418,7 +418,7 @@ TEST_F(ListBlocksTest, ListContainsItem) // [list2] contains -Infinity auto list2 = std::make_shared("d", "list2"); - auto block2 = createListItemBlock("c", "data_listcontainsitem", list2, SpecialValue::NegativeInfinity); + auto block2 = createListItemBlock("c", "data_listcontainsitem", list2, -std::numeric_limits::infinity()); compiler.init(); compiler.setBlock(block1); @@ -428,7 +428,7 @@ TEST_F(ListBlocksTest, ListContainsItem) compiler.end(); ASSERT_EQ(compiler.bytecode(), std::vector({ vm::OP_START, vm::OP_CONST, 0, vm::OP_LIST_CONTAINS, 0, vm::OP_CONST, 1, vm::OP_LIST_CONTAINS, 1, vm::OP_HALT })); - ASSERT_EQ(compiler.constValues(), std::vector({ "hello world", Value(SpecialValue::NegativeInfinity) })); + ASSERT_EQ(compiler.constValues(), std::vector({ "hello world", -std::numeric_limits::infinity() })); ASSERT_TRUE(compiler.variables().empty()); ASSERT_EQ( compiler.lists(), diff --git a/test/blocks/looks_blocks_test.cpp b/test/blocks/looks_blocks_test.cpp index 041c32b8..5defa145 100644 --- a/test/blocks/looks_blocks_test.cpp +++ b/test/blocks/looks_blocks_test.cpp @@ -1476,7 +1476,9 @@ TEST_F(LooksBlocksTest, SwitchCostumeToImpl) static unsigned int bytecode13[] = { vm::OP_START, vm::OP_CONST, 12, vm::OP_EXEC, 0, vm::OP_HALT }; static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_HALT }; static BlockFunc functions[] = { &LooksBlocks::switchCostumeTo }; - static Value constValues[] = { "costume2", 0, 1, 2, 3, "2", "3", SpecialValue::NaN, SpecialValue::Infinity, SpecialValue::NegativeInfinity, "", " ", "next costume", "previous costume" }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "costume2", 0, 1, 2, 3, "2", "3", nan, inf, -inf, "", " ", "next costume", "previous costume" }; Target target; target.addCostume(std::make_shared("costume1", "c1", "svg")); @@ -1791,9 +1793,9 @@ TEST_F(LooksBlocksTest, SwitchBackdropToImpl) static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_HALT }; static unsigned int bytecode15[] = { vm::OP_START, vm::OP_CONST, 14, vm::OP_EXEC, 0, vm::OP_HALT }; static BlockFunc functions[] = { &LooksBlocks::switchBackdropTo }; - static Value constValues[] = { - "backdrop2", 0, 1, 2, 3, "2", "3", SpecialValue::NaN, SpecialValue::Infinity, SpecialValue::NegativeInfinity, "", " ", "next backdrop", "previous backdrop", "random backdrop" - }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "2", "3", nan, inf, -inf, "", " ", "next backdrop", "previous backdrop", "random backdrop" }; Target target; @@ -2068,9 +2070,9 @@ TEST_F(LooksBlocksTest, SwitchBackdropToAndWaitImpl) static unsigned int bytecode14[] = { vm::OP_START, vm::OP_CONST, 13, vm::OP_EXEC, 0, vm::OP_HALT }; static unsigned int bytecode15[] = { vm::OP_START, vm::OP_CONST, 14, vm::OP_EXEC, 0, vm::OP_HALT }; static BlockFunc functions[] = { &LooksBlocks::switchBackdropToAndWait }; - static Value constValues[] = { - "backdrop2", 0, 1, 2, 3, "2", "3", SpecialValue::NaN, SpecialValue::Infinity, SpecialValue::NegativeInfinity, "", " ", "next backdrop", "previous backdrop", "random backdrop" - }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "backdrop2", 0, 1, 2, 3, "2", "3", nan, inf, -inf, "", " ", "next backdrop", "previous backdrop", "random backdrop" }; Target target; diff --git a/test/blocks/operator_blocks_test.cpp b/test/blocks/operator_blocks_test.cpp index d902c700..3bb97f5c 100644 --- a/test/blocks/operator_blocks_test.cpp +++ b/test/blocks/operator_blocks_test.cpp @@ -832,7 +832,9 @@ TEST_F(OperatorBlocksTest, MathOpLn) vm::OP_HALT }; static BlockFunc functions[] = { &OperatorBlocks::op_ln }; - static Value constValues[] = { SpecialValue::NegativeInfinity, -2.5, 0, SpecialValue::NaN, std::exp(1), 50, SpecialValue::Infinity }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { -inf, -2.5, 0, nan, std::exp(1), 50, inf }; VirtualMachine vm; vm.setBytecode(bytecode); @@ -885,7 +887,9 @@ TEST_F(OperatorBlocksTest, MathOpLog) vm::OP_HALT }; static BlockFunc functions[] = { &OperatorBlocks::op_log }; - static Value constValues[] = { SpecialValue::NegativeInfinity, -2.5, 0, SpecialValue::NaN, 100, 1500, SpecialValue::Infinity }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { -inf, -2.5, 0, nan, 100, 1500, inf }; VirtualMachine vm; vm.setBytecode(bytecode); @@ -938,7 +942,9 @@ TEST_F(OperatorBlocksTest, MathOpExp) vm::OP_HALT }; static BlockFunc functions[] = { &OperatorBlocks::op_eexp }; - static Value constValues[] = { SpecialValue::NegativeInfinity, -3.25, 0, SpecialValue::NaN, 1, 5, SpecialValue::Infinity }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { -inf, -3.25, 0, nan, 1, 5, inf }; VirtualMachine vm; vm.setBytecode(bytecode); @@ -991,7 +997,9 @@ TEST_F(OperatorBlocksTest, MathOp10Exp) vm::OP_HALT }; static BlockFunc functions[] = { &OperatorBlocks::op_10exp }; - static Value constValues[] = { SpecialValue::NegativeInfinity, -2, 0, SpecialValue::NaN, 1, 5.5, SpecialValue::Infinity }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { -inf, -2, 0, nan, 1, 5.5, inf }; VirtualMachine vm; vm.setBytecode(bytecode); diff --git a/test/scratch_classes/value_test.cpp b/test/scratch_classes/value_test.cpp index 82dc4748..bb7c71f0 100644 --- a/test/scratch_classes/value_test.cpp +++ b/test/scratch_classes/value_test.cpp @@ -20,59 +20,6 @@ TEST(ValueTest, DefaultConstructor) ASSERT_FALSE(v.isString()); } -TEST(ValueTest, FloatConstructor) -{ - { - Value v(3.14f); - ASSERT_EQ(v.toDouble(), 3.14); - ASSERT_EQ(v.type(), ValueType::Number); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_TRUE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - } - - { - Value v(std::numeric_limits::infinity()); - ASSERT_EQ(v.type(), ValueType::Infinity); - ASSERT_TRUE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - } - - { - Value v(-std::numeric_limits::infinity()); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); - ASSERT_FALSE(v.isInfinity()); - ASSERT_TRUE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - } - - { - Value v(std::numeric_limits::quiet_NaN()); - ASSERT_EQ(v.type(), ValueType::NaN); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_TRUE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_FALSE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - } -} - TEST(ValueTest, DoubleConstructor) { { @@ -105,11 +52,11 @@ TEST(ValueTest, DoubleConstructor) { Value v(std::numeric_limits::infinity()); - ASSERT_EQ(v.type(), ValueType::Infinity); + ASSERT_EQ(v.type(), ValueType::Number); ASSERT_TRUE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); + ASSERT_TRUE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); ASSERT_FALSE(v.isString()); @@ -117,11 +64,11 @@ TEST(ValueTest, DoubleConstructor) { Value v(-std::numeric_limits::infinity()); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); + ASSERT_EQ(v.type(), ValueType::Number); ASSERT_FALSE(v.isInfinity()); ASSERT_TRUE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); + ASSERT_TRUE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); ASSERT_FALSE(v.isString()); @@ -129,62 +76,17 @@ TEST(ValueTest, DoubleConstructor) { Value v(std::numeric_limits::quiet_NaN()); - ASSERT_EQ(v.type(), ValueType::NaN); + ASSERT_EQ(v.type(), ValueType::Number); ASSERT_FALSE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_TRUE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); + ASSERT_TRUE(v.isNumber()); ASSERT_FALSE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); ASSERT_FALSE(v.isString()); } } -TEST(ValueTest, IntConstructor) -{ - Value v(static_cast(55)); - ASSERT_EQ(v.toInt(), 55); - ASSERT_EQ(v.type(), ValueType::Number); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_TRUE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_TRUE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, SizeTConstructor) -{ - Value v(static_cast(100)); - ASSERT_EQ(v.toLong(), 100); - ASSERT_EQ(v.type(), ValueType::Number); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_TRUE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_TRUE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, LongConstructor) -{ - Value v(123L); - ASSERT_EQ(v.toLong(), 123L); - ASSERT_EQ(v.type(), ValueType::Number); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_TRUE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_TRUE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - TEST(ValueTest, BoolConstructor) { { @@ -307,38 +209,38 @@ TEST(ValueTest, StdStringConstructor) { Value v(std::string("Infinity")); - ASSERT_EQ(v.type(), ValueType::Infinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_TRUE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v(std::string("-Infinity")); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_TRUE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v(std::string("NaN")); - ASSERT_EQ(v.type(), ValueType::NaN); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_TRUE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_FALSE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } } @@ -360,83 +262,41 @@ TEST(ValueTest, CStringConstructor) { Value v("Infinity"); - ASSERT_EQ(v.type(), ValueType::Infinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_TRUE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v("-Infinity"); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_TRUE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v("NaN"); - ASSERT_EQ(v.type(), ValueType::NaN); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_TRUE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_FALSE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } } -TEST(ValueTest, InfinityConstructor) -{ - Value v(SpecialValue::Infinity); - ASSERT_EQ(v.type(), ValueType::Infinity); - ASSERT_TRUE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_TRUE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, NegativeInfinityConstructor) -{ - Value v(SpecialValue::NegativeInfinity); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); - ASSERT_FALSE(v.isInfinity()); - ASSERT_TRUE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_TRUE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, NaNConstructor) -{ - Value v(SpecialValue::NaN); - ASSERT_EQ(v.type(), ValueType::NaN); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_TRUE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_FALSE(v.isValidNumber()); - ASSERT_TRUE(v.isInt()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - TEST(ValueTest, CopyConstructor) { { @@ -494,91 +354,6 @@ TEST(ValueTest, CopyConstructor) ASSERT_FALSE(v2.isBool()); ASSERT_TRUE(v2.isString()); } - - { - Value v1(SpecialValue::NaN); - Value v2(v1); - ASSERT_EQ(v2.toDouble(), 0); - ASSERT_EQ(v1.type(), v2.type()); - ASSERT_FALSE(v2.isInfinity()); - ASSERT_FALSE(v2.isNegativeInfinity()); - ASSERT_TRUE(v2.isNaN()); - ASSERT_FALSE(v2.isNumber()); - ASSERT_FALSE(v2.isValidNumber()); - ASSERT_FALSE(v2.isBool()); - ASSERT_FALSE(v2.isString()); - } - - { - Value v1(SpecialValue::Infinity); - Value v2(v1); - ASSERT_EQ(v1.type(), v2.type()); - ASSERT_TRUE(v2.isInfinity()); - ASSERT_FALSE(v2.isNegativeInfinity()); - ASSERT_FALSE(v2.isNaN()); - ASSERT_FALSE(v2.isNumber()); - ASSERT_TRUE(v2.isValidNumber()); - ASSERT_FALSE(v2.isBool()); - ASSERT_FALSE(v2.isString()); - } - - { - Value v1(SpecialValue::NegativeInfinity); - Value v2(v1); - ASSERT_EQ(v1.type(), v2.type()); - ASSERT_FALSE(v2.isInfinity()); - ASSERT_TRUE(v2.isNegativeInfinity()); - ASSERT_FALSE(v2.isNaN()); - ASSERT_FALSE(v2.isNumber()); - ASSERT_TRUE(v2.isValidNumber()); - ASSERT_FALSE(v2.isBool()); - ASSERT_FALSE(v2.isString()); - } -} - -TEST(ValueTest, FloatAssignment) -{ - Value v; - v = 3.14f; - ASSERT_EQ(v.toDouble(), 3.14); - ASSERT_EQ(v.type(), ValueType::Number); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_TRUE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - - v = std::numeric_limits::infinity(); - ASSERT_EQ(v.type(), ValueType::Infinity); - ASSERT_TRUE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - - v = -std::numeric_limits::infinity(); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); - ASSERT_FALSE(v.isInfinity()); - ASSERT_TRUE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - - v = -std::numeric_limits::quiet_NaN(); - ASSERT_EQ(v.type(), ValueType::NaN); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_TRUE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_FALSE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); } TEST(ValueTest, DoubleAssignment) @@ -596,62 +371,32 @@ TEST(ValueTest, DoubleAssignment) ASSERT_FALSE(v.isString()); v = std::numeric_limits::infinity(); - ASSERT_EQ(v.type(), ValueType::Infinity); + ASSERT_EQ(v.type(), ValueType::Number); ASSERT_TRUE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); + ASSERT_TRUE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); ASSERT_FALSE(v.isString()); v = -std::numeric_limits::infinity(); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); - ASSERT_FALSE(v.isInfinity()); - ASSERT_TRUE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); - - v = -std::numeric_limits::quiet_NaN(); - ASSERT_EQ(v.type(), ValueType::NaN); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_TRUE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_FALSE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, IntAssignment) -{ - Value v; - v = static_cast(55); - ASSERT_EQ(v.toInt(), 55); ASSERT_EQ(v.type(), ValueType::Number); ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); + ASSERT_TRUE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_TRUE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); ASSERT_FALSE(v.isString()); -} -TEST(ValueTest, LongAssignment) -{ - Value v; - v = 123L; - ASSERT_EQ(v.toLong(), 123L); + v = -std::numeric_limits::quiet_NaN(); ASSERT_EQ(v.type(), ValueType::Number); ASSERT_FALSE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); + ASSERT_TRUE(v.isNaN()); ASSERT_TRUE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); + ASSERT_FALSE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); ASSERT_FALSE(v.isString()); } @@ -707,42 +452,42 @@ TEST(ValueTest, StdStringAssignment) Value v; v = std::string("Infinity"); ASSERT_EQ(v.toString(), "Infinity"); - ASSERT_EQ(v.type(), ValueType::Infinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_TRUE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v; v = std::string("-Infinity"); ASSERT_EQ(v.toString(), "-Infinity"); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_TRUE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v; v = std::string("NaN"); ASSERT_EQ(v.toString(), "NaN"); - ASSERT_EQ(v.type(), ValueType::NaN); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_TRUE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_FALSE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } } @@ -766,87 +511,45 @@ TEST(ValueTest, CStringAssignment) Value v; v = "Infinity"; ASSERT_EQ(v.toString(), "Infinity"); - ASSERT_EQ(v.type(), ValueType::Infinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_TRUE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v; v = "-Infinity"; ASSERT_EQ(v.toString(), "-Infinity"); - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_TRUE(v.isNegativeInfinity()); ASSERT_FALSE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_TRUE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } { Value v; v = "NaN"; ASSERT_EQ(v.toString(), "NaN"); - ASSERT_EQ(v.type(), ValueType::NaN); + ASSERT_EQ(v.type(), ValueType::String); ASSERT_FALSE(v.isInfinity()); ASSERT_FALSE(v.isNegativeInfinity()); ASSERT_TRUE(v.isNaN()); ASSERT_FALSE(v.isNumber()); ASSERT_FALSE(v.isValidNumber()); ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); + ASSERT_TRUE(v.isString()); } } -TEST(ValueTest, InfinityAssignment) -{ - Value v; - v = SpecialValue::Infinity; - ASSERT_EQ(v.type(), ValueType::Infinity); - ASSERT_TRUE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, NegativeInfinityAssignment) -{ - Value v; - v = SpecialValue::NegativeInfinity; - ASSERT_EQ(v.type(), ValueType::NegativeInfinity); - ASSERT_FALSE(v.isInfinity()); - ASSERT_TRUE(v.isNegativeInfinity()); - ASSERT_FALSE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_TRUE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - -TEST(ValueTest, NaNAssignment) -{ - Value v; - v = SpecialValue::NaN; - ASSERT_EQ(v.type(), ValueType::NaN); - ASSERT_FALSE(v.isInfinity()); - ASSERT_FALSE(v.isNegativeInfinity()); - ASSERT_TRUE(v.isNaN()); - ASSERT_FALSE(v.isNumber()); - ASSERT_FALSE(v.isValidNumber()); - ASSERT_FALSE(v.isBool()); - ASSERT_FALSE(v.isString()); -} - TEST(ValueTest, CopyAssignment) { { @@ -908,49 +611,6 @@ TEST(ValueTest, CopyAssignment) ASSERT_FALSE(v2.isBool()); ASSERT_TRUE(v2.isString()); } - - { - Value v1(SpecialValue::NaN); - Value v2; - v2 = v1; - ASSERT_EQ(v2.toDouble(), 0); - ASSERT_EQ(v1.type(), v2.type()); - ASSERT_FALSE(v2.isInfinity()); - ASSERT_FALSE(v2.isNegativeInfinity()); - ASSERT_TRUE(v2.isNaN()); - ASSERT_FALSE(v2.isNumber()); - ASSERT_FALSE(v2.isValidNumber()); - ASSERT_FALSE(v2.isBool()); - ASSERT_FALSE(v2.isString()); - } - - { - Value v1(SpecialValue::Infinity); - Value v2; - v2 = v1; - ASSERT_EQ(v1.type(), v2.type()); - ASSERT_TRUE(v2.isInfinity()); - ASSERT_FALSE(v2.isNegativeInfinity()); - ASSERT_FALSE(v2.isNaN()); - ASSERT_FALSE(v2.isNumber()); - ASSERT_TRUE(v2.isValidNumber()); - ASSERT_FALSE(v2.isBool()); - ASSERT_FALSE(v2.isString()); - } - - { - Value v1(SpecialValue::NegativeInfinity); - Value v2; - v2 = v1; - ASSERT_EQ(v1.type(), v2.type()); - ASSERT_FALSE(v2.isInfinity()); - ASSERT_TRUE(v2.isNegativeInfinity()); - ASSERT_FALSE(v2.isNaN()); - ASSERT_FALSE(v2.isNumber()); - ASSERT_TRUE(v2.isValidNumber()); - ASSERT_FALSE(v2.isBool()); - ASSERT_FALSE(v2.isString()); - } } TEST(ValueTest, ToInt) @@ -962,13 +622,9 @@ TEST(ValueTest, ToInt) v = 2.54; ASSERT_EQ(v.toInt(), 2); - v = 2.54f; - ASSERT_EQ(v.toInt(), 2); v = -2.54; ASSERT_EQ(v.toInt(), -2); - v = -2.54f; - ASSERT_EQ(v.toInt(), -2); v = false; ASSERT_EQ(v.toInt(), 0); @@ -1113,13 +769,9 @@ TEST(ValueTest, ToLong) v = 2.54; ASSERT_EQ(v.toLong(), 2); - v = 2.54f; - ASSERT_EQ(v.toLong(), 2); v = -2.54; ASSERT_EQ(v.toLong(), -2); - v = -2.54f; - ASSERT_EQ(v.toLong(), -2); v = false; ASSERT_EQ(v.toLong(), 0); @@ -1262,13 +914,9 @@ TEST(ValueTest, ToDouble) v = 2.54; ASSERT_EQ(v.toDouble(), 2.54); - v = 2.54f; - ASSERT_EQ(v.toDouble(), 2.54); v = -2.54; ASSERT_EQ(v.toDouble(), -2.54); - v = -2.54f; - ASSERT_EQ(v.toDouble(), -2.54); v = false; ASSERT_EQ(v.toDouble(), 0.0); @@ -1500,13 +1148,9 @@ TEST(ValueTest, ToBool) v = 2.54; ASSERT_EQ(v.toBool(), true); - v = 2.54f; - ASSERT_EQ(v.toBool(), true); v = -2.54; ASSERT_EQ(v.toBool(), true); - v = -2.54f; - ASSERT_EQ(v.toBool(), true); v = false; ASSERT_EQ(v.toBool(), false); @@ -1547,7 +1191,7 @@ TEST(ValueTest, ToBool) v = "-Infinity"; ASSERT_EQ(v.toBool(), true); v = "NaN"; - ASSERT_EQ(v.toBool(), false); + ASSERT_EQ(v.toBool(), true); v = "something"; ASSERT_EQ(v.toBool(), true); @@ -1692,44 +1336,24 @@ TEST(ValueTest, ToString) ASSERT_EQ(v.toString(), "2"); ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = 2.0f; - cStrings.push_back(value_toCString(&v.data())); - ASSERT_EQ(v.toString(), "2"); - ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); - ASSERT_EQ(std::string(cStrings.back()), v.toString()); v = -2.0; cStrings.push_back(value_toCString(&v.data())); ASSERT_EQ(v.toString(), "-2"); ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = -2.0f; - cStrings.push_back(value_toCString(&v.data())); - ASSERT_EQ(v.toString(), "-2"); - ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); - ASSERT_EQ(std::string(cStrings.back()), v.toString()); v = 2.54; cStrings.push_back(value_toCString(&v.data())); ASSERT_EQ(v.toString(), "2.54"); ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = 2.54f; - cStrings.push_back(value_toCString(&v.data())); - ASSERT_EQ(v.toString(), "2.54"); - ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); - ASSERT_EQ(std::string(cStrings.back()), v.toString()); v = -2.54; cStrings.push_back(value_toCString(&v.data())); ASSERT_EQ(v.toString(), "-2.54"); ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = -2.54f; - cStrings.push_back(value_toCString(&v.data())); - ASSERT_EQ(v.toString(), "-2.54"); - ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); - ASSERT_EQ(std::string(cStrings.back()), v.toString()); v = 2550.625021000115; cStrings.push_back(value_toCString(&v.data())); @@ -1737,24 +1361,12 @@ TEST(ValueTest, ToString) ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = 2550.625021000115f; - cStrings.push_back(value_toCString(&v.data())); - ASSERT_EQ(v.toString(), "2550.625"); - ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); - ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = -2550.625021000115; cStrings.push_back(value_toCString(&v.data())); ASSERT_EQ(v.toString(), "-2550.625021000115"); ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = -2550.625021000115f; - cStrings.push_back(value_toCString(&v.data())); - ASSERT_EQ(v.toString(), "-2550.625"); - ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); - ASSERT_EQ(std::string(cStrings.back()), v.toString()); - v = 9.4324e+20; cStrings.push_back(value_toCString(&v.data())); ASSERT_EQ(v.toString(), "943240000000000000000"); @@ -1892,6 +1504,22 @@ TEST(ValueTest, ToString) ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); ASSERT_EQ(std::string(cStrings.back()), v.toString()); + v = std::numeric_limits::infinity(); + cStrings.push_back(value_toCString(&v.data())); + ASSERT_EQ(v.toString(), "Infinity"); + ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); + ASSERT_EQ(std::string(cStrings.back()), v.toString()); + v = -std::numeric_limits::infinity(); + cStrings.push_back(value_toCString(&v.data())); + ASSERT_EQ(v.toString(), "-Infinity"); + ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); + ASSERT_EQ(std::string(cStrings.back()), v.toString()); + v = std::numeric_limits::quiet_NaN(); + cStrings.push_back(value_toCString(&v.data())); + ASSERT_EQ(v.toString(), "NaN"); + ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString()); + ASSERT_EQ(std::string(cStrings.back()), v.toString()); + for (char *s : cStrings) free(s); } @@ -2646,12 +2274,12 @@ TEST(ValueTest, EqualityOperators) } { - Value v1(SpecialValue::Infinity); - Value v2(SpecialValue::Infinity); - Value v3(SpecialValue::NegativeInfinity); - Value v4(SpecialValue::NegativeInfinity); - Value v5(SpecialValue::NaN); - Value v6(SpecialValue::NaN); + Value v1(std::numeric_limits::infinity()); + Value v2(std::numeric_limits::infinity()); + Value v3(-std::numeric_limits::infinity()); + Value v4(-std::numeric_limits::infinity()); + Value v5(std::numeric_limits::quiet_NaN()); + Value v6(std::numeric_limits::quiet_NaN()); ASSERT_TRUE(v1 == v2); ASSERT_FALSE(v1 != v2); @@ -2784,9 +2412,9 @@ TEST(ValueTest, EqualityOperators) { Value v1 = 5; Value v2 = 0; - Value v3(SpecialValue::Infinity); - Value v4(SpecialValue::NegativeInfinity); - Value v5(SpecialValue::NaN); + Value v3(std::numeric_limits::infinity()); + Value v4(-std::numeric_limits::infinity()); + Value v5(std::numeric_limits::quiet_NaN()); ASSERT_FALSE(v1 == v3); ASSERT_TRUE(v1 != v3); @@ -2888,9 +2516,9 @@ TEST(ValueTest, EqualityOperators) { Value v1 = true; Value v2 = false; - Value v3(SpecialValue::Infinity); - Value v4(SpecialValue::NegativeInfinity); - Value v5(SpecialValue::NaN); + Value v3(std::numeric_limits::infinity()); + Value v4(-std::numeric_limits::infinity()); + Value v5(std::numeric_limits::quiet_NaN()); ASSERT_FALSE(v1 == v3); ASSERT_TRUE(v1 != v3); @@ -2912,9 +2540,9 @@ TEST(ValueTest, EqualityOperators) Value v4 = "-infinity"; Value v5 = "NaN"; Value v6 = "nan"; - Value v7(SpecialValue::Infinity); - Value v8(SpecialValue::NegativeInfinity); - Value v9(SpecialValue::NaN); + Value v7(std::numeric_limits::infinity()); + Value v8(-std::numeric_limits::infinity()); + Value v9(std::numeric_limits::quiet_NaN()); // Infinity ASSERT_TRUE(v1 == v7); @@ -2982,9 +2610,9 @@ TEST(ValueTest, EqualityOperators) Value v2 = " "; Value v3 = ""; Value v4 = "0"; - Value v5(SpecialValue::Infinity); - Value v6(SpecialValue::NegativeInfinity); - Value v7(SpecialValue::NaN); + Value v5(std::numeric_limits::infinity()); + Value v6(-std::numeric_limits::infinity()); + Value v7(std::numeric_limits::quiet_NaN()); // Infinity ASSERT_FALSE(v1 == v5); @@ -3077,6 +2705,18 @@ TEST(ValueTest, DoubleToCString) ret = value_doubleToCString(-0.001); ASSERT_EQ(strcmp(ret, "-0.001"), 0); free(ret); + + ret = value_doubleToCString(std::numeric_limits::infinity()); + ASSERT_EQ(strcmp(ret, "Infinity"), 0); + free(ret); + + ret = value_doubleToCString(-std::numeric_limits::infinity()); + ASSERT_EQ(strcmp(ret, "-Infinity"), 0); + free(ret); + + ret = value_doubleToCString(std::numeric_limits::quiet_NaN()); + ASSERT_EQ(strcmp(ret, "NaN"), 0); + free(ret); } TEST(ValueTest, BoolToCString) diff --git a/test/virtual_machine/virtual_machine_test.cpp b/test/virtual_machine/virtual_machine_test.cpp index a6e123f4..892db4d5 100644 --- a/test/virtual_machine/virtual_machine_test.cpp +++ b/test/virtual_machine/virtual_machine_test.cpp @@ -995,7 +995,9 @@ TEST(VirtualMachineTest, OP_LIST_DEL) 0, OP_CONST, 9, OP_LIST_DEL, 0, OP_READ_LIST, 0, OP_CONST, 10, OP_LIST_DEL, 0, OP_READ_LIST, 0, OP_CONST, 11, OP_LIST_DEL, 0, OP_READ_LIST, 0, OP_CONST, 12, OP_LIST_DEL, 0, OP_READ_LIST, 0, OP_CONST, 13, OP_LIST_DEL, 0, OP_READ_LIST, 0, OP_HALT }; - static Value constValues[] = { 3, 1, "6", 0, 7, -1, 9, SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN, "invalid", "last", "random", "all" }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { 3, 1, "6", 0, 7, -1, 9, -inf, inf, nan, "invalid", "last", "random", "all" }; List list1("", "list1"); list1.append("a"); list1.append("b"); @@ -1067,7 +1069,9 @@ TEST(VirtualMachineTest, OP_LIST_INSERT) 0, OP_CONST, 0, OP_CONST, 10, OP_LIST_INSERT, 0, OP_READ_LIST, 0, OP_CONST, 0, OP_CONST, 11, OP_LIST_INSERT, 0, OP_READ_LIST, 0, OP_CONST, 0, OP_CONST, 12, OP_LIST_INSERT, 0, OP_READ_LIST, 0, OP_CONST, 0, OP_CONST, 13, OP_LIST_INSERT, 0, OP_READ_LIST, 0, OP_HALT }; - static Value constValues[] = { "new item", "3", 1, 10, 0, 12, -1, 14, SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN, "last", "random", "invalid" }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "new item", "3", 1, 10, 0, 12, -1, 14, -inf, inf, nan, "last", "random", "invalid" }; List list1("", "list1"); list1.append("a"); list1.append("b"); @@ -1118,7 +1122,9 @@ TEST(VirtualMachineTest, OP_LIST_REPLACE) 0, OP_CONST, 10, OP_CONST, 0, OP_LIST_REPLACE, 0, OP_READ_LIST, 0, OP_CONST, 11, OP_CONST, 11, OP_LIST_REPLACE, 0, OP_READ_LIST, 0, OP_CONST, 12, OP_CONST, 14, OP_LIST_REPLACE, 0, OP_READ_LIST, 0, OP_CONST, 13, OP_CONST, 0, OP_LIST_REPLACE, 0, OP_READ_LIST, 0, OP_HALT }; - static Value constValues[] = { "new item", 3, "1", 8, 0, 9, -1, 12, SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN, "last", "random", "invalid", "test" }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "new item", 3, "1", 8, 0, 9, -1, 12, -inf, inf, nan, "last", "random", "invalid", "test" }; List list1("", "list1"); list1.append("a"); list1.append("b"); @@ -1166,7 +1172,9 @@ TEST(VirtualMachineTest, OP_LIST_GET_ITEM) 0, OP_CONST, 5, OP_LIST_GET_ITEM, 0, OP_CONST, 6, OP_LIST_GET_ITEM, 0, OP_CONST, 7, OP_LIST_GET_ITEM, 0, OP_CONST, 8, OP_LIST_GET_ITEM, 0, OP_CONST, 9, OP_LIST_GET_ITEM, 0, OP_CONST, 10, OP_LIST_GET_ITEM, 0, OP_CONST, 11, OP_LIST_GET_ITEM, 0, OP_CONST, 12, OP_LIST_GET_ITEM, 0, OP_HALT }; - static Value constValues[] = { 3, 1, "8", 0, 9, -1, 12, SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN, "last", "random", "invalid" }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { 3, 1, "8", 0, 9, -1, 12, -inf, inf, nan, "last", "random", "invalid" }; List list1("", "list1"); list1.append("a"); list1.append("b"); @@ -1213,7 +1221,9 @@ TEST(VirtualMachineTest, OP_LIST_INDEX_OF) OP_START, OP_CONST, 0, OP_LIST_INDEX_OF, 0, OP_CONST, 1, OP_LIST_INDEX_OF, 0, OP_CONST, 2, OP_LIST_INDEX_OF, 0, OP_CONST, 3, OP_LIST_INDEX_OF, 0, OP_CONST, 4, OP_LIST_INDEX_OF, 0, OP_CONST, 5, OP_LIST_INDEX_OF, 0, OP_CONST, 6, OP_LIST_INDEX_OF, 0, OP_CONST, 7, OP_LIST_INDEX_OF, 0, OP_HALT }; - static Value constValues[] = { "c", "A", "e", "", "invalid", SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "c", "A", "e", "", "invalid", -inf, inf, nan }; List list1("", "list1"); list1.append("a"); list1.append("b"); @@ -1221,7 +1231,7 @@ TEST(VirtualMachineTest, OP_LIST_INDEX_OF) list1.append("d"); list1.append("e"); list1.append(""); - list1.append(SpecialValue::Infinity); + list1.append(inf); list1.append(8); List *lists[] = { &list1 }; @@ -1268,7 +1278,9 @@ TEST(VirtualMachineTest, OP_LIST_CONTAINS) OP_START, OP_CONST, 0, OP_LIST_CONTAINS, 0, OP_CONST, 1, OP_LIST_CONTAINS, 0, OP_CONST, 2, OP_LIST_CONTAINS, 0, OP_CONST, 3, OP_LIST_CONTAINS, 0, OP_CONST, 4, OP_LIST_CONTAINS, 0, OP_CONST, 5, OP_LIST_CONTAINS, 0, OP_CONST, 6, OP_LIST_CONTAINS, 0, OP_CONST, 7, OP_LIST_CONTAINS, 0, OP_HALT }; - static Value constValues[] = { "c", "A", "e", "", "invalid", SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "c", "A", "e", "", "invalid", -inf, inf, nan }; List list1("", "list1"); list1.append("a"); list1.append("b"); @@ -1276,7 +1288,7 @@ TEST(VirtualMachineTest, OP_LIST_CONTAINS) list1.append("d"); list1.append("e"); list1.append(""); - list1.append(SpecialValue::Infinity); + list1.append(inf); list1.append(8); List *lists[] = { &list1 }; @@ -1299,7 +1311,8 @@ TEST(VirtualMachineTest, OP_LIST_CONTAINS) TEST(VirtualMachineTest, OP_STR_CONCAT) { static unsigned int bytecode[] = { OP_START, OP_CONST, 0, OP_CONST, 1, OP_STR_CONCAT, OP_CONST, 2, OP_STR_CONCAT, OP_CONST, 3, OP_STR_CONCAT, OP_HALT }; - static Value constValues[] = { "abc ", "def", " ghi", SpecialValue::NegativeInfinity }; + static const double inf = std::numeric_limits::infinity(); + static Value constValues[] = { "abc ", "def", " ghi", -inf }; VirtualMachine vm; vm.setBytecode(bytecode); @@ -1316,7 +1329,9 @@ TEST(VirtualMachineTest, OP_STR_AT) OP_STR_AT, OP_CONST, 0, OP_CONST, 6, OP_STR_AT, OP_CONST, 0, OP_CONST, 7, OP_STR_AT, OP_CONST, 0, OP_CONST, 8, OP_STR_AT, OP_CONST, 0, OP_CONST, 9, OP_STR_AT, OP_CONST, 0, OP_CONST, 10, OP_STR_AT, OP_CONST, 0, OP_CONST, 11, OP_STR_AT, OP_CONST, 0, OP_CONST, 12, OP_STR_AT, OP_CONST, 0, OP_CONST, 13, OP_STR_AT, OP_HALT }; - static Value constValues[] = { "abcd efg hijý", 3, 1, 14, 0, 15, -1, 16, SpecialValue::NegativeInfinity, SpecialValue::Infinity, SpecialValue::NaN, "last", "random", "invalid" }; + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + static Value constValues[] = { "abcd efg hijý", 3, 1, 14, 0, 15, -1, 16, -inf, inf, nan, "last", "random", "invalid" }; VirtualMachine vm; vm.setBytecode(bytecode);