From 77e4caef4fa7fe0569c8fd5fb7b72e44e26c1362 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 31 Aug 2018 10:39:14 -0700 Subject: [PATCH] Revert "Store trees' children in TreeArrays, not w/ separate pointer and length" This reverts commit 09be0b6ef5902ce114494b994a9118880e4f4762. --- src/runtime/array.h | 14 ++-- src/runtime/get_changed_ranges.c | 8 +- src/runtime/node.c | 14 ++-- src/runtime/parser.c | 31 ++++---- src/runtime/reusable_node.h | 8 +- src/runtime/subtree.c | 121 ++++++++++++++++--------------- src/runtime/subtree.h | 15 ++-- src/runtime/tree_cursor.c | 14 ++-- test/runtime/subtree_test.cc | 82 ++++++++++----------- 9 files changed, 154 insertions(+), 153 deletions(-) diff --git a/src/runtime/array.h b/src/runtime/array.h index b32487a2..60cfc800 100644 --- a/src/runtime/array.h +++ b/src/runtime/array.h @@ -12,18 +12,18 @@ extern "C" { #include #include "runtime/alloc.h" -#define Array(T) \ - struct { \ +#define Array(T) \ + struct { \ + T *contents; \ uint32_t size; \ uint32_t capacity; \ - T *contents; \ } #define array_init(self) \ ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) #define array_new() \ - { 0, 0, NULL } + { NULL, 0, 0 } #define array_get(self, index) \ (assert((uint32_t)index < (self)->size), &(self)->contents[index]) @@ -47,11 +47,11 @@ extern "C" { (self)->contents[(self)->size++] = (element)) #define array_push_all(self, other) \ - array_splice((self), (self)->size, 0, (other)) + array_splice((self), (self)->size, 0, (other)->size, (other)->contents) -#define array_splice(self, index, old_count, new_array) \ +#define array_splice(self, index, old_count, new_count, new_contents) \ array__splice((VoidArray *)(self), array__elem_size(self), index, old_count, \ - (new_array)->size, (new_array)->contents) + new_count, new_contents) #define array_insert(self, index, element) \ array__splice((VoidArray *)(self), array__elem_size(self), index, 0, 1, &element) diff --git a/src/runtime/get_changed_ranges.c b/src/runtime/get_changed_ranges.c index f83e0493..9054e65a 100644 --- a/src/runtime/get_changed_ranges.c +++ b/src/runtime/get_changed_ranges.c @@ -129,8 +129,8 @@ static bool iterator_descend(Iterator *self, uint32_t goal_position) { TreeCursorEntry entry = *array_back(&self->cursor.stack); Length position = entry.position; uint32_t structural_child_index = 0; - for (uint32_t i = 0; i < entry.subtree->children.size; i++) { - const Subtree *child = entry.subtree->children.contents[i]; + for (uint32_t i = 0; i < entry.subtree->child_count; i++) { + const Subtree *child = entry.subtree->children[i]; Length child_left = length_add(position, child->padding); Length child_right = length_add(child_left, child->size); @@ -181,11 +181,11 @@ static void iterator_advance(Iterator *self) { const Subtree *parent = array_back(&self->cursor.stack)->subtree; uint32_t child_index = entry.child_index + 1; - if (parent->children.size > child_index) { + if (parent->child_count > child_index) { Length position = length_add(entry.position, ts_subtree_total_size(entry.subtree)); uint32_t structural_child_index = entry.structural_child_index; if (!entry.subtree->extra) structural_child_index++; - const Subtree *next_child = parent->children.contents[child_index]; + const Subtree *next_child = parent->children[child_index]; array_push(&self->cursor.stack, ((TreeCursorEntry){ .subtree = next_child, diff --git a/src/runtime/node.c b/src/runtime/node.c index f002d446..9ae5dad2 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -63,8 +63,8 @@ static inline ChildIterator ts_node_iterate_children(const TSNode *node) { } static inline bool ts_node_child_iterator_next(ChildIterator *self, TSNode *result) { - if (self->child_index == self->parent->children.size) return false; - const Subtree *child = self->parent->children.contents[self->child_index]; + if (self->child_index == self->parent->child_count) return false; + const Subtree *child = self->parent->children[self->child_index]; TSSymbol alias_symbol = 0; if (!child->extra) { if (self->alias_sequence) { @@ -108,7 +108,7 @@ static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) { static inline uint32_t ts_node__relevant_child_count(TSNode self, bool include_anonymous) { const Subtree *tree = ts_node__subtree(self); - if (tree->children.size > 0) { + if (tree->child_count > 0) { if (include_anonymous) { return tree->visible_child_count; } else { @@ -154,8 +154,8 @@ static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool incl } static bool ts_subtree_has_trailing_empty_descendant(const Subtree *self, const Subtree *other) { - for (unsigned i = self->children.size - 1; i + 1 > 0; i--) { - const Subtree *child = self->children.contents[i]; + for (unsigned i = self->child_count - 1; i + 1 > 0; i--) { + const Subtree *child = self->children[i]; if (child->size.bytes > 0 || child->padding.bytes > 0) break; if (child == other || ts_subtree_has_trailing_empty_descendant(child, other)) return true; } @@ -453,7 +453,7 @@ TSNode ts_node_named_child(TSNode self, uint32_t child_index) { uint32_t ts_node_child_count(TSNode self) { const Subtree *tree = ts_node__subtree(self); - if (tree->children.size > 0) { + if (tree->child_count > 0) { return tree->visible_child_count; } else { return 0; @@ -462,7 +462,7 @@ uint32_t ts_node_child_count(TSNode self) { uint32_t ts_node_named_child_count(TSNode self) { const Subtree *tree = ts_node__subtree(self); - if (tree->children.size > 0) { + if (tree->child_count > 0) { return tree->named_child_count; } else { return 0; diff --git a/src/runtime/parser.c b/src/runtime/parser.c index efeab009..546db10f 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -134,9 +134,9 @@ static bool ts_parser__breakdown_top_of_stack(TSParser *self, StackVersion versi TSStateId state = ts_stack_state(self->stack, slice.version); const Subtree *parent = *array_front(&slice.subtrees); - for (uint32_t j = 0; j < parent->children.size; j++) { - const Subtree *child = parent->children.contents[j]; - pending = child->children.size > 0; + for (uint32_t j = 0; j < parent->child_count; j++) { + const Subtree *child = parent->children[j]; + pending = child->child_count > 0; if (child->symbol == ts_builtin_sym_error) { state = ERROR_STATE; @@ -168,7 +168,7 @@ static void ts_parser__breakdown_lookahead(TSParser *self, const Subtree **looka TSStateId state, ReusableNode *reusable_node) { bool did_descend = false; const Subtree *tree = reusable_node_tree(reusable_node); - while (tree->children.size > 0 && tree->parse_state != state) { + while (tree->child_count > 0 && tree->parse_state != state) { LOG("state_mismatch sym:%s", SYM_NAME(tree->symbol)); reusable_node_descend(reusable_node); tree = reusable_node_tree(reusable_node); @@ -599,7 +599,7 @@ static void ts_parser__shift(TSParser *self, StackVersion version, TSStateId sta subtree_to_push = lookahead; } - bool is_pending = subtree_to_push->children.size > 0; + bool is_pending = subtree_to_push->child_count > 0; ts_stack_push(self->stack, version, subtree_to_push, is_pending, state); if (subtree_to_push->has_external_tokens) { ts_stack_set_last_external_token( @@ -610,8 +610,8 @@ static void ts_parser__shift(TSParser *self, StackVersion version, TSStateId sta static bool ts_parser__replace_children(TSParser *self, Subtree *tree, SubtreeArray *children) { self->scratch_tree = *tree; - self->scratch_tree.children.size = 0; - ts_subtree_set_children(&self->scratch_tree, children, self->language); + self->scratch_tree.child_count = 0; + ts_subtree_set_children(&self->scratch_tree, children->contents, children->size, self->language); if (ts_parser__select_tree(self, tree, &self->scratch_tree)) { *tree = self->scratch_tree; return true; @@ -697,7 +697,7 @@ static StackVersion ts_parser__reduce(TSParser *self, StackVersion version, TSSy // Push the parent node onto the stack, along with any extra tokens that // were previously on top of the stack. ts_stack_push(self->stack, slice_version, parent, false, next_state); - for (uint32_t j = parent->children.size; j < slice.subtrees.size; j++) { + for (uint32_t j = parent->child_count; j < slice.subtrees.size; j++) { ts_stack_push(self->stack, slice_version, slice.subtrees.contents[j], false, next_state); } @@ -728,10 +728,10 @@ static void ts_parser__accept(TSParser *self, StackVersion version, const Subtre for (uint32_t j = trees.size - 1; j + 1 > 0; j--) { const Subtree *child = trees.contents[j]; if (!child->extra) { - for (uint32_t k = 0; k < child->children.size; k++) { - ts_subtree_retain(child->children.contents[k]); + for (uint32_t k = 0; k < child->child_count; k++) { + ts_subtree_retain(child->children[k]); } - array_splice(&trees, j, 1, &child->children); + array_splice(&trees, j, 1, child->child_count, child->children); root = ts_subtree_new_node( &self->tree_pool, child->symbol, &trees, child->alias_sequence_id, self->language @@ -957,8 +957,9 @@ static bool ts_parser__recover_to_state(TSParser *self, StackVersion version, un SubtreeArray error_trees = ts_stack_pop_error(self->stack, slice.version); if (error_trees.size > 0) { assert(error_trees.size == 1); - array_splice(&slice.subtrees, 0, 0, &error_trees.contents[0]->children); - for (unsigned j = 0; j < error_trees.contents[0]->children.size; j++) { + const Subtree *error_tree = error_trees.contents[0]; + array_splice(&slice.subtrees, 0, 0, error_tree->child_count, error_tree->children); + for (unsigned j = 0; j < error_tree->child_count; j++) { ts_subtree_retain(slice.subtrees.contents[j]); } ts_subtree_array_delete(&self->tree_pool, &error_trees); @@ -1163,7 +1164,7 @@ static void ts_parser__advance(TSParser *self, StackVersion version, bool allow_ LOG("shift state:%u", next_state); } - if (lookahead->children.size > 0) { + if (lookahead->child_count > 0) { ts_parser__breakdown_lookahead(self, &lookahead, state, &self->reusable_node); next_state = ts_language_next_state(self->language, state, lookahead->symbol); } @@ -1194,7 +1195,7 @@ static void ts_parser__advance(TSParser *self, StackVersion version, bool allow_ } case TSParseActionTypeRecover: { - if (lookahead->children.size > 0) { + if (lookahead->child_count > 0) { ts_parser__breakdown_lookahead(self, &lookahead, ERROR_STATE, &self->reusable_node); } diff --git a/src/runtime/reusable_node.h b/src/runtime/reusable_node.h index 28186525..3a915fcc 100644 --- a/src/runtime/reusable_node.h +++ b/src/runtime/reusable_node.h @@ -59,10 +59,10 @@ static inline void reusable_node_advance(ReusableNode *self) { next_index = popped_entry.child_index + 1; if (self->stack.size == 0) return; tree = array_back(&self->stack)->tree; - } while (tree->children.size <= next_index); + } while (tree->child_count <= next_index); array_push(&self->stack, ((StackEntry) { - .tree = tree->children.contents[next_index], + .tree = tree->children[next_index], .child_index = next_index, .byte_offset = byte_offset, })); @@ -70,9 +70,9 @@ static inline void reusable_node_advance(ReusableNode *self) { static inline bool reusable_node_descend(ReusableNode *self) { StackEntry last_entry = *array_back(&self->stack); - if (last_entry.tree->children.size > 0) { + if (last_entry.tree->child_count > 0) { array_push(&self->stack, ((StackEntry) { - .tree = last_entry.tree->children.contents[0], + .tree = last_entry.tree->children[0], .child_index = 0, .byte_offset = last_entry.byte_offset, })); diff --git a/src/runtime/subtree.c b/src/runtime/subtree.c index b6dcee5a..7e9d6c0f 100644 --- a/src/runtime/subtree.c +++ b/src/runtime/subtree.c @@ -186,8 +186,12 @@ Subtree *ts_subtree_new_error(SubtreePool *pool, Length size, Length padding, Subtree *ts_subtree_new_copy(SubtreePool *pool, const Subtree *self) { Subtree *result = ts_subtree_pool_allocate(pool); *result = *self; - if (result->children.size > 0) { - ts_subtree_array_copy(self->children, &result->children); + if (result->child_count > 0) { + result->children = ts_calloc(self->child_count, sizeof(const Subtree *)); + memcpy(result->children, self->children, self->child_count * sizeof(const Subtree *)); + for (uint32_t i = 0; i < result->child_count; i++) { + ts_subtree_retain(result->children[i]); + } } else if (result->has_external_tokens) { result->external_scanner_state = ts_external_scanner_state_copy(&self->external_scanner_state); } @@ -211,25 +215,25 @@ static void ts_subtree__compress(Subtree *self, unsigned count, const TSLanguage Subtree *tree = self; for (unsigned i = 0; i < count; i++) { - if (tree->ref_count > 1 || tree->children.size != 2) break; + if (tree->ref_count > 1 || tree->child_count != 2) break; - Subtree *child = (Subtree *)tree->children.contents[0]; + Subtree *child = (Subtree *)tree->children[0]; if ( child->ref_count > 1 || - child->children.size != 2 || + child->child_count != 2 || child->symbol != tree->symbol ) break; - Subtree *grandchild = (Subtree *)child->children.contents[0]; + Subtree *grandchild = (Subtree *)child->children[0]; if ( grandchild->ref_count > 1 || - grandchild->children.size != 2 || + grandchild->child_count != 2 || grandchild->symbol != tree->symbol ) break; - tree->children.contents[0] = grandchild; - child->children.contents[0] = grandchild->children.contents[1]; - grandchild->children.contents[1] = child; + tree->children[0] = grandchild; + child->children[0] = grandchild->children[1]; + grandchild->children[1] = child; array_push(stack, tree); tree = grandchild; } @@ -237,11 +241,11 @@ static void ts_subtree__compress(Subtree *self, unsigned count, const TSLanguage while (stack->size > initial_stack_size) { tree = array_pop(stack); assert(tree); - Subtree *child = (Subtree *)tree->children.contents[0]; - Subtree *grandchild = (Subtree *)child->children.contents[1]; - ts_subtree_set_children(grandchild, &grandchild->children, language); - ts_subtree_set_children(child, &child->children, language); - ts_subtree_set_children(tree, &tree->children, language); + Subtree *child = (Subtree *)tree->children[0]; + Subtree *grandchild = (Subtree *)child->children[1]; + ts_subtree_set_children(grandchild, grandchild->children, grandchild->child_count, language); + ts_subtree_set_children(child, child->children, child->child_count, language); + ts_subtree_set_children(tree, tree->children, tree->child_count, language); } } @@ -257,10 +261,10 @@ void ts_subtree_balance(const Subtree *self, SubtreePool *pool, const TSLanguage assert(tree); if (tree->repeat_depth > 0 && - tree->children.contents[0]->repeat_depth > tree->children.contents[1]->repeat_depth) { + tree->children[0]->repeat_depth > tree->children[1]->repeat_depth) { unsigned n = ( - tree->children.contents[0]->repeat_depth - - tree->children.contents[1]->repeat_depth + tree->children[0]->repeat_depth - + tree->children[1]->repeat_depth ); for (unsigned i = n / 2; i > 0; i /= 2) { ts_subtree__compress(tree, i, language, &pool->tree_stack); @@ -268,8 +272,8 @@ void ts_subtree_balance(const Subtree *self, SubtreePool *pool, const TSLanguage } } - for (uint32_t i = 0; i < tree->children.size; i++) { - const Subtree *child = tree->children.contents[i]; + for (uint32_t i = 0; i < tree->child_count; i++) { + const Subtree *child = tree->children[i]; if (child->ref_count == 1) { array_push(&pool->tree_stack, (Subtree *)child); } @@ -277,12 +281,13 @@ void ts_subtree_balance(const Subtree *self, SubtreePool *pool, const TSLanguage } } -void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLanguage *language) { - if (self->children.size > 0 && children->contents != self->children.contents) { - array_delete(&self->children); +void ts_subtree_set_children(Subtree *self, const Subtree **children, uint32_t child_count, const TSLanguage *language) { + if (self->child_count > 0 && children != self->children) { + ts_free(self->children); } - self->children = *children; + self->child_count = child_count; + self->children = children; self->named_child_count = 0; self->visible_child_count = 0; self->error_cost = 0; @@ -294,8 +299,8 @@ void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLang uint32_t non_extra_index = 0; const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id); - for (uint32_t i = 0; i < self->children.size; i++) { - const Subtree *child = self->children.contents[i]; + for (uint32_t i = 0; i < self->child_count; i++) { + const Subtree *child = self->children[i]; if (i == 0) { self->padding = child->padding; @@ -321,7 +326,7 @@ void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLang } else if (child->visible) { self->visible_child_count++; if (child->named) self->named_child_count++; - } else if (child->children.size > 0) { + } else if (child->child_count > 0) { self->visible_child_count += child->visible_child_count; self->named_child_count += child->named_child_count; } @@ -340,10 +345,10 @@ void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLang self->error_cost += ERROR_COST_PER_RECOVERY + ERROR_COST_PER_SKIPPED_CHAR * self->size.bytes + ERROR_COST_PER_SKIPPED_LINE * self->size.extent.row; - for (uint32_t i = 0; i < self->children.size; i++) { - const Subtree *child = self->children.contents[i]; + for (uint32_t i = 0; i < self->child_count; i++) { + const Subtree *child = self->children[i]; if (child->extra) continue; - if (child->symbol == ts_builtin_sym_error && child->children.size == 0) continue; + if (child->symbol == ts_builtin_sym_error && child->child_count == 0) continue; if (child->visible) { self->error_cost += ERROR_COST_PER_SKIPPED_TREE; } else { @@ -352,14 +357,14 @@ void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLang } } - if (self->children.size > 0) { - const Subtree *first_child = self->children.contents[0]; - const Subtree *last_child = self->children.contents[self->children.size - 1]; + if (self->child_count > 0) { + const Subtree *first_child = self->children[0]; + const Subtree *last_child = self->children[self->child_count - 1]; self->first_leaf = first_child->first_leaf; if (first_child->fragile_left) self->fragile_left = true; if (last_child->fragile_right) self->fragile_right = true; if ( - self->children.size == 2 && + self->child_count == 2 && !self->visible && !self->named && first_child->symbol == self->symbol && last_child->symbol == self->symbol @@ -381,7 +386,7 @@ Subtree *ts_subtree_new_node(SubtreePool *pool, TSSymbol symbol, SubtreeArray *c result->fragile_left = true; result->fragile_right = true; } - ts_subtree_set_children(result, children, language); + ts_subtree_set_children(result, children->contents, children->size, language); return result; } @@ -414,14 +419,14 @@ void ts_subtree_release(SubtreePool *pool, const Subtree *self) { while (pool->tree_stack.size > 0) { Subtree *tree = array_pop(&pool->tree_stack); - if (tree->children.size > 0) { - for (uint32_t i = 0; i < tree->children.size; i++) { - const Subtree *child = tree->children.contents[i]; + if (tree->child_count > 0) { + for (uint32_t i = 0; i < tree->child_count; i++) { + const Subtree *child = tree->children[i]; if (atomic_dec((volatile uint32_t *)&child->ref_count) == 0) { array_push(&pool->tree_stack, (Subtree *)child); } } - array_delete(&tree->children); + ts_free(tree->children); } else if (tree->has_external_tokens) { ts_external_scanner_state_delete(&tree->external_scanner_state); } @@ -442,12 +447,12 @@ bool ts_subtree_eq(const Subtree *self, const Subtree *other) { if (self->padding.bytes != other->padding.bytes) return false; if (self->size.bytes != other->size.bytes) return false; if (self->symbol == ts_builtin_sym_error) return self->lookahead_char == other->lookahead_char; - if (self->children.size != other->children.size) return false; + if (self->child_count != other->child_count) return false; if (self->visible_child_count != other->visible_child_count) return false; if (self->named_child_count != other->named_child_count) return false; - for (uint32_t i = 0; i < self->children.size; i++) { - if (!ts_subtree_eq(self->children.contents[i], other->children.contents[i])) { + for (uint32_t i = 0; i < self->child_count; i++) { + if (!ts_subtree_eq(self->children[i], other->children[i])) { return false; } } @@ -459,13 +464,13 @@ int ts_subtree_compare(const Subtree *left, const Subtree *right) { return -1; if (right->symbol < left->symbol) return 1; - if (left->children.size < right->children.size) + if (left->child_count < right->child_count) return -1; - if (right->children.size < left->children.size) + if (right->child_count < left->child_count) return 1; - for (uint32_t i = 0; i < left->children.size; i++) { - const Subtree *left_child = left->children.contents[i]; - const Subtree *right_child = right->children.contents[i]; + for (uint32_t i = 0; i < left->child_count; i++) { + const Subtree *left_child = left->children[i]; + const Subtree *right_child = right->children[i]; switch (ts_subtree_compare(left_child, right_child)) { case -1: return -1; @@ -538,8 +543,8 @@ const Subtree *ts_subtree_edit(const Subtree *self, const TSInputEdit *edit, Sub result->has_changes = true; Length child_left, child_right = length_zero(); - for (uint32_t i = 0; i < result->children.size; i++) { - const Subtree **child = &result->children.contents[i]; + for (uint32_t i = 0; i < result->child_count; i++) { + const Subtree **child = &result->children[i]; Length child_size = ts_subtree_total_size(*child); child_left = child_right; child_right = length_add(child_left, child_size); @@ -589,9 +594,9 @@ const Subtree *ts_subtree_edit(const Subtree *self, const TSInputEdit *edit, Sub const Subtree *ts_subtree_last_external_token(const Subtree *tree) { if (!tree->has_external_tokens) return NULL; - while (tree->children.size > 0) { - for (uint32_t i = tree->children.size - 1; i + 1 > 0; i--) { - const Subtree *child = tree->children.contents[i]; + while (tree->child_count > 0) { + for (uint32_t i = tree->child_count - 1; i + 1 > 0; i--) { + const Subtree *child = tree->children[i]; if (child->has_external_tokens) { tree = child; break; @@ -638,7 +643,7 @@ static size_t ts_subtree__write_to_string(const Subtree *self, char *string, siz } if (visible) { - if (self->symbol == ts_builtin_sym_error && self->children.size == 0 && self->size.bytes > 0) { + if (self->symbol == ts_builtin_sym_error && self->child_count == 0 && self->size.bytes > 0) { cursor += snprintf(*writer, limit, "(UNEXPECTED "); cursor += ts_subtree__write_char_to_string(*writer, limit, self->lookahead_char); } else if (self->is_missing) { @@ -652,8 +657,8 @@ static size_t ts_subtree__write_to_string(const Subtree *self, char *string, siz const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id); uint32_t structural_child_index = 0; - for (uint32_t i = 0; i < self->children.size; i++) { - const Subtree *child = self->children.contents[i]; + for (uint32_t i = 0; i < self->child_count; i++) { + const Subtree *child = self->children[i]; if (child->extra) { cursor += ts_subtree__write_to_string( child, *writer, limit, @@ -694,7 +699,7 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t byte_offset, TSSymbol symbol = alias_symbol ? alias_symbol : self->symbol; fprintf(f, "tree_%p [label=\"%s\"", self, ts_language_symbol_name(language, symbol)); - if (self->children.size == 0) + if (self->child_count == 0) fprintf(f, ", shape=plaintext"); if (self->extra) fprintf(f, ", fontcolor=gray"); @@ -716,8 +721,8 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t byte_offset, const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id); uint32_t structural_child_index = 0; - for (uint32_t i = 0; i < self->children.size; i++) { - const Subtree *child = self->children.contents[i]; + for (uint32_t i = 0; i < self->child_count; i++) { + const Subtree *child = self->children[i]; if (child->extra) { ts_subtree__print_dot_graph(child, byte_offset, language, 0, f); } else { diff --git a/src/runtime/subtree.h b/src/runtime/subtree.h index 0fdba75f..f33ec607 100644 --- a/src/runtime/subtree.h +++ b/src/runtime/subtree.h @@ -36,6 +36,7 @@ struct Subtree { uint32_t node_count; uint32_t repeat_depth; int32_t dynamic_precedence; + uint32_t child_count; bool visible : 1; bool named : 1; @@ -55,19 +56,13 @@ struct Subtree { union { struct { - SubtreeArray children; + const Subtree **children; uint32_t visible_child_count; uint32_t named_child_count; uint16_t alias_sequence_id; }; - struct { - uint32_t _2; - ExternalScannerState external_scanner_state; - }; - struct { - uint32_t _1; - int32_t lookahead_char; - }; + ExternalScannerState external_scanner_state; + int32_t lookahead_char; }; }; @@ -100,7 +95,7 @@ void ts_subtree_retain(const Subtree *tree); void ts_subtree_release(SubtreePool *, const Subtree *tree); bool ts_subtree_eq(const Subtree *tree1, const Subtree *tree2); int ts_subtree_compare(const Subtree *tree1, const Subtree *tree2); -void ts_subtree_set_children(Subtree *, SubtreeArray *, const TSLanguage *); +void ts_subtree_set_children(Subtree *, const Subtree **, uint32_t, const TSLanguage *); void ts_subtree_balance(const Subtree *, SubtreePool *, const TSLanguage *); const Subtree *ts_subtree_edit(const Subtree *, const TSInputEdit *edit, SubtreePool *); char *ts_subtree_string(const Subtree *, const TSLanguage *, bool include_all); diff --git a/src/runtime/tree_cursor.c b/src/runtime/tree_cursor.c index 467681ff..93a8be7f 100644 --- a/src/runtime/tree_cursor.c +++ b/src/runtime/tree_cursor.c @@ -34,8 +34,8 @@ static inline ChildIterator ts_tree_cursor_iterate_children(const TreeCursor *se static inline bool ts_tree_cursor_child_iterator_next(ChildIterator *self, TreeCursorEntry *result, bool *visible) { - if (self->child_index == self->parent->children.size) return false; - const Subtree *child = self->parent->children.contents[self->child_index]; + if (self->child_index == self->parent->child_count) return false; + const Subtree *child = self->parent->children[self->child_index]; *result = (TreeCursorEntry) { .subtree = child, .position = self->position, @@ -51,8 +51,8 @@ static inline bool ts_tree_cursor_child_iterator_next(ChildIterator *self, self->child_index++; if (!child->extra) self->structural_child_index++; - if (self->child_index < self->parent->children.size) { - const Subtree *child = self->parent->children.contents[self->child_index]; + if (self->child_index < self->parent->child_count) { + const Subtree *child = self->parent->children[self->child_index]; self->position = length_add(self->position, child->padding); } @@ -104,7 +104,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *_self) { return true; } - if (entry.subtree->children.size > 0 && entry.subtree->visible_child_count > 0) { + if (entry.subtree->child_count > 0 && entry.subtree->visible_child_count > 0) { array_push(&self->stack, entry); did_descend = true; break; @@ -130,7 +130,7 @@ int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *_self, uint32_t g while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { uint32_t end_byte = entry.position.bytes + entry.subtree->size.bytes; bool at_goal = end_byte > goal_byte; - uint32_t visible_child_count = entry.subtree->children.size > 0 + uint32_t visible_child_count = entry.subtree->child_count > 0 ? entry.subtree->visible_child_count : 0; @@ -183,7 +183,7 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *_self) { return true; } - if (entry.subtree->children.size > 0 && entry.subtree->visible_child_count > 0) { + if (entry.subtree->child_count > 0 && entry.subtree->visible_child_count > 0) { array_push(&self->stack, entry); ts_tree_cursor_goto_first_child(_self); return true; diff --git a/test/runtime/subtree_test.cc b/test/runtime/subtree_test.cc index 2ad8d8d5..7001980d 100644 --- a/test/runtime/subtree_test.cc +++ b/test/runtime/subtree_test.cc @@ -5,12 +5,12 @@ #include "runtime/length.h" void assert_consistent(const Subtree *tree) { - if (tree->children.size == 0) return; - AssertThat(tree->children.contents[0]->padding, Equals(tree->padding)); + if (tree->child_count == 0) return; + AssertThat(tree->children[0]->padding, Equals(tree->padding)); Length total_children_size = length_zero(); - for (size_t i = 0; i < tree->children.size; i++) { - const Subtree *child = tree->children.contents[i]; + for (size_t i = 0; i < tree->child_count; i++) { + const Subtree *child = tree->children[i]; assert_consistent(child); total_children_size = length_add(total_children_size, ts_subtree_total_size(child)); } @@ -217,13 +217,13 @@ describe("Subtree", []() { AssertThat(tree->padding, Equals({2, {0, 2}})); AssertThat(tree->size, Equals({13, {0, 13}})); - AssertThat(tree->children.contents[0]->has_changes, IsFalse()); - AssertThat(tree->children.contents[0]->padding, Equals({2, {0, 2}})); - AssertThat(tree->children.contents[0]->size, Equals({3, {0, 3}})); + AssertThat(tree->children[0]->has_changes, IsFalse()); + AssertThat(tree->children[0]->padding, Equals({2, {0, 2}})); + AssertThat(tree->children[0]->size, Equals({3, {0, 3}})); - AssertThat(tree->children.contents[1]->has_changes, IsFalse()); - AssertThat(tree->children.contents[1]->padding, Equals({2, {0, 2}})); - AssertThat(tree->children.contents[1]->size, Equals({3, {0, 3}})); + AssertThat(tree->children[1]->has_changes, IsFalse()); + AssertThat(tree->children[1]->padding, Equals({2, {0, 2}})); + AssertThat(tree->children[1]->size, Equals({3, {0, 3}})); ts_subtree_release(&pool, new_tree); }); @@ -245,13 +245,13 @@ describe("Subtree", []() { AssertThat(tree->padding, Equals({3, {0, 3}})); AssertThat(tree->size, Equals({13, {0, 13}})); - AssertThat(tree->children.contents[0]->has_changes, IsTrue()); - AssertThat(tree->children.contents[0]->padding, Equals({3, {0, 3}})); - AssertThat(tree->children.contents[0]->size, Equals({3, {0, 3}})); + AssertThat(tree->children[0]->has_changes, IsTrue()); + AssertThat(tree->children[0]->padding, Equals({3, {0, 3}})); + AssertThat(tree->children[0]->size, Equals({3, {0, 3}})); - AssertThat(tree->children.contents[1]->has_changes, IsFalse()); - AssertThat(tree->children.contents[1]->padding, Equals({2, {0, 2}})); - AssertThat(tree->children.contents[1]->size, Equals({3, {0, 3}})); + AssertThat(tree->children[1]->has_changes, IsFalse()); + AssertThat(tree->children[1]->padding, Equals({2, {0, 2}})); + AssertThat(tree->children[1]->size, Equals({3, {0, 3}})); }); }); @@ -272,9 +272,9 @@ describe("Subtree", []() { AssertThat(tree->padding, Equals({5, {0, 5}})); AssertThat(tree->size, Equals({11, {0, 11}})); - AssertThat(tree->children.contents[0]->has_changes, IsTrue()); - AssertThat(tree->children.contents[0]->padding, Equals({5, {0, 5}})); - AssertThat(tree->children.contents[0]->size, Equals({1, {0, 1}})); + AssertThat(tree->children[0]->has_changes, IsTrue()); + AssertThat(tree->children[0]->padding, Equals({5, {0, 5}})); + AssertThat(tree->children[0]->size, Equals({1, {0, 1}})); }); }); @@ -295,11 +295,11 @@ describe("Subtree", []() { AssertThat(tree->padding, Equals({4, {0, 4}})); AssertThat(tree->size, Equals({13, {0, 13}})); - AssertThat(tree->children.contents[0]->has_changes, IsTrue()); - AssertThat(tree->children.contents[0]->padding, Equals({4, {0, 4}})); - AssertThat(tree->children.contents[0]->size, Equals({3, {0, 3}})); + AssertThat(tree->children[0]->has_changes, IsTrue()); + AssertThat(tree->children[0]->padding, Equals({4, {0, 4}})); + AssertThat(tree->children[0]->size, Equals({3, {0, 3}})); - AssertThat(tree->children.contents[1]->has_changes, IsFalse()); + AssertThat(tree->children[1]->has_changes, IsFalse()); }); }); @@ -320,11 +320,11 @@ describe("Subtree", []() { AssertThat(tree->padding, Equals({2, {0, 2}})); AssertThat(tree->size, Equals({16, {0, 16}})); - AssertThat(tree->children.contents[0]->has_changes, IsTrue()); - AssertThat(tree->children.contents[0]->padding, Equals({2, {0, 2}})); - AssertThat(tree->children.contents[0]->size, Equals({6, {0, 6}})); + AssertThat(tree->children[0]->has_changes, IsTrue()); + AssertThat(tree->children[0]->padding, Equals({2, {0, 2}})); + AssertThat(tree->children[0]->size, Equals({6, {0, 6}})); - AssertThat(tree->children.contents[1]->has_changes, IsFalse()); + AssertThat(tree->children[1]->has_changes, IsFalse()); }); }); @@ -345,23 +345,23 @@ describe("Subtree", []() { AssertThat(tree->padding, Equals({4, {0, 4}})); AssertThat(tree->size, Equals({4, {0, 4}})); - AssertThat(tree->children.contents[0]->has_changes, IsTrue()); - AssertThat(tree->children.contents[0]->padding, Equals({4, {0, 4}})); - AssertThat(tree->children.contents[0]->size, Equals({0, {0, 0}})); + AssertThat(tree->children[0]->has_changes, IsTrue()); + AssertThat(tree->children[0]->padding, Equals({4, {0, 4}})); + AssertThat(tree->children[0]->size, Equals({0, {0, 0}})); - AssertThat(tree->children.contents[1]->has_changes, IsTrue()); - AssertThat(tree->children.contents[1]->padding, Equals({0, {0, 0}})); - AssertThat(tree->children.contents[1]->size, Equals({0, {0, 0}})); + AssertThat(tree->children[1]->has_changes, IsTrue()); + AssertThat(tree->children[1]->padding, Equals({0, {0, 0}})); + AssertThat(tree->children[1]->size, Equals({0, {0, 0}})); - AssertThat(tree->children.contents[2]->has_changes, IsTrue()); - AssertThat(tree->children.contents[2]->padding, Equals({1, {0, 1}})); - AssertThat(tree->children.contents[2]->size, Equals({3, {0, 3}})); + AssertThat(tree->children[2]->has_changes, IsTrue()); + AssertThat(tree->children[2]->padding, Equals({1, {0, 1}})); + AssertThat(tree->children[2]->size, Equals({3, {0, 3}})); }); }); describe("edits within a tree's range of scanned bytes", [&]() { it("marks preceding trees as changed", [&]() { - Subtree *mutable_child = (Subtree *)tree->children.contents[0]; + Subtree *mutable_child = (Subtree *)tree->children[0]; mutable_child->bytes_scanned = 7; TSInputEdit edit; @@ -375,7 +375,7 @@ describe("Subtree", []() { tree = ts_subtree_edit(tree, &edit, &pool); assert_consistent(tree); - AssertThat(tree->children.contents[0]->has_changes, IsTrue()); + AssertThat(tree->children[0]->has_changes, IsTrue()); }); }); @@ -393,8 +393,8 @@ describe("Subtree", []() { assert_consistent(tree); AssertThat(tree->size.bytes, Equals(14u)); - AssertThat(tree->children.contents[2]->has_changes, IsTrue()); - AssertThat(tree->children.contents[2]->size.bytes, Equals(4u)); + AssertThat(tree->children[2]->has_changes, IsTrue()); + AssertThat(tree->children[2]->size.bytes, Equals(4u)); }); }); @@ -412,7 +412,7 @@ describe("Subtree", []() { assert_consistent(tree); AssertThat(tree->size.bytes, Equals(13u)); - AssertThat(tree->children.contents[2]->size.bytes, Equals(3u)); + AssertThat(tree->children[2]->size.bytes, Equals(3u)); }); }); });