diff --git a/src/cvalue.h b/src/cvalue.h index 8274e24..628f439 100644 --- a/src/cvalue.h +++ b/src/cvalue.h @@ -32,35 +32,46 @@ typedef union CValue { cosmo_Number num; } CValue; -#define MASK_SIGN_BIT ((uint64_t)1 << 63) -#define MASK_TYPE ((uint64_t)0xf) -#define MASK_PAYLOAD ((uint64_t)0xfffffffffff0) +#define MASK_TYPE ((uint64_t)0x7) +#define MASK_PAYLOAD ((uint64_t)0x0007fffffffffff8) -#define MAKE_PAYLOAD(x) ((uint64_t)(x) << 4) +// 3 bits (low bits) are reserved for the type +#define MAKE_PAYLOAD(x) (((uint64_t)(x) << 3) & MASK_PAYLOAD) +#define READ_PAYLOAD(x) (((x).data & MASK_PAYLOAD) >> 3) // The bits that must be set to indicate a quiet NaN. -#define MASK_QUIETNAN ((uint64_t)0x7ffc000000000000) +#define MASK_QUIETNAN ((uint64_t)0x7ff8000000000000) + +#define GET_TYPE(x) \ + ((((x).data & MASK_QUIETNAN) == MASK_QUIETNAN) ? ((x).data & MASK_TYPE) : COSMO_TNUMBER) // sadly this requires a bit more than a simple macro :( -static inline CosmoType GET_TYPE(CValue val) { +/*static inline CosmoType GET_TYPE(CValue val) { // it's not not a number (its a number) if ((((val.data) & MASK_QUIETNAN) != MASK_QUIETNAN)) return COSMO_TNUMBER; - if ((((val.data) & (MASK_QUIETNAN | MASK_SIGN_BIT)) == (MASK_QUIETNAN | MASK_SIGN_BIT))) - return COSMO_TOBJ; - return (val.data & MASK_TYPE); -} +}*/ + +#define SIG_MASK (MASK_QUIETNAN | MASK_TYPE) +#define BOOL_SIG (MASK_QUIETNAN | COSMO_TBOOLEAN) +#define OBJ_SIG (MASK_QUIETNAN | COSMO_TOBJ) +#define NIL_SIG (MASK_QUIETNAN | COSMO_TNIL) #define cosmoV_newNumber(x) ((CValue){.num = x}) -#define cosmoV_newObj(x) ((CValue){.data = MASK_SIGN_BIT | MASK_QUIETNAN | (uint64_t)(uintptr_t)(x)}) +#define cosmoV_newObj(x) ((CValue){.data = MASK_QUIETNAN | MAKE_PAYLOAD((uintptr_t)x) | COSMO_TOBJ}) #define cosmoV_newBoolean(x) ((CValue){.data = MASK_QUIETNAN | MAKE_PAYLOAD(x) | COSMO_TBOOLEAN}) #define cosmoV_newNil() ((CValue){.data = MASK_QUIETNAN | COSMO_TNIL}) #define cosmoV_readNumber(x) ((x).num) -#define cosmoV_readBoolean(x) ((bool)((x).data & MASK_PAYLOAD)) -#define cosmoV_readObj(x) (((CObj*)(uintptr_t)(((x).data) & ~(MASK_SIGN_BIT | MASK_QUIETNAN)))) +#define cosmoV_readBoolean(x) ((bool)READ_PAYLOAD(x)) +#define cosmoV_readObj(x) ((CObj*)READ_PAYLOAD(x)) + +#define IS_NUMBER(x) (((x).data & MASK_QUIETNAN) != MASK_QUIETNAN) +#define IS_BOOLEAN(x) (((x).data & SIG_MASK) == BOOL_SIG) +#define IS_NIL(x) (((x).data & SIG_MASK) == NIL_SIG) +#define IS_OBJ(x) (((x).data & SIG_MASK) == OBJ_SIG) #else /* @@ -90,13 +101,13 @@ typedef struct CValue { #define cosmoV_readBoolean(x) ((bool)(x).val.b) #define cosmoV_readObj(x) ((CObj*)(x).val.obj) -#endif - #define IS_NUMBER(x) (GET_TYPE(x) == COSMO_TNUMBER) #define IS_BOOLEAN(x) (GET_TYPE(x) == COSMO_TBOOLEAN) #define IS_NIL(x) (GET_TYPE(x) == COSMO_TNIL) #define IS_OBJ(x) (GET_TYPE(x) == COSMO_TOBJ) +#endif + typedef CValue* StkPtr; typedef struct CValueArray {