From 70e0e75d242bcd73b9c24ab264045791a28a9f62 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 14 May 2018 21:32:36 -0700 Subject: [PATCH] Switch to using values for storing function entries. --- include/table.h | 13 +--- src/libabacus.c | 162 ++++++++++++++++++++++++++++++++++++------------ src/table.c | 14 ----- 3 files changed, 122 insertions(+), 67 deletions(-) diff --git a/include/table.h b/include/table.h index 60d9001..95490df 100644 --- a/include/table.h +++ b/include/table.h @@ -32,8 +32,7 @@ struct libab_table_s { enum libab_table_entry_variant_e { ENTRY_VALUE, ENTRY_BASETYPE, - ENTRY_OP, - ENTRY_FUN + ENTRY_OP }; /** @@ -50,7 +49,6 @@ struct libab_table_entry_s { */ union { libab_operator op; - libab_function function; libab_basetype* basetype; libab_ref value; } data_u; @@ -94,15 +92,6 @@ libab_table_entry* libab_table_search(libab_table* table, const char* string); */ libab_operator* libab_table_search_operator(libab_table* table, const char* string, int type); -/** - * Searches for the given string in the table, returning a value only - * if it is a function. - * @param table the table to search. - * @param string the string to search for. - * @return the found function, or NULL if it was not found. - */ -libab_function* libab_table_search_function(libab_table* table, - const char* string); /** * Searches for the given basetype in the table, returning a value * only if it's a basetype. diff --git a/src/libabacus.c b/src/libabacus.c index 3812877..4874c04 100644 --- a/src/libabacus.c +++ b/src/libabacus.c @@ -2,8 +2,35 @@ #include "lexer.h" #include "reserved.h" #include "util.h" +#include "value.h" #include +void _free_function_list(void* function_list) { + libab_function_list_free(function_list); + free(function_list); +} + +static libab_basetype _basetype_function_list = { + _free_function_list, + NULL, + 0 +}; + +void _free_function(void* function) { + libab_function_free(function); + free(function); +} + +static libab_basetype_param _basetype_function_params[] = { + { BT_LIST, NULL } +}; + +static libab_basetype _basetype_function = { + _free_function, + _basetype_function_params, + 1 +}; + libab_result _prepare_types(libab* ab, void (*free_function)(void*)); libab_result libab_init(libab* ab, void* (*parse_function)(const char*), @@ -128,27 +155,103 @@ libab_result libab_register_operator_postfix(libab* ab, const char* op, return _register_operator(ab, op, OPERATOR_POSTFIX, 0, 0, type, func); } -libab_result libab_register_function(libab* ab, const char* name, - libab_ref* type, libab_function_ptr func) { +libab_result _create_value_function_internal(libab_ref* into, libab_ref* type, + libab_function_ptr func) { + libab_ref function_ref; + libab_result result = libab_create_function_internal(&function_ref, type, func); + libab_ref_null(into); + if(result == LIBAB_SUCCESS) { + libab_ref_free(into); + result = libab_create_value_ref(into, &function_ref, type); + } + libab_ref_free(&function_ref); + return result; +} + +libab_result _create_value_function_list(libab_ref* into, libab_ref* type) { + libab_ref list_ref; + libab_result result = libab_create_function_list(&list_ref, type); + libab_ref_null(into); + if(result == LIBAB_SUCCESS) { + libab_ref_free(into); + result = libab_create_value_ref(into, &list_ref, type); + } + libab_ref_free(&list_ref); + return result; +} + +static int _table_compare_value(const void* left, const void* right) { + const libab_table_entry* entry = right; + return entry->variant == ENTRY_VALUE; +} + +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; - libab_function* new_function = NULL; - libab_table_entry* new_entry; - if ((new_entry = malloc(sizeof(*new_entry)))) { - new_entry->variant = ENTRY_FUN; - new_function = &new_entry->data_u.function; - result = libab_function_init_internal(new_function, type, func); + + 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(&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; } - if (result == LIBAB_SUCCESS) { - result = libab_table_put(libab_ref_get(&ab->table), name, new_entry); - } + return result; +} - if (result != LIBAB_SUCCESS) { - if(new_function) - libab_function_free(new_function); - free(new_entry); +libab_result libab_register_function(libab* ab, const char* name, + libab_ref* type, libab_function_ptr func) { + libab_table_entry* existing_entry; + libab_ref function_value; + libab_result result = + _create_value_function_internal(&function_value, type, func); + + if(result == LIBAB_SUCCESS) { + existing_entry = + libab_table_search_filter(libab_ref_get(&ab->table), name, NULL, _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); } return result; @@ -174,32 +277,6 @@ libab_result libab_register_basetype(libab* ab, const char* name, return result; } -void _free_function_list(void* function_list) { - libab_function_list_free(function_list); - free(function_list); -} - -static libab_basetype _basetype_function_list = { - _free_function_list, - NULL, - 0 -}; - -void _free_function(void* function) { - libab_function_free(function); - free(function); -} - -static libab_basetype_param _basetype_function_params[] = { - { BT_LIST, NULL } -}; - -static libab_basetype _basetype_function = { - _free_function, - _basetype_function_params, - 1 -}; - libab_result _prepare_types(libab* ab, void (*free_function)(void*)) { libab_result result = LIBAB_SUCCESS; @@ -253,6 +330,9 @@ libab_result libab_create_type(libab* ab, libab_ref* into, const char* type) { if (result == LIBAB_SUCCESS) { result = libab_parser_parse_type(&ab->parser, &tokens, type, into); } + if (result == LIBAB_SUCCESS) { + result = libab_resolve_parsetype(libab_ref_get(into), libab_ref_get(&ab->table)); + } ll_foreach(&tokens, NULL, compare_always, libab_lexer_foreach_match_free); ll_free(&tokens); return result; diff --git a/src/table.c b/src/table.c index f1f8f9d..8e2945f 100644 --- a/src/table.c +++ b/src/table.c @@ -53,18 +53,6 @@ libab_operator* libab_table_search_operator(libab_table* table, return entry ? &entry->data_u.op : NULL; } -int _table_compare_function(const void* left, const void* right) { - const libab_table_entry* entry = right; - return entry->variant == ENTRY_FUN; -} - -libab_function* libab_table_search_function(libab_table* table, - const char* string) { - libab_table_entry* entry = - libab_table_search_filter(table, string, NULL, _table_compare_function); - return entry ? &entry->data_u.function : NULL; -} - int _table_compare_basetype(const void* left, const void* right) { const libab_table_entry* entry = right; return entry->variant == ENTRY_BASETYPE; @@ -116,8 +104,6 @@ void libab_table_free(libab_table* table) { void libab_table_entry_free(libab_table_entry* entry) { if (entry->variant == ENTRY_OP) { libab_operator_free(&entry->data_u.op); - } else if (entry->variant == ENTRY_FUN) { - libab_function_free(&entry->data_u.function); } else if (entry->variant == ENTRY_BASETYPE) { libab_basetype_free(entry->data_u.basetype); } else if (entry->variant == ENTRY_VALUE) {