/
value.h
175 lines (153 loc) · 3.96 KB
/
value.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//> Chunks of Bytecode value-h
#ifndef clox_value_h
#define clox_value_h
//> Optimization include-string
#include <string.h>
//< Optimization include-string
#include "common.h"
//> Strings forward-declare-obj
typedef struct Obj Obj;
//> forward-declare-obj-string
typedef struct ObjString ObjString;
//< forward-declare-obj-string
//< Strings forward-declare-obj
//> Optimization nan-boxing
#ifdef NAN_BOXING
//> qnan
//> sign-bit
#define SIGN_BIT ((uint64_t)0x8000000000000000)
//< sign-bit
#define QNAN ((uint64_t)0x7ffc000000000000)
//< qnan
//> tags
#define TAG_NIL 1 // 01.
#define TAG_FALSE 2 // 10.
#define TAG_TRUE 3 // 11.
//< tags
typedef uint64_t Value;
//> is-number
//> is-bool
#define IS_BOOL(value) (((value) | 1) == TRUE_VAL)
//< is-bool
//> is-nil
#define IS_NIL(value) ((value) == NIL_VAL)
//< is-nil
#define IS_NUMBER(value) (((value) & QNAN) != QNAN)
//< is-number
//> is-obj
#define IS_OBJ(value) \
(((value) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT))
//< is-obj
//> as-number
//> as-bool
#define AS_BOOL(value) ((value) == TRUE_VAL)
//< as-bool
#define AS_NUMBER(value) valueToNum(value)
//< as-number
//> as-obj
#define AS_OBJ(value) \
((Obj*)(uintptr_t)((value) & ~(SIGN_BIT | QNAN)))
//< as-obj
//> number-val
//> bool-val
#define BOOL_VAL(b) ((b) ? TRUE_VAL : FALSE_VAL)
//< bool-val
//> false-true-vals
#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE))
#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE))
//< false-true-vals
//> nil-val
#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL))
//< nil-val
#define NUMBER_VAL(num) numToValue(num)
//< number-val
//> obj-val
#define OBJ_VAL(obj) \
(Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj))
//< obj-val
//> value-to-num
static inline double valueToNum(Value value) {
double num;
memcpy(&num, &value, sizeof(Value));
return num;
}
//< value-to-num
//> num-to-value
static inline Value numToValue(double num) {
Value value;
memcpy(&value, &num, sizeof(double));
return value;
}
//< num-to-value
#else
//< Optimization nan-boxing
//> Types of Values value-type
typedef enum {
VAL_BOOL,
VAL_NIL, // [user-types]
VAL_NUMBER,
//> Strings val-obj
VAL_OBJ
//< Strings val-obj
} ValueType;
//< Types of Values value-type
/* Chunks of Bytecode value-h < Types of Values value
typedef double Value;
*/
//> Types of Values value
typedef struct {
ValueType type;
union {
bool boolean;
double number;
//> Strings union-object
Obj* obj;
//< Strings union-object
} as; // [as]
} Value;
//< Types of Values value
//> Types of Values is-macros
#define IS_BOOL(value) ((value).type == VAL_BOOL)
#define IS_NIL(value) ((value).type == VAL_NIL)
#define IS_NUMBER(value) ((value).type == VAL_NUMBER)
//> Strings is-obj
#define IS_OBJ(value) ((value).type == VAL_OBJ)
//< Strings is-obj
//< Types of Values is-macros
//> Types of Values as-macros
//> Strings as-obj
#define AS_OBJ(value) ((value).as.obj)
//< Strings as-obj
#define AS_BOOL(value) ((value).as.boolean)
#define AS_NUMBER(value) ((value).as.number)
//< Types of Values as-macros
//> Types of Values value-macros
#define BOOL_VAL(value) ((Value){VAL_BOOL, {.boolean = value}})
#define NIL_VAL ((Value){VAL_NIL, {.number = 0}})
#define NUMBER_VAL(value) ((Value){VAL_NUMBER, {.number = value}})
//> Strings obj-val
#define OBJ_VAL(object) ((Value){VAL_OBJ, {.obj = (Obj*)object}})
//< Strings obj-val
//< Types of Values value-macros
//> Optimization end-if-nan-boxing
#endif
//< Optimization end-if-nan-boxing
//> value-array
typedef struct {
int capacity;
int count;
Value* values;
} ValueArray;
//< value-array
//> array-fns-h
//> Types of Values values-equal-h
bool valuesEqual(Value a, Value b);
//< Types of Values values-equal-h
void initValueArray(ValueArray* array);
void writeValueArray(ValueArray* array, Value value);
void freeValueArray(ValueArray* array);
//< array-fns-h
//> print-value-h
void printValue(Value value);
//< print-value-h
#endif