From 8253cd1f699036930dfc18949e7f2a122df609f5 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 9 May 2018 15:05:40 -0700 Subject: [PATCH] Add initialization functions for operators and functions. --- include/custom.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++- src/custom.c | 40 +++++++++++++++++++++++++++++++++++++- src/libabacus.c | 21 ++++++++++---------- 3 files changed, 99 insertions(+), 12 deletions(-) diff --git a/include/custom.h b/include/custom.h index ec23b23..fc3b103 100644 --- a/include/custom.h +++ b/include/custom.h @@ -2,6 +2,7 @@ #define LIBABACUS_CUSTOM_H #include "parsetype.h" +#include "tree.h" /** * A function pointer that is called @@ -40,7 +41,7 @@ struct libab_behavior_impl_s { /** * The tree-based implementation. */ - libab_ref tree; + libab_tree* tree; } data_u; }; @@ -103,16 +104,63 @@ typedef struct libab_behavior_s libab_behavior; typedef struct libab_operator_s libab_operator; typedef struct libab_function_s libab_function; +/** + * Initializes a behavior that uses an internal function. + * @param behavior the behavior to initialize. + * @param type the type of the behavior. + * @param func the function that this behavior calls. + */ +void libab_behavior_init_internal(libab_behavior* behavior, + libab_ref* type, libab_function_ptr func); +/** + * Initializes a behavior that uses a tree that has been + * parsed from the user. + * @param behavior the behavior to initialize. + * @param type the type of the behavior. + * @param tree the tree that this behavior uses. + */ +void libab_behavior_init_tree(libab_behavior* behavior, libab_ref* type, + libab_tree* tree); /** * Frees the given behavior. * @param behavior the behavior to free. */ void libab_behavior_free(libab_behavior* behavior); +/** + * Initializes an operator with the given info. + * @param op the operator to initialize. + * @param variant the variant of the operator (infix, prefix, etc) + * @param precedence the precedence of the operator. + * @param associativity the associativity (left = -1, right = 1) of the operator. + * @param type the type of the operator. + * @param func the function used to implement the operator. + */ +void libab_operator_init(libab_operator* op, libab_operator_variant variant, + int precedence, int associativity, libab_ref* type, + libab_function_ptr func); /** * Frees the given operator. * @param op the operator to free. */ void libab_operator_free(libab_operator* op); +/** + * Initializes a function with the given internal behavior. + * @param function the function to initialize. + * @param type the type of the function. + * @param fun the function implementation. + * @return the result of the initialization. + */ +libab_result libab_function_init_internal(libab_function* function, libab_ref* type, + libab_function_ptr fun); +/** + * Initializes a function with the given tree behavior. + * @param function the function to initialize. + * @param type the type of the function. + * @param tree the tree that represents the function's behavior. + * @return the result of the initialization. + */ +libab_result libab_function_init_tree(libab_function* function, libab_ref* type, + libab_tree* tree); /** * Frees the given function. * @param fun the function to free. diff --git a/src/custom.c b/src/custom.c index 26ad452..32b96f0 100644 --- a/src/custom.c +++ b/src/custom.c @@ -1,16 +1,54 @@ #include "custom.h" +void libab_behavior_init_internal(libab_behavior* behavior, libab_ref* type, + libab_function_ptr func) { + behavior->impl.variant = BIMPL_INTERNAL; + behavior->impl.data_u.internal = func; + libab_ref_copy(type, &behavior->type); +} + +void libab_behavior_init_tree(libab_behavior* behavior, libab_ref* type, + libab_tree* tree) { + behavior->impl.variant = BIMPL_TREE; + behavior->impl.data_u.tree = tree; + libab_ref_copy(type, &behavior->type); +} + void libab_behavior_free(libab_behavior* behavior) { libab_ref_free(&behavior->type); if (behavior->impl.variant == BIMPL_TREE) { - libab_ref_free(&behavior->impl.data_u.tree); + libab_tree_free_recursive(behavior->impl.data_u.tree); } } +void libab_operator_init(libab_operator* op, libab_operator_variant variant, + int precedence, int associativity, libab_ref* type, + libab_function_ptr func) { + op->type = variant; + op->precedence = precedence; + op->associativity = associativity; + libab_behavior_init_internal(&op->behavior, type, func); +} + void libab_operator_free(libab_operator* op) { libab_behavior_free(&op->behavior); } +libab_result _function_init(libab_function* function) { + return LIBAB_SUCCESS; +} +libab_result libab_function_init_internal(libab_function* function, libab_ref* type, + libab_function_ptr fun) { + libab_result result = _function_init(function); + libab_behavior_init_internal(&function->behavior, type, fun); + return result; +} +libab_result libab_function_init_tree(libab_function* function, libab_ref* type, + libab_tree* tree) { + libab_result result = _function_init(function); + libab_behavior_init_tree(&function->behavior, type, tree); + return result; +} void libab_function_free(libab_function* fun) { libab_behavior_free(&fun->behavior); } diff --git a/src/libabacus.c b/src/libabacus.c index d6fd73b..9fedc70 100644 --- a/src/libabacus.c +++ b/src/libabacus.c @@ -78,12 +78,12 @@ libab_result _register_operator(libab* ab, const char* op, char op_buffer[8]; libab_result result = LIBAB_SUCCESS; libab_table_entry* new_entry; + libab_operator* new_operator = NULL; if ((new_entry = malloc(sizeof(*new_entry)))) { new_entry->variant = ENTRY_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(&(new_entry->data_u.op.behavior), type, func); + new_operator = &(new_entry->data_u.op); + libab_operator_init(new_operator, token_type, + precedence, associativity, type, func); } else { result = LIBAB_MALLOC; } @@ -99,8 +99,8 @@ libab_result _register_operator(libab* ab, const char* op, } if (result != LIBAB_SUCCESS) { - if (new_entry) - libab_ref_free(&new_entry->data_u.op.behavior.type); + if (new_operator) + libab_operator_free(new_operator); eval_config_remove(&ab->lexer.config, op, TOKEN_OP); free(new_entry); } @@ -131,11 +131,12 @@ libab_result libab_register_operator_postfix(libab* ab, const char* op, libab_result libab_register_function(libab* ab, const char* name, libab_ref* type, libab_function_ptr func) { 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; - _initialize_behavior(&(new_entry->data_u.function.behavior), type, - func); + new_function = &new_entry->data_u.function; + result = libab_function_init_internal(new_function, type, func); } else { result = LIBAB_MALLOC; } @@ -145,8 +146,8 @@ libab_result libab_register_function(libab* ab, const char* name, } if (result != LIBAB_SUCCESS) { - if (new_entry) - libab_ref_free(&new_entry->data_u.function.behavior.type); + if(new_function) + libab_function_free(new_function); free(new_entry); }