Add pseudo-refcounting to tree creation.

This commit is contained in:
Danila Fedorin 2018-06-12 23:34:18 -07:00
parent b5b4d7816a
commit 39dd07b134
5 changed files with 28 additions and 59 deletions

View File

@ -67,8 +67,6 @@ enum libab_lexer_token_e {
TOKEN_KW_ARROW,
TOKEN_KW_FUN,
TOKEN_KW_RETURN,
TOKEN_KW_LET,
TOKEN_KW_BE,
TOKEN_LAST
};

View File

@ -119,5 +119,11 @@ int libab_tree_has_vector(libab_tree_variant var);
* @param tree the tree to free.
*/
void libab_tree_free_recursive(libab_tree* tree);
/**
* Frees the tree, taking into account reference-counted
* nodes.
* @param tree the tree to free.
*/
void libab_tree_refcount_free(libab_tree* tree);
#endif

View File

@ -16,13 +16,11 @@ libab_result libab_lexer_init(libab_lexer* lexer) {
"do",
"->",
"fun",
"return",
"let",
"be"};
"return"};
libab_lexer_token tokens[] = {
TOKEN_CHAR, TOKEN_ID, TOKEN_NUM, TOKEN_KW_IF,
TOKEN_KW_ELSE, TOKEN_KW_WHILE, TOKEN_KW_DO, TOKEN_KW_ARROW,
TOKEN_KW_FUN, TOKEN_KW_RETURN, TOKEN_KW_LET, TOKEN_KW_BE};
TOKEN_KW_FUN, TOKEN_KW_RETURN };
const size_t count = sizeof(tokens) / sizeof(libab_lexer_token);
eval_config_init(&lexer->config);

View File

@ -489,51 +489,6 @@ libab_result _parse_fun_param(struct parser_state* state,
return result;
}
libab_result _parse_def_fun(struct parser_state* state,
libab_tree** store_into) {
libab_result result = LIBAB_SUCCESS;
libab_tree* temp;
if (_parser_is_type(state, TOKEN_KW_LET)) {
_parser_state_step(state);
if (!_parser_eof(state)) {
result = _parser_construct_node_both(state, state->current_match,
store_into);
} else {
result = LIBAB_UNEXPECTED;
}
} else {
result = LIBAB_UNEXPECTED;
}
if (result == LIBAB_SUCCESS) {
_parser_state_step(state);
libab_ref_null(&(*store_into)->type);
(*store_into)->variant = TREE_FUN;
result = _parser_consume_char(state, ':');
}
if (result == LIBAB_SUCCESS) {
libab_ref_free(&(*store_into)->type);
result = _parse_type(state, &(*store_into)->type);
}
if (result == LIBAB_SUCCESS) {
result = _parser_consume_type(state, TOKEN_KW_BE);
}
if (result == LIBAB_SUCCESS) {
PARSE_CHILD(result, state, _parse_expression, temp,
&(*store_into)->children);
}
if (result != LIBAB_SUCCESS && *store_into) {
libab_tree_free_recursive(*store_into);
*store_into = NULL;
}
return result;
}
libab_result _parse_fun(struct parser_state* state, libab_tree** store_into) {
libab_result result = LIBAB_SUCCESS;
int is_parenth, is_comma;
@ -551,6 +506,7 @@ libab_result _parse_fun(struct parser_state* state, libab_tree** store_into) {
_parser_state_step(state);
libab_ref_null(&(*store_into)->type);
(*store_into)->variant = TREE_FUN;
(*store_into)->int_value = 1;
result = _parser_consume_char(state, '(');
}
while (result == LIBAB_SUCCESS && !_parser_eof(state) &&
@ -778,8 +734,6 @@ libab_result _parse_atom(struct parser_state* state, libab_tree** store_into) {
result = _parse_braced_block(state, store_into);
} else if (_parser_is_type(state, TOKEN_KW_FUN)) {
result = _parse_fun(state, store_into);
} else if (_parser_is_type(state, TOKEN_KW_LET)) {
result = _parse_def_fun(state, store_into);
} else if (_parser_is_type(state, TOKEN_KW_RETURN)) {
result = _parse_return(state, store_into);
} else {

View File

@ -47,10 +47,23 @@ int _tree_foreach_free(void* data, va_list args) {
return 0;
}
int _tree_needs_free(libab_tree* tree) {
return ((tree->variant == TREE_FUN && --tree->int_value) | (tree->variant != TREE_FUN));
}
void libab_tree_free_recursive(libab_tree* tree) {
if(_tree_needs_free(tree)) {
if (libab_tree_has_vector(tree->variant)) {
vec_foreach(&tree->children, NULL, compare_always, _tree_foreach_free);
}
libab_tree_free(tree);
free(tree);
}
}
void libab_tree_refcount_free(libab_tree* tree) {
if(_tree_needs_free(tree)) {
libab_tree_free(tree);
free(tree);
}
}