mirror of
https://github.com/janet-lang/janet
synced 2025-01-02 20:00:26 +00:00
Add support for weak references in arrays.
Also change weak table syntax to not require keyword arguments.
This commit is contained in:
parent
6efb965dab
commit
84ad161f1e
1
.gitignore
vendored
1
.gitignore
vendored
@ -57,6 +57,7 @@ xxd.exe
|
|||||||
# VSCode
|
# VSCode
|
||||||
.vs
|
.vs
|
||||||
.clangd
|
.clangd
|
||||||
|
.cache
|
||||||
|
|
||||||
# Swap files
|
# Swap files
|
||||||
*.swp
|
*.swp
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(def weak-k (table/new 10 :k))
|
(def weak-k (table/weak-keys 10))
|
||||||
(def weak-v (table/new 10 :v))
|
(def weak-v (table/weak-values 10))
|
||||||
(def weak-kv (table/new 10 :kv))
|
(def weak-kv (table/weak 10))
|
||||||
|
|
||||||
(put weak-kv (gensym) 10)
|
(put weak-kv (gensym) 10)
|
||||||
(put weak-kv :hello :world)
|
(put weak-kv :hello :world)
|
||||||
|
@ -30,9 +30,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* Creates a new array */
|
static void janet_array_impl(JanetArray *array, int32_t capacity) {
|
||||||
JanetArray *janet_array(int32_t capacity) {
|
|
||||||
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
|
|
||||||
Janet *data = NULL;
|
Janet *data = NULL;
|
||||||
if (capacity > 0) {
|
if (capacity > 0) {
|
||||||
janet_vm.next_collection += capacity * sizeof(Janet);
|
janet_vm.next_collection += capacity * sizeof(Janet);
|
||||||
@ -44,6 +42,19 @@ JanetArray *janet_array(int32_t capacity) {
|
|||||||
array->count = 0;
|
array->count = 0;
|
||||||
array->capacity = capacity;
|
array->capacity = capacity;
|
||||||
array->data = data;
|
array->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates a new array */
|
||||||
|
JanetArray *janet_array(int32_t capacity) {
|
||||||
|
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
|
||||||
|
janet_array_impl(array, capacity);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates a new array with weak references */
|
||||||
|
JanetArray *janet_array_weak(int32_t capacity) {
|
||||||
|
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY_WEAK, sizeof(JanetArray));
|
||||||
|
janet_array_impl(array, capacity);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +143,15 @@ JANET_CORE_FN(cfun_array_new,
|
|||||||
return janet_wrap_array(array);
|
return janet_wrap_array(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JANET_CORE_FN(cfun_array_weak,
|
||||||
|
"(array/weak capacity)",
|
||||||
|
"Creates a new empty array with a pre-allocated capacity and support for weak references. Similar to `array/new`.") {
|
||||||
|
janet_fixarity(argc, 1);
|
||||||
|
int32_t cap = janet_getinteger(argv, 0);
|
||||||
|
JanetArray *array = janet_array_weak(cap);
|
||||||
|
return janet_wrap_array(array);
|
||||||
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_array_new_filled,
|
JANET_CORE_FN(cfun_array_new_filled,
|
||||||
"(array/new-filled count &opt value)",
|
"(array/new-filled count &opt value)",
|
||||||
"Creates a new array of `count` elements, all set to `value`, which defaults to nil. Returns the new array.") {
|
"Creates a new array of `count` elements, all set to `value`, which defaults to nil. Returns the new array.") {
|
||||||
@ -352,6 +372,7 @@ JANET_CORE_FN(cfun_array_clear,
|
|||||||
void janet_lib_array(JanetTable *env) {
|
void janet_lib_array(JanetTable *env) {
|
||||||
JanetRegExt array_cfuns[] = {
|
JanetRegExt array_cfuns[] = {
|
||||||
JANET_CORE_REG("array/new", cfun_array_new),
|
JANET_CORE_REG("array/new", cfun_array_new),
|
||||||
|
JANET_CORE_REG("array/weak", cfun_array_weak),
|
||||||
JANET_CORE_REG("array/new-filled", cfun_array_new_filled),
|
JANET_CORE_REG("array/new-filled", cfun_array_new_filled),
|
||||||
JANET_CORE_REG("array/fill", cfun_array_fill),
|
JANET_CORE_REG("array/fill", cfun_array_fill),
|
||||||
JANET_CORE_REG("array/pop", cfun_array_pop),
|
JANET_CORE_REG("array/pop", cfun_array_pop),
|
||||||
|
@ -164,7 +164,9 @@ static void janet_mark_array(JanetArray *array) {
|
|||||||
if (janet_gc_reachable(array))
|
if (janet_gc_reachable(array))
|
||||||
return;
|
return;
|
||||||
janet_gc_mark(array);
|
janet_gc_mark(array);
|
||||||
janet_mark_many(array->data, array->count);
|
if (janet_gc_type((JanetGCObject *) array) == JANET_MEMORY_ARRAY) {
|
||||||
|
janet_mark_many(array->data, array->count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void janet_mark_table(JanetTable *table) {
|
static void janet_mark_table(JanetTable *table) {
|
||||||
@ -392,23 +394,32 @@ void janet_sweep() {
|
|||||||
if (current->flags & (JANET_MEM_REACHABLE | JANET_MEM_DISABLED)) {
|
if (current->flags & (JANET_MEM_REACHABLE | JANET_MEM_DISABLED)) {
|
||||||
/* Check for dead references */
|
/* Check for dead references */
|
||||||
enum JanetMemoryType type = janet_gc_type(current);
|
enum JanetMemoryType type = janet_gc_type(current);
|
||||||
JanetTable *table = (JanetTable *) current;
|
if (type == JANET_MEMORY_ARRAY_WEAK) {
|
||||||
int check_values = (type == JANET_MEMORY_TABLE_WEAKV) || (type == JANET_MEMORY_TABLE_WEAKKV);
|
JanetArray *array = (JanetArray *) current;
|
||||||
int check_keys = (type == JANET_MEMORY_TABLE_WEAKK) || (type == JANET_MEMORY_TABLE_WEAKKV);
|
for (uint32_t i = 0; i < (uint32_t) array->count; i++) {
|
||||||
JanetKV *end = table->data + table->capacity;
|
if (!janet_check_liveref(array->data[i])) {
|
||||||
JanetKV *kvs = table->data;
|
array->data[i] = janet_wrap_nil();
|
||||||
while (kvs < end) {
|
}
|
||||||
int drop = 0;
|
}
|
||||||
if (check_keys && !janet_check_liveref(kvs->key)) drop = 1;
|
} else {
|
||||||
if (check_values && !janet_check_liveref(kvs->value)) drop = 1;
|
JanetTable *table = (JanetTable *) current;
|
||||||
if (drop) {
|
int check_values = (type == JANET_MEMORY_TABLE_WEAKV) || (type == JANET_MEMORY_TABLE_WEAKKV);
|
||||||
/* Inlined from janet_table_remove without search */
|
int check_keys = (type == JANET_MEMORY_TABLE_WEAKK) || (type == JANET_MEMORY_TABLE_WEAKKV);
|
||||||
table->count--;
|
JanetKV *end = table->data + table->capacity;
|
||||||
table->deleted++;
|
JanetKV *kvs = table->data;
|
||||||
kvs->key = janet_wrap_nil();
|
while (kvs < end) {
|
||||||
kvs->value = janet_wrap_false();
|
int drop = 0;
|
||||||
|
if (check_keys && !janet_check_liveref(kvs->key)) drop = 1;
|
||||||
|
if (check_values && !janet_check_liveref(kvs->value)) drop = 1;
|
||||||
|
if (drop) {
|
||||||
|
/* Inlined from janet_table_remove without search */
|
||||||
|
table->count--;
|
||||||
|
table->deleted++;
|
||||||
|
kvs->key = janet_wrap_nil();
|
||||||
|
kvs->value = janet_wrap_false();
|
||||||
|
}
|
||||||
|
kvs++;
|
||||||
}
|
}
|
||||||
kvs++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current = next;
|
current = next;
|
||||||
|
@ -59,7 +59,8 @@ enum JanetMemoryType {
|
|||||||
JANET_MEMORY_THREADED_ABSTRACT,
|
JANET_MEMORY_THREADED_ABSTRACT,
|
||||||
JANET_MEMORY_TABLE_WEAKK,
|
JANET_MEMORY_TABLE_WEAKK,
|
||||||
JANET_MEMORY_TABLE_WEAKV,
|
JANET_MEMORY_TABLE_WEAKV,
|
||||||
JANET_MEMORY_TABLE_WEAKKV
|
JANET_MEMORY_TABLE_WEAKKV,
|
||||||
|
JANET_MEMORY_ARRAY_WEAK
|
||||||
};
|
};
|
||||||
|
|
||||||
/* To allocate collectable memory, one must call janet_alloc, initialize the memory,
|
/* To allocate collectable memory, one must call janet_alloc, initialize the memory,
|
||||||
|
@ -309,23 +309,49 @@ JanetTable *janet_table_proto_flatten(JanetTable *t) {
|
|||||||
/* C Functions */
|
/* C Functions */
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_table_new,
|
JANET_CORE_FN(cfun_table_new,
|
||||||
"(table/new capacity &opt weak)",
|
"(table/new capacity)",
|
||||||
"Creates a new empty table with pre-allocated memory "
|
"Creates a new empty table with pre-allocated memory "
|
||||||
"for `capacity` entries. This means that if one knows the number of "
|
"for `capacity` entries. This means that if one knows the number of "
|
||||||
"entries going into a table on creation, extra memory allocation "
|
"entries going into a table on creation, extra memory allocation "
|
||||||
"can be avoided. Optionally provide a keyword flags `:kv` to create a table with "
|
"can be avoided. "
|
||||||
"weak referenecs to keys, values, or both. "
|
|
||||||
"Returns the new table.") {
|
"Returns the new table.") {
|
||||||
janet_arity(argc, 1, 2);
|
janet_fixarity(argc, 1);
|
||||||
int32_t cap = janet_getnat(argv, 0);
|
int32_t cap = janet_getnat(argv, 0);
|
||||||
if (argc == 1) {
|
return janet_wrap_table(janet_table(cap));
|
||||||
return janet_wrap_table(janet_table(cap));
|
}
|
||||||
}
|
/*
|
||||||
uint32_t flags = janet_getflags(argv, 1, "kv");
|
uint32_t flags = janet_getflags(argv, 1, "kv");
|
||||||
if (flags == 0) return janet_wrap_table(janet_table(cap));
|
if (flags == 0) return janet_wrap_table(janet_table(cap));
|
||||||
if (flags == 1) return janet_wrap_table(janet_table_weakk(cap));
|
if (flags == 1) return janet_wrap_table(janet_table_weakk(cap));
|
||||||
if (flags == 2) return janet_wrap_table(janet_table_weakv(cap));
|
if (flags == 2) return janet_wrap_table(janet_table_weakv(cap));
|
||||||
return janet_wrap_table(janet_table_weakkv(cap));
|
return janet_wrap_table(janet_table_weakkv(cap));
|
||||||
|
*/
|
||||||
|
|
||||||
|
JANET_CORE_FN(cfun_table_weak,
|
||||||
|
"(table/weak capacity)",
|
||||||
|
"Creates a new empty table with weak references to keys and values. Similar to `table/new`. "
|
||||||
|
"Returns the new table.") {
|
||||||
|
janet_fixarity(argc, 1);
|
||||||
|
int32_t cap = janet_getnat(argv, 0);
|
||||||
|
return janet_wrap_table(janet_table_weakkv(cap));
|
||||||
|
}
|
||||||
|
|
||||||
|
JANET_CORE_FN(cfun_table_weak_keys,
|
||||||
|
"(table/weak-keys capacity)",
|
||||||
|
"Creates a new empty table with weak references to keys and normal references to values. Similar to `table/new`. "
|
||||||
|
"Returns the new table.") {
|
||||||
|
janet_fixarity(argc, 1);
|
||||||
|
int32_t cap = janet_getnat(argv, 0);
|
||||||
|
return janet_wrap_table(janet_table_weakk(cap));
|
||||||
|
}
|
||||||
|
|
||||||
|
JANET_CORE_FN(cfun_table_weak_values,
|
||||||
|
"(table/weak-values capacity)",
|
||||||
|
"Creates a new empty table with normal references to keys and weak references to values. Similar to `table/new`. "
|
||||||
|
"Returns the new table.") {
|
||||||
|
janet_fixarity(argc, 1);
|
||||||
|
int32_t cap = janet_getnat(argv, 0);
|
||||||
|
return janet_wrap_table(janet_table_weakv(cap));
|
||||||
}
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_table_getproto,
|
JANET_CORE_FN(cfun_table_getproto,
|
||||||
@ -401,6 +427,9 @@ JANET_CORE_FN(cfun_table_proto_flatten,
|
|||||||
void janet_lib_table(JanetTable *env) {
|
void janet_lib_table(JanetTable *env) {
|
||||||
JanetRegExt table_cfuns[] = {
|
JanetRegExt table_cfuns[] = {
|
||||||
JANET_CORE_REG("table/new", cfun_table_new),
|
JANET_CORE_REG("table/new", cfun_table_new),
|
||||||
|
JANET_CORE_REG("table/weak", cfun_table_weak),
|
||||||
|
JANET_CORE_REG("table/weak-keys", cfun_table_weak_keys),
|
||||||
|
JANET_CORE_REG("table/weak-values", cfun_table_weak_values),
|
||||||
JANET_CORE_REG("table/to-struct", cfun_table_tostruct),
|
JANET_CORE_REG("table/to-struct", cfun_table_tostruct),
|
||||||
JANET_CORE_REG("table/getproto", cfun_table_getproto),
|
JANET_CORE_REG("table/getproto", cfun_table_getproto),
|
||||||
JANET_CORE_REG("table/setproto", cfun_table_setproto),
|
JANET_CORE_REG("table/setproto", cfun_table_setproto),
|
||||||
|
@ -1590,6 +1590,7 @@ JANET_API double janet_rng_double(JanetRNG *rng);
|
|||||||
|
|
||||||
/* Array functions */
|
/* Array functions */
|
||||||
JANET_API JanetArray *janet_array(int32_t capacity);
|
JANET_API JanetArray *janet_array(int32_t capacity);
|
||||||
|
JANET_API JanetArray *janet_array_weak(int32_t capacity);
|
||||||
JANET_API JanetArray *janet_array_n(const Janet *elements, int32_t n);
|
JANET_API JanetArray *janet_array_n(const Janet *elements, int32_t n);
|
||||||
JANET_API void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth);
|
JANET_API void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth);
|
||||||
JANET_API void janet_array_setcount(JanetArray *array, int32_t count);
|
JANET_API void janet_array_setcount(JanetArray *array, int32_t count);
|
||||||
|
Loading…
Reference in New Issue
Block a user