apfl/src/resizable.h

77 lines
1.4 KiB
C
Raw Normal View History

2021-12-10 20:22:16 +00:00
#ifndef APFL_RESIZABLE
#define APFL_RESIZABLE 1
#include <stddef.h>
#include <stdbool.h>
#include "apfl.h"
2021-12-10 20:22:16 +00:00
#define APFL_RESIZABLE_TRAIT(T, N) \
T* N; \
size_t len; \
size_t cap;
#define APFL_RESIZABLE_ARGS(S, N) (void **)(&(S).N), &(S).len, &(S).cap
void apfl_resizable_init(void **mem, size_t *len, size_t *cap);
bool apfl_resizable_resize(
struct apfl_allocator,
size_t elem_size,
void **mem,
size_t *len,
size_t *cap,
size_t newlen
);
2021-12-10 20:22:16 +00:00
bool apfl_resizable_ensure_cap(
struct apfl_allocator,
size_t elem_size,
void **mem,
size_t *cap,
size_t want_cap
);
bool apfl_resizable_ensure_cap_for_more_elements(
struct apfl_allocator,
size_t elem_size,
void **mem,
size_t len,
size_t *cap,
size_t more_elements
);
Implement mark&sweep garbage collection and bytecode compilation Instead of the previous refcount base garbage collection, we're now using a basic tri-color mark&sweep collector. This is done to support cyclical value relationships in the future (functions can form cycles, all values implemented up to this point can not). The collector maintains a set of roots and a set of objects (grouped into blocks). The GC enabled objects are no longer allocated manually, but will be allocated by the GC. The GC also wraps an allocator, this way the GC knows, if we ran out of memory and will try to get out of this situation by performing a full collection cycle. The tri-color abstraction was chosen for two reasons: - We don't have to maintain a list of objects that need to be marked, we can simply grab the next grey one. - It should allow us to later implement incremental collection (right now we only do a stop-the-world collection). This also switches to a bytecode based evaluation of the code: We no longer directly evaluate the AST, but first compile it into a series of instructions, that are evaluated in a separate step. This was done in preparation for inplementing functions: We only need to turn a function body into instructions instead of evaluating the node again with each call of the function. Also, since an instruction list is implemented as a GC object, this then removes manual memory management of the function body and it's child nodes. Since the GC and the bytecode go hand in hand, this was done in one (giant) commit. As a downside, we've now lost the ability do do list matching on assignments. I've already started to work on implementing this in the new architecture, but left it out of this commit, as it's already quite a large commit :)
2022-04-11 20:24:22 +00:00
bool apfl_resizable_check_cut_args(size_t len, size_t cut_start, size_t cut_len);
bool apfl_resizable_cut_without_resize(
size_t elem_size,
void **mem,
size_t *len,
size_t cut_start,
size_t cut_len
);
2022-01-20 20:33:04 +00:00
bool apfl_resizable_splice(
struct apfl_allocator,
2022-01-20 20:33:04 +00:00
size_t elem_size,
void **mem,
size_t *len,
size_t *cap,
size_t start,
size_t cut_len,
const void *other_mem,
size_t other_len
);
2021-12-10 20:22:16 +00:00
bool apfl_resizable_append(
struct apfl_allocator,
size_t elem_size,
void **mem,
size_t *len,
size_t *cap,
const void *other_mem,
size_t other_len
);
2021-12-10 20:22:16 +00:00
2022-01-20 20:33:04 +00:00
2021-12-10 20:22:16 +00:00
#endif