Make overloading code a utility function and call from interpreter.
This fixes #10.
This commit is contained in:
parent
25dd70f040
commit
4425b27b52
|
@ -103,6 +103,17 @@ libab_result libab_create_value_ref(libab* ab, libab_ref* into,
|
||||||
*/
|
*/
|
||||||
libab_result libab_create_value_raw(libab* ab, libab_ref* into,
|
libab_result libab_create_value_raw(libab* ab, libab_ref* into,
|
||||||
void* data, libab_ref* type);
|
void* data, libab_ref* type);
|
||||||
|
/**
|
||||||
|
* Overloads a function of the given name.
|
||||||
|
* @param table the table to insert the function into.
|
||||||
|
* @param name the name of the function.
|
||||||
|
* @param function the function to register.
|
||||||
|
* @return the result of the overload.
|
||||||
|
*/
|
||||||
|
libab_result libab_overload_function(libab* ab,
|
||||||
|
libab_table* table,
|
||||||
|
const char* name,
|
||||||
|
libab_ref* function);
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
|
|
@ -1224,7 +1224,7 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
||||||
_interpreter_create_function_value(state, tree, scope, &function);
|
_interpreter_create_function_value(state, tree, scope, &function);
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = libab_put_table_value(libab_ref_get(scope),
|
result = libab_overload_function(state->ab, libab_ref_get(scope),
|
||||||
tree->string_value, &function);
|
tree->string_value, &function);
|
||||||
if(result != LIBAB_SUCCESS) {
|
if(result != LIBAB_SUCCESS) {
|
||||||
libab_ref_free(&function);
|
libab_ref_free(&function);
|
||||||
|
|
|
@ -161,92 +161,16 @@ libab_result _create_value_function_internal(libab* ab,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(ab, &list_ref, type);
|
|
||||||
libab_ref_null(into);
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(into);
|
|
||||||
result = libab_create_value_ref(ab, into, &list_ref, type);
|
|
||||||
}
|
|
||||||
libab_ref_free(&list_ref);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _libab_register_function_existing(libab* ab,
|
|
||||||
libab_table_entry* entry,
|
|
||||||
libab_ref* function_val) {
|
|
||||||
libab_value* old_value;
|
|
||||||
libab_parsetype* old_type;
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
|
|
||||||
old_value = libab_ref_get(&entry->data_u.value);
|
|
||||||
old_type = libab_ref_get(&old_value->type);
|
|
||||||
|
|
||||||
if (old_type->data_u.base == &_basetype_function_list) {
|
|
||||||
libab_function_list* list = libab_ref_get(&old_value->data);
|
|
||||||
result = libab_function_list_insert(list, function_val);
|
|
||||||
} else if (old_type->data_u.base == &_basetype_function) {
|
|
||||||
libab_ref new_list;
|
|
||||||
result =
|
|
||||||
_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);
|
|
||||||
result = libab_function_list_insert(list, &entry->data_u.value);
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
|
||||||
result = libab_function_list_insert(list, function_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
|
||||||
libab_ref_swap(&entry->data_u.value, &new_list);
|
|
||||||
}
|
|
||||||
libab_ref_free(&new_list);
|
|
||||||
} else {
|
|
||||||
libab_ref_swap(&entry->data_u.value, function_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _libab_register_function_new(libab* ab, const char* name,
|
|
||||||
libab_ref* function_val) {
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
libab_table_entry* entry;
|
|
||||||
if ((entry = malloc(sizeof(*entry)))) {
|
|
||||||
entry->variant = ENTRY_VALUE;
|
|
||||||
libab_ref_copy(function_val, &entry->data_u.value);
|
|
||||||
result = libab_table_put(libab_ref_get(&ab->table), name, entry);
|
|
||||||
|
|
||||||
if (result != LIBAB_SUCCESS) {
|
|
||||||
libab_table_entry_free(entry);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = LIBAB_MALLOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result libab_register_function(libab* ab, const char* name,
|
libab_result libab_register_function(libab* ab, const char* name,
|
||||||
libab_ref* type, libab_function_ptr func) {
|
libab_ref* type, libab_function_ptr func) {
|
||||||
libab_table_entry* existing_entry;
|
|
||||||
libab_ref function_value;
|
libab_ref function_value;
|
||||||
libab_result result =
|
libab_result result =
|
||||||
_create_value_function_internal(ab, &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(
|
libab_overload_function(ab, libab_ref_get(&ab->table), name, &function_value);
|
||||||
libab_ref_get(&ab->table), name, NULL, libab_table_compare_value);
|
|
||||||
if (existing_entry) {
|
|
||||||
result = _libab_register_function_existing(ab, existing_entry,
|
|
||||||
&function_value);
|
|
||||||
} else {
|
|
||||||
result = _libab_register_function_new(ab, name, &function_value);
|
|
||||||
}
|
|
||||||
libab_ref_free(&function_value);
|
|
||||||
}
|
}
|
||||||
|
libab_ref_free(&function_value);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
88
src/util.c
88
src/util.c
|
@ -290,6 +290,94 @@ libab_result libab_create_value_raw(libab* ab, libab_ref* into,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(ab, &list_ref, type);
|
||||||
|
libab_ref_null(into);
|
||||||
|
if (result == LIBAB_SUCCESS) {
|
||||||
|
libab_ref_free(into);
|
||||||
|
result = libab_create_value_ref(ab, into, &list_ref, type);
|
||||||
|
}
|
||||||
|
libab_ref_free(&list_ref);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
libab_result _register_function_existing(libab* ab,
|
||||||
|
libab_table_entry* entry,
|
||||||
|
libab_ref* function_val) {
|
||||||
|
libab_value* old_value;
|
||||||
|
libab_parsetype* old_type;
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
|
||||||
|
old_value = libab_ref_get(&entry->data_u.value);
|
||||||
|
old_type = libab_ref_get(&old_value->type);
|
||||||
|
|
||||||
|
if (old_type->data_u.base == libab_get_basetype_function_list(ab)) {
|
||||||
|
libab_function_list* list = libab_ref_get(&old_value->data);
|
||||||
|
result = libab_function_list_insert(list, function_val);
|
||||||
|
} else if (old_type->data_u.base == libab_get_basetype_function(ab)) {
|
||||||
|
libab_ref new_list;
|
||||||
|
result =
|
||||||
|
_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);
|
||||||
|
result = libab_function_list_insert(list, &entry->data_u.value);
|
||||||
|
if (result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_function_list_insert(list, function_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == LIBAB_SUCCESS) {
|
||||||
|
libab_ref_swap(&entry->data_u.value, &new_list);
|
||||||
|
}
|
||||||
|
libab_ref_free(&new_list);
|
||||||
|
} else {
|
||||||
|
libab_ref_swap(&entry->data_u.value, function_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _register_function_new(libab* ab, const char* name,
|
||||||
|
libab_ref* function_val) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_table_entry* entry;
|
||||||
|
if ((entry = malloc(sizeof(*entry)))) {
|
||||||
|
entry->variant = ENTRY_VALUE;
|
||||||
|
libab_ref_copy(function_val, &entry->data_u.value);
|
||||||
|
result = libab_table_put(libab_ref_get(&ab->table), name, entry);
|
||||||
|
|
||||||
|
if (result != LIBAB_SUCCESS) {
|
||||||
|
libab_table_entry_free(entry);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
libab_result libab_overload_function(libab* ab,
|
||||||
|
libab_table* table,
|
||||||
|
const char* name,
|
||||||
|
libab_ref* function) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_table_entry* existing_entry = libab_table_search_filter(
|
||||||
|
table, name, NULL, libab_table_compare_value);
|
||||||
|
|
||||||
|
if (existing_entry) {
|
||||||
|
result = _register_function_existing(ab, existing_entry,
|
||||||
|
function);
|
||||||
|
} else {
|
||||||
|
result = _register_function_new(ab, name, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void _gc_visit_function_children(void* function, libab_visitor_function_ptr visitor, void* data) {
|
void _gc_visit_function_children(void* function, libab_visitor_function_ptr visitor, void* data) {
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
libab_function* func = function;
|
libab_function* func = function;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user