Files
jsrt/lib/rt/core.h
T
2026-10-03 14:06:24 +00:00

96 lines
2.6 KiB
C

// 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 <stdbool.h>
#include <stddef.h>
#include <stdint.h>
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 <stdio.h>
#include <stdlib.h>
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