From a11d66cbd327d6c95164ba9cdd27d57c7a6273d8 Mon Sep 17 00:00:00 2001 From: Michel Hermier Date: Thu, 3 Dec 2020 20:37:53 +0100 Subject: [PATCH] WIP wren/core: Add DEF_NUM_CONSTANT (with Num::infinity and Num::nan). (#781) * wren/vm: Add "wren_math.h". * wren/core: Add DEF_NUM_CONSTANT. * wren/core: Add `Num::infinity` constant. * wren/core: Add `Num::nan` constant. --- doc/site/modules/core/num.markdown | 10 +++++++++ src/vm/wren_core.c | 30 ++++++++++++++------------ src/vm/wren_math.h | 34 ++++++++++++++++++++++++++++++ src/vm/wren_value.c | 4 +--- src/vm/wren_value.h | 17 +++------------ 5 files changed, 64 insertions(+), 31 deletions(-) create mode 100644 src/vm/wren_math.h diff --git a/doc/site/modules/core/num.markdown b/doc/site/modules/core/num.markdown index d1f9fb83..3639712b 100644 --- a/doc/site/modules/core/num.markdown +++ b/doc/site/modules/core/num.markdown @@ -9,6 +9,16 @@ Attempts to parse `value` as a decimal literal and return it as an instance of It is a runtime error if `value` is not a string. +### Num.**infinity** + +The value of &infinity;. + +### Num.**nan** + +One value representing a NaN. + +Provides a default sane NaN number suitable for the vm internal values. + ### Num.**pi** The value of π. diff --git a/src/vm/wren_core.c b/src/vm/wren_core.c index 033351fa..ecf8d3c6 100644 --- a/src/vm/wren_core.c +++ b/src/vm/wren_core.c @@ -7,6 +7,7 @@ #include "wren_common.h" #include "wren_core.h" +#include "wren_math.h" #include "wren_primitive.h" #include "wren_value.h" @@ -596,10 +597,19 @@ DEF_PRIMITIVE(num_fromString) RETURN_NUM(number); } -DEF_PRIMITIVE(num_pi) -{ - RETURN_NUM(3.14159265358979323846); -} +// Defines a primitive on Num that calls infix [op] and returns [type]. +#define DEF_NUM_CONSTANT(name, value) \ + DEF_PRIMITIVE(num_##name) \ + { \ + RETURN_NUM(value); \ + } + +DEF_NUM_CONSTANT(infinity, INFINITY) +DEF_NUM_CONSTANT(nan, WREN_DOUBLE_NAN) +DEF_NUM_CONSTANT(pi, 3.14159265358979323846) + +DEF_NUM_CONSTANT(largest, DBL_MAX) +DEF_NUM_CONSTANT(smallest, DBL_MIN) // Defines a primitive on Num that calls infix [op] and returns [type]. #define DEF_NUM_INFIX(name, op, type) \ @@ -749,16 +759,6 @@ DEF_PRIMITIVE(num_sign) } } -DEF_PRIMITIVE(num_largest) -{ - RETURN_NUM(DBL_MAX); -} - -DEF_PRIMITIVE(num_smallest) -{ - RETURN_NUM(DBL_MIN); -} - DEF_PRIMITIVE(num_toString) { RETURN_VAL(wrenNumToString(vm, AS_NUM(args[0]))); @@ -1277,6 +1277,8 @@ void wrenInitializeCore(WrenVM* vm) vm->numClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Num")); PRIMITIVE(vm->numClass->obj.classObj, "fromString(_)", num_fromString); + PRIMITIVE(vm->numClass->obj.classObj, "infinity", num_infinity); + PRIMITIVE(vm->numClass->obj.classObj, "nan", num_nan); PRIMITIVE(vm->numClass->obj.classObj, "pi", num_pi); PRIMITIVE(vm->numClass->obj.classObj, "largest", num_largest); PRIMITIVE(vm->numClass->obj.classObj, "smallest", num_smallest); diff --git a/src/vm/wren_math.h b/src/vm/wren_math.h new file mode 100644 index 00000000..bb5a2b39 --- /dev/null +++ b/src/vm/wren_math.h @@ -0,0 +1,34 @@ +#ifndef wren_math_h +#define wren_math_h + +#include +#include + +// A union to let us reinterpret a double as raw bits and back. +typedef union +{ + uint64_t bits64; + uint32_t bits32[2]; + double num; +} WrenDoubleBits; + +#define WREN_DOUBLE_QNAN_POS_MIN_BITS (UINT64_C(0x7FF8000000000000)) +#define WREN_DOUBLE_QNAN_POS_MAX_BITS (UINT64_C(0x7FFFFFFFFFFFFFFF)) + +#define WREN_DOUBLE_NAN (wrenDoubleFromBits(WREN_DOUBLE_QNAN_POS_MIN_BITS)) + +static inline double wrenDoubleFromBits(uint64_t bits) +{ + WrenDoubleBits data; + data.bits64 = bits; + return data.num; +} + +static inline uint64_t wrenDoubleToBits(double num) +{ + WrenDoubleBits data; + data.num = num; + return data.bits64; +} + +#endif diff --git a/src/vm/wren_value.c b/src/vm/wren_value.c index ec82bf3c..705987c8 100644 --- a/src/vm/wren_value.c +++ b/src/vm/wren_value.c @@ -374,9 +374,7 @@ static inline uint32_t hashBits(uint64_t hash) static inline uint32_t hashNumber(double num) { // Hash the raw bits of the value. - DoubleBits bits; - bits.num = num; - return hashBits(bits.bits64); + return hashBits(wrenDoubleToBits(num)); } // Generates a hash code for [object]. diff --git a/src/vm/wren_value.h b/src/vm/wren_value.h index ae50b551..349534d6 100644 --- a/src/vm/wren_value.h +++ b/src/vm/wren_value.h @@ -5,6 +5,7 @@ #include #include "wren_common.h" +#include "wren_math.h" #include "wren_utils.h" // This defines the built-in types and their core representations in memory. @@ -613,14 +614,6 @@ typedef struct #endif -// A union to let us reinterpret a double as raw bits and back. -typedef union -{ - uint64_t bits64; - uint32_t bits32[2]; - double num; -} DoubleBits; - // Creates a new "raw" class. It has no metaclass or superclass whatsoever. // This is only used for bootstrapping the initial Object and Class classes, // which are a little special. @@ -854,9 +847,7 @@ static inline Value wrenObjectToValue(Obj* obj) static inline double wrenValueToNum(Value value) { #if WREN_NAN_TAGGING - DoubleBits data; - data.bits64 = value; - return data.num; + return wrenDoubleFromBits(value); #else return value.as.num; #endif @@ -866,9 +857,7 @@ static inline double wrenValueToNum(Value value) static inline Value wrenNumToValue(double num) { #if WREN_NAN_TAGGING - DoubleBits data; - data.num = num; - return data.bits64; + return wrenDoubleToBits(num); #else Value value; value.type = VAL_NUM;