Chapter 30.3

This commit is contained in:
Tom Willemse 2022-08-15 12:17:15 -07:00
parent b30eb232f6
commit 9080455fae
3 changed files with 65 additions and 0 deletions

View file

@ -5,6 +5,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define NAN_BOXING
/* #define DEBUG_PRINT_CODE */ /* #define DEBUG_PRINT_CODE */
/* #define DEBUG_TRACE_EXECUTION */ /* #define DEBUG_TRACE_EXECUTION */

View file

@ -29,6 +29,17 @@ void freeValueArray(ValueArray *array) {
} }
void printValue(Value value) { 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) { switch (value.type) {
case VAL_BOOL: case VAL_BOOL:
printf(AS_BOOL(value) ? "true" : "false"); printf(AS_BOOL(value) ? "true" : "false");
@ -43,9 +54,16 @@ void printValue(Value value) {
printObject(value); printObject(value);
break; break;
} }
#endif // NAN_BOXING
} }
bool valuesEqual(Value a, Value b) { 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) if (a.type != b.type)
return false; return false;
switch (a.type) { switch (a.type) {
@ -61,4 +79,5 @@ bool valuesEqual(Value a, Value b) {
default: default:
return false; /* Unreachable */ return false; /* Unreachable */
} }
#endif // NAN_BOXING
} }

View file

@ -1,11 +1,54 @@
#ifndef clox_value_h #ifndef clox_value_h
#define clox_value_h #define clox_value_h
#include <string.h>
#include "common.h" #include "common.h"
typedef struct Obj Obj; typedef struct Obj Obj;
typedef struct ObjString ObjString; 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 { typedef enum {
VAL_BOOL, VAL_BOOL,
VAL_NIL, VAL_NIL,
@ -36,6 +79,8 @@ typedef struct {
#define NUMBER_VAL(value) ((Value){VAL_NUMBER, {.number = value}}) #define NUMBER_VAL(value) ((Value){VAL_NUMBER, {.number = value}})
#define OBJ_VAL(value) ((Value){VAL_OBJ, {.obj = (Obj *)value}}) #define OBJ_VAL(value) ((Value){VAL_OBJ, {.obj = (Obj *)value}})
#endif // NAN_BOXING
typedef struct { typedef struct {
int capacity; int capacity;
int count; int count;