forked from microsoft/devicescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdevs_value.h
More file actions
232 lines (186 loc) · 7.4 KB
/
devs_value.h
File metadata and controls
232 lines (186 loc) · 7.4 KB
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#pragma once
#include <stdint.h>
#include <stdbool.h>
typedef union {
double _f;
uint64_t u64;
struct {
uint32_t mantisa32;
uint32_t mantisa20 : 20;
uint32_t exponent : 11;
uint32_t sign : 1;
};
struct {
int32_t val_int32;
uint32_t exp_sign;
};
// this is for better view in the debugger
struct {
uint32_t handle_value;
uint32_t handle_type : 4;
uint32_t handle_hi_value : 16;
uint32_t handle_eq_0 : 11;
uint32_t handle_unused : 1;
};
} value_t;
#define DEVS_INT_TAG (0U - 1U)
#define DEVS_HANDLE_TAG 0x00000000
// optimization parameter
#define DEVS_MAX_ASCII_STRING 50
// closure: ptr to env + static fn
// bound fn: ptr to gc_obj + static fn
#define DEVS_HANDLE_TYPE_MASK 0xf
#define DEVS_HANDLE_TYPE_FLOAT64 0x10
#define DEVS_HANDLE_TYPE_SPECIAL 0x0
#define DEVS_HANDLE_TYPE_FIBER 0x1
#define DEVS_HANDLE_TYPE_ROLE 0x2
#define DEVS_HANDLE_TYPE_STATIC_FUNCTION 0x3
#define DEVS_HANDLE_TYPE_IMG_BUFFERISH 0x4
#define DEVS_HANDLE_TYPE_BOUND_FUNCTION_STATIC 0x5
#define DEVS_HANDLE_TYPE_ROLE_MEMBER 0x6
#define DEVS_HANDLE_TYPE_GC_OBJECT 0x8 // see devs_handle_type_is_ptr()
#define DEVS_HANDLE_TYPE_CLOSURE 0x9
#define DEVS_HANDLE_TYPE_BOUND_FUNCTION 0xA
#define DEVS_SPECIAL_UNDEFINED 0 // has to be zero! UNDEFINED is represented as all zero
#define DEVS_SPECIAL_FALSE 1
#define DEVS_SPECIAL_NAN 2
#define DEVS_SPECIAL_NULL 3
#define DEVS_SPECIAL_TRUE 0x40
#define DEVS_SPECIAL_INF 0x42
#define DEVS_SPECIAL_MINF 0x43
#define DEVS_PACK_SHIFT 28
#define DEVS_SPECIAL_THROW_JMP_OFF 0x400
#define DEVS_SPECIAL_THROW_JMP_LEVEL_SHIFT 4
#define DEVS_SPECIAL_THROW_JMP_LEVEL_MAX ((1 << DEVS_SPECIAL_THROW_JMP_LEVEL_SHIFT) - 1)
#define DEVS_SPECIAL_THROW_JMP_PC_MAX \
((1 << (DEVS_PACK_SHIFT - DEVS_SPECIAL_THROW_JMP_LEVEL_SHIFT)) - 1)
#define DEVS_SPECIAL_BUILTIN_OBJ_FIRST 0x60
#define DEVS_SPECIAL_BUILTIN_OBJ_LAST (DEVS_SPECIAL_BUILTIN_OBJ_FIRST + DEVS_BUILTIN_OBJECT___MAX)
value_t devs_value_encode_throw_jmp_pc(int pc, unsigned lev);
static inline bool devs_handle_is_builtin(uint32_t hv) {
return DEVS_SPECIAL_BUILTIN_OBJ_FIRST <= hv && hv <= DEVS_SPECIAL_BUILTIN_OBJ_LAST;
}
static inline bool devs_handle_is_throw_jmp(uint32_t hv) {
return hv >= DEVS_SPECIAL_THROW_JMP_OFF;
}
static inline int devs_handle_decode_throw_jmp_pc(uint32_t hv, unsigned *lev) {
hv -= DEVS_SPECIAL_THROW_JMP_OFF;
*lev = hv & DEVS_SPECIAL_THROW_JMP_LEVEL_MAX;
return hv >> DEVS_SPECIAL_THROW_JMP_LEVEL_SHIFT;
}
static inline bool devs_is_tagged_int(value_t t) {
return (t.exp_sign + 1) == 0;
}
static inline bool devs_handle_type_is_ptr(int tp) {
return (tp & 0x8) != 0;
}
static inline bool devs_is_handle(value_t t) {
return t.exponent == 0;
}
static inline int devs_handle_type(value_t t) {
return devs_is_handle(t) ? (t.exp_sign & DEVS_HANDLE_TYPE_MASK) : DEVS_HANDLE_TYPE_FLOAT64;
}
static inline uint32_t devs_handle_value(value_t t) {
return t.mantisa32;
}
// high_value is 16 bit
static inline uint16_t devs_handle_high_value(value_t t) {
return (t.exp_sign << 12) >> (12 + 4);
}
static inline bool devs_handle_is_ptr(value_t t) {
return devs_handle_type_is_ptr(devs_handle_type(t));
}
#if JD_64
void *devs_handle_ptr_value(devs_ctx_t *ctx, value_t t);
#else
static inline void *devs_handle_ptr_value(devs_ctx_t *ctx, value_t t) {
return (void *)t.mantisa32;
}
#endif
static inline value_t devs_value_from_handle(int type, uint32_t value) {
value_t r;
r.exp_sign = DEVS_HANDLE_TAG + type;
r.mantisa32 = value;
return r;
}
static inline bool devs_is_undefined(value_t t) {
return t.u64 == 0;
}
static inline bool devs_bufferish_is_buffer(value_t v) {
return (devs_handle_value(v) >> DEVS_STRIDX__SHIFT) == DEVS_STRIDX_BUFFER;
}
static inline bool devs_is_special(value_t t) {
return t.exp_sign == DEVS_HANDLE_TAG + DEVS_HANDLE_TYPE_SPECIAL;
}
static inline bool devs_is_nan(value_t t) {
return devs_is_special(t) && devs_handle_value(t) == DEVS_SPECIAL_NAN;
}
bool devs_is_null_or_undefined(value_t t);
bool devs_is_nullish(value_t t);
// this excludes NaN and Inf
bool devs_is_number(value_t t);
value_t devs_value_from_double(double v);
value_t devs_value_from_int(int v);
value_t devs_value_from_bool(int v);
value_t devs_value_from_pointer(devs_ctx_t *ctx, int handle_type, void *ptr);
static inline value_t devs_value_from_gc_obj(devs_ctx_t *ctx, void *ptr) {
return devs_value_from_pointer(ctx, DEVS_HANDLE_TYPE_GC_OBJECT, ptr);
}
int32_t devs_value_to_int(devs_ctx_t *ctx, value_t v);
double devs_value_to_double(devs_ctx_t *ctx, value_t v);
bool devs_value_to_bool(devs_ctx_t *ctx, value_t v);
// === in JS (including NaN !== NaN)
bool devs_value_ieee_eq(devs_ctx_t *ctx, value_t a, value_t b);
// === in JS but eq(NaN, NaN) == true
bool devs_value_eq(devs_ctx_t *ctx, value_t a, value_t b);
// == in JS
bool devs_value_approx_eq(devs_ctx_t *ctx, value_t a, value_t b);
bool devs_value_eq_builtin_string(devs_ctx_t *ctx, value_t a, unsigned idx);
// returns one of DEVS_OBJECT_TYPE_*
unsigned devs_value_typeof(devs_ctx_t *ctx, value_t v);
value_t devs_value_bufferish(devs_ctx_t *ctx, unsigned tp, uint32_t lit);
extern const value_t devs_zero;
extern const value_t devs_one;
extern const value_t devs_nan;
extern const value_t devs_inf;
extern const value_t devs_minf;
extern const value_t devs_int_min;
extern const value_t devs_max_int_1;
extern const value_t devs_true;
extern const value_t devs_false;
extern const value_t devs_null;
static inline value_t devs_undefined_(void) {
value_t v = {.u64 = 0};
return v;
}
#define devs_undefined (devs_undefined_())
#define devs_void devs_undefined
#define devs_error devs_undefined
bool devs_is_buffer(devs_ctx_t *ctx, value_t v);
bool devs_buffer_is_writable(devs_ctx_t *ctx, value_t v);
void *devs_buffer_data(devs_ctx_t *ctx, value_t v, unsigned *sz);
// this returns NULL if v is neither buffer not string
const void *devs_bufferish_data(devs_ctx_t *ctx, value_t v, unsigned *sz);
bool devs_is_array(devs_ctx_t *ctx, value_t v);
bool devs_is_string(devs_ctx_t *ctx, value_t v);
value_t devs_string_concat(devs_ctx_t *ctx, value_t a, value_t b);
const char *devs_string_get_utf8(devs_ctx_t *ctx, value_t s, unsigned *size);
/**
* If this returns NULL then `v` is not a string or is ASCII-only.
*/
const devs_utf8_string_t *devs_string_get_utf8_struct(devs_ctx_t *ctx, value_t v);
value_t devs_value_to_string(devs_ctx_t *ctx, value_t v);
value_t devs_string_vsprintf(devs_ctx_t *ctx, const char *format, va_list ap);
__attribute__((format(printf, 2, 3))) value_t devs_string_sprintf(devs_ctx_t *ctx,
const char *format, ...);
value_t devs_string_from_utf8(devs_ctx_t *ctx, const uint8_t *utf8, unsigned size);
value_t devs_builtin_string(unsigned idx);
value_t devs_string_slice(devs_ctx_t *ctx, value_t str, int start, int endp);
void devs_value_pin(devs_ctx_t *ctx, value_t v);
void devs_value_unpin(devs_ctx_t *ctx, value_t v);
bool devs_value_is_pinned(devs_ctx_t *ctx, value_t v);
// assumes string is valid utf8; don't run on buffers
value_t devs_json_parse(devs_ctx_t *ctx, const char *str, unsigned sz, bool do_throw);
value_t devs_json_stringify(devs_ctx_t *ctx, value_t v, int indent, bool do_throw);
value_t devs_inspect(devs_ctx_t *ctx, value_t v, unsigned size);
uint32_t devs_compute_timeout(devs_ctx_t *ctx, value_t t);