-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathvalue.h
128 lines (99 loc) · 3 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
#ifndef VAIVEN_VISITOR_HEADER_VALUE
#define VAIVEN_VISITOR_HEADER_VALUE
#include "inttypes.h"
#include "type_info.h"
namespace vaiven {
// the largest double is nan
// 11111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000
// largest ptr is <= 0x00007FFFFFFFFFFF
// 00000000 00000000 01111111 11111111 11111111 11111111 11111111 11111111
// if we flip NaN, we can say all doubles are >= 0x0007FFFFFFFFFFFF
// 00000000 00000111 11111111 11111111 11111111 11111111 11111111 11111111
// that means we can distinguish some magical values
// 00000000 00000000 10000000 00000000 00000000 00000000 00000000 00000001 true
// 00000000 00000000 10000000 00000000 00000000 00000000 00000000 00000000 false
// 00000000 00000001 00000000 00000000 00000000 00000000 00000000 00000010 void
// 00000000 00000010 00000000 00000000 ........ ........ ........ ........ 32 bit int
const uint64_t MAX_PTR = 0x00007FFFFFFFFFFF;
const uint64_t MIN_DBL = 0x0007FFFFFFFFFFFF;
const uint64_t FALSE = 0x0000800000000000;
const uint64_t TRUE = 0x0000800000000001;
const uint64_t VOID = 0x0002000000000000;
const uint64_t INT_TAG = 0x0001000000000000;
const uint64_t BOOL_TAG = 0x0000800000000000;
const uint64_t VALUE_TAG_SHIFT = 32;
const uint64_t INT_TAG_SHIFTED = 0x00010000;
const uint64_t BOOL_TAG_SHIFTED = 0x00008000;
struct ValueAfterHeader {
int32_t asInt;
uint32_t header;
};
class Gcable;
class Value {
private:
union {
Gcable* asPtr;
double asDouble;
uint64_t raw;
ValueAfterHeader withHeader;
} internals;
public:
inline Value(int32_t fromInt) {
internals.withHeader.header = INT_TAG_SHIFTED;
internals.withHeader.asInt = fromInt;
}
inline Value(bool fromBool) {
internals.raw = fromBool ? TRUE : FALSE;
}
inline Value(Gcable* fromPtr) {
internals.asPtr = fromPtr;
}
inline Value(double fromDouble) {
internals.asDouble = fromDouble;
internals.raw = ~internals.raw;
}
inline Value() {
internals.raw = VOID;
}
inline bool isInt() const {
return internals.raw >> VALUE_TAG_SHIFT == INT_TAG_SHIFTED;
}
inline bool isPtr() const {
return internals.raw <= MAX_PTR;
}
inline bool isDouble() const {
return internals.raw >= MIN_DBL;
}
inline bool isBool() const {
return internals.raw >> VALUE_TAG_SHIFT == BOOL_TAG_SHIFTED;
}
inline bool isTrue() const {
return internals.raw == TRUE;
}
inline bool isFalse() const {
return internals.raw == FALSE;
}
inline bool isVoid() const {
return internals.raw == VOID;
}
inline int32_t getInt() const {
return internals.withHeader.asInt;
}
inline Gcable* getPtr() const {
return internals.asPtr;
}
inline double getDouble() const {
Value val = *this;
val.internals.raw = ~val.internals.raw;
return val.internals.asDouble;
}
inline bool getBool() const {
return internals.withHeader.asInt;
}
inline uint64_t getRaw() const {
return internals.raw;
}
VaivenStaticType getStaticType() const;
};
}
#endif