From 3ada78a5571a5ff0d1ca2a6fb2e9681a50c60c02 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Tue, 17 Apr 2018 22:14:07 -0700 Subject: [PATCH] Use reference counting for types. --- include/custom.h | 2 +- include/parser.h | 2 +- include/parsetype.h | 18 +++---------- include/tree.h | 2 +- src/custom.c | 2 +- src/libabacus.c | 14 +++++----- src/parser.c | 62 +++++++++++++++++++++++++++++---------------- src/parsetype.c | 11 +------- src/tree.c | 4 +-- 9 files changed, 58 insertions(+), 59 deletions(-) diff --git a/include/custom.h b/include/custom.h index 6db76d7..4b02ad9 100644 --- a/include/custom.h +++ b/include/custom.h @@ -31,7 +31,7 @@ struct libab_behavior_s { /** * The type of the function. */ - libab_parsetype* type; + libab_ref type; }; /** * A struct that holds informatiion diff --git a/include/parser.h b/include/parser.h index 5f5239a..16bebc6 100644 --- a/include/parser.h +++ b/include/parser.h @@ -33,7 +33,7 @@ void libab_parser_init(libab_parser* parser, libab_table* table); libab_result libab_parser_parse(libab_parser* parser, ll* tokens, const char* string, libab_tree** store_into); libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens, - const char* string, libab_parsetype** store_into); + const char* string, libab_ref* store_into); /** * Releases the resources allocated by the parser. * @param parser the parser to release. diff --git a/include/parsetype.h b/include/parsetype.h index acfa4bd..a94a525 100644 --- a/include/parsetype.h +++ b/include/parsetype.h @@ -2,7 +2,7 @@ #define LIBABACUS_PARSETYPE_H #include "result.h" -#include "vec.h" +#include "ref_vec.h" #include "basetype.h" #define LIBABACUS_TYPE_F_PARENT (1) @@ -10,13 +10,7 @@ #define LIBABACUS_TYPE_F_RESOLVED (1 << 2) /** - * A parse type. - * A parse type is a type as it was parsed, not - * resolved. Effectively, it doesn't have to be valid, - * or it can contain references to types whose adresses - * are not yet known. The parse type is recursive, - * with PT_STRING being the "base case", and PT_PARENT - * meaning an initialized children vector with the sub-parse types. + * A type, either parsed or resolved. */ struct libab_parsetype_s { /** @@ -40,7 +34,7 @@ struct libab_parsetype_s { * A vector of children that this parse type contains. * The children are effectively type parameters. */ - vec children; + libab_ref_vec children; }; typedef struct libab_parsetype_s libab_parsetype; @@ -51,11 +45,5 @@ typedef struct libab_parsetype_s libab_parsetype; * @param type the type to free. */ void libab_parsetype_free(libab_parsetype* type); -/** - * Recursively frees the given parse type, calling free - * on every single type (including the one passed in). - * @param type the type to free. - */ -void libab_parsetype_free_recursive(libab_parsetype* type); #endif diff --git a/include/tree.h b/include/tree.h index 774191a..a84fb2b 100644 --- a/include/tree.h +++ b/include/tree.h @@ -35,7 +35,7 @@ struct libab_tree_s { /** * The parse type of this node, if applicable. */ - libab_parsetype* parse_type; + libab_ref type; /** * The variant of tree node. */ diff --git a/src/custom.c b/src/custom.c index dc2afae..0939490 100644 --- a/src/custom.c +++ b/src/custom.c @@ -1,7 +1,7 @@ #include "custom.h" void libab_behavior_free(libab_behavior* behavior) { - libab_parsetype_free_recursive(behavior->type); + libab_ref_free(&behavior->type); } void libab_operator_free(libab_operator* op) { diff --git a/src/libabacus.c b/src/libabacus.c index b437944..a95c4ec 100644 --- a/src/libabacus.c +++ b/src/libabacus.c @@ -55,7 +55,7 @@ libab_result _register_operator(libab* ab, const char* op, libab_operator_varian libab_table_entry* new_entry; if((new_entry = malloc(sizeof(*new_entry)))) { new_entry->variant = ENTRY_OP; - new_entry->data_u.op.behavior.type = NULL; + libab_ref_null(&new_entry->data_u.op.behavior.type); new_entry->data_u.op.precedence = precedence; new_entry->data_u.op.associativity = associativity; new_entry->data_u.op.type = token_type; @@ -64,6 +64,7 @@ libab_result _register_operator(libab* ab, const char* op, libab_operator_varian } if(result == LIBAB_SUCCESS) { + libab_ref_free(&new_entry->data_u.op.behavior.type); result = _initialize_behavior(ab, &(new_entry->data_u.op.behavior), type, func); } @@ -77,8 +78,8 @@ libab_result _register_operator(libab* ab, const char* op, libab_operator_varian } if(result != LIBAB_SUCCESS) { - if(new_entry && new_entry->data_u.op.behavior.type) - libab_parsetype_free_recursive(new_entry->data_u.op.behavior.type); + if(new_entry) + libab_ref_free(&new_entry->data_u.op.behavior.type); eval_config_remove(&ab->lexer.config, op, TOKEN_OP); free(new_entry); } @@ -103,12 +104,13 @@ libab_result libab_register_function(libab* ab, const char* name, const char* ty libab_table_entry* new_entry; if((new_entry = malloc(sizeof(*new_entry)))) { new_entry->variant = ENTRY_FUN; - new_entry->data_u.function.behavior.type = NULL; + libab_ref_null(&new_entry->data_u.function.behavior.type); } else { result = LIBAB_MALLOC; } if(result == LIBAB_SUCCESS) { + libab_ref_free(&new_entry->data_u.function.behavior.type); result = _initialize_behavior(ab, &(new_entry->data_u.function.behavior), type, func); } @@ -118,8 +120,8 @@ libab_result libab_register_function(libab* ab, const char* name, const char* ty } if(result != LIBAB_SUCCESS) { - if(new_entry && new_entry->data_u.function.behavior.type) - libab_parsetype_free_recursive(new_entry->data_u.function.behavior.type); + if(new_entry) + libab_ref_free(&new_entry->data_u.function.behavior.type); free(new_entry); } diff --git a/src/parser.c b/src/parser.c index e91943b..a4e296a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -113,7 +113,7 @@ libab_result _parser_consume_type(struct parser_state* state, libab_result _parse_block(struct parser_state*, libab_tree**, int); libab_result _parse_expression(struct parser_state* state, libab_tree** store_into); -libab_result _parse_type(struct parser_state* state, libab_parsetype** into); +libab_result _parse_type(struct parser_state* state, libab_ref* ref); libab_result _parse_braced_block(struct parser_state* state, libab_tree** store_into) { return _parse_block(state, store_into, 1); @@ -135,20 +135,18 @@ libab_result _parser_allocate_type(libab_parsetype** into, const char* source, s return result; } -libab_result _parser_append_type(struct parser_state* state, vec* into) { +libab_result _parser_append_type(struct parser_state* state, libab_ref_vec* into) { libab_result result = LIBAB_SUCCESS; - libab_parsetype* temp = NULL; + libab_ref temp; result = _parse_type(state, &temp); if(result == LIBAB_SUCCESS) { - result = libab_convert_ds_result(vec_add(into, temp)); - if(result != LIBAB_SUCCESS) { - libab_parsetype_free_recursive(temp); - } + result = libab_ref_vec_insert(into, &temp); + libab_ref_free(&temp); } return result; } -libab_result _parse_type_list(struct parser_state* state, vec* into, char end_char) { +libab_result _parse_type_list(struct parser_state* state, libab_ref_vec* into, char end_char) { libab_result result = LIBAB_SUCCESS; int is_parenth, is_comma; while(result == LIBAB_SUCCESS && !_parser_eof(state) && !_parser_is_char(state, end_char)) { @@ -198,7 +196,7 @@ libab_result _parse_type_id(struct parser_state* state, libab_parsetype** into) if(placeholder_flag) { result = LIBAB_UNEXPECTED; } else { - result = libab_convert_ds_result(vec_init(&(*into)->children)); + result = libab_ref_vec_init(&(*into)->children); if(result != LIBAB_SUCCESS) { free((*into)->data_u.name); free(*into); @@ -212,7 +210,7 @@ libab_result _parse_type_id(struct parser_state* state, libab_parsetype** into) } if(result != LIBAB_SUCCESS && *into) { - libab_parsetype_free_recursive(*into); + libab_parsetype_free(*into); *into = NULL; } @@ -224,7 +222,7 @@ libab_result _parse_type_function(struct parser_state* state, libab_result result = _parser_allocate_type(into, "function", 0, 8); if(result == LIBAB_SUCCESS) { (*into)->variant |= LIBABACUS_TYPE_F_PARENT; - result = libab_convert_ds_result(vec_init(&(*into)->children)); + result = libab_ref_vec_init(&(*into)->children); if(result != LIBAB_SUCCESS) { free((*into)->data_u.name); free(*into); @@ -247,7 +245,7 @@ libab_result _parse_type_function(struct parser_state* state, } if(result != LIBAB_SUCCESS && *into) { - libab_parsetype_free_recursive(*into); + libab_parsetype_free(*into); *into = NULL; } @@ -259,7 +257,7 @@ libab_result _parse_type_array(struct parser_state* state, libab_result result = _parser_allocate_type(into, "array", 0, 5); if(result == LIBAB_SUCCESS) { (*into)->variant |= LIBABACUS_TYPE_F_PARENT; - result = libab_convert_ds_result(vec_init(&(*into)->children)); + result = libab_ref_vec_init(&(*into)->children); if(result != LIBAB_SUCCESS) { free((*into)->data_u.name); free(*into); @@ -277,14 +275,14 @@ libab_result _parse_type_array(struct parser_state* state, } if(result != LIBAB_SUCCESS && *into) { - libab_parsetype_free_recursive(*into); + libab_parsetype_free(*into); *into = NULL; } return result; } -libab_result _parse_type(struct parser_state* state, libab_parsetype** into) { +libab_result _parse_type_raw(struct parser_state* state, libab_parsetype** into) { libab_result result; if(_parser_is_type(state, TOKEN_ID) || _parser_is_char(state, '\'')) { result = _parse_type_id(state, into); @@ -299,6 +297,23 @@ libab_result _parse_type(struct parser_state* state, libab_parsetype** into) { return result; } +void _parse_type_free(void* data) { + libab_parsetype_free(data); +} + +libab_result _parse_type(struct parser_state* state, libab_ref* into) { + libab_parsetype* store_into; + libab_result result = _parse_type_raw(state, &store_into); + if(result == LIBAB_SUCCESS) { + result = libab_ref_new(into, store_into, _parse_type_free); + if(result != LIBAB_SUCCESS) { + libab_parsetype_free(store_into); + libab_ref_null(into); + } + } + return result; +} + libab_result _parser_allocate_node(libab_lexer_match* match, libab_tree** into) { libab_result result = LIBAB_SUCCESS; if(((*into) = malloc(sizeof(**into))) == NULL) { @@ -429,12 +444,13 @@ libab_result _parse_fun_param(struct parser_state* state, libab_tree** store_int if(result == LIBAB_SUCCESS) { _parser_state_step(state); (*store_into)->variant = TREE_FUN_PARAM; - (*store_into)->parse_type = NULL; + libab_ref_null(&(*store_into)->type); result = _parser_consume_char(state, ':'); } if(result == LIBAB_SUCCESS) { - result = _parse_type(state, &(*store_into)->parse_type); + libab_ref_free(&(*store_into)->type); + result = _parse_type(state, &(*store_into)->type); } if(result != LIBAB_SUCCESS && *store_into) { @@ -460,13 +476,14 @@ libab_result _parse_def_fun(struct parser_state* state, libab_tree** store_into) if(result == LIBAB_SUCCESS) { _parser_state_step(state); - (*store_into)->parse_type = NULL; + libab_ref_null(&(*store_into)->type); (*store_into)->variant = TREE_FUN; result = _parser_consume_char(state, ':'); } if(result == LIBAB_SUCCESS) { - result = _parse_type(state, &(*store_into)->parse_type); + libab_ref_free(&(*store_into)->type); + result = _parse_type(state, &(*store_into)->type); } if(result == LIBAB_SUCCESS) { @@ -499,7 +516,7 @@ libab_result _parse_fun(struct parser_state* state, libab_tree** store_into) { } if(result == LIBAB_SUCCESS) { _parser_state_step(state); - (*store_into)->parse_type = NULL; + libab_ref_null(&(*store_into)->type); (*store_into)->variant = TREE_FUN; result = _parser_consume_char(state, '('); } @@ -526,7 +543,8 @@ libab_result _parse_fun(struct parser_state* state, libab_tree** store_into) { } if(result == LIBAB_SUCCESS) { - result = _parse_type(state, &(*store_into)->parse_type); + libab_ref_free(&(*store_into)->type); + result = _parse_type(state, &(*store_into)->type); } if(result == LIBAB_SUCCESS) { @@ -1072,7 +1090,7 @@ libab_result libab_parser_parse(libab_parser* parser, ll* tokens, return result; } libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens, - const char* string, libab_parsetype** store_into) { + const char* string, libab_ref* store_into) { struct parser_state state; _parser_state_init(&state, tokens, string, parser->base_table); diff --git a/src/parsetype.c b/src/parsetype.c index e270ab0..0586f91 100644 --- a/src/parsetype.c +++ b/src/parsetype.c @@ -1,20 +1,11 @@ #include "parsetype.h" #include -int _foreach_free_child(void* data, va_list args) { - libab_parsetype_free_recursive(data); - return 0; -} void libab_parsetype_free(libab_parsetype* type) { if(!(type->variant & LIBABACUS_TYPE_F_RESOLVED)) { free(type->data_u.name); } -} -void libab_parsetype_free_recursive(libab_parsetype* type) { if(type->variant & LIBABACUS_TYPE_F_PARENT) { - vec_foreach(&(type->children), NULL, compare_always, _foreach_free_child); - vec_free(&(type->children)); + libab_ref_vec_free(&(type->children)); } - libab_parsetype_free(type); - free(type); } diff --git a/src/tree.c b/src/tree.c index 4016249..58c86fc 100644 --- a/src/tree.c +++ b/src/tree.c @@ -35,8 +35,8 @@ void libab_tree_free(libab_tree* tree) { free_type = libab_tree_has_type(tree->variant); if(free_string) free(tree->string_value); if(free_vector) vec_free(&tree->children); - if(free_type && tree->parse_type) - libab_parsetype_free_recursive(tree->parse_type); + if(free_type) + libab_ref_free(&tree->type); } int _tree_foreach_free(void* data, va_list args) {