Make vector struct type-safe

This commit is contained in:
Max Brunsfeld 2016-02-17 14:45:00 -08:00
parent 3f08bfb264
commit 6fa7eca966
6 changed files with 223 additions and 246 deletions

View file

@ -37,13 +37,13 @@ int tree_selection_spy_callback(void *data, TSTree *left, TSTree *right) {
return 1;
}
void free_pop_results(Vector *pop_results) {
void free_pop_results(StackPopResultVector *pop_results) {
for (size_t i = 0; i < pop_results->size; i++) {
StackPopResult *pop_result = (StackPopResult *)vector_get(pop_results, i);
StackPopResult *pop_result = &pop_results->contents[i];
bool matches_prior_trees = false;
for (size_t j = 0; j < i; j++) {
StackPopResult *prior_result = (StackPopResult *)vector_get(pop_results, j);
StackPopResult *prior_result = &pop_results->contents[j];
if (pop_result->trees == prior_result->trees) {
matches_prior_trees = true;
break;
@ -141,10 +141,10 @@ describe("Stack", [&]() {
/*
* A0.
*/
Vector results = ts_stack_pop(stack, 0, 2, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
AssertThat(results.size, Equals<size_t>(1));
StackPopResult result = *(StackPopResult *)vector_get(&results, 0);
StackPopResult result = *vector_get(&results, 0);
AssertThat(result.tree_count, Equals<size_t>(2));
AssertThat(result.trees[0], Equals(trees[1]));
AssertThat(result.trees[1], Equals(trees[2]));
@ -168,10 +168,10 @@ describe("Stack", [&]() {
it("does not count 'extra' trees toward the count", [&]() {
trees[1]->extra = true;
Vector results = ts_stack_pop(stack, 0, 2, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
AssertThat(results.size, Equals<size_t>(1));
StackPopResult result = *(StackPopResult *)vector_get(&results, 0);
StackPopResult result = *vector_get(&results, 0);
AssertThat(result.tree_count, Equals<size_t>(3));
AssertThat(result.trees[0], Equals(trees[0]));
AssertThat(result.trees[1], Equals(trees[1]));
@ -182,10 +182,10 @@ describe("Stack", [&]() {
});
it("pops the entire stack when given a negative count", [&]() {
Vector results = ts_stack_pop(stack, 0, -1, false);
StackPopResultVector results = ts_stack_pop(stack, 0, -1, false);
AssertThat(results.size, Equals<size_t>(1));
StackPopResult result = *(StackPopResult *)vector_get(&results, 0);
StackPopResult result = *vector_get(&results, 0);
AssertThat(result.tree_count, Equals<size_t>(3));
AssertThat(result.trees[0], Equals(trees[0]));
AssertThat(result.trees[1], Equals(trees[1]));
@ -213,7 +213,7 @@ describe("Stack", [&]() {
* \.
*/
ts_stack_push(stack, 0, stateD, trees[3]);
Vector pop_results = ts_stack_pop(stack, 1, 1, false);
StackPopResultVector pop_results = ts_stack_pop(stack, 1, 1, false);
AssertThat(ts_stack_head_count(stack), Equals(2));
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[3], stateD, tree_len * 4}));
@ -381,16 +381,16 @@ describe("Stack", [&]() {
* A0__B1__C2.
* \__E4.
*/
Vector pop = ts_stack_pop(stack, 0, 2, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
AssertThat(pop.size, Equals<size_t>(2));
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
AssertThat(results.size, Equals<size_t>(2));
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
AssertThat(pop1.head_index, Equals(0));
AssertThat(pop1.tree_count, Equals<size_t>(2));
AssertThat(pop1.trees[0], Equals(trees[3]));
AssertThat(pop1.trees[1], Equals(trees[6]));
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
AssertThat(pop2.head_index, Equals(1));
AssertThat(pop2.tree_count, Equals<size_t>(2));
AssertThat(pop2.trees[0], Equals(trees[5]));
@ -400,7 +400,7 @@ describe("Stack", [&]() {
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[2], stateC, tree_len * 3}));
AssertThat(*ts_stack_head(stack, 1), Equals<StackEntry>({trees[4], stateE, tree_len * 3}));
free_pop_results(&pop);
free_pop_results(&results);
});
});
@ -417,12 +417,12 @@ describe("Stack", [&]() {
* A0__B1__C2__D3__G6.
* \__E4__F5__/
*/
Vector pop = ts_stack_pop(stack, 0, 1, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 1, false);
AssertThat(pop.size, Equals<size_t>(1));
AssertThat(results.size, Equals<size_t>(1));
AssertThat(ts_stack_head_count(stack), Equals(1));
free_pop_results(&pop);
free_pop_results(&results);
});
});
@ -439,23 +439,23 @@ describe("Stack", [&]() {
* A0__B1__C2__D3.
* \__E4__F5.
*/
Vector pop = ts_stack_pop(stack, 0, 2, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
AssertThat(ts_stack_head_count(stack), Equals(2));
AssertThat(pop.size, Equals<size_t>(2));
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
AssertThat(results.size, Equals<size_t>(2));
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
AssertThat(pop1.head_index, Equals(0));
AssertThat(pop1.tree_count, Equals<size_t>(2));
AssertThat(pop1.trees[0], Equals(trees[6]));
AssertThat(pop1.trees[1], Equals(trees[7]));
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
AssertThat(pop2.head_index, Equals(1));
AssertThat(pop2.tree_count, Equals<size_t>(2));
AssertThat(pop2.trees[0], Equals(trees[6]));
AssertThat(pop2.trees[1], Equals(trees[7]));
free_pop_results(&pop);
free_pop_results(&results);
});
});
@ -467,17 +467,17 @@ describe("Stack", [&]() {
/*
* A0__B1.
*/
Vector pop = ts_stack_pop(stack, 0, 3, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 3, false);
AssertThat(ts_stack_head_count(stack), Equals(1));
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[1], stateB, tree_len * 2}));
AssertThat(pop.size, Equals<size_t>(1));
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
AssertThat(results.size, Equals<size_t>(1));
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
AssertThat(pop1.tree_count, Equals<size_t>(3));
AssertThat(pop1.head_index, Equals(0));
AssertThat(pop1.trees[0], Equals(trees[2]));
free_pop_results(&pop);
free_pop_results(&results);
});
});
@ -488,17 +488,17 @@ describe("Stack", [&]() {
/*
* A0__B1.
*/
Vector pop = ts_stack_pop(stack, 0, 3, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 3, false);
AssertThat(ts_stack_head_count(stack), Equals(1));
AssertThat(*ts_stack_head(stack, 0), Equals<StackEntry>({trees[1], stateB, tree_len * 2}));
AssertThat(pop.size, Equals<size_t>(1));
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
AssertThat(results.size, Equals<size_t>(1));
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
AssertThat(pop1.tree_count, Equals<size_t>(3));
AssertThat(pop1.head_index, Equals(0));
AssertThat(pop1.trees[0], Equals(trees[4]));
free_pop_results(&pop);
free_pop_results(&results);
});
});
});
@ -540,31 +540,31 @@ describe("Stack", [&]() {
* \__E4__F5.
* \__G6__H7.
*/
Vector pop = ts_stack_pop(stack, 0, 2, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 2, false);
AssertThat(ts_stack_head_count(stack), Equals(3));
AssertThat(pop.size, Equals<size_t>(3));
AssertThat(results.size, Equals<size_t>(3));
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
AssertThat(ts_stack_top_tree(stack, 0), Equals(trees[3]));
AssertThat(pop1.head_index, Equals(0));
AssertThat(pop1.tree_count, Equals<size_t>(2));
AssertThat(pop1.trees[0], Equals(trees[8]));
AssertThat(pop1.trees[1], Equals(trees[9]));
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
AssertThat(ts_stack_top_tree(stack, 1), Equals(trees[5]));
AssertThat(pop2.head_index, Equals(1));
AssertThat(pop2.tree_count, Equals<size_t>(2));
AssertThat(pop2.trees, Equals(pop1.trees));
StackPopResult pop3 = *(StackPopResult *)vector_get(&pop, 2);
StackPopResult pop3 = *(StackPopResult *)vector_get(&results, 2);
AssertThat(ts_stack_top_tree(stack, 2), Equals(trees[7]));
AssertThat(pop3.head_index, Equals(2));
AssertThat(pop3.tree_count, Equals<size_t>(2));
AssertThat(pop3.trees, Equals(pop1.trees));
free_pop_results(&pop);
free_pop_results(&results);
});
});
@ -575,12 +575,12 @@ describe("Stack", [&]() {
* \__E4.
* \__G6.
*/
Vector pop = ts_stack_pop(stack, 0, 3, false);
StackPopResultVector results = ts_stack_pop(stack, 0, 3, false);
AssertThat(ts_stack_head_count(stack), Equals(3));
AssertThat(pop.size, Equals<size_t>(3));
AssertThat(results.size, Equals<size_t>(3));
StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0);
StackPopResult pop1 = *(StackPopResult *)vector_get(&results, 0);
AssertThat(ts_stack_top_tree(stack, 0), Equals(trees[2]));
AssertThat(pop1.head_index, Equals(0));
AssertThat(pop1.tree_count, Equals<size_t>(3));
@ -588,7 +588,7 @@ describe("Stack", [&]() {
AssertThat(pop1.trees[1], Equals(trees[8]));
AssertThat(pop1.trees[2], Equals(trees[9]));
StackPopResult pop2 = *(StackPopResult *)vector_get(&pop, 1);
StackPopResult pop2 = *(StackPopResult *)vector_get(&results, 1);
AssertThat(ts_stack_top_tree(stack, 1), Equals(trees[4]));
AssertThat(pop2.head_index, Equals(1));
AssertThat(pop2.tree_count, Equals<size_t>(3));
@ -596,7 +596,7 @@ describe("Stack", [&]() {
AssertThat(pop2.trees[1], Equals(trees[8]));
AssertThat(pop2.trees[2], Equals(trees[9]));
StackPopResult pop3 = *(StackPopResult *)vector_get(&pop, 2);
StackPopResult pop3 = *(StackPopResult *)vector_get(&results, 2);
AssertThat(ts_stack_top_tree(stack, 2), Equals(trees[6]));
AssertThat(pop3.head_index, Equals(2));
AssertThat(pop3.tree_count, Equals<size_t>(3));
@ -604,7 +604,7 @@ describe("Stack", [&]() {
AssertThat(pop3.trees[1], Equals(trees[8]));
AssertThat(pop3.trees[2], Equals(trees[9]));
free_pop_results(&pop);
free_pop_results(&results);
});
});
});

View file

@ -26,11 +26,11 @@
#define BOOL_STRING(value) (value ? "true" : "false")
typedef struct {
struct LookaheadState {
TSTree *reusable_subtree;
size_t reusable_subtree_pos;
bool is_verifying;
} LookaheadState;
};
typedef enum {
UpdatedStackHead,
@ -47,8 +47,8 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self,
TSTree *last_child = NULL;
do {
Vector pop_results = ts_stack_pop(self->stack, head, 1, false);
if (!vector_valid(&pop_results))
StackPopResultVector pop_results = ts_stack_pop(self->stack, head, 1, false);
if (!pop_results.size)
return FailedToUpdateStackHead;
assert(pop_results.size > 0);
@ -64,7 +64,7 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self,
ts_tree_total_size(parent).chars);
for (size_t i = 0; i < pop_results.size; i++) {
StackPopResult *pop_result = vector_get(&pop_results, i);
StackPopResult *pop_result = &pop_results.contents[i];
assert(pop_result->trees == removed_trees);
int head_index = pop_result->head_index;
@ -238,9 +238,8 @@ static TSTree *ts_parser__get_next_lookahead(TSParser *self, int head) {
static int ts_parser__split(TSParser *self, int head) {
int result = ts_stack_split(self->stack, head);
assert(result == (int)self->lookahead_states.size);
LookaheadState lookahead_state =
*(LookaheadState *)vector_get(&self->lookahead_states, head);
vector_push(&self->lookahead_states, &lookahead_state);
LookaheadState lookahead_state = *vector_get(&self->lookahead_states, head);
vector_push(&self->lookahead_states, lookahead_state);
return result;
}
@ -311,14 +310,15 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
vector_clear(&self->reduce_parents);
const TSSymbolMetadata *all_metadata = self->language->symbol_metadata;
TSSymbolMetadata metadata = all_metadata[symbol];
Vector pop_results = ts_stack_pop(self->stack, head, child_count, count_extra);
if (!vector_valid(&pop_results))
StackPopResultVector pop_results =
ts_stack_pop(self->stack, head, child_count, count_extra);
if (!pop_results.size)
return FailedToUpdateStackHead;
size_t removed_heads = 0;
for (size_t i = 0; i < pop_results.size; i++) {
StackPopResult *pop_result = vector_get(&pop_results, i);
StackPopResult *pop_result = &pop_results.contents[i];
/*
* If the same set of trees led to a previous stack head, reuse the parent
@ -328,10 +328,9 @@ 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 = vector_get(&pop_results, j);
StackPopResult *prior_result = &pop_results.contents[j];
if (pop_result->trees == prior_result->trees) {
TSTree **existing_parent = vector_get(&self->reduce_parents, j);
parent = *existing_parent;
parent = self->reduce_parents.contents[j];
trailing_extra_count = pop_result->tree_count - parent->child_count;
ts_tree_retain(parent);
for (size_t k = parent->child_count; k < pop_result->tree_count; k++)
@ -359,7 +358,7 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
}
}
if (!vector_push(&self->reduce_parents, &parent))
if (!vector_push(&self->reduce_parents, parent))
goto error;
int new_head = pop_result->head_index - removed_heads;
@ -372,13 +371,14 @@ static ParseActionResult ts_parser__reduce(TSParser *self, int head,
}
/*
* If the stack has split in the process of popping, create a duplicate of
* If the stack has split in the process of popping, create a duplicate
* of
* the lookahead state for this head, for the new head.
*/
LOG("split_during_reduce new_head:%d", new_head);
LookaheadState lookahead_state =
*(LookaheadState *)vector_get(&self->lookahead_states, head);
if (!vector_push(&self->lookahead_states, &lookahead_state))
*vector_get(&self->lookahead_states, head);
if (!vector_push(&self->lookahead_states, lookahead_state))
goto error;
}
@ -565,18 +565,18 @@ static ParseActionResult ts_parser__start(TSParser *self, TSInput input,
.is_verifying = false,
};
vector_clear(&self->lookahead_states);
vector_push(&self->lookahead_states, &lookahead_state);
vector_push(&self->lookahead_states, lookahead_state);
self->finished_tree = NULL;
return UpdatedStackHead;
}
static ParseActionResult ts_parser__accept(TSParser *self, int head) {
Vector pop_results = ts_stack_pop(self->stack, head, -1, true);
StackPopResultVector pop_results = ts_stack_pop(self->stack, head, -1, true);
if (!pop_results.size)
goto error;
for (size_t j = 0; j < pop_results.size; j++) {
StackPopResult *pop_result = vector_get(&pop_results, j);
StackPopResult *pop_result = &pop_results.contents[j];
for (size_t i = 0; i < pop_result->tree_count; i++) {
if (!pop_result->trees[i]->extra) {
@ -622,7 +622,7 @@ static ParseActionResult ts_parser__accept(TSParser *self, int head) {
error:
if (pop_results.size) {
StackPopResult *pop_result = vector_get(&pop_results, 0);
StackPopResult *pop_result = vector_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);
@ -745,8 +745,8 @@ bool ts_parser_init(TSParser *self) {
ts_lexer_init(&self->lexer);
self->finished_tree = NULL;
self->stack = NULL;
self->lookahead_states = vector_new(sizeof(LookaheadState));
self->reduce_parents = vector_new(sizeof(TSTree *));
vector_init(&self->lookahead_states);
vector_init(&self->reduce_parents);
self->stack = ts_stack_new();
if (!self->stack)

View file

@ -8,12 +8,14 @@ extern "C" {
#include "runtime/stack.h"
#include "runtime/vector.h"
typedef struct LookaheadState LookaheadState;
typedef struct {
TSLexer lexer;
Stack *stack;
const TSLanguage *language;
Vector lookahead_states;
Vector reduce_parents;
Vector(LookaheadState) lookahead_states;
Vector(TSTree *) reduce_parents;
TSTree *finished_tree;
bool is_split;
} TSParser;

View file

@ -19,23 +19,23 @@ typedef struct StackNode {
short unsigned int ref_count;
} StackNode;
struct Stack {
Vector heads;
Vector pop_results;
Vector pop_paths;
Vector node_pool;
void *tree_selection_payload;
TreeSelectionFunction tree_selection_function;
};
typedef Vector(TSTree *) TreeVector;
typedef struct {
size_t goal_tree_count;
StackNode *node;
Vector trees;
TreeVector trees;
bool is_shared;
} PopPath;
static StackNode *NULL_NODE = NULL;
struct Stack {
Vector(StackNode *) heads;
StackPopResultVector pop_results;
Vector(PopPath) pop_paths;
Vector(StackNode *) node_pool;
void *tree_selection_payload;
TreeSelectionFunction tree_selection_function;
};
/*
* Section: Stack lifecycle
@ -50,10 +50,10 @@ Stack *ts_stack_new() {
if (!self)
goto error;
self->heads = vector_new(sizeof(StackNode *));
self->pop_results = vector_new(sizeof(StackPopResult));
self->pop_paths = vector_new(sizeof(PopPath));
self->node_pool = vector_new(sizeof(StackNode *));
vector_init(&self->heads);
vector_init(&self->pop_results);
vector_init(&self->pop_paths);
vector_init(&self->node_pool);
self->tree_selection_payload = NULL;
self->tree_selection_function = ts_stack__default_tree_selection;
@ -69,7 +69,7 @@ Stack *ts_stack_new() {
if (!vector_grow(&self->node_pool, 20))
goto error;
vector_push(&self->heads, &NULL_NODE);
vector_push(&self->heads, NULL);
return self;
@ -108,7 +108,7 @@ TSTree *ts_stack_top_tree(const Stack *self, int head) {
}
StackEntry *ts_stack_head(Stack *self, int head) {
StackNode *node = *(StackNode **)vector_get(&self->heads, head);
StackNode *node = self->heads.contents[head];
return node ? &node->entry : NULL;
}
@ -148,7 +148,7 @@ static bool stack_node_release(Stack *self, StackNode *node) {
if (self->node_pool.size >= MAX_NODE_POOL_SIZE)
ts_free(node);
else
vector_push(&self->node_pool, &node);
vector_push(&self->node_pool, node);
return true;
} else {
@ -156,7 +156,8 @@ static bool stack_node_release(Stack *self, StackNode *node) {
}
}
static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state, TSTree *tree) {
static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state,
TSTree *tree) {
assert(tree->ref_count > 0);
StackNode *node;
if (self->node_pool.size == 0) {
@ -164,7 +165,7 @@ static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state,
if (!node)
return NULL;
} else {
node = *(StackNode **)vector_pop(&self->node_pool);
node = vector_pop(&self->node_pool);
}
ts_tree_retain(tree);
@ -184,8 +185,8 @@ static StackNode *stack_node_new(Stack *self, StackNode *next, TSStateId state,
static void ts_stack__add_alternative_tree(Stack *self, StackNode *node,
TSTree *tree) {
if (tree != node->entry.tree) {
int comparison = self->tree_selection_function(
self->tree_selection_payload, node->entry.tree, tree);
int comparison = self->tree_selection_function(self->tree_selection_payload,
node->entry.tree, tree);
if (comparison > 0) {
ts_tree_retain(tree);
@ -211,7 +212,8 @@ static void ts_stack__add_alternative_pop_result(Stack *self,
for (size_t i = 0; i < result->tree_count; i++) {
TSTree *tree = result->trees[i];
TSTree *new_tree = new_result->trees[i];
int comparison = self->tree_selection_function(self->tree_selection_payload, tree, new_tree);
int comparison = self->tree_selection_function(
self->tree_selection_payload, tree, new_tree);
if (comparison < 0) {
break;
} else if (comparison > 0) {
@ -230,7 +232,6 @@ static void ts_stack__add_alternative_pop_result(Stack *self,
}
}
static void ts_stack__add_node_successor(Stack *self, StackNode *node,
StackNode *new_successor) {
for (int i = 0; i < node->successor_count; i++) {
@ -259,7 +260,7 @@ static void ts_stack__add_node_successor(Stack *self, StackNode *node,
*/
static int ts_stack__add_head(Stack *self, StackNode *node) {
if (vector_push(&self->heads, &node)) {
if (vector_push(&self->heads, node)) {
stack_node_retain(node);
return self->heads.size - 1;
} else {
@ -269,16 +270,15 @@ static int ts_stack__add_head(Stack *self, StackNode *node) {
static int ts_stack__find_head(Stack *self, StackNode *node) {
for (size_t i = 0; i < self->heads.size; i++) {
StackNode **existing_node = vector_get(&self->heads, i);
if (*existing_node == node)
if (self->heads.contents[i] == node)
return i;
}
return -1;
}
void ts_stack_remove_head(Stack *self, int head_index) {
StackNode **node = vector_get(&self->heads, head_index);
stack_node_release(self, *node);
StackNode *node = *vector_get(&self->heads, head_index);
stack_node_release(self, node);
vector_erase(&self->heads, head_index);
}
@ -288,57 +288,55 @@ void ts_stack_remove_head(Stack *self, int head_index) {
StackPushResult ts_stack_push(Stack *self, int head_index, TSStateId state,
TSTree *tree) {
assert((size_t)head_index < self->heads.size);
assert(tree);
TSLength position = ts_tree_total_size(tree);
StackNode **current_head = vector_get(&self->heads, head_index);
if (*current_head)
position = ts_length_add((*current_head)->entry.position, position);
StackNode *current_head = *vector_get(&self->heads, head_index);
if (current_head)
position = ts_length_add(current_head->entry.position, position);
for (int i = 0; i < head_index; i++) {
StackNode **prior_node = vector_get(&self->heads, i);
StackEntry prior_entry = (*prior_node)->entry;
if (prior_entry.state == state && ts_length_eq(prior_entry.position, position)) {
ts_stack__add_alternative_tree(self, *prior_node, tree);
ts_stack__add_node_successor(self, *prior_node, *current_head);
StackNode *prior_node = self->heads.contents[i];
StackEntry prior_entry = prior_node->entry;
if (prior_entry.state == state &&
ts_length_eq(prior_entry.position, position)) {
ts_stack__add_alternative_tree(self, prior_node, tree);
ts_stack__add_node_successor(self, prior_node, current_head);
ts_stack_remove_head(self, head_index);
return StackPushResultMerged;
}
}
StackNode *new_head = stack_node_new(self, *current_head, state, tree);
StackNode *new_head = stack_node_new(self, current_head, state, tree);
if (!new_head)
return StackPushResultFailed;
stack_node_release(self, *current_head);
vector_set(&self->heads, head_index, &new_head);
stack_node_release(self, current_head);
self->heads.contents[head_index] = new_head;
return StackPushResultContinued;
}
int ts_stack_split(Stack *self, int head_index) {
StackNode **head = vector_get(&self->heads, head_index);
return ts_stack__add_head(self, *head);
StackNode *head = self->heads.contents[head_index];
return ts_stack__add_head(self, head);
}
Vector ts_stack_pop(Stack *self, int head_index, int child_count,
bool count_extra) {
StackPopResultVector ts_stack_pop(Stack *self, int head_index, int child_count,
bool count_extra) {
vector_clear(&self->pop_results);
vector_clear(&self->pop_paths);
StackNode *previous_head = *(StackNode **)vector_get(&self->heads, head_index);
StackNode *previous_head = *vector_get(&self->heads, head_index);
int capacity = (child_count == -1) ? STARTING_TREE_CAPACITY : child_count;
PopPath initial_path = {
.goal_tree_count = child_count,
.node = previous_head,
.trees = vector_new(sizeof(TSTree *)),
.is_shared = false,
};
vector_init(&initial_path.trees);
if (!vector_grow(&initial_path.trees, capacity))
goto error;
if (!vector_push(&self->pop_paths, &initial_path))
if (!vector_push(&self->pop_paths, initial_path))
goto error;
/*
@ -350,7 +348,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
all_paths_done = true;
for (size_t i = 0; i < self->pop_paths.size; i++) {
PopPath *path = vector_get(&self->pop_paths, i);
PopPath *path = &self->pop_paths.contents[i];
StackNode *node = path->node;
if (!node || path->trees.size == path->goal_tree_count)
@ -369,23 +367,19 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
* the additional successors.
*/
if (path->is_shared) {
path->trees = vector_copy(&path->trees);
for (size_t j = 0; j < path->trees.size; j++) {
TSTree **tree = vector_get(&path->trees, j);
ts_tree_retain(*tree);
}
path->trees = (TreeVector)vector_copy(&path->trees);
for (size_t j = 0; j < path->trees.size; j++)
ts_tree_retain(path->trees.contents[j]);
path->is_shared = false;
}
ts_tree_retain(node->entry.tree);
if (!vector_push(&path->trees, &node->entry.tree))
if (!vector_push(&path->trees, node->entry.tree))
goto error;
path->node = path->node->successors[0];
PopPath path_copy = *path;
for (int j = 1; j < node->successor_count; j++) {
if (!vector_push(&self->pop_paths, &path_copy))
if (!vector_push(&self->pop_paths, *path))
goto error;
PopPath *next_path = vector_back(&self->pop_paths);
@ -396,7 +390,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
}
for (size_t i = 0; i < self->pop_paths.size; i++) {
PopPath *path = vector_get(&self->pop_paths, i);
PopPath *path = &self->pop_paths.contents[i];
if (!path->is_shared)
vector_reverse(&path->trees);
@ -409,7 +403,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
if (i == 0) {
stack_node_retain(path->node);
vector_set(&self->heads, head_index, &path->node);
self->heads.contents[head_index] = path->node;
result.head_index = head_index;
} else {
result.head_index = ts_stack__find_head(self, path->node);
@ -420,7 +414,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
} else {
bool merged_result = false;
for (size_t j = 0; j < self->pop_results.size; j++) {
StackPopResult *prior_result = vector_get(&self->pop_results, j);
StackPopResult *prior_result = &self->pop_results.contents[j];
if (prior_result->head_index == result.head_index) {
ts_stack__add_alternative_pop_result(self, prior_result, &result);
merged_result = true;
@ -432,7 +426,7 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
}
}
if (!vector_push(&self->pop_results, &result))
if (!vector_push(&self->pop_results, result))
goto error;
}
@ -441,30 +435,29 @@ Vector ts_stack_pop(Stack *self, int head_index, int child_count,
error:
vector_delete(&initial_path.trees);
return vector_new(0);
StackPopResultVector result;
vector_init(&result);
return result;
}
void ts_stack_shrink(Stack *self, int head_index, int count) {
StackNode **head = vector_get(&self->heads, head_index);
StackNode *new_head = *head;
StackNode *head = *vector_get(&self->heads, head_index);
StackNode *new_head = head;
for (int i = 0; i < count; i++) {
if (new_head->successor_count == 0)
break;
new_head = new_head->successors[0];
}
stack_node_retain(new_head);
stack_node_release(self, *head);
vector_set(&self->heads, head_index, new_head);
stack_node_release(self, head);
self->heads.contents[head_index] = new_head;
}
void ts_stack_clear(Stack *self) {
for (size_t i = 0; i < self->heads.size; i++) {
StackNode **head = vector_get(&self->heads, i);
stack_node_release(self, *head);
}
for (size_t i = 0; i < self->heads.size; i++)
stack_node_release(self, self->heads.contents[i]);
vector_clear(&self->heads);
vector_push(&self->heads, &NULL_NODE);
vector_push(&self->heads, NULL);
}
void ts_stack_set_tree_selection_callback(Stack *self, void *payload,
@ -479,12 +472,11 @@ void ts_stack_delete(Stack *self) {
if (self->pop_paths.contents)
vector_delete(&self->pop_paths);
ts_stack_clear(self);
for (size_t i = 0; i < self->node_pool.size; i++) {
StackNode **node = vector_get(&self->node_pool, i);
ts_free(*node);
}
if (self->node_pool.contents)
if (self->node_pool.contents) {
for (size_t i = 0; i < self->node_pool.size; i++)
ts_free(self->node_pool.contents[i]);
vector_delete(&self->node_pool);
}
vector_delete(&self->heads);
ts_free(self);
}

View file

@ -28,6 +28,8 @@ typedef enum {
StackPushResultContinued,
} StackPushResult;
typedef Vector(StackPopResult) StackPopResultVector;
typedef int (*TreeSelectionFunction)(void *, TSTree *, TSTree *);
/*
@ -90,7 +92,8 @@ StackPushResult ts_stack_push(Stack *, int head, TSStateId, TSTree *);
* which had previously been merged. It returns a struct that indicates the
* index of each revealed head and the trees removed from that head.
*/
Vector ts_stack_pop(Stack *, int head, int count, bool count_extra);
StackPopResultVector ts_stack_pop(Stack *, int head, int count,
bool count_extra);
/*
* Remove the given number of entries from the given head of the stack.

View file

@ -11,120 +11,100 @@ extern "C" {
#include <stdbool.h>
#include "runtime/alloc.h"
typedef struct {
void *contents;
size_t size;
size_t capacity;
size_t element_size;
} Vector;
#define Vector(T) \
struct { \
T *contents; \
size_t size; \
size_t capacity; \
}
static inline Vector vector_new(size_t element_size) {
Vector result;
result.contents = NULL;
result.size = 0;
result.capacity = 0;
result.element_size = element_size;
return result;
#define vector_init(self) \
((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
#define vector_get(self, index) \
(assert((size_t)index < (self)->size), &(self)->contents[index])
#define vector_front(self) vector_get(self, 0)
#define vector_back(self) vector_get(self, (self)->size - 1)
#define vector_clear(self) ((self)->size = 0)
#define vector_grow(self, new_capacity) \
vector__grow((VoidVector *)(self), vector__elem_size(self), new_capacity)
#define vector_erase(self, index) \
vector__erase((VoidVector *)(self), vector__elem_size(self), index)
#define vector_delete(self) vector__delete((VoidVector *)self)
#define vector_push(self, element) \
(((self)->size < (self)->capacity || \
vector_grow((self), (self)->capacity * 2)) && \
((self)->contents[(self)->size++] = (element), true))
#define vector_pop(self) ((self)->contents[--(self)->size])
#define vector_reverse(self) \
vector__reverse((VoidVector *)(self), vector__elem_size(self))
#define vector_copy(self) \
{ \
memcpy(ts_calloc((self)->capacity, vector__elem_size(self)), \
(self)->contents, (self)->size *vector__elem_size(self)), \
(self)->size, (self)->capacity, \
}
// Private
typedef Vector(void) VoidVector;
#define vector__elem_size(self) sizeof(*(self)->contents)
static inline void vector__delete(VoidVector *self) {
ts_free(self->contents);
self->contents = NULL;
self->size = 0;
self->capacity = 0;
}
static inline bool vector_grow(Vector *self, size_t capacity) {
if (capacity == 0)
static inline void vector__erase(VoidVector *self, size_t element_size,
size_t index) {
assert(index < self->size);
char *contents = (char *)self->contents;
memmove(contents + index * element_size, contents + (index + 1) * element_size,
(self->size - index - 1) * element_size);
self->size--;
}
static inline bool vector__grow(VoidVector *self, size_t element_size,
size_t new_capacity) {
if (new_capacity == 0)
return true;
void *new_contents;
if (self->contents)
new_contents = ts_realloc(self->contents, capacity * self->element_size);
new_contents = ts_realloc(self->contents, new_capacity * element_size);
else
new_contents = ts_calloc(capacity, self->element_size);
new_contents = ts_calloc(new_capacity, element_size);
if (!new_contents)
return false;
self->capacity = capacity;
self->capacity = new_capacity;
self->contents = new_contents;
return true;
}
static inline bool vector_valid(Vector *self) {
return self->element_size > 0;
}
static inline void vector_delete(Vector *self) {
if (self->contents) {
ts_free(self->contents);
self->contents = NULL;
self->size = 0;
self->capacity = 0;
}
}
static inline void *vector_get(Vector *self, size_t index) {
assert(index < self->size);
return (void *)((char *)self->contents + index * self->element_size);
}
static inline void vector_set(Vector *self, size_t index, void *entry) {
assert(index < self->size);
char *location = (char *)self->contents + index * self->element_size;
memcpy(location, (char *)entry, self->element_size);
}
static inline void *vector_back(Vector *self) {
assert(self->size > 0);
return vector_get(self, self->size - 1);
}
static inline void *vector_pop(Vector *self) {
void *result = vector_back(self);
self->size--;
return result;
}
static inline void vector_clear(Vector *self) {
self->size = 0;
}
static inline void vector_erase(Vector *self, size_t index) {
assert(index < self->size);
static inline void vector__reverse(VoidVector *self, size_t element_size) {
char swap[element_size];
char *contents = (char *)self->contents;
memmove(contents + index * self->element_size,
contents + (index + 1) * self->element_size,
(self->size - index - 1) * self->element_size);
self->size--;
}
static inline bool vector_push(Vector *self, void *entry) {
if (self->size == self->capacity) {
self->capacity += 4;
void *contents =
ts_realloc(self->contents, self->capacity * self->element_size);
if (!contents)
return false;
self->contents = contents;
for (size_t i = 0, limit = self->size / 2; i < limit; i++) {
size_t offset = i * element_size;
size_t reverse_offset = (self->size - 1 - i) * element_size;
memcpy(&swap, contents + offset, element_size);
memcpy(contents + offset, contents + reverse_offset, element_size);
memcpy(contents + reverse_offset, &swap, element_size);
}
self->size++;
vector_set(self, self->size - 1, entry);
return true;
}
static inline void vector_reverse(Vector *self) {
char swap[self->element_size];
char *contents = (char *)self->contents;
size_t limit = self->size / 2;
for (size_t i = 0; i < limit; i++) {
size_t offset = i * self->element_size;
size_t reverse_offset = (self->size - 1 - i) * self->element_size;
memcpy(&swap, contents + offset, self->element_size);
memcpy(contents + offset, contents + reverse_offset, self->element_size);
memcpy(contents + reverse_offset, &swap, self->element_size);
}
}
static inline Vector vector_copy(Vector *self) {
Vector copy = *self;
copy.contents = memcpy(ts_calloc(self->capacity, self->element_size),
self->contents, self->size * self->element_size);
return copy;
}
#ifdef __cplusplus