// Values and objects: the types that every other part uses, the object // header and its tags, the allocator and errors. See docs/model.md #pragma once #include #include #include typedef struct { char _; } undefined_t; typedef struct { char _; } null_t; // A string: UTF-16 code units, as JS counts them typedef struct jsrt_string *string_t; // The start of every object: the site that created it, which tells its shape // and, for a fn, its code typedef struct { uint32_t site; } jsrt_header; // The sites below 3 are tags. An object of a value shape is a struct, not a // pointer, so its header tells if it is undefined, null or absent instead #define JSRT_SITE_UNDEFINED 0 #define JSRT_SITE_NULL 1 #define JSRT_SITE_ABSENT 2 // A pointer to an object or a string can also be one of these. NULL is null extern jsrt_header jsrt_undefined_cell, jsrt_absent_cell; #define JSRT_UNDEFINED ((void *)&jsrt_undefined_cell) #define JSRT_ABSENT ((void *)&jsrt_absent_cell) // a field that an object lacks // Whether the objects of each site are fns, by site. The emitted C defines it extern const bool jsrt_fn_sites[]; // A new heap cell of `size` bytes, all zero void *jsrt_alloc(size_t size); // `items`, an array's elements of `size` bytes each, with room for at least // `need` of them. `*cap` is the room that it has, and is set to the new room void *jsrt_grow(void *items, int32_t *cap, int32_t need, size_t size); // Throws a TypeError. Exceptions are not supported yet, so it stops the program _Noreturn void jsrt_type_error(void); // `p`, a pointer to an object or a string. A sentinel for null, undefined or // absent throws a TypeError void *jsrt_some(void *p); #ifdef JSRT_IMPLEMENTATION #include #include jsrt_header jsrt_undefined_cell = { JSRT_SITE_UNDEFINED }; jsrt_header jsrt_absent_cell = { JSRT_SITE_ABSENT }; void *jsrt_alloc(size_t size) { void *p = calloc(1, size); if (!p) { fputs("jsrt: out of memory\n", stderr); abort(); } return p; } void *jsrt_grow(void *items, int32_t *cap, int32_t need, size_t size) { if (need <= *cap) { return items; } int32_t room = *cap * 2 > need ? *cap * 2 : need < 4 ? 4 : need; items = realloc(items, (size_t)room * size); if (!items) { fputs("jsrt: out of memory\n", stderr); abort(); } *cap = room; return items; } _Noreturn void jsrt_type_error(void) { fputs("TypeError\n", stderr); exit(1); } void *jsrt_some(void *p) { if (p == NULL || p == JSRT_UNDEFINED || p == JSRT_ABSENT) { jsrt_type_error(); } return p; } #endif // JSRT_IMPLEMENTATION