diff --git a/spec/runtime/stack_spec.cc b/spec/runtime/stack_spec.cc index 5343654b..bf336f35 100644 --- a/spec/runtime/stack_spec.cc +++ b/spec/runtime/stack_spec.cc @@ -39,21 +39,21 @@ int tree_selection_spy_callback(void *data, TSTree *left, TSTree *right) { void free_pop_results(StackPopResultArray *pop_results) { for (size_t i = 0; i < pop_results->size; i++) { - StackPopResult *pop_result = &pop_results->contents[i]; + StackPopResult pop_result = pop_results->contents[i]; bool matches_prior_trees = false; for (size_t j = 0; j < i; j++) { - StackPopResult *prior_result = &pop_results->contents[j]; - if (pop_result->trees == prior_result->trees) { + StackPopResult prior_result = pop_results->contents[j]; + if (pop_result.trees.contents == prior_result.trees.contents) { matches_prior_trees = true; break; } } if (!matches_prior_trees) { - for (size_t j = 0; j < pop_result->tree_count; j++) - ts_tree_release(pop_result->trees[j]); - ts_free(pop_result->trees); + for (size_t j = 0; j < pop_result.trees.size; j++) + ts_tree_release(pop_result.trees.contents[j]); + array_delete(&pop_result.trees); } } } @@ -145,9 +145,9 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(1)); StackPopResult result = results.contents[0]; - AssertThat(result.tree_count, Equals(2)); - AssertThat(result.trees[0], Equals(trees[1])); - AssertThat(result.trees[1], Equals(trees[2])); + AssertThat(result.trees.size, Equals(2)); + AssertThat(result.trees.contents[0], Equals(trees[1])); + AssertThat(result.trees.contents[1], Equals(trees[2])); AssertThat(*ts_stack_head(stack, 0), Equals({trees[0], stateA, tree_len})); free_pop_results(&results); @@ -158,8 +158,8 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(1)); result = results.contents[0]; - AssertThat(result.tree_count, Equals(1)); - AssertThat(result.trees[0], Equals(trees[0])); + AssertThat(result.trees.size, Equals(1)); + AssertThat(result.trees.contents[0], Equals(trees[0])); AssertThat(ts_stack_head(stack, 0), Equals(nullptr)); free_pop_results(&results); @@ -172,10 +172,10 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(1)); StackPopResult result = results.contents[0]; - AssertThat(result.tree_count, Equals(3)); - AssertThat(result.trees[0], Equals(trees[0])); - AssertThat(result.trees[1], Equals(trees[1])); - AssertThat(result.trees[2], Equals(trees[2])); + AssertThat(result.trees.size, Equals(3)); + AssertThat(result.trees.contents[0], Equals(trees[0])); + AssertThat(result.trees.contents[1], Equals(trees[1])); + AssertThat(result.trees.contents[2], Equals(trees[2])); AssertThat(ts_stack_head(stack, 0), Equals(nullptr)); free_pop_results(&results); @@ -186,10 +186,10 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(1)); StackPopResult result = results.contents[0]; - AssertThat(result.tree_count, Equals(3)); - AssertThat(result.trees[0], Equals(trees[0])); - AssertThat(result.trees[1], Equals(trees[1])); - AssertThat(result.trees[2], Equals(trees[2])); + AssertThat(result.trees.size, Equals(3)); + AssertThat(result.trees.contents[0], Equals(trees[0])); + AssertThat(result.trees.contents[1], Equals(trees[1])); + AssertThat(result.trees.contents[2], Equals(trees[2])); free_pop_results(&results); }); @@ -220,7 +220,7 @@ describe("Stack", [&]() { AssertThat(*ts_stack_head(stack, 1), Equals({trees[1], stateB, tree_len * 2})); AssertThat(pop_results.size, Equals(1)); StackPopResult pop_result = pop_results.contents[0]; - AssertThat(pop_result.tree_count, Equals(1)); + AssertThat(pop_result.trees.size, Equals(1)); free_pop_results(&pop_results); /* @@ -386,15 +386,15 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(2)); StackPopResult pop1 = results.contents[0]; AssertThat(pop1.head_index, Equals(0)); - AssertThat(pop1.tree_count, Equals(2)); - AssertThat(pop1.trees[0], Equals(trees[3])); - AssertThat(pop1.trees[1], Equals(trees[6])); + AssertThat(pop1.trees.size, Equals(2)); + AssertThat(pop1.trees.contents[0], Equals(trees[3])); + AssertThat(pop1.trees.contents[1], Equals(trees[6])); StackPopResult pop2 = results.contents[1]; AssertThat(pop2.head_index, Equals(1)); - AssertThat(pop2.tree_count, Equals(2)); - AssertThat(pop2.trees[0], Equals(trees[5])); - AssertThat(pop2.trees[1], Equals(trees[6])); + AssertThat(pop2.trees.size, Equals(2)); + AssertThat(pop2.trees.contents[0], Equals(trees[5])); + AssertThat(pop2.trees.contents[1], Equals(trees[6])); AssertThat(ts_stack_head_count(stack), Equals(2)); AssertThat(*ts_stack_head(stack, 0), Equals({trees[2], stateC, tree_len * 3})); @@ -445,15 +445,15 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(2)); StackPopResult pop1 = results.contents[0]; AssertThat(pop1.head_index, Equals(0)); - AssertThat(pop1.tree_count, Equals(2)); - AssertThat(pop1.trees[0], Equals(trees[6])); - AssertThat(pop1.trees[1], Equals(trees[7])); + AssertThat(pop1.trees.size, Equals(2)); + AssertThat(pop1.trees.contents[0], Equals(trees[6])); + AssertThat(pop1.trees.contents[1], Equals(trees[7])); StackPopResult pop2 = results.contents[1]; AssertThat(pop2.head_index, Equals(1)); - AssertThat(pop2.tree_count, Equals(2)); - AssertThat(pop2.trees[0], Equals(trees[6])); - AssertThat(pop2.trees[1], Equals(trees[7])); + AssertThat(pop2.trees.size, Equals(2)); + AssertThat(pop2.trees.contents[0], Equals(trees[6])); + AssertThat(pop2.trees.contents[1], Equals(trees[7])); free_pop_results(&results); }); @@ -473,9 +473,9 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(1)); StackPopResult pop1 = results.contents[0]; - AssertThat(pop1.tree_count, Equals(3)); + AssertThat(pop1.trees.size, Equals(3)); AssertThat(pop1.head_index, Equals(0)); - AssertThat(pop1.trees[0], Equals(trees[2])); + AssertThat(pop1.trees.contents[0], Equals(trees[2])); free_pop_results(&results); }); @@ -494,9 +494,9 @@ describe("Stack", [&]() { AssertThat(results.size, Equals(1)); StackPopResult pop1 = results.contents[0]; - AssertThat(pop1.tree_count, Equals(3)); + AssertThat(pop1.trees.size, Equals(3)); AssertThat(pop1.head_index, Equals(0)); - AssertThat(pop1.trees[0], Equals(trees[4])); + AssertThat(pop1.trees.contents[0], Equals(trees[4])); free_pop_results(&results); }); @@ -548,21 +548,21 @@ describe("Stack", [&]() { StackPopResult pop1 = results.contents[0]; AssertThat(ts_stack_top_tree(stack, 0), Equals(trees[3])); AssertThat(pop1.head_index, Equals(0)); - AssertThat(pop1.tree_count, Equals(2)); - AssertThat(pop1.trees[0], Equals(trees[8])); - AssertThat(pop1.trees[1], Equals(trees[9])); + AssertThat(pop1.trees.size, Equals(2)); + AssertThat(pop1.trees.contents[0], Equals(trees[8])); + AssertThat(pop1.trees.contents[1], Equals(trees[9])); StackPopResult pop2 = results.contents[1]; AssertThat(ts_stack_top_tree(stack, 1), Equals(trees[5])); AssertThat(pop2.head_index, Equals(1)); - AssertThat(pop2.tree_count, Equals(2)); - AssertThat(pop2.trees, Equals(pop1.trees)); + AssertThat(pop2.trees.size, Equals(2)); + AssertThat(pop2.trees.contents, Equals(pop1.trees.contents)); StackPopResult pop3 = results.contents[2]; AssertThat(ts_stack_top_tree(stack, 2), Equals(trees[7])); AssertThat(pop3.head_index, Equals(2)); - AssertThat(pop3.tree_count, Equals(2)); - AssertThat(pop3.trees, Equals(pop1.trees)); + AssertThat(pop3.trees.size, Equals(2)); + AssertThat(pop3.trees.contents, Equals(pop1.trees.contents)); free_pop_results(&results); }); @@ -583,26 +583,26 @@ describe("Stack", [&]() { StackPopResult pop1 = results.contents[0]; AssertThat(ts_stack_top_tree(stack, 0), Equals(trees[2])); AssertThat(pop1.head_index, Equals(0)); - AssertThat(pop1.tree_count, Equals(3)); - AssertThat(pop1.trees[0], Equals(trees[3])); - AssertThat(pop1.trees[1], Equals(trees[8])); - AssertThat(pop1.trees[2], Equals(trees[9])); + AssertThat(pop1.trees.size, Equals(3)); + AssertThat(pop1.trees.contents[0], Equals(trees[3])); + AssertThat(pop1.trees.contents[1], Equals(trees[8])); + AssertThat(pop1.trees.contents[2], Equals(trees[9])); StackPopResult pop2 = results.contents[1]; AssertThat(ts_stack_top_tree(stack, 1), Equals(trees[4])); AssertThat(pop2.head_index, Equals(1)); - AssertThat(pop2.tree_count, Equals(3)); - AssertThat(pop2.trees[0], Equals(trees[5])); - AssertThat(pop2.trees[1], Equals(trees[8])); - AssertThat(pop2.trees[2], Equals(trees[9])); + AssertThat(pop2.trees.size, Equals(3)); + AssertThat(pop2.trees.contents[0], Equals(trees[5])); + AssertThat(pop2.trees.contents[1], Equals(trees[8])); + AssertThat(pop2.trees.contents[2], Equals(trees[9])); StackPopResult pop3 = results.contents[2]; AssertThat(ts_stack_top_tree(stack, 2), Equals(trees[6])); AssertThat(pop3.head_index, Equals(2)); - AssertThat(pop3.tree_count, Equals(3)); - AssertThat(pop3.trees[0], Equals(trees[7])); - AssertThat(pop3.trees[1], Equals(trees[8])); - AssertThat(pop3.trees[2], Equals(trees[9])); + AssertThat(pop3.trees.size, Equals(3)); + AssertThat(pop3.trees.contents[0], Equals(trees[7])); + AssertThat(pop3.trees.contents[1], Equals(trees[8])); + AssertThat(pop3.trees.contents[2], Equals(trees[9])); free_pop_results(&results); }); diff --git a/src/runtime/array.h b/src/runtime/array.h index 7434316f..7390277e 100644 --- a/src/runtime/array.h +++ b/src/runtime/array.h @@ -43,6 +43,14 @@ extern "C" { array_grow((self), (self)->capacity * 2)) && \ ((self)->contents[(self)->size++] = (element), true)) +#define array_splice(self, index, old_count, new_count, new_elements) \ + array__splice((VoidArray *)(self), \ + array__elem_size(self), \ + index, \ + old_count, \ + new_count, \ + new_elements) \ + #define array_pop(self) ((self)->contents[--(self)->size]) #define array_reverse(self) \ @@ -95,6 +103,30 @@ static inline bool array__grow(VoidArray *self, size_t element_size, return true; } +static inline bool array__splice(VoidArray *self, size_t element_size, + size_t index, size_t old_count, + size_t new_count, void *elements) { + assert(index + old_count <= self->size); + assert(index < self->size); + size_t new_size = self->size + new_count - old_count; + size_t old_end = index + old_count; + size_t new_end = index + new_count; + if (new_size >= self->capacity) { + if (!array__grow(self, element_size, new_size)) + return false; + } + + char *contents = (char *)self->contents; + if (self->size > old_end) + memmove(contents + new_end * element_size, + contents + old_end * element_size, + (self->size - old_end) * element_size); + if (new_count > 0) + memcpy((contents + index * element_size), elements, new_count * element_size); + self->size += new_count - old_count; + return true; +} + static inline void array__reverse(VoidArray *self, size_t element_size) { char swap[element_size]; char *contents = (char *)self->contents; diff --git a/src/runtime/parser.c b/src/runtime/parser.c index e60c7a75..f36d83a3 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -56,17 +56,16 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self, * Since only one entry (not counting extra trees) is being popped from the * stack, there should only be one possible array of removed trees. */ - StackPopResult *first_result = array_get(&pop_results, 0); - assert(first_result->tree_count > 0); - TSTree **removed_trees = first_result->trees; - TSTree *parent = removed_trees[0]; + StackPopResult first_result = pop_results.contents[0]; + TreeArray removed_trees = first_result.trees; + TSTree *parent = *array_front(&removed_trees); LOG("breakdown_pop sym:%s, size:%lu", SYM_NAME(parent->symbol), ts_tree_total_size(parent).chars); for (size_t i = 0; i < pop_results.size; i++) { - StackPopResult *pop_result = &pop_results.contents[i]; - assert(pop_result->trees == removed_trees); - int head_index = pop_result->head_index; + StackPopResult pop_result = pop_results.contents[i]; + assert(pop_result.trees.contents == removed_trees.contents); + int head_index = pop_result.head_index; StackPushResult last_push = StackPushResultContinued; TSStateId state = ts_stack_top_state(self->stack, head_index); @@ -87,8 +86,8 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self, goto error; } - for (size_t j = 1, count = pop_result->tree_count; j < count; j++) { - TSTree *tree = pop_result->trees[j]; + for (size_t j = 1, count = pop_result.trees.size; j < count; j++) { + TSTree *tree = pop_result.trees.contents[j]; last_push = ts_stack_push(self->stack, head_index, state, tree); if (last_push == StackPushResultFailed) goto error; @@ -100,9 +99,9 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self, assert(last_push == StackPushResultMerged); } - for (size_t j = 0, count = first_result->tree_count; j < count; j++) - ts_tree_release(first_result->trees[j]); - ts_free(removed_trees); + for (size_t j = 0, count = first_result.trees.size; j < count; j++) + ts_tree_release(first_result.trees.contents[j]); + array_delete(&removed_trees); } while (last_child && last_child->child_count > 0); @@ -318,7 +317,7 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head, size_t removed_heads = 0; for (size_t i = 0; i < pop_results.size; i++) { - StackPopResult *pop_result = &pop_results.contents[i]; + StackPopResult pop_result = pop_results.contents[i]; /* * If the same set of trees led to a previous stack head, reuse the parent @@ -328,32 +327,32 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head, TSTree *parent = NULL; size_t trailing_extra_count = 0; for (size_t j = 0; j < i; j++) { - StackPopResult *prior_result = &pop_results.contents[j]; - if (pop_result->trees == prior_result->trees) { + StackPopResult prior_result = pop_results.contents[j]; + if (pop_result.trees.contents == prior_result.trees.contents) { parent = self->reduce_parents.contents[j]; - trailing_extra_count = pop_result->tree_count - parent->child_count; + trailing_extra_count = pop_result.trees.size - parent->child_count; ts_tree_retain(parent); - for (size_t k = parent->child_count; k < pop_result->tree_count; k++) - ts_tree_retain(pop_result->trees[k]); + for (size_t k = parent->child_count; k < pop_result.trees.size; k++) + ts_tree_retain(pop_result.trees.contents[k]); break; } } if (!parent) { - for (size_t j = pop_result->tree_count - 1; j + 1 > 0; j--) { - if (pop_result->trees[j]->extra) { + for (size_t j = pop_result.trees.size - 1; j + 1 > 0; j--) { + if (pop_result.trees.contents[j]->extra) { trailing_extra_count++; } else break; } - size_t child_count = pop_result->tree_count - trailing_extra_count; + size_t child_count = pop_result.trees.size - trailing_extra_count; parent = - ts_tree_make_node(symbol, child_count, pop_result->trees, metadata); + ts_tree_make_node(symbol, child_count, pop_result.trees.contents, metadata); if (!parent) { - for (size_t i = 0; i < pop_result->tree_count; i++) - ts_tree_release(pop_result->trees[i]); - ts_free(pop_result->trees); + for (size_t i = 0; i < pop_result.trees.size; i++) + ts_tree_release(pop_result.trees.contents[i]); + array_delete(&pop_result.trees); goto error; } } @@ -361,7 +360,7 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head, if (!array_push(&self->reduce_parents, parent)) goto error; - int new_head = pop_result->head_index - removed_heads; + int new_head = pop_result.head_index - removed_heads; if (i > 0) { if (symbol == ts_builtin_sym_error) { @@ -425,8 +424,8 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head, if (trailing_extra_count > 0) { for (size_t j = 0; j < trailing_extra_count; j++) { - size_t index = pop_result->tree_count - trailing_extra_count + j; - TSTree *tree = pop_result->trees[index]; + size_t index = pop_result.trees.size - trailing_extra_count + j; + TSTree *tree = pop_result.trees.contents[index]; switch (ts_stack_push(self->stack, new_head, state, tree)) { case StackPushResultFailed: return FailedToUpdateStackHead; @@ -575,34 +574,19 @@ static ParseActionResult ts_parser__accept(TSParser *self, int head) { goto error; for (size_t j = 0; j < pop_results.size; j++) { - StackPopResult *pop_result = &pop_results.contents[j]; + StackPopResult pop_result = pop_results.contents[j]; + TreeArray trees = pop_result.trees; - for (size_t i = 0; i < pop_result->tree_count; i++) { - if (!pop_result->trees[i]->extra) { - TSTree *root = pop_result->trees[i]; - size_t leading_extra_count = i; - size_t trailing_extra_count = pop_result->tree_count - 1 - i; - size_t new_count = - root->child_count + leading_extra_count + trailing_extra_count; + for (size_t i = 0; i < trees.size; i++) { + if (!trees.contents[i]->extra) { + TSTree *root = trees.contents[i]; + if (!array_splice(&trees, i, 1, root->child_count, root->children)) + goto error; + ts_tree_set_children(root, trees.size, trees.contents); + if (!trees.size) + array_delete(&trees); - if (new_count > 0) { - TSTree **new_children = ts_calloc(new_count, sizeof(TSTree *)); - if (!new_children) - goto error; - if (leading_extra_count > 0) - memcpy(new_children, pop_result->trees, - leading_extra_count * sizeof(TSTree *)); - if (root->child_count > 0) - memcpy(new_children + leading_extra_count, root->children, - root->child_count * sizeof(TSTree *)); - if (trailing_extra_count > 0) - memcpy(new_children + leading_extra_count + root->child_count, - pop_result->trees + leading_extra_count + 1, - trailing_extra_count * sizeof(TSTree *)); - ts_tree_set_children(root, new_count, new_children); - } - - ts_parser__remove_head(self, pop_result->head_index); + ts_parser__remove_head(self, pop_result.head_index); int comparison = ts_parser__select_tree(self, self->finished_tree, root); if (comparison > 0) { ts_tree_release(self->finished_tree); @@ -611,7 +595,6 @@ static ParseActionResult ts_parser__accept(TSParser *self, int head) { ts_tree_release(root); } - ts_free(pop_result->trees); break; } } @@ -621,10 +604,10 @@ static ParseActionResult ts_parser__accept(TSParser *self, int head) { error: if (pop_results.size) { - StackPopResult *pop_result = array_front(&pop_results); - for (size_t i = 0; i < pop_result->tree_count; i++) - ts_tree_release(pop_result->trees[i]); - ts_free(pop_result->trees); + StackPopResult pop_result = *array_front(&pop_results); + for (size_t i = 0; i < pop_result.trees.size; i++) + ts_tree_release(pop_result.trees.contents[i]); + array_delete(&pop_result.trees); } return FailedToUpdateStackHead; } diff --git a/src/runtime/stack.c b/src/runtime/stack.c index 2f7cfc64..56e5eb07 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -19,8 +19,6 @@ typedef struct StackNode { short unsigned int ref_count; } StackNode; -typedef Array(TSTree *) TreeArray; - typedef struct { size_t goal_tree_count; StackNode *node; @@ -197,21 +195,21 @@ static void ts_stack__add_alternative_tree(Stack *self, StackNode *node, } static void ts_stack__clear_pop_result(Stack *self, StackPopResult *result) { - for (size_t i = 0; i < result->tree_count; i++) - ts_tree_release(result->trees[i]); - ts_free(result->trees); + for (size_t i = 0; i < result->trees.size; i++) + ts_tree_release(result->trees.contents[i]); + array_delete(&result->trees); } static void ts_stack__add_alternative_pop_result(Stack *self, StackPopResult *result, StackPopResult *new_result) { bool should_update = false; - if (result->tree_count < new_result->tree_count) { + if (result->trees.size < new_result->trees.size) { should_update = true; - } else if (result->tree_count == new_result->tree_count) { - for (size_t i = 0; i < result->tree_count; i++) { - TSTree *tree = result->trees[i]; - TSTree *new_tree = new_result->trees[i]; + } else if (result->trees.size == new_result->trees.size) { + for (size_t i = 0; i < result->trees.size; i++) { + TSTree *tree = result->trees.contents[i]; + TSTree *new_tree = new_result->trees.contents[i]; int comparison = self->tree_selection_function( self->tree_selection_payload, tree, new_tree); if (comparison < 0) { @@ -226,7 +224,7 @@ static void ts_stack__add_alternative_pop_result(Stack *self, if (should_update) { ts_stack__clear_pop_result(self, result); result->trees = new_result->trees; - result->tree_count = new_result->tree_count; + result->trees.size = new_result->trees.size; } else { ts_stack__clear_pop_result(self, new_result); } @@ -394,8 +392,7 @@ StackPopResultArray ts_stack_pop(Stack *self, int head_index, int child_count, array_reverse(&path->trees); StackPopResult result = { - .trees = path->trees.contents, - .tree_count = path->trees.size, + .trees = path->trees, .head_index = -1, }; diff --git a/src/runtime/stack.h b/src/runtime/stack.h index 874a618c..d8a83dd1 100644 --- a/src/runtime/stack.h +++ b/src/runtime/stack.h @@ -16,9 +16,10 @@ typedef struct { TSLength position; } StackEntry; +typedef Array(TSTree *) TreeArray; + typedef struct { - TSTree **trees; - size_t tree_count; + TreeArray trees; int head_index; } StackPopResult;