Chapter 30.3
This commit is contained in:
parent
b30eb232f6
commit
9080455fae
3 changed files with 65 additions and 0 deletions
|
@ -5,6 +5,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define NAN_BOXING
|
||||
/* #define DEBUG_PRINT_CODE */
|
||||
/* #define DEBUG_TRACE_EXECUTION */
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue