value.h
Go to the documentation of this file.
1 #pragma once
6 #include <stdio.h>
7 #include <string.h>
8 #include "kuroko.h"
9 
16 typedef enum {
17  KRK_VAL_BOOLEAN = 0xFFFC,
18  KRK_VAL_INTEGER = 0xFFFD,
19  KRK_VAL_HANDLER = 0xFFFE,
20  KRK_VAL_NONE = 0xFFFF,
21  KRK_VAL_KWARGS = 0x7FFC,
22  KRK_VAL_OBJECT = 0x7FFD,
23  KRK_VAL_NOTIMPL = 0x7FFE,
24 } KrkValueType;
25 
26 /*
27  * The following poorly-named macros define bit patterns for identifying
28  * various boxed types.
29  *
30  * Boxing is done by first setting all of the bits of MASK_NAN. If all of
31  * these bits are set, a value is not a float. If any of them are not set,
32  * then a value is a float - and possibly a real NaN.
33  *
34  * Three other bits - one before and two after the MASK_NAN bits - determine
35  * what type the value actually is. KWARGS sets none of the identifying bits,
36  * NONE sets all of them.
37  */
38 #define KRK_VAL_MASK_BOOLEAN ((uint64_t)0xFFFC000000000000) /* 1..1100 */
39 #define KRK_VAL_MASK_INTEGER ((uint64_t)0xFFFD000000000000) /* 1..1101 */
40 #define KRK_VAL_MASK_HANDLER ((uint64_t)0xFFFE000000000000) /* 1..1110 */
41 #define KRK_VAL_MASK_NONE ((uint64_t)0xFFFF000000000000) /* 1..1111 */
42 #define KRK_VAL_MASK_KWARGS ((uint64_t)0x7FFC000000000000) /* 0..1100 */
43 #define KRK_VAL_MASK_OBJECT ((uint64_t)0x7FFD000000000000) /* 0..1101 */
44 #define KRK_VAL_MASK_NOTIMPL ((uint64_t)0x7FFE000000000000) /* 0..1110 */
45 #define KRK_VAL_MASK_NAN ((uint64_t)0x7FFC000000000000)
46 #define KRK_VAL_MASK_LOW ((uint64_t)0x0000FFFFFFFFFFFF)
47 
62 typedef uint64_t KrkValue;
63 
70 typedef struct {
71  size_t capacity;
72  size_t count;
75 
86 extern void krk_initValueArray(KrkValueArray * array);
87 
98 extern void krk_writeValueArray(KrkValueArray * array, KrkValue value);
99 
111 extern void krk_freeValueArray(KrkValueArray * array);
112 
129 extern void krk_printValue(FILE * f, KrkValue value);
130 
147 extern void krk_printValueSafe(FILE * f, KrkValue value);
148 
160 
172 extern int krk_valuesSame(KrkValue a, KrkValue b);
173 
183 
184 extern KrkValue krk_parse_int(const char * start, size_t width, unsigned int base);
185 
186 typedef union {
187  KrkValue val;
188  double dbl;
189 } KrkValueDbl;
190 
191 #ifdef KRK_SANITIZE_OBJECT_POINTERS
196 #include <assert.h>
197 static inline uintptr_t _krk_sanitize(uintptr_t input) {
198  assert(input != 0);
199  return input;
200 }
201 #else
202 #define _krk_sanitize(ptr) (ptr)
203 #endif
204 
210 #ifdef KRK_HEAP_TAG_BYTE
211 #define KRK_HEAP_TAG ((uintptr_t)KRK_HEAP_TAG_BYTE << 56)
212 #else
213 #define KRK_HEAP_TAG 0
214 #endif
215 
216 #define NONE_VAL(value) ((KrkValue)(KRK_VAL_MASK_LOW | KRK_VAL_MASK_NONE))
217 #define NOTIMPL_VAL(value) ((KrkValue)(KRK_VAL_MASK_LOW | KRK_VAL_MASK_NOTIMPL))
218 #define BOOLEAN_VAL(value) ((KrkValue)(((uint64_t)(value) & KRK_VAL_MASK_LOW) | KRK_VAL_MASK_BOOLEAN))
219 #define INTEGER_VAL(value) ((KrkValue)(((uint64_t)(value) & KRK_VAL_MASK_LOW) | KRK_VAL_MASK_INTEGER))
220 #define KWARGS_VAL(value) ((KrkValue)((uint32_t)(value) | KRK_VAL_MASK_KWARGS))
221 #define OBJECT_VAL(value) ((KrkValue)((_krk_sanitize((uintptr_t)(value)) & KRK_VAL_MASK_LOW) | KRK_VAL_MASK_OBJECT))
222 #define HANDLER_VAL(ty,ta) ((KrkValue)((uint64_t)((((uint64_t)ty) << 32) | ((uint32_t)ta)) | KRK_VAL_MASK_HANDLER))
223 #define FLOATING_VAL(value) (((KrkValueDbl){.dbl = (value)}).val)
224 
225 #define KRK_VAL_TYPE(value) ((value) >> 48)
226 
227 #define KRK_IX(value) ((uint64_t)((value) & KRK_VAL_MASK_LOW))
228 #define KRK_SX(value) ((uint64_t)((value) & 0x800000000000))
229 #define AS_INTEGER(value) ((krk_integer_type)(KRK_SX(value) ? (KRK_IX(value) | KRK_VAL_MASK_NONE) : (KRK_IX(value))))
230 #define AS_BOOLEAN(value) AS_INTEGER(value)
231 
232 #define AS_NOTIMPL(value) ((krk_integer_type)((value) & KRK_VAL_MASK_LOW))
233 #define AS_HANDLER(value) ((uint64_t)((value) & KRK_VAL_MASK_LOW))
234 #define AS_OBJECT(value) ((KrkObj*)(uintptr_t)(((value) & KRK_VAL_MASK_LOW) | KRK_HEAP_TAG))
235 #define AS_FLOATING(value) (((KrkValueDbl){.val = (value)}).dbl)
236 
237 /* This is a silly optimization: because of the arrangement of the identifying
238  * bits, (TYPE & MASK_HANDLER) == MASK_BOOLEAN can be used to tell if something
239  * is either an integer or a boolean - and booleans are also integers, so this
240  * is how we check if something is an integer in the general case; for everything
241  * else, we check against MASK_NONE because it sets all the identifying bits. */
242 #define IS_INTEGER(value) ((((value) >> 48L) & (KRK_VAL_MASK_HANDLER >> 48L)) == (KRK_VAL_MASK_BOOLEAN >> 48L))
243 #define IS_BOOLEAN(value) (((value) >> 48L) == (KRK_VAL_MASK_BOOLEAN >> 48L))
244 #define IS_NONE(value) (((value) >> 48L) == (KRK_VAL_MASK_NONE >> 48L))
245 #define IS_HANDLER(value) (((value) >> 48L) == (KRK_VAL_MASK_HANDLER >> 48L))
246 #define IS_OBJECT(value) (((value) >> 48L) == (KRK_VAL_MASK_OBJECT >> 48L))
247 #define IS_KWARGS(value) (((value) >> 48L) == (KRK_VAL_MASK_KWARGS >> 48L))
248 #define IS_NOTIMPL(value) (((value) >> 48L) == (KRK_VAL_MASK_NOTIMPL >> 48L))
249 /* ... and as we said above, if any of the MASK_NAN bits are unset, it's a float. */
250 #define IS_FLOATING(value) (((value) & KRK_VAL_MASK_NAN) != KRK_VAL_MASK_NAN)
251 
252 #define AS_HANDLER_TYPE(value) (AS_HANDLER(value) >> 32)
253 #define AS_HANDLER_TARGET(value) (AS_HANDLER(value) & 0xFFFFFFFF)
254 #define IS_HANDLER_TYPE(value,type) (IS_HANDLER(value) && AS_HANDLER_TYPE(value) == type)
255 
256 #define KWARGS_SINGLE (INT32_MAX)
257 #define KWARGS_LIST (INT32_MAX-1)
258 #define KWARGS_DICT (INT32_MAX-2)
259 #define KWARGS_NIL (INT32_MAX-3)
260 #define KWARGS_UNSET (0)
261 
262 #define PRIkrk_int "%" PRId64
263 #define PRIkrk_hex "%" PRIx64
264 
Top-level header with configuration macros.
Flexible vector of stack references.
Definition: value.h:70
size_t capacity
Definition: value.h:71
KrkValue * values
Definition: value.h:73
void krk_initValueArray(KrkValueArray *array)
Initialize a value array.
Definition: value.c:11
void krk_freeValueArray(KrkValueArray *array)
Release relesources used by a value array.
Definition: value.c:28
void krk_writeValueArray(KrkValueArray *array, KrkValue value)
Add a value to a value array.
Definition: value.c:17
size_t count
Definition: value.h:72
Stack reference or primative value.
int krk_valuesEqual(KrkValue a, KrkValue b)
Compare two values for equality.
void krk_printValue(FILE *f, KrkValue value)
Print a string representation of a value.
Definition: value.c:33
int krk_valuesSame(KrkValue a, KrkValue b)
Compare two values by identity.
Definition: value.c:151
int krk_valuesSameOrEqual(KrkValue a, KrkValue b)
Compare two values by identity, then by equality.
void krk_printValueSafe(FILE *f, KrkValue value)
Print a value without calling the VM.
Definition: value.c:52
KrkValueType
Tag enum for basic value types.
Definition: value.h:16