From 1e215ecfa5ca36ffd1a85855c690db65f6582852 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Tue, 1 May 2018 21:48:15 -0700 Subject: [PATCH] Add a function for preparing for execution. --- include/libabacus.h | 22 ++++++++- src/libabacus.c | 109 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/include/libabacus.h b/include/libabacus.h index 4c425a0..9ef4dab 100644 --- a/include/libabacus.h +++ b/include/libabacus.h @@ -31,6 +31,7 @@ struct libab_s { * to run a tree. */ libab_interpreter intr; + /** * The table used to store top-level * things like functions and operators. @@ -41,6 +42,22 @@ struct libab_s { * The allocator used to construct number instances. */ libab_impl impl; + + /** + * The number type instance. + */ + libab_ref type_num; + /** + * The function list type instance. + */ + libab_ref type_function_list; + + /** + * Internal; the number basetype. This cannot be a static + * variable like other built-in types because it has a free function + * specified by the user. + */ + libab_basetype basetype_num; }; typedef struct libab_s libab; @@ -49,9 +66,12 @@ typedef struct libab_s libab; * Initializes the libabacus struct as well * as all its internal structures such as the lexer. * @param ab the libabacus instance used to keep state. + * @param parse_function function used to parse a number. + * @param free_function function used to free the parsed number. * @return the result of the initialization. */ -libab_result libab_init(libab* ab); +libab_result libab_init(libab* ab, void* (*parse_function)(const char*), + void (*free_function)(void*)); /** * Registers an operator with libabacus. * @param ab the libabacus instance to reigster the operator with. diff --git a/src/libabacus.c b/src/libabacus.c index 6283853..6f4dc0c 100644 --- a/src/libabacus.c +++ b/src/libabacus.c @@ -4,26 +4,50 @@ #include "util.h" #include -libab_result libab_init(libab* ab) { +libab_result _prepare_types(libab* ab, void (*free_function)(void*)); + +libab_result libab_init(libab* ab, void* (*parse_function)(const char*), + void (*free_function)(void*)) { + int parser_initialized = 0; + int lexer_initialized = 0; libab_ref null_ref; libab_result result; libab_ref_null(&null_ref); + libab_ref_null(&ab->type_num); + libab_ref_null(&ab->type_function_list); + + ab->impl.parse_num = parse_function; result = libab_create_table(&ab->table, &null_ref); + if (result == LIBAB_SUCCESS) { + result = _prepare_types(ab, free_function); + } + if(result == LIBAB_SUCCESS) { + parser_initialized = 1; libab_parser_init(&ab->parser, &ab->table); libab_interpreter_init(&ab->intr, &ab->table, &ab->impl); result = libab_lexer_init(&ab->lexer); } if (result == LIBAB_SUCCESS) { + lexer_initialized = 1; result = libab_register_reserved_operators(&ab->lexer); } if (result != LIBAB_SUCCESS) { libab_ref_free(&ab->table); - libab_parser_free(&ab->parser); - libab_lexer_free(&ab->lexer); + libab_ref_free(&ab->type_num); + libab_ref_free(&ab->type_function_list); + + if(parser_initialized) { + libab_parser_free(&ab->parser); + libab_interpreter_free(&ab->intr); + } + + if(lexer_initialized) { + libab_lexer_free(&ab->lexer); + } } libab_ref_free(&null_ref); @@ -40,7 +64,7 @@ void _sanitize(char* to, const char* from, size_t buffer_size) { to[index] = '\0'; } -void _initialize_behavior(libab* ab, libab_behavior* behavior, libab_ref* type, +void _initialize_behavior(libab_behavior* behavior, libab_ref* type, libab_function_ptr func) { behavior->impl.variant = BIMPL_INTERNAL; behavior->impl.data_u.internal = func; @@ -59,7 +83,7 @@ libab_result _register_operator(libab* ab, const char* op, new_entry->data_u.op.precedence = precedence; new_entry->data_u.op.associativity = associativity; new_entry->data_u.op.type = token_type; - _initialize_behavior(ab, &(new_entry->data_u.op.behavior), type, func); + _initialize_behavior(&(new_entry->data_u.op.behavior), type, func); } else { result = LIBAB_MALLOC; } @@ -110,7 +134,7 @@ libab_result libab_register_function(libab* ab, const char* name, libab_table_entry* new_entry; if ((new_entry = malloc(sizeof(*new_entry)))) { new_entry->variant = ENTRY_FUN; - _initialize_behavior(ab, &(new_entry->data_u.function.behavior), type, + _initialize_behavior(&(new_entry->data_u.function.behavior), type, func); } else { result = LIBAB_MALLOC; @@ -149,6 +173,77 @@ 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; + + ab->basetype_num.count = 0; + ab->basetype_num.params = NULL; + ab->basetype_num.free_function = free_function; + + libab_ref_null(&ab->type_num); + libab_ref_null(&ab->type_function_list); + + if (result == LIBAB_SUCCESS) { + libab_ref_free(&ab->type_num); + result = libab_instantiate_basetype(&ab->basetype_num, + &ab->type_num, 0); + } + + if (result == LIBAB_SUCCESS) { + libab_ref_free(&ab->type_function_list); + result = libab_instantiate_basetype(&_basetype_function_list, + &ab->type_function_list, 0); + } + + if (result == LIBAB_SUCCESS) { + result = libab_register_basetype(ab, "num", &ab->basetype_num); + } + + if (result == LIBAB_SUCCESS) { + result = libab_register_basetype(ab, "function", &_basetype_function); + } + + if (result == LIBAB_SUCCESS) { + result = libab_register_basetype(ab, "function_list", + &_basetype_function_list); + } + + if(result != LIBAB_SUCCESS) { + libab_ref_free(&ab->type_num); + libab_ref_free(&ab->type_function_list); + libab_ref_null(&ab->type_num); + libab_ref_null(&ab->type_function_list); + } + + return result; +} + libab_result libab_create_type(libab* ab, libab_ref* into, const char* type) { libab_result result; ll tokens; @@ -164,6 +259,8 @@ libab_result libab_create_type(libab* ab, libab_ref* into, const char* type) { libab_result libab_free(libab* ab) { libab_ref_free(&ab->table); + libab_ref_free(&ab->type_num); + libab_ref_free(&ab->type_function_list); libab_parser_free(&ab->parser); libab_interpreter_free(&ab->intr); return libab_lexer_free(&ab->lexer);