Use reference counting for types.

This commit is contained in:
Danila Fedorin 2018-04-17 22:14:07 -07:00
parent 264f420186
commit 3ada78a557
9 changed files with 58 additions and 59 deletions

View File

@ -31,7 +31,7 @@ struct libab_behavior_s {
/**
* The type of the function.
*/
libab_parsetype* type;
libab_ref type;
};
/**
* A struct that holds informatiion

View File

@ -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.

View File

@ -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

View File

@ -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.
*/

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);

View File

@ -1,20 +1,11 @@
#include "parsetype.h"
#include <stdlib.h>
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);
}

View File

@ -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) {