Switch values to having their data refcounted separately.
This allows for values to be "cast" and have a different type, while still referencing the same data.
This commit is contained in:
@@ -25,7 +25,7 @@ libab_result _interpreter_create_num_val(struct interpreter_state* state,
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
|
||||
if((data = state->ab->impl.parse_num(from))) {
|
||||
result = libab_create_value(into, data, &state->ab->type_num);
|
||||
result = libab_create_value_raw(into, data, &state->ab->type_num);
|
||||
|
||||
if(result != LIBAB_SUCCESS) {
|
||||
((libab_parsetype*) libab_ref_get(&state->ab->type_num))->data_u.base->free_function(data);
|
||||
|
||||
31
src/util.c
31
src/util.c
@@ -155,11 +155,11 @@ void _free_value(void* value) {
|
||||
free(value);
|
||||
}
|
||||
|
||||
libab_result libab_create_value(libab_ref* into, void* data, libab_ref* type) {
|
||||
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data, libab_ref* type) {
|
||||
libab_value* value;
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
if((value = malloc(sizeof(*value)))) {
|
||||
libab_value_init(value, data, type);
|
||||
libab_value_init_ref(value, data, type);
|
||||
result = libab_ref_new(into, value, _free_value);
|
||||
|
||||
if(result != LIBAB_SUCCESS) {
|
||||
@@ -175,6 +175,31 @@ libab_result libab_create_value(libab_ref* into, void* data, libab_ref* type) {
|
||||
return result;
|
||||
}
|
||||
|
||||
libab_result libab_create_value_raw(libab_ref* into, void* data, libab_ref* type) {
|
||||
libab_value* value;
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
|
||||
if((value = malloc(sizeof(*value)))) {
|
||||
result = libab_value_init_raw(value, data, type);
|
||||
} else {
|
||||
result = LIBAB_MALLOC;
|
||||
}
|
||||
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
result = libab_ref_new(into, value, _free_value);
|
||||
if(result != LIBAB_SUCCESS) {
|
||||
libab_value_free(value);
|
||||
}
|
||||
}
|
||||
|
||||
if(result != LIBAB_SUCCESS) {
|
||||
libab_ref_null(into);
|
||||
free(value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
|
||||
libab_function_list* list;
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
@@ -186,7 +211,7 @@ libab_result libab_create_function_list(libab_ref* into, libab_ref* type) {
|
||||
}
|
||||
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
result = libab_create_value(into, list, type);
|
||||
result = libab_create_value_raw(into, list, type);
|
||||
if(result != LIBAB_SUCCESS) {
|
||||
libab_function_list_free(list);
|
||||
libab_ref_free(into);
|
||||
|
||||
30
src/value.c
30
src/value.c
@@ -1,17 +1,27 @@
|
||||
#include "value.h"
|
||||
#include "parsetype.h"
|
||||
|
||||
void libab_value_init(libab_value* value, void* data, libab_ref* type) {
|
||||
value->data = data;
|
||||
void libab_value_init_ref(libab_value* value, libab_ref* data, libab_ref* type) {
|
||||
libab_ref_copy(data, &value->data);
|
||||
libab_ref_copy(type, &value->type);
|
||||
}
|
||||
|
||||
void libab_value_free(libab_value* value) {
|
||||
void (*free_function)(void*);
|
||||
libab_parsetype* value_type;
|
||||
value_type = libab_ref_get(&value->type);
|
||||
free_function = value_type->data_u.base->free_function;
|
||||
libab_ref_free(&value->type);
|
||||
if (free_function)
|
||||
free_function(value->data);
|
||||
libab_result libab_value_init_raw(libab_value* value, void* data, libab_ref* type) {
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
libab_ref tmp_ref;
|
||||
|
||||
result = libab_ref_new(&tmp_ref, data,
|
||||
((libab_parsetype*) libab_ref_get(type))->data_u.base->free_function);
|
||||
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
libab_value_init_ref(value, &tmp_ref, type);
|
||||
libab_ref_free(&tmp_ref);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void libab_value_free(libab_value* value) {
|
||||
libab_ref_free(&value->data);
|
||||
libab_ref_free(&value->type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user