aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2022-08-15 12:17:15 -0700
committerGravatar Tom Willemse2022-08-15 12:17:15 -0700
commit9080455fae1ce1625d41f5d1f20c5a0448934085 (patch)
tree1dea8d59fa44acaf4c53c60285aa9546cc20966e
parentb30eb232f69c7cb48ce20b353f9575c4632209b6 (diff)
downloadcrafting-interpreters-master.tar.gz
crafting-interpreters-master.zip
Chapter 30.3HEADmaster
-rw-r--r--clox/src/common.h1
-rw-r--r--clox/src/value.c19
-rw-r--r--clox/src/value.h45
3 files changed, 65 insertions, 0 deletions
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 <stddef.h>
#include <stdint.h>
+#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 <string.h>
+
#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;