From 9080455fae1ce1625d41f5d1f20c5a0448934085 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Mon, 15 Aug 2022 12:17:15 -0700 Subject: [PATCH] Chapter 30.3 --- clox/src/common.h | 1 + clox/src/value.c | 19 +++++++++++++++++++ clox/src/value.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/clox/src/common.h b/clox/src/common.h index bfb76f4..b41797b 100644 --- a/clox/src/common.h +++ b/clox/src/common.h @@ -5,6 +5,7 @@ #include #include +#define NAN_BOXING /* #define DEBUG_PRINT_CODE */ /* #define DEBUG_TRACE_EXECUTION */ diff --git a/clox/src/value.c b/clox/src/value.c index e442181..8b6cb56 100644 --- a/clox/src/value.c +++ b/clox/src/value.c @@ -29,6 +29,17 @@ void freeValueArray(ValueArray *array) { } void printValue(Value value) { +#ifdef NAN_BOXING + if (IS_BOOL(value)) { + printf(AS_BOOL(value) ? "true" : "false"); + } else if (IS_NIL(value)) { + printf("nil"); + } else if (IS_NUMBER(value)) { + printf("%g", AS_NUMBER(value)); + } else if (IS_OBJ(value)) { + printObject(value); + } +#else switch (value.type) { case VAL_BOOL: printf(AS_BOOL(value) ? "true" : "false"); @@ -43,9 +54,16 @@ void printValue(Value value) { printObject(value); break; } +#endif // NAN_BOXING } bool valuesEqual(Value a, Value b) { +#ifdef NAN_BOXING + if (IS_NUMBER(a) && IS_NUMBER(b)) { + return AS_NUMBER(a) == AS_NUMBER(b); + } + return a == b; +#else if (a.type != b.type) return false; switch (a.type) { @@ -61,4 +79,5 @@ bool valuesEqual(Value a, Value b) { default: return false; /* Unreachable */ } +#endif // NAN_BOXING } diff --git a/clox/src/value.h b/clox/src/value.h index 7dbf99e..ea76d86 100644 --- a/clox/src/value.h +++ b/clox/src/value.h @@ -1,11 +1,54 @@ #ifndef clox_value_h #define clox_value_h +#include + #include "common.h" typedef struct Obj Obj; typedef struct ObjString ObjString; +#ifdef NAN_BOXING + +#define SIGN_BIT ((uint64_t)0x8000000000000000) +#define QNAN ((uint64_t)0x7ffc000000000000) + +#define TAG_NIL 1 /* 01 */ +#define TAG_FALSE 2 /* 10 */ +#define TAG_TRUE 3 /* 11 */ + +typedef uint64_t Value; + +#define IS_BOOL(value) (((value) | 1) == TRUE_VAL) +#define IS_NIL(value) ((value) == NIL_VAL) +#define IS_NUMBER(value) (((value)&QNAN) != QNAN) +#define IS_OBJ(value) (((value) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT)) + +#define AS_BOOL(value) ((value) == TRUE_VAL) +#define AS_NUMBER(value) valueToNum(value) +#define AS_OBJ(value) ((Obj *)(uintptr_t)((value) & ~(SIGN_BIT | QNAN))) + +#define BOOL_VAL(b) ((b) ? TRUE_VAL : FALSE_VAL) +#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE)) +#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE)) +#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL)) +#define NUMBER_VAL(num) numToValue(num) +#define OBJ_VAL(obj) (Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj)) + +static inline double valueToNum(Value value) { + double num; + memcpy(&num, &value, sizeof(Value)); + return num; +} + +static inline Value numToValue(double num) { + Value value; + memcpy(&value, &num, sizeof(double)); + return value; +} + +#else + typedef enum { VAL_BOOL, VAL_NIL, @@ -36,6 +79,8 @@ typedef struct { #define NUMBER_VAL(value) ((Value){VAL_NUMBER, {.number = value}}) #define OBJ_VAL(value) ((Value){VAL_OBJ, {.obj = (Obj *)value}}) +#endif // NAN_BOXING + typedef struct { int capacity; int count;