Intermediate commit before visitor refactor.

This commit is contained in:
Danila Fedorin 2018-08-11 18:22:18 -07:00
parent 80e7c95915
commit f4ecb82c46
10 changed files with 172 additions and 91 deletions

View File

@ -1,8 +1,8 @@
#ifndef LIBABACUS_GC_H #ifndef LIBABACUS_GC_H
#define LIBABACUS_GC_H #define LIBABACUS_GC_H
struct libab_ref_s; #include "refcount.h"
struct libab_ref_count_s; #include "gc_functions.h"
/** /**
* Struct used to create an interface * Struct used to create an interface
@ -10,18 +10,16 @@ struct libab_ref_count_s;
*/ */
struct libab_gc_list_s { struct libab_gc_list_s {
/** /**
* The head of the linked list. * The head sentinel node.
*/ */
struct libab_ref_count_s* head; struct libab_ref_count_s head_sentinel;
/** /**
* The tail of the linked list. * The tail sentinel node.
*/ */
struct libab_ref_count_s* tail; struct libab_ref_count_s tail_sentinel;
}; };
typedef struct libab_gc_list_s libab_gc_list; typedef struct libab_gc_list_s libab_gc_list;
typedef void (*libab_visitor_function_ptr)(struct libab_ref_count_s* , void*);
typedef void (*libab_visit_function_ptr)(void*, libab_visitor_function_ptr, void*);
/** /**
* Initializes a garbage collection tracking list. * Initializes a garbage collection tracking list.
@ -34,7 +32,7 @@ void libab_gc_list_init(libab_gc_list* list);
* @param visitor the function to call for each child. * @param visitor the function to call for each child.
* @param data the data to pass to the visitor. * @param data the data to pass to the visitor.
*/ */
void libab_gc_visit_chilren(struct libab_ref_s* ref, libab_visitor_function_ptr visitor, void* data); void libab_gc_visit_children(struct libab_ref_s* ref, libab_visitor_function_ptr visitor, void* data);
/** /**
* Adds the given reference to the given garbage collection list, * Adds the given reference to the given garbage collection list,
* and specifies a function used to reach its children. * and specifies a function used to reach its children.

10
include/gc_functions.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LIBABACUS_GC_FUNCTIONS_H
#define LIBABACUS_GC_FUNCTIONS_H
struct libab_ref_count_s;
struct libab_ref_s;
typedef void (*libab_visitor_function_ptr)(struct libab_ref_count_s* , void*);
typedef void (*libab_visit_function_ptr)(void*, libab_visitor_function_ptr, void*);
#endif

View File

@ -9,6 +9,7 @@
#include "parser.h" #include "parser.h"
#include "result.h" #include "result.h"
#include "table.h" #include "table.h"
#include "gc.h"
/** /**
* The main struct of libabacus, * The main struct of libabacus,
@ -59,6 +60,12 @@ struct libab_s {
* The unit type instance. * The unit type instance.
*/ */
libab_ref type_unit; libab_ref type_unit;
/**
* List of containers references
* that should be tracked by the
* garbage collector for cycles.
*/
libab_gc_list containers;
/** /**
* Internal; the number basetype. This cannot be a static * Internal; the number basetype. This cannot be a static

View File

@ -2,7 +2,7 @@
#define LIBABACUS_REFCOUNT_H #define LIBABACUS_REFCOUNT_H
#include "result.h" #include "result.h"
#include "gc.h" #include "gc_functions.h"
/** /**
* A struct for holding * A struct for holding

View File

@ -7,6 +7,7 @@
#include "parsetype.h" #include "parsetype.h"
#include "result.h" #include "result.h"
#include "table.h" #include "table.h"
#include "libabacus.h"
#include <string.h> #include <string.h>
/** /**
@ -78,11 +79,12 @@ libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
libab_ref* into, size_t n, ...); libab_ref* into, size_t n, ...);
/** /**
* Creates a new libab_table, and stores it into the given reference. * Creates a new libab_table, and stores it into the given reference.
* @param ab the libabacus instance in which the table is being created.
* @param into the reference to store the table into. * @param into the reference to store the table into.
* @param parent the parent reference to store. * @param parent the parent reference to store.
* @return the result of the instantiation. * @return the result of the instantiation.
*/ */
libab_result libab_create_table(libab_ref* into, libab_ref* parent); libab_result libab_create_table(libab* ab, libab_ref* into, libab_ref* parent);
/** /**
* Allocates a new reference counted value with the given type and data. * Allocates a new reference counted value with the given type and data.
* @param into the reference to store the allocated data into. * @param into the reference to store the allocated data into.
@ -90,8 +92,8 @@ libab_result libab_create_table(libab_ref* into, libab_ref* parent);
* @param type the type to give the value. * @param type the type to give the value.
* @return the result of necessary allocations. * @return the result of necessary allocations.
*/ */
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data, libab_result libab_create_value_ref(libab* ab, libab_ref* into,
libab_ref* type); libab_ref* data, libab_ref* type);
/** /**
* Allocates a new reference counted value with the given type and data. * Allocates a new reference counted value with the given type and data.
* @param into the reference to store the allocated data into. * @param into the reference to store the allocated data into.
@ -99,8 +101,8 @@ libab_result libab_create_value_ref(libab_ref* into, libab_ref* data,
* @param type the type to give the value. * @param type the type to give the value.
* @return the result of necessary allocations. * @return the result of necessary allocations.
*/ */
libab_result libab_create_value_raw(libab_ref* into, void* data, libab_result libab_create_value_raw(libab* ab, libab_ref* into,
libab_ref* type); void* data, libab_ref* type);
/** /**
* Allocates a function that uses internal code to run. * Allocates a function that uses internal code to run.
* @param into the reference into which to store the new function. * @param into the reference into which to store the new function.
@ -109,7 +111,7 @@ libab_result libab_create_value_raw(libab_ref* into, void* data,
* @param scope the scope in which this function was declared. * @param scope the scope in which this function was declared.
* @return libab_result the result of any necessary allocations. * @return libab_result the result of any necessary allocations.
*/ */
libab_result libab_create_function_internal(libab_ref* into, libab_result libab_create_function_internal(libab* ab, libab_ref* into,
void (*free_function)(void*), void (*free_function)(void*),
libab_function_ptr fun, libab_function_ptr fun,
libab_ref* scope); libab_ref* scope);
@ -121,7 +123,7 @@ libab_result libab_create_function_internal(libab_ref* into,
* @param scope the scope in which this function was declared. * @param scope the scope in which this function was declared.
* @return libab_result the result of any necessary allocations. * @return libab_result the result of any necessary allocations.
*/ */
libab_result libab_create_function_tree(libab_ref* into, libab_result libab_create_function_tree(libab* ab, libab_ref* into,
void (*free_function)(void*), void (*free_function)(void*),
libab_tree* tree, libab_tree* tree,
libab_ref* scope); libab_ref* scope);
@ -133,7 +135,7 @@ libab_result libab_create_function_tree(libab_ref* into,
* @param scope the scope in which this function was declared. * @param scope the scope in which this function was declared.
* @return libab_result the result of any necessary allocations. * @return libab_result the result of any necessary allocations.
*/ */
libab_result libab_create_function_behavior(libab_ref* into, libab_result libab_create_function_behavior(libab* ab, libab_ref* into,
void (*free_function)(void*), void (*free_function)(void*),
libab_behavior* behavior, libab_behavior* behavior,
libab_ref* scope); libab_ref* scope);
@ -143,7 +145,7 @@ libab_result libab_create_function_behavior(libab_ref* into,
* @param the function_list type. * @param the function_list type.
* @return the result of the allocations. * @return the result of the allocations.
*/ */
libab_result libab_create_function_list(libab_ref* into, libab_ref* type); libab_result libab_create_function_list(libab* ab, libab_ref* into, libab_ref* type);
/** /**
* Creates a new table entry that holds the given value. * Creates a new table entry that holds the given value.
* @param table the table to store the entry into. * @param table the table to store the entry into.

View File

@ -1,31 +1,32 @@
#include "gc.h" #include "gc.h"
#include "refcount.h" #include "refcount.h"
#include <stdlib.h> #include <stdlib.h>
#include <memory.h>
void libab_gc_list_init(libab_gc_list* list) { void libab_gc_list_init(libab_gc_list* list) {
list->head = list->tail = NULL; memset(&list->head_sentinel, 0, sizeof(list->head_sentinel));
memset(&list->tail_sentinel, 0, sizeof(list->tail_sentinel));
list->head_sentinel.next = &list->tail_sentinel;
list->tail_sentinel.prev = &list->head_sentinel;
} }
void _gc_count_visit_children(libab_ref_count* ref, libab_visitor_function_ptr func, void* data) { void _gc_count_visit_children(libab_ref_count* ref, libab_visitor_function_ptr func, void* data) {
if(ref->strong && ref->visit_children) ref->visit_children(ref->data, func, data); if(ref->strong && ref->visit_children) ref->visit_children(ref->data, func, data);
} }
void libab_gc_visit_children(libab_ref* ref, libab_visitor_function_ptr func, void* data) { void libab_gc_visit_children(libab_ref* ref, libab_visitor_function_ptr func, void* data) {
_gc_count_visit_children(ref->count, func, data); if(!ref->null) _gc_count_visit_children(ref->count, func, data);
} }
void _libab_gc_list_append(libab_gc_list* list, void _libab_gc_list_append(libab_gc_list* list,
libab_ref_count* node) { libab_ref_count* node) {
libab_ref_count* before;
if(node->next) node->next->prev = node->prev; if(node->next) node->next->prev = node->prev;
if(node->prev) node->prev->next = node->next; if(node->prev) node->prev->next = node->next;
before = &list->tail_sentinel;
node->prev = list->tail; node->next = before;
node->next = NULL; node->prev = before->prev;
if(list->head) { before->prev->next = node;
list->tail->next = node; before->prev = node;
} else {
list->head = node;
}
list->tail = node;
} }
void libab_gc_add(libab_ref* ref, void libab_gc_add(libab_ref* ref,
libab_visit_function_ptr visit_children, libab_visit_function_ptr visit_children,
@ -35,7 +36,7 @@ void libab_gc_add(libab_ref* ref,
} }
void _gc_decrement(libab_ref_count* count, void* data) { void _gc_decrement(libab_ref_count* count, void* data) {
if(count->visit_children) count->gc--; count->gc--;
} }
void _gc_save(libab_ref_count* count, void* data) { void _gc_save(libab_ref_count* count, void* data) {
libab_gc_list* list = data; libab_gc_list* list = data;
@ -51,27 +52,30 @@ void libab_gc_run(libab_gc_list* list) {
libab_ref_count* head; libab_ref_count* head;
size_t count = 0; size_t count = 0;
head = list->head; #define ITERATE(CODE) head = list->head_sentinel.next; \
while(head) { while(head != &list->tail_sentinel) { \
head->gc = head->weak; CODE;\
head = head->next; \
} }
head = list->head; libab_gc_list_init(&safe);
while(head) { ITERATE(head->gc = head->weak);
_gc_count_visit_children(head, _gc_decrement, NULL); ITERATE(_gc_count_visit_children(head, _gc_decrement, NULL));
} ITERATE(printf("%d outside references\n", head->gc));
ITERATE(_gc_count_visit_children(head, _gc_save, &safe));
ITERATE(count++);
head = list->head;
while(head) {
_gc_count_visit_children(head, _gc_save, &safe);
}
head = list->head;
while(head) {
count++;
}
printf("Can free %d\n", count); printf("Can free %d\n", count);
list->head = safe.head; if(safe.head_sentinel.next != &safe.tail_sentinel) {
list->tail = safe.tail; printf("Safe isn't empty!\n");
list->head_sentinel.next = safe.head_sentinel.next;
list->head_sentinel.next->prev = &list->head_sentinel;
list->tail_sentinel.prev = safe.tail_sentinel.prev;
list->tail_sentinel.prev->next = &list->tail_sentinel;
} else {
printf("Safe is empty!\n");
list->head_sentinel.next = &list->tail_sentinel;
list->tail_sentinel.prev = &list->head_sentinel;
}
} }

View File

@ -30,7 +30,7 @@ libab_result create_double_value(libab* ab, double val, libab_ref* into) {
double* new_double = malloc(sizeof(*new_double)); double* new_double = malloc(sizeof(*new_double));
if(new_double) { if(new_double) {
*new_double = val; *new_double = val;
result = libab_create_value_raw(into, new_double, &type_num); result = libab_create_value_raw(ab, into, new_double, &type_num);
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
free(new_double); free(new_double);
} }
@ -216,6 +216,7 @@ libab_result loop(libab* ab, int interaction_count, libab_ref* scope) {
int main() { int main() {
libab_result result; libab_result result;
libab_ref scope; libab_ref scope;
libab_ref test;
libab ab; libab ab;
if (libab_init(&ab, impl_parse, impl_free) != LIBAB_SUCCESS) { if (libab_init(&ab, impl_parse, impl_free) != LIBAB_SUCCESS) {
@ -225,10 +226,12 @@ int main() {
result = register_functions(&ab); result = register_functions(&ab);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
result = libab_create_table(&scope, &ab.table); result = libab_create_table(&ab, &scope, &ab.table);
} }
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
loop(&ab, INTERACTIONS, &scope); loop(&ab, INTERACTIONS, &scope);
libab_table_search_value(libab_ref_get(&scope), "test", &test);
printf("%p\n", libab_ref_get(&test));
libab_ref_free(&scope); libab_ref_free(&scope);
} }

View File

@ -13,7 +13,7 @@ libab_result _create_bool_value(libab* ab, int val, libab_ref* into) {
new_bool = malloc(sizeof(*new_bool)); new_bool = malloc(sizeof(*new_bool));
if(new_bool) { if(new_bool) {
*new_bool = val; *new_bool = val;
result = libab_create_value_raw(into, new_bool, &type_bool); result = libab_create_value_raw(ab, into, new_bool, &type_bool);
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
free(new_bool); free(new_bool);
} }
@ -33,7 +33,7 @@ libab_result libab_interpreter_init(libab_interpreter* intr, libab* ab) {
libab_ref_null(&intr->value_false); libab_ref_null(&intr->value_false);
libab_ref_null(&unit_data); libab_ref_null(&unit_data);
result = libab_create_value_ref(&intr->value_unit, &unit_data, &ab->type_unit); result = libab_create_value_ref(ab, &intr->value_unit, &unit_data, &ab->type_unit);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(&intr->value_true); libab_ref_free(&intr->value_true);
result = _create_bool_value(ab, 1, &intr->value_true); result = _create_bool_value(ab, 1, &intr->value_true);
@ -75,7 +75,7 @@ libab_result _interpreter_create_num_val(struct interpreter_state* state,
if ((data = state->ab->impl.parse_num(from))) { if ((data = state->ab->impl.parse_num(from))) {
libab_ref_free(into); libab_ref_free(into);
result = libab_create_value_raw(into, data, &state->ab->type_num); result = libab_create_value_raw(state->ab, into, data, &state->ab->type_num);
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
((libab_parsetype*)libab_ref_get(&state->ab->type_num)) ((libab_parsetype*)libab_ref_get(&state->ab->type_num))
@ -466,13 +466,14 @@ libab_result _interpreter_find_match(libab_function_list* function_values,
* @param type the new type. * @param type the new type.
* @param into the reference into which to store the new value. * @param into the reference into which to store the new value.
*/ */
libab_result _interpreter_cast_param(libab_ref* param, libab_ref* type, libab_result _interpreter_cast_param(libab* ab, libab_ref* param,
libab_ref* type,
libab_ref_vec* into) { libab_ref_vec* into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
libab_value* old_value = libab_ref_get(param); libab_value* old_value = libab_ref_get(param);
libab_ref new_value; libab_ref new_value;
result = libab_create_value_ref(&new_value, &old_value->data, type); result = libab_create_value_ref(ab, &new_value, &old_value->data, type);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
result = libab_ref_vec_insert(into, &new_value); result = libab_ref_vec_insert(into, &new_value);
} }
@ -488,7 +489,8 @@ libab_result _interpreter_cast_param(libab_ref* param, libab_ref* type,
* @param into the pre-initialized vector to store the new values into. * @param into the pre-initialized vector to store the new values into.
* @return the result of any allocations. * @return the result of any allocations.
*/ */
libab_result _interpreter_cast_params(libab_ref_vec* params, libab_result _interpreter_cast_params(libab* ab,
libab_ref_vec* params,
libab_ref_vec* new_types, libab_ref_vec* new_types,
libab_ref_vec* into) { libab_ref_vec* into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
@ -500,7 +502,7 @@ libab_result _interpreter_cast_params(libab_ref_vec* params,
libab_ref_vec_index(params, index, &temp_param); libab_ref_vec_index(params, index, &temp_param);
libab_ref_vec_index(new_types, index, &temp_type); libab_ref_vec_index(new_types, index, &temp_type);
result = _interpreter_cast_param(&temp_param, &temp_type, into); result = _interpreter_cast_param(ab, &temp_param, &temp_type, into);
libab_ref_free(&temp_param); libab_ref_free(&temp_param);
libab_ref_free(&temp_type); libab_ref_free(&temp_type);
@ -531,7 +533,7 @@ libab_result _interpreter_call_tree(struct interpreter_state* state,
libab_ref param; libab_ref param;
libab_table* new_scope_raw; libab_table* new_scope_raw;
size_t i; size_t i;
libab_result result = libab_create_table(&new_scope, scope); libab_result result = libab_create_table(state->ab, &new_scope, scope);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
new_scope_raw = libab_ref_get(&new_scope); new_scope_raw = libab_ref_get(&new_scope);
@ -581,22 +583,24 @@ libab_result _interpreter_call_behavior(struct interpreter_state* state,
* @param function the function to copy. * @param function the function to copy.
* @param into the reference to store the copy into. * @param into the reference to store the copy into.
*/ */
libab_result _interpreter_copy_function_basic(libab_ref* function, libab_result _interpreter_copy_function_basic(libab* ab,
libab_ref* function,
libab_ref* scope, libab_ref* scope,
libab_ref* into) { libab_ref* into) {
libab_function* func = libab_ref_get(function); libab_function* func = libab_ref_get(function);
void (*free_function)(void*) = function->count->free_func; void (*free_function)(void*) = function->count->free_func;
return libab_create_function_behavior(into, free_function, &func->behavior, scope); return libab_create_function_behavior(ab, into, free_function, &func->behavior, scope);
} }
libab_result _interpreter_copy_function_with_params(libab_ref* function, libab_result _interpreter_copy_function_with_params(libab* ab,
libab_ref* function,
libab_ref_vec* params, libab_ref_vec* params,
libab_ref* scope, libab_ref* scope,
libab_ref* into) { libab_ref* into) {
int index = 0; int index = 0;
libab_ref param; libab_ref param;
libab_function* func; libab_function* func;
libab_result result = _interpreter_copy_function_basic(function, scope, into); libab_result result = _interpreter_copy_function_basic(ab, function, scope, into);
func = libab_ref_get(into); func = libab_ref_get(into);
for(; index < params->size && result == LIBAB_SUCCESS; index++) { for(; index < params->size && result == LIBAB_SUCCESS; index++) {
@ -669,14 +673,14 @@ libab_result _interpreter_partially_apply(struct interpreter_state* state,
value = libab_ref_get(function); value = libab_ref_get(function);
libab_ref_null(&new_type); libab_ref_null(&new_type);
result = _interpreter_copy_function_with_params(&value->data, params, scope, &new_function); result = _interpreter_copy_function_with_params(state->ab, &value->data, params, scope, &new_function);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(&new_type); libab_ref_free(&new_type);
result = _interpreter_copy_type_offset(&value->type, 0, &new_type); result = _interpreter_copy_type_offset(&value->type, 0, &new_type);
} }
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
result = libab_create_value_ref(into, &new_function, &new_type); result = libab_create_value_ref(state->ab, into, &new_function, &new_type);
} else { } else {
libab_ref_null(into); libab_ref_null(into);
} }
@ -711,10 +715,11 @@ libab_result _interpreter_foreach_insert_param(const libab_ref* param,
return result; return result;
} }
libab_result _interpreter_create_scope(libab_ref* into, libab_result _interpreter_create_scope(libab* ab,
libab_ref* into,
libab_ref* parent_scope, libab_ref* parent_scope,
libab_ref_trie* param_map) { libab_ref_trie* param_map) {
libab_result result = libab_create_table(into, parent_scope); libab_result result = libab_create_table(ab, into, parent_scope);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
result = libab_ref_trie_foreach(param_map, _interpreter_foreach_insert_param, into); result = libab_ref_trie_foreach(param_map, _interpreter_foreach_insert_param, into);
@ -750,7 +755,7 @@ libab_result _interpreter_perform_function_call(struct interpreter_state* state,
function_type = libab_ref_get(&function_value->type); function_type = libab_ref_get(&function_value->type);
new_params = params->size - function->params.size; new_params = params->size - function->params.size;
result = _interpreter_create_scope(&new_scope, &function->scope, param_map); result = _interpreter_create_scope(state->ab, &new_scope, &function->scope, param_map);
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
@ -789,7 +794,7 @@ libab_result _interpreter_cast_and_perform_function_call(
function = libab_ref_get(&function_value->data); function = libab_ref_get(&function_value->data);
result = libab_ref_vec_init_copy(&new_params, &function->params); result = libab_ref_vec_init_copy(&new_params, &function->params);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
result = _interpreter_cast_params(params, new_types, &new_params); result = _interpreter_cast_params(state->ab, params, new_types, &new_params);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
result = _interpreter_perform_function_call(state, to_call, result = _interpreter_perform_function_call(state, to_call,
@ -1117,7 +1122,7 @@ libab_result _interpreter_create_function_value(
libab_ref_null(&type); libab_ref_null(&type);
libab_ref_null(into); libab_ref_null(into);
result = libab_create_function_tree(&function, libab_free_function, tree, scope); result = libab_create_function_tree(state->ab, &function, libab_free_function, tree, scope);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(&type); libab_ref_free(&type);
@ -1126,7 +1131,7 @@ libab_result _interpreter_create_function_value(
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(into); libab_ref_free(into);
result = libab_create_value_ref(into, &function, &type); result = libab_create_value_ref(state->ab, into, &function, &type);
} }
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
@ -1175,7 +1180,7 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
(mode == SCOPE_NORMAL && libab_tree_has_scope(tree->variant)); (mode == SCOPE_NORMAL && libab_tree_has_scope(tree->variant));
if (needs_scope) { if (needs_scope) {
result = libab_create_table(&new_scope, scope); result = libab_create_table(state->ab, &new_scope, scope);
scope = &new_scope; scope = &new_scope;
} }

View File

@ -27,6 +27,7 @@ libab_result libab_init(libab* ab, void* (*parse_function)(const char*),
int interpreter_initialized = 0; int interpreter_initialized = 0;
libab_ref null_ref; libab_ref null_ref;
libab_result result; libab_result result;
libab_gc_list_init(&ab->containers);
libab_ref_null(&null_ref); libab_ref_null(&null_ref);
libab_ref_null(&ab->type_num); libab_ref_null(&ab->type_num);
libab_ref_null(&ab->type_bool); libab_ref_null(&ab->type_bool);
@ -34,7 +35,7 @@ libab_result libab_init(libab* ab, void* (*parse_function)(const char*),
libab_ref_null(&ab->type_unit); libab_ref_null(&ab->type_unit);
ab->impl.parse_num = parse_function; ab->impl.parse_num = parse_function;
result = libab_create_table(&ab->table, &null_ref); result = libab_create_table(ab, &ab->table, &null_ref);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
libab_ref_free(&ab->type_num); libab_ref_free(&ab->type_num);
@ -144,28 +145,29 @@ libab_result libab_register_operator_postfix(libab* ab, const char* op,
return _register_operator(ab, op, OPERATOR_POSTFIX, 0, 0, function); return _register_operator(ab, op, OPERATOR_POSTFIX, 0, 0, function);
} }
libab_result _create_value_function_internal(libab_ref* into, libab_ref* type, libab_result _create_value_function_internal(libab* ab,
libab_ref* into, libab_ref* type,
libab_function_ptr func, libab_function_ptr func,
libab_ref* scope) { libab_ref* scope) {
libab_ref function_ref; libab_ref function_ref;
libab_result result = libab_result result =
libab_create_function_internal(&function_ref, libab_free_function, func, scope); libab_create_function_internal(ab, &function_ref, libab_free_function, func, scope);
libab_ref_null(into); libab_ref_null(into);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
libab_ref_free(into); libab_ref_free(into);
result = libab_create_value_ref(into, &function_ref, type); result = libab_create_value_ref(ab, into, &function_ref, type);
} }
libab_ref_free(&function_ref); libab_ref_free(&function_ref);
return result; return result;
} }
libab_result _create_value_function_list(libab_ref* into, libab_ref* type) { libab_result _create_value_function_list(libab* ab, libab_ref* into, libab_ref* type) {
libab_ref list_ref; libab_ref list_ref;
libab_result result = libab_create_function_list(&list_ref, type); libab_result result = libab_create_function_list(ab, &list_ref, type);
libab_ref_null(into); libab_ref_null(into);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
libab_ref_free(into); libab_ref_free(into);
result = libab_create_value_ref(into, &list_ref, type); result = libab_create_value_ref(ab, into, &list_ref, type);
} }
libab_ref_free(&list_ref); libab_ref_free(&list_ref);
return result; return result;
@ -187,7 +189,7 @@ libab_result _libab_register_function_existing(libab* ab,
} else if (old_type->data_u.base == &_basetype_function) { } else if (old_type->data_u.base == &_basetype_function) {
libab_ref new_list; libab_ref new_list;
result = result =
_create_value_function_list(&new_list, &ab->type_function_list); _create_value_function_list(ab, &new_list, &ab->type_function_list);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
libab_function_list* list = libab_function_list* list =
libab_ref_get(&((libab_value*)libab_ref_get(&new_list))->data); libab_ref_get(&((libab_value*)libab_ref_get(&new_list))->data);
@ -232,7 +234,7 @@ libab_result libab_register_function(libab* ab, const char* name,
libab_table_entry* existing_entry; libab_table_entry* existing_entry;
libab_ref function_value; libab_ref function_value;
libab_result result = libab_result result =
_create_value_function_internal(&function_value, type, func, &ab->table); _create_value_function_internal(ab, &function_value, type, func, &ab->table);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
existing_entry = libab_table_search_filter( existing_entry = libab_table_search_filter(
@ -516,6 +518,7 @@ libab_result libab_run_tree_scoped(libab* ab, libab_tree* tree, libab_ref* scope
} }
libab_result libab_free(libab* ab) { libab_result libab_free(libab* ab) {
libab_result result = LIBAB_SUCCESS;
libab_table_free(libab_ref_get(&ab->table)); libab_table_free(libab_ref_get(&ab->table));
libab_ref_free(&ab->table); libab_ref_free(&ab->table);
libab_ref_free(&ab->type_num); libab_ref_free(&ab->type_num);
@ -524,5 +527,7 @@ libab_result libab_free(libab* ab) {
libab_ref_free(&ab->type_unit); libab_ref_free(&ab->type_unit);
libab_parser_free(&ab->parser); libab_parser_free(&ab->parser);
libab_interpreter_free(&ab->intr); libab_interpreter_free(&ab->intr);
return libab_lexer_free(&ab->lexer); result = libab_lexer_free(&ab->lexer);
libab_gc_run(&ab->containers);
return result;
} }

View File

@ -2,6 +2,7 @@
#include "value.h" #include "value.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "free_functions.h" #include "free_functions.h"
libab_result libab_convert_lex_result(liblex_result to_convert) { libab_result libab_convert_lex_result(liblex_result to_convert) {
@ -186,7 +187,29 @@ libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
return result; return result;
} }
libab_result libab_create_table(libab_ref* into, libab_ref* parent) { void _gc_visit_table_entry(libab_table_entry* entry, libab_visitor_function_ptr visitor, void* data) {
if (entry->variant == ENTRY_VALUE) {
libab_gc_visit_children(&entry->data_u.value, visitor, data);
}
}
void _gc_visit_table_trie(libab_trie_node* parent, libab_visitor_function_ptr visitor, void* data) {
ll_node* head = parent->values.head;
if(parent == NULL) return;
_gc_visit_table_trie(parent->child, visitor, data);
_gc_visit_table_trie(parent->next, visitor, data);
while(head != NULL) {
_gc_visit_table_entry(head->data, visitor, data);
head = head->next;
}
}
void _gc_visit_table_children(void* parent, libab_visitor_function_ptr visitor, void* data) {
libab_table* table = parent;
libab_gc_visit_children(&table->parent, visitor, data);
}
libab_result libab_create_table(libab* ab, libab_ref* into, libab_ref* parent) {
libab_table* table; libab_table* table;
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
if ((table = malloc(sizeof(*table)))) { if ((table = malloc(sizeof(*table)))) {
@ -203,12 +226,19 @@ libab_result libab_create_table(libab_ref* into, libab_ref* parent) {
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
} else {
libab_gc_add(into, _gc_visit_table_children, &ab->containers);
} }
return result; return result;
} }
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data, void _gc_visit_value_children(void* val, libab_visitor_function_ptr visitor, void* data) {
libab_ref* type) { libab_value* value = val;
libab_gc_visit_children(&value->data, visitor, data);
}
libab_result libab_create_value_ref(libab* ab, libab_ref* into,
libab_ref* data, libab_ref* type) {
libab_value* value; libab_value* value;
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
if ((value = malloc(sizeof(*value)))) { if ((value = malloc(sizeof(*value)))) {
@ -224,12 +254,14 @@ libab_result libab_create_value_ref(libab_ref* into, libab_ref* data,
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
} else {
libab_gc_add(into, _gc_visit_value_children, &ab->containers);
} }
return result; return result;
} }
libab_result libab_create_value_raw(libab_ref* into, void* data, libab_result libab_create_value_raw(libab* ab, libab_ref* into,
libab_ref* type) { void* data, libab_ref* type) {
libab_value* value; libab_value* value;
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
@ -249,12 +281,19 @@ libab_result libab_create_value_raw(libab_ref* into, void* data,
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
free(value); free(value);
} else {
libab_gc_add(into, _gc_visit_value_children, &ab->containers);
} }
return result; return result;
} }
libab_result libab_create_function_internal(libab_ref* into, void _gc_visit_function_children(void* function, libab_visitor_function_ptr visitor, void* data) {
libab_function* func = function;
libab_gc_visit_children(&func->scope, visitor, data);
}
libab_result libab_create_function_internal(libab* ab, libab_ref* into,
void (*free_function)(void*), void (*free_function)(void*),
libab_function_ptr fun, libab_function_ptr fun,
libab_ref* scope) { libab_ref* scope) {
@ -277,12 +316,14 @@ libab_result libab_create_function_internal(libab_ref* into,
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
free(new_function); free(new_function);
} else {
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
} }
return result; return result;
} }
libab_result libab_create_function_tree(libab_ref* into, libab_result libab_create_function_tree(libab* ab, libab_ref* into,
void (*free_function)(void*), void (*free_function)(void*),
libab_tree* tree, libab_tree* tree,
libab_ref* scope) { libab_ref* scope) {
@ -305,12 +346,14 @@ libab_result libab_create_function_tree(libab_ref* into,
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
free(new_function); free(new_function);
} else {
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
} }
return result; return result;
} }
libab_result libab_create_function_behavior(libab_ref* into, libab_result libab_create_function_behavior(libab* ab, libab_ref* into,
void (*free_function)(void*), void (*free_function)(void*),
libab_behavior* behavior, libab_behavior* behavior,
libab_ref* scope) { libab_ref* scope) {
@ -333,12 +376,14 @@ libab_result libab_create_function_behavior(libab_ref* into,
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
free(new_function); free(new_function);
} else {
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
} }
return result; return result;
} }
libab_result libab_create_function_list(libab_ref* into, libab_ref* type) { libab_result libab_create_function_list(libab* ab, libab_ref* into, libab_ref* type) {
libab_function_list* list; libab_function_list* list;
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
@ -360,6 +405,8 @@ libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_null(into); libab_ref_null(into);
free(list); free(list);
} else {
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
} }
return result; return result;