From babb8261a3c43b028a84b222737094e17d45dca6 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 22 May 2018 14:42:57 -0700 Subject: [PATCH] Extract an iterator from TreeCursor methods --- src/runtime/node.c | 24 ++--- src/runtime/tree_cursor.c | 213 ++++++++++++++++++-------------------- 2 files changed, 114 insertions(+), 123 deletions(-) diff --git a/src/runtime/node.c b/src/runtime/node.c index 15a1572a..3c858b92 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -10,7 +10,7 @@ typedef struct { uint32_t child_index; uint32_t structural_child_index; const TSSymbol *alias_sequence; -} NodeChildIterator; +} ChildIterator; // TSNode - constructors @@ -48,16 +48,16 @@ static inline const TSTree *ts_node__tree(const TSNode *self) { return self->tree; } -// NodeChildIterator +// ChildIterator -static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) { +static inline ChildIterator ts_node_iterate_children(const TSNode *node) { const TSTree *tree = ts_node__tree(node); const Subtree *subtree = ts_node__subtree(*node); const TSSymbol *alias_sequence = ts_language_alias_sequence( tree->language, subtree->alias_sequence_id ); - return (NodeChildIterator) { + return (ChildIterator) { .tree = tree, .parent = subtree, .position = {ts_node_start_byte(*node), ts_node_start_point(*node)}, @@ -67,7 +67,7 @@ static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) }; } -static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) { +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]; TSSymbol alias_symbol = 0; @@ -133,7 +133,7 @@ static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool incl TSNode child; uint32_t index = 0; - NodeChildIterator iterator = ts_node_child_iterator_begin(&result); + ChildIterator iterator = ts_node_iterate_children(&result); while (ts_node_child_iterator_next(&iterator, &child)) { if (ts_node__is_relevant(child, include_anonymous)) { if (index == child_index) return child; @@ -168,7 +168,7 @@ static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous) bool found_child_containing_target = false; TSNode child; - NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + ChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { if (iterator.position.bytes >= target_end_byte) { found_child_containing_target = ts_node__subtree(child) != ts_node__subtree(self); @@ -217,7 +217,7 @@ static inline TSNode ts_node__next_sibling(TSNode self, bool include_anonymous) TSNode child_containing_target = ts_node__null(); TSNode child; - NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + ChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { if (iterator.position.bytes < target_end_byte) continue; if (ts_node_start_byte(child) <= ts_node_start_byte(self)) { @@ -268,7 +268,7 @@ static inline TSNode ts_node__first_child_for_byte(TSNode self, uint32_t goal, did_descend = false; TSNode child; - NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + ChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { if (ts_node_end_byte(child) > goal) { if (ts_node__is_relevant(child, include_anonymous)) { @@ -296,7 +296,7 @@ static inline TSNode ts_node__descendant_for_byte_range(TSNode self, uint32_t mi did_descend = false; TSNode child; - NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + ChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { if (iterator.position.bytes > max) { if (ts_node_start_byte(child) > min) break; @@ -324,7 +324,7 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi did_descend = false; TSNode child; - NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + ChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { const Subtree *child_tree = ts_node__subtree(child); if (iterator.child_index != 1) { @@ -407,7 +407,7 @@ TSNode ts_node_parent(TSNode self) { did_descend = false; TSNode child; - NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + ChildIterator iterator = ts_node_iterate_children(&node); while (ts_node_child_iterator_next(&iterator, &child)) { if ( ts_node_start_byte(child) > ts_node_start_byte(self) || diff --git a/src/runtime/tree_cursor.c b/src/runtime/tree_cursor.c index c7c106b3..f2d9279f 100644 --- a/src/runtime/tree_cursor.c +++ b/src/runtime/tree_cursor.c @@ -4,6 +4,56 @@ #include "runtime/language.h" #include "runtime/tree.h" +typedef struct { + const Subtree *parent; + const TSTree *tree; + Length position; + uint32_t child_index; + uint32_t structural_child_index; + const TSSymbol *alias_sequence; +} ChildIterator; + +// ChildIterator + +static inline ChildIterator ts_tree_cursor_iterate_children(const TreeCursor *self) { + TreeCursorEntry *last_entry = array_back(&self->stack); + const TSSymbol *alias_sequence = ts_language_alias_sequence( + self->tree->language, + last_entry->subtree->alias_sequence_id + ); + return (ChildIterator) { + .tree = self->tree, + .parent = last_entry->subtree, + .position = last_entry->position, + .child_index = 0, + .structural_child_index = 0, + .alias_sequence = alias_sequence, + }; +} + +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]; + *result = (TreeCursorEntry) { + .subtree = child, + .position = self->position, + .child_index = self->child_index, + .structural_child_index = self->structural_child_index, + }; + *visible = child->visible; + if (!child->extra && self->alias_sequence) { + *visible |= self->alias_sequence[self->structural_child_index]; + } + self->position = length_add(self->position, ts_subtree_total_size(child)); + self->child_index++; + if (!child->extra) self->structural_child_index++; + return true; +} + +// TSTreeCursor - lifecycle + TSTreeCursor ts_tree_cursor_new(const TSTree *tree) { TSTreeCursor self; ts_tree_cursor_init((TreeCursor *)&self, tree); @@ -26,47 +76,29 @@ void ts_tree_cursor_delete(TSTreeCursor *_self) { array_delete(&self->stack); } +// TSTreeCursor - walking the tree + bool ts_tree_cursor_goto_first_child(TSTreeCursor *_self) { TreeCursor *self = (TreeCursor *)_self; - TreeCursorEntry *last_entry = array_back(&self->stack); - const Subtree *subtree = last_entry->subtree; - if (subtree->children.size == 0 || subtree->visible_child_count == 0) return false; - Length position = last_entry->position; bool did_descend; do { did_descend = false; - const TSSymbol *alias_sequence = ts_language_alias_sequence( - self->tree->language, - subtree->alias_sequence_id - ); - uint32_t structural_child_index = 0; - for (uint32_t i = 0; i < subtree->children.size; i++) { - const Subtree *child = subtree->children.contents[i]; - bool visible = child->visible; - if (!child->extra) { - visible |= alias_sequence && alias_sequence[structural_child_index]; + bool visible; + TreeCursorEntry entry; + ChildIterator iterator = ts_tree_cursor_iterate_children(self); + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + if (visible) { + array_push(&self->stack, entry); + return true; } - if (visible || (child->children.size > 0 && child->visible_child_count > 0)) { - array_push(&self->stack, ((TreeCursorEntry) { - .subtree = child, - .child_index = i, - .structural_child_index = structural_child_index, - .position = position, - })); - - if (visible) { - return true; - } else { - subtree = child; - did_descend = true; - break; - } + if (entry.subtree->children.size > 0 && entry.subtree->visible_child_count > 0) { + array_push(&self->stack, entry); + did_descend = true; + break; } - if (!child->extra) structural_child_index++; - position = length_add(position, ts_subtree_total_size(child)); } } while (did_descend); @@ -76,59 +108,37 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *_self) { int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *_self, uint32_t goal_byte) { TreeCursor *self = (TreeCursor *)_self; uint32_t initial_size = self->stack.size; - TreeCursorEntry *last_entry = array_back(&self->stack); - const Subtree *subtree = last_entry->subtree; - Length position = last_entry->position; uint32_t visible_child_index = 0; bool did_descend; do { did_descend = false; - const TSSymbol *alias_sequence = ts_language_alias_sequence( - self->tree->language, - subtree->alias_sequence_id - ); - uint32_t structural_child_index = 0; - for (uint32_t i = 0; i < subtree->children.size; i++) { - const Subtree *child = subtree->children.contents[i]; - Length next_position = length_add(position, ts_subtree_total_size(child)); - bool at_goal = next_position.bytes > goal_byte; - - bool visible = child->visible; - if (!child->extra) { - visible |= alias_sequence && alias_sequence[structural_child_index]; - } - - uint32_t visible_child_count = child->children.size > 0 ? child->visible_child_count : 0; + bool visible; + TreeCursorEntry entry; + ChildIterator iterator = ts_tree_cursor_iterate_children(self); + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + bool at_goal = iterator.position.bytes > goal_byte; + uint32_t visible_child_count = entry.subtree->children.size > 0 + ? entry.subtree->visible_child_count + : 0; if (at_goal) { - if (visible || visible_child_count > 0) { - array_push(&self->stack, ((TreeCursorEntry) { - .subtree = child, - .child_index = i, - .structural_child_index = structural_child_index, - .position = position, - })); - - if (visible) { - return visible_child_index; - } else { - subtree = child; - did_descend = true; - break; - } - } - } else { if (visible) { - visible_child_index++; - } else { - visible_child_index += visible_child_count; + array_push(&self->stack, entry); + return visible_child_index; } - } - if (!child->extra) structural_child_index++; - position = next_position; + if (visible_child_count > 0) { + array_push(&self->stack, entry); + did_descend = true; + break; + } + } else if (visible) { + visible_child_index++; + } else { + visible_child_index += visible_child_count; + } } } while (did_descend); @@ -138,53 +148,34 @@ int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *_self, uint32_t g bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *_self) { TreeCursor *self = (TreeCursor *)_self; - TreeCursorEntry *child_entry = array_back(&self->stack); + uint32_t initial_size = self->stack.size; - for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) { - TreeCursorEntry *parent_entry = &self->stack.contents[i]; + while (self->stack.size > 1) { + bool visible; + TreeCursorEntry entry = array_pop(&self->stack); + ChildIterator iterator = ts_tree_cursor_iterate_children(self); + iterator.child_index = entry.child_index; + iterator.structural_child_index = entry.structural_child_index; + iterator.position = entry.position; - const Subtree *parent = parent_entry->subtree; - uint32_t child_index = child_entry->child_index; - uint32_t structural_child_index = child_entry->structural_child_index; - Length position = child_entry->position; - const Subtree *child = parent->children.contents[child_index]; - const TSSymbol *alias_sequence = ts_language_alias_sequence( - self->tree->language, - parent->alias_sequence_id - ); + ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible); + if (visible && self->stack.size + 1 < initial_size) break; - while (++child_index < parent->children.size) { - if (!child->extra) structural_child_index++; - position = length_add(position, ts_subtree_total_size(child)); - child = parent->children.contents[child_index]; - - bool visible = child->visible; - if (!child->extra) { - visible |= alias_sequence && alias_sequence[structural_child_index]; + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + if (visible) { + array_push(&self->stack, entry); + return true; } - if (visible || (child->children.size > 0 && child->visible_child_count > 0)) { - self->stack.contents[i + 1] = (TreeCursorEntry) { - .subtree = child, - .child_index = child_index, - .structural_child_index = structural_child_index, - .position = position, - }; - self->stack.size = i + 2; - - if (visible) { - return true; - } else { - ts_tree_cursor_goto_first_child(_self); - return true; - } + if (entry.subtree->children.size > 0 && entry.subtree->visible_child_count > 0) { + array_push(&self->stack, entry); + ts_tree_cursor_goto_first_child(_self); + return true; } } - - child_entry = parent_entry; - if (parent->visible) break; } + self->stack.size = initial_size; return false; }