Intermediate commit before visitor refactor.
This commit is contained in:
parent
80e7c95915
commit
f4ecb82c46
16
include/gc.h
16
include/gc.h
|
@ -1,8 +1,8 @@
|
|||
#ifndef LIBABACUS_GC_H
|
||||
#define LIBABACUS_GC_H
|
||||
|
||||
struct libab_ref_s;
|
||||
struct libab_ref_count_s;
|
||||
#include "refcount.h"
|
||||
#include "gc_functions.h"
|
||||
|
||||
/**
|
||||
* Struct used to create an interface
|
||||
|
@ -10,18 +10,16 @@ struct libab_ref_count_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 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.
|
||||
|
@ -34,7 +32,7 @@ void libab_gc_list_init(libab_gc_list* list);
|
|||
* @param visitor the function to call for each child.
|
||||
* @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,
|
||||
* and specifies a function used to reach its children.
|
||||
|
|
10
include/gc_functions.h
Normal file
10
include/gc_functions.h
Normal 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
|
|
@ -9,6 +9,7 @@
|
|||
#include "parser.h"
|
||||
#include "result.h"
|
||||
#include "table.h"
|
||||
#include "gc.h"
|
||||
|
||||
/**
|
||||
* The main struct of libabacus,
|
||||
|
@ -59,6 +60,12 @@ struct libab_s {
|
|||
* The unit type instance.
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define LIBABACUS_REFCOUNT_H
|
||||
|
||||
#include "result.h"
|
||||
#include "gc.h"
|
||||
#include "gc_functions.h"
|
||||
|
||||
/**
|
||||
* A struct for holding
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "parsetype.h"
|
||||
#include "result.h"
|
||||
#include "table.h"
|
||||
#include "libabacus.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
|
@ -78,11 +79,12 @@ libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
|
|||
libab_ref* into, size_t n, ...);
|
||||
/**
|
||||
* 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 parent the parent reference to store.
|
||||
* @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.
|
||||
* @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.
|
||||
* @return the result of necessary allocations.
|
||||
*/
|
||||
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data,
|
||||
libab_ref* type);
|
||||
libab_result libab_create_value_ref(libab* ab, libab_ref* into,
|
||||
libab_ref* data, libab_ref* type);
|
||||
/**
|
||||
* Allocates a new reference counted value with the given type and data.
|
||||
* @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.
|
||||
* @return the result of necessary allocations.
|
||||
*/
|
||||
libab_result libab_create_value_raw(libab_ref* into, void* data,
|
||||
libab_ref* type);
|
||||
libab_result libab_create_value_raw(libab* ab, libab_ref* into,
|
||||
void* data, libab_ref* type);
|
||||
/**
|
||||
* Allocates a function that uses internal code to run.
|
||||
* @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.
|
||||
* @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*),
|
||||
libab_function_ptr fun,
|
||||
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.
|
||||
* @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*),
|
||||
libab_tree* tree,
|
||||
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.
|
||||
* @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*),
|
||||
libab_behavior* behavior,
|
||||
libab_ref* scope);
|
||||
|
@ -143,7 +145,7 @@ libab_result libab_create_function_behavior(libab_ref* into,
|
|||
* @param the function_list type.
|
||||
* @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.
|
||||
* @param table the table to store the entry into.
|
||||
|
|
64
src/gc.c
64
src/gc.c
|
@ -1,31 +1,32 @@
|
|||
#include "gc.h"
|
||||
#include "refcount.h"
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
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) {
|
||||
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) {
|
||||
_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,
|
||||
libab_ref_count* node) {
|
||||
libab_ref_count* before;
|
||||
if(node->next) node->next->prev = node->prev;
|
||||
if(node->prev) node->prev->next = node->next;
|
||||
|
||||
node->prev = list->tail;
|
||||
node->next = NULL;
|
||||
if(list->head) {
|
||||
list->tail->next = node;
|
||||
} else {
|
||||
list->head = node;
|
||||
}
|
||||
list->tail = node;
|
||||
before = &list->tail_sentinel;
|
||||
node->next = before;
|
||||
node->prev = before->prev;
|
||||
before->prev->next = node;
|
||||
before->prev = node;
|
||||
}
|
||||
void libab_gc_add(libab_ref* ref,
|
||||
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) {
|
||||
if(count->visit_children) count->gc--;
|
||||
count->gc--;
|
||||
}
|
||||
void _gc_save(libab_ref_count* count, void* data) {
|
||||
libab_gc_list* list = data;
|
||||
|
@ -51,27 +52,30 @@ void libab_gc_run(libab_gc_list* list) {
|
|||
libab_ref_count* head;
|
||||
size_t count = 0;
|
||||
|
||||
head = list->head;
|
||||
while(head) {
|
||||
head->gc = head->weak;
|
||||
#define ITERATE(CODE) head = list->head_sentinel.next; \
|
||||
while(head != &list->tail_sentinel) { \
|
||||
CODE;\
|
||||
head = head->next; \
|
||||
}
|
||||
|
||||
head = list->head;
|
||||
while(head) {
|
||||
_gc_count_visit_children(head, _gc_decrement, NULL);
|
||||
}
|
||||
libab_gc_list_init(&safe);
|
||||
ITERATE(head->gc = head->weak);
|
||||
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);
|
||||
|
||||
list->head = safe.head;
|
||||
list->tail = safe.tail;
|
||||
if(safe.head_sentinel.next != &safe.tail_sentinel) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ libab_result create_double_value(libab* ab, double val, libab_ref* into) {
|
|||
double* new_double = malloc(sizeof(*new_double));
|
||||
if(new_double) {
|
||||
*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) {
|
||||
free(new_double);
|
||||
}
|
||||
|
@ -216,6 +216,7 @@ libab_result loop(libab* ab, int interaction_count, libab_ref* scope) {
|
|||
int main() {
|
||||
libab_result result;
|
||||
libab_ref scope;
|
||||
libab_ref test;
|
||||
libab ab;
|
||||
|
||||
if (libab_init(&ab, impl_parse, impl_free) != LIBAB_SUCCESS) {
|
||||
|
@ -225,10 +226,12 @@ int main() {
|
|||
|
||||
result = register_functions(&ab);
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
result = libab_create_table(&scope, &ab.table);
|
||||
result = libab_create_table(&ab, &scope, &ab.table);
|
||||
}
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ libab_result _create_bool_value(libab* ab, int val, libab_ref* into) {
|
|||
new_bool = malloc(sizeof(*new_bool));
|
||||
if(new_bool) {
|
||||
*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) {
|
||||
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(&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) {
|
||||
libab_ref_free(&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))) {
|
||||
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) {
|
||||
((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 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_result result = LIBAB_SUCCESS;
|
||||
libab_value* old_value = libab_ref_get(param);
|
||||
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) {
|
||||
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.
|
||||
* @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* into) {
|
||||
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(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_type);
|
||||
|
@ -531,7 +533,7 @@ libab_result _interpreter_call_tree(struct interpreter_state* state,
|
|||
libab_ref param;
|
||||
libab_table* new_scope_raw;
|
||||
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) {
|
||||
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 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* into) {
|
||||
libab_function* func = libab_ref_get(function);
|
||||
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* scope,
|
||||
libab_ref* into) {
|
||||
int index = 0;
|
||||
libab_ref param;
|
||||
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);
|
||||
|
||||
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);
|
||||
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) {
|
||||
libab_ref_free(&new_type);
|
||||
result = _interpreter_copy_type_offset(&value->type, 0, &new_type);
|
||||
}
|
||||
|
||||
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 {
|
||||
libab_ref_null(into);
|
||||
}
|
||||
|
@ -711,10 +715,11 @@ libab_result _interpreter_foreach_insert_param(const libab_ref* param,
|
|||
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_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) {
|
||||
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);
|
||||
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) {
|
||||
libab_ref_null(into);
|
||||
|
@ -789,7 +794,7 @@ libab_result _interpreter_cast_and_perform_function_call(
|
|||
function = libab_ref_get(&function_value->data);
|
||||
result = libab_ref_vec_init_copy(&new_params, &function->params);
|
||||
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) {
|
||||
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(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) {
|
||||
libab_ref_free(&type);
|
||||
|
@ -1126,7 +1131,7 @@ libab_result _interpreter_create_function_value(
|
|||
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
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) {
|
||||
|
@ -1175,7 +1180,7 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|||
(mode == SCOPE_NORMAL && libab_tree_has_scope(tree->variant));
|
||||
|
||||
if (needs_scope) {
|
||||
result = libab_create_table(&new_scope, scope);
|
||||
result = libab_create_table(state->ab, &new_scope, scope);
|
||||
scope = &new_scope;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ libab_result libab_init(libab* ab, void* (*parse_function)(const char*),
|
|||
int interpreter_initialized = 0;
|
||||
libab_ref null_ref;
|
||||
libab_result result;
|
||||
libab_gc_list_init(&ab->containers);
|
||||
libab_ref_null(&null_ref);
|
||||
libab_ref_null(&ab->type_num);
|
||||
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);
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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_ref* scope) {
|
||||
libab_ref function_ref;
|
||||
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);
|
||||
if (result == LIBAB_SUCCESS) {
|
||||
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);
|
||||
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_result result = libab_create_function_list(&list_ref, type);
|
||||
libab_result result = libab_create_function_list(ab, &list_ref, type);
|
||||
libab_ref_null(into);
|
||||
if (result == LIBAB_SUCCESS) {
|
||||
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);
|
||||
return result;
|
||||
|
@ -187,7 +189,7 @@ libab_result _libab_register_function_existing(libab* ab,
|
|||
} else if (old_type->data_u.base == &_basetype_function) {
|
||||
libab_ref new_list;
|
||||
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) {
|
||||
libab_function_list* list =
|
||||
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_ref function_value;
|
||||
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) {
|
||||
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 result = LIBAB_SUCCESS;
|
||||
libab_table_free(libab_ref_get(&ab->table));
|
||||
libab_ref_free(&ab->table);
|
||||
libab_ref_free(&ab->type_num);
|
||||
|
@ -524,5 +527,7 @@ libab_result libab_free(libab* ab) {
|
|||
libab_ref_free(&ab->type_unit);
|
||||
libab_parser_free(&ab->parser);
|
||||
libab_interpreter_free(&ab->intr);
|
||||
return libab_lexer_free(&ab->lexer);
|
||||
result = libab_lexer_free(&ab->lexer);
|
||||
libab_gc_run(&ab->containers);
|
||||
return result;
|
||||
}
|
||||
|
|
65
src/util.c
65
src/util.c
|
@ -2,6 +2,7 @@
|
|||
#include "value.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "free_functions.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_result result = LIBAB_SUCCESS;
|
||||
if ((table = malloc(sizeof(*table)))) {
|
||||
|
@ -203,12 +226,19 @@ libab_result libab_create_table(libab_ref* into, libab_ref* parent) {
|
|||
|
||||
if (result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_table_children, &ab->containers);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data,
|
||||
libab_ref* type) {
|
||||
void _gc_visit_value_children(void* val, libab_visitor_function_ptr visitor, void* data) {
|
||||
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_result result = LIBAB_SUCCESS;
|
||||
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) {
|
||||
libab_ref_null(into);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_value_children, &ab->containers);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
libab_result libab_create_value_raw(libab_ref* into, void* data,
|
||||
libab_ref* type) {
|
||||
libab_result libab_create_value_raw(libab* ab, libab_ref* into,
|
||||
void* data, libab_ref* type) {
|
||||
libab_value* value;
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
|
||||
|
@ -249,12 +281,19 @@ libab_result libab_create_value_raw(libab_ref* into, void* data,
|
|||
if (result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
free(value);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_value_children, &ab->containers);
|
||||
}
|
||||
|
||||
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*),
|
||||
libab_function_ptr fun,
|
||||
libab_ref* scope) {
|
||||
|
@ -277,12 +316,14 @@ libab_result libab_create_function_internal(libab_ref* into,
|
|||
if (result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
free(new_function);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
|
||||
}
|
||||
|
||||
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*),
|
||||
libab_tree* tree,
|
||||
libab_ref* scope) {
|
||||
|
@ -305,12 +346,14 @@ libab_result libab_create_function_tree(libab_ref* into,
|
|||
if (result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
free(new_function);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
|
||||
}
|
||||
|
||||
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*),
|
||||
libab_behavior* behavior,
|
||||
libab_ref* scope) {
|
||||
|
@ -333,12 +376,14 @@ libab_result libab_create_function_behavior(libab_ref* into,
|
|||
if(result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
free(new_function);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
|
||||
}
|
||||
|
||||
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_result result = LIBAB_SUCCESS;
|
||||
|
||||
|
@ -360,6 +405,8 @@ libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
|
|||
if (result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
free(list);
|
||||
} else {
|
||||
libab_gc_add(into, _gc_visit_function_children, &ab->containers);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue
Block a user