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. * The type of the function.
*/ */
libab_parsetype* type; libab_ref type;
}; };
/** /**
* A struct that holds informatiion * 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, libab_result libab_parser_parse(libab_parser* parser, ll* tokens,
const char* string, libab_tree** store_into); const char* string, libab_tree** store_into);
libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens, 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. * Releases the resources allocated by the parser.
* @param parser the parser to release. * @param parser the parser to release.

View File

@ -2,7 +2,7 @@
#define LIBABACUS_PARSETYPE_H #define LIBABACUS_PARSETYPE_H
#include "result.h" #include "result.h"
#include "vec.h" #include "ref_vec.h"
#include "basetype.h" #include "basetype.h"
#define LIBABACUS_TYPE_F_PARENT (1) #define LIBABACUS_TYPE_F_PARENT (1)
@ -10,13 +10,7 @@
#define LIBABACUS_TYPE_F_RESOLVED (1 << 2) #define LIBABACUS_TYPE_F_RESOLVED (1 << 2)
/** /**
* A parse type. * A type, either parsed or resolved.
* 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.
*/ */
struct libab_parsetype_s { struct libab_parsetype_s {
/** /**
@ -40,7 +34,7 @@ struct libab_parsetype_s {
* A vector of children that this parse type contains. * A vector of children that this parse type contains.
* The children are effectively type parameters. * The children are effectively type parameters.
*/ */
vec children; libab_ref_vec children;
}; };
typedef struct libab_parsetype_s libab_parsetype; typedef struct libab_parsetype_s libab_parsetype;
@ -51,11 +45,5 @@ typedef struct libab_parsetype_s libab_parsetype;
* @param type the type to free. * @param type the type to free.
*/ */
void libab_parsetype_free(libab_parsetype* type); 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 #endif

View File

@ -35,7 +35,7 @@ struct libab_tree_s {
/** /**
* The parse type of this node, if applicable. * The parse type of this node, if applicable.
*/ */
libab_parsetype* parse_type; libab_ref type;
/** /**
* The variant of tree node. * The variant of tree node.
*/ */

View File

@ -1,7 +1,7 @@
#include "custom.h" #include "custom.h"
void libab_behavior_free(libab_behavior* behavior) { 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) { 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; libab_table_entry* new_entry;
if((new_entry = malloc(sizeof(*new_entry)))) { if((new_entry = malloc(sizeof(*new_entry)))) {
new_entry->variant = ENTRY_OP; 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.precedence = precedence;
new_entry->data_u.op.associativity = associativity; new_entry->data_u.op.associativity = associativity;
new_entry->data_u.op.type = token_type; 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) { 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); 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(result != LIBAB_SUCCESS) {
if(new_entry && new_entry->data_u.op.behavior.type) if(new_entry)
libab_parsetype_free_recursive(new_entry->data_u.op.behavior.type); libab_ref_free(&new_entry->data_u.op.behavior.type);
eval_config_remove(&ab->lexer.config, op, TOKEN_OP); eval_config_remove(&ab->lexer.config, op, TOKEN_OP);
free(new_entry); 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; libab_table_entry* new_entry;
if((new_entry = malloc(sizeof(*new_entry)))) { if((new_entry = malloc(sizeof(*new_entry)))) {
new_entry->variant = ENTRY_FUN; new_entry->variant = ENTRY_FUN;
new_entry->data_u.function.behavior.type = NULL; libab_ref_null(&new_entry->data_u.function.behavior.type);
} else { } else {
result = LIBAB_MALLOC; result = LIBAB_MALLOC;
} }
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(&new_entry->data_u.function.behavior.type);
result = _initialize_behavior(ab, result = _initialize_behavior(ab,
&(new_entry->data_u.function.behavior), type, func); &(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(result != LIBAB_SUCCESS) {
if(new_entry && new_entry->data_u.function.behavior.type) if(new_entry)
libab_parsetype_free_recursive(new_entry->data_u.function.behavior.type); libab_ref_free(&new_entry->data_u.function.behavior.type);
free(new_entry); 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_block(struct parser_state*, libab_tree**, int);
libab_result _parse_expression(struct parser_state* state, libab_tree** store_into); 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) { libab_result _parse_braced_block(struct parser_state* state, libab_tree** store_into) {
return _parse_block(state, store_into, 1); 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; 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_result result = LIBAB_SUCCESS;
libab_parsetype* temp = NULL; libab_ref temp;
result = _parse_type(state, &temp); result = _parse_type(state, &temp);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
result = libab_convert_ds_result(vec_add(into, temp)); result = libab_ref_vec_insert(into, &temp);
if(result != LIBAB_SUCCESS) { libab_ref_free(&temp);
libab_parsetype_free_recursive(temp);
}
} }
return result; 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; libab_result result = LIBAB_SUCCESS;
int is_parenth, is_comma; int is_parenth, is_comma;
while(result == LIBAB_SUCCESS && !_parser_eof(state) && !_parser_is_char(state, end_char)) { 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) { if(placeholder_flag) {
result = LIBAB_UNEXPECTED; result = LIBAB_UNEXPECTED;
} else { } else {
result = libab_convert_ds_result(vec_init(&(*into)->children)); result = libab_ref_vec_init(&(*into)->children);
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
free((*into)->data_u.name); free((*into)->data_u.name);
free(*into); free(*into);
@ -212,7 +210,7 @@ libab_result _parse_type_id(struct parser_state* state, libab_parsetype** into)
} }
if(result != LIBAB_SUCCESS && *into) { if(result != LIBAB_SUCCESS && *into) {
libab_parsetype_free_recursive(*into); libab_parsetype_free(*into);
*into = NULL; *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); libab_result result = _parser_allocate_type(into, "function", 0, 8);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
(*into)->variant |= LIBABACUS_TYPE_F_PARENT; (*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) { if(result != LIBAB_SUCCESS) {
free((*into)->data_u.name); free((*into)->data_u.name);
free(*into); free(*into);
@ -247,7 +245,7 @@ libab_result _parse_type_function(struct parser_state* state,
} }
if(result != LIBAB_SUCCESS && *into) { if(result != LIBAB_SUCCESS && *into) {
libab_parsetype_free_recursive(*into); libab_parsetype_free(*into);
*into = NULL; *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); libab_result result = _parser_allocate_type(into, "array", 0, 5);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
(*into)->variant |= LIBABACUS_TYPE_F_PARENT; (*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) { if(result != LIBAB_SUCCESS) {
free((*into)->data_u.name); free((*into)->data_u.name);
free(*into); free(*into);
@ -277,14 +275,14 @@ libab_result _parse_type_array(struct parser_state* state,
} }
if(result != LIBAB_SUCCESS && *into) { if(result != LIBAB_SUCCESS && *into) {
libab_parsetype_free_recursive(*into); libab_parsetype_free(*into);
*into = NULL; *into = NULL;
} }
return result; 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; libab_result result;
if(_parser_is_type(state, TOKEN_ID) || _parser_is_char(state, '\'')) { if(_parser_is_type(state, TOKEN_ID) || _parser_is_char(state, '\'')) {
result = _parse_type_id(state, into); result = _parse_type_id(state, into);
@ -299,6 +297,23 @@ libab_result _parse_type(struct parser_state* state, libab_parsetype** into) {
return result; 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 _parser_allocate_node(libab_lexer_match* match, libab_tree** into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
if(((*into) = malloc(sizeof(**into))) == NULL) { 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) { if(result == LIBAB_SUCCESS) {
_parser_state_step(state); _parser_state_step(state);
(*store_into)->variant = TREE_FUN_PARAM; (*store_into)->variant = TREE_FUN_PARAM;
(*store_into)->parse_type = NULL; libab_ref_null(&(*store_into)->type);
result = _parser_consume_char(state, ':'); result = _parser_consume_char(state, ':');
} }
if(result == LIBAB_SUCCESS) { 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) { 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) { if(result == LIBAB_SUCCESS) {
_parser_state_step(state); _parser_state_step(state);
(*store_into)->parse_type = NULL; libab_ref_null(&(*store_into)->type);
(*store_into)->variant = TREE_FUN; (*store_into)->variant = TREE_FUN;
result = _parser_consume_char(state, ':'); result = _parser_consume_char(state, ':');
} }
if(result == LIBAB_SUCCESS) { 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) { if(result == LIBAB_SUCCESS) {
@ -499,7 +516,7 @@ libab_result _parse_fun(struct parser_state* state, libab_tree** store_into) {
} }
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
_parser_state_step(state); _parser_state_step(state);
(*store_into)->parse_type = NULL; libab_ref_null(&(*store_into)->type);
(*store_into)->variant = TREE_FUN; (*store_into)->variant = TREE_FUN;
result = _parser_consume_char(state, '('); 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) { 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) { if(result == LIBAB_SUCCESS) {
@ -1072,7 +1090,7 @@ libab_result libab_parser_parse(libab_parser* parser, ll* tokens,
return result; return result;
} }
libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens, 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; struct parser_state state;
_parser_state_init(&state, tokens, string, parser->base_table); _parser_state_init(&state, tokens, string, parser->base_table);

View File

@ -1,20 +1,11 @@
#include "parsetype.h" #include "parsetype.h"
#include <stdlib.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) { void libab_parsetype_free(libab_parsetype* type) {
if(!(type->variant & LIBABACUS_TYPE_F_RESOLVED)) { if(!(type->variant & LIBABACUS_TYPE_F_RESOLVED)) {
free(type->data_u.name); free(type->data_u.name);
} }
}
void libab_parsetype_free_recursive(libab_parsetype* type) {
if(type->variant & LIBABACUS_TYPE_F_PARENT) { if(type->variant & LIBABACUS_TYPE_F_PARENT) {
vec_foreach(&(type->children), NULL, compare_always, _foreach_free_child); libab_ref_vec_free(&(type->children));
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); free_type = libab_tree_has_type(tree->variant);
if(free_string) free(tree->string_value); if(free_string) free(tree->string_value);
if(free_vector) vec_free(&tree->children); if(free_vector) vec_free(&tree->children);
if(free_type && tree->parse_type) if(free_type)
libab_parsetype_free_recursive(tree->parse_type); libab_ref_free(&tree->type);
} }
int _tree_foreach_free(void* data, va_list args) { int _tree_foreach_free(void* data, va_list args) {