From a544200a6c9f012e4c111c83b46619ccf572523a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 23 Sep 2020 11:47:47 -0700 Subject: [PATCH] Simplify query code for matching supertypes --- lib/src/query.c | 45 ++++++++-------- lib/src/tree_cursor.c | 120 ++++++++++++++++-------------------------- lib/src/tree_cursor.h | 11 +++- 3 files changed, 77 insertions(+), 99 deletions(-) diff --git a/lib/src/query.c b/lib/src/query.c index 288656ac..8c86badb 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -640,10 +640,10 @@ static inline AnalysisStateEntry *analysis_state__top(AnalysisState *self) { } static inline bool analysis_state__has_supertype(AnalysisState *self, TSSymbol symbol) { - for (unsigned i = 0; i < self->depth; i++) { - if (self->stack[i].parent_symbol == symbol) return true; - } - return false; + for (unsigned i = 0; i < self->depth; i++) { + if (self->stack[i].parent_symbol == symbol) return true; + } + return false; } /*********************** @@ -1141,9 +1141,10 @@ static bool ts_query__analyze_patterns(TSQuery *self, unsigned *error_offset) { if (step->field && step->field != field_id) { does_match = false; } - if (step->supertype_symbol) { - if (!analysis_state__has_supertype(state, step->supertype_symbol)) does_match = false; - } + if ( + step->supertype_symbol && + !analysis_state__has_supertype(state, step->supertype_symbol) + ) does_match = false; } // If this is a hidden child, then push a new entry to the stack, in order to @@ -2594,11 +2595,17 @@ static inline bool ts_query_cursor__advance( bool has_later_siblings; bool has_later_named_siblings; bool can_have_later_siblings_with_this_field; - TSFieldId field_id = ts_tree_cursor_current_status( + TSFieldId field_id = 0; + TSSymbol supertypes[8] = {0}; + unsigned supertype_count = 8; + ts_tree_cursor_current_status( &self->cursor, + &field_id, &has_later_siblings, &has_later_named_siblings, - &can_have_later_siblings_with_this_field + &can_have_later_siblings_with_this_field, + supertypes, + &supertype_count ); LOG( "enter node. type:%s, field:%s, row:%u state_count:%u, finished_state_count:%u\n", @@ -2617,6 +2624,7 @@ static inline bool ts_query_cursor__advance( // If this node matches the first step of the pattern, then add a new // state at the start of this pattern. if (step->field && field_id != step->field) continue; + if (step->supertype_symbol && !supertype_count) continue; ts_query_cursor__add_state(self, pattern); } @@ -2665,19 +2673,14 @@ static inline bool ts_query_cursor__advance( node_does_match = false; } if (step->supertype_symbol) { - bool has_supertype = ts_tree_cursor_has_supertype(&self->cursor, step->supertype_symbol); - - if (symbol == 1) { - LOG( - " has supertype %s: %d", - ts_language_symbol_name(self->query->language, step->supertype_symbol), - has_supertype - ); - } - - if (!has_supertype) { - node_does_match = false; + bool has_supertype = false; + for (unsigned j = 0; j < supertype_count; j++) { + if (supertypes[j] == step->supertype_symbol) { + has_supertype = true; + break; + } } + if (!has_supertype) node_does_match = false; } if (step->field) { if (step->field == field_id) { diff --git a/lib/src/tree_cursor.c b/lib/src/tree_cursor.c index 8ef17960..64e8b414 100644 --- a/lib/src/tree_cursor.c +++ b/lib/src/tree_cursor.c @@ -246,14 +246,19 @@ TSNode ts_tree_cursor_current_node(const TSTreeCursor *_self) { // Private - Get various facts about the current node that are needed // when executing tree queries. -TSFieldId ts_tree_cursor_current_status( +void ts_tree_cursor_current_status( const TSTreeCursor *_self, + TSFieldId *field_id, bool *has_later_siblings, bool *has_later_named_siblings, - bool *can_have_later_siblings_with_this_field + bool *can_have_later_siblings_with_this_field, + TSSymbol *supertypes, + unsigned *supertype_count ) { const TreeCursor *self = (const TreeCursor *)_self; - TSFieldId result = 0; + unsigned max_supertypes = *supertype_count; + *field_id = 0; + *supertype_count = 0; *has_later_siblings = false; *has_later_named_siblings = false; *can_have_later_siblings_with_this_field = false; @@ -269,24 +274,31 @@ TSFieldId ts_tree_cursor_current_status( parent_entry->subtree->ptr->production_id ); - // If the subtree is visible, return its public-facing symbol. - // Otherwise, return zero. - #define subtree_visible_symbol(subtree, structural_child_index) \ - (( \ - !ts_subtree_extra(subtree) && \ - alias_sequence && \ - alias_sequence[structural_child_index] \ - ) ? \ - alias_sequence[structural_child_index] : \ - ts_subtree_visible(subtree) ? \ - ts_subtree_symbol(subtree) : \ - 0) \ + #define subtree_symbol(subtree, structural_child_index) \ + (( \ + !ts_subtree_extra(subtree) && \ + alias_sequence && \ + alias_sequence[structural_child_index] \ + ) ? \ + alias_sequence[structural_child_index] : \ + ts_subtree_symbol(subtree)) // Stop walking up when a visible ancestor is found. - if ( - i != self->stack.size - 1 && - subtree_visible_symbol(*entry->subtree, entry->structural_child_index) - ) break; + TSSymbol entry_symbol = subtree_symbol( + *entry->subtree, + entry->structural_child_index + ); + TSSymbolMetadata entry_metadata = ts_language_symbol_metadata( + self->tree->language, + entry_symbol + ); + if (i != self->stack.size - 1 && entry_metadata.visible) break; + + // Record any supertypes + if (entry_metadata.supertype && *supertype_count < max_supertypes) { + supertypes[*supertype_count] = entry_symbol; + (*supertype_count)++; + } // Determine if the current node has later siblings. if (!*has_later_siblings) { @@ -295,19 +307,21 @@ TSFieldId ts_tree_cursor_current_status( if (!ts_subtree_extra(*entry->subtree)) structural_child_index++; for (unsigned j = entry->child_index + 1; j < sibling_count; j++) { Subtree sibling = parent_entry->subtree->ptr->children[j]; - if (ts_subtree_visible_child_count(sibling) > 0) { + TSSymbolMetadata sibling_metadata = ts_language_symbol_metadata( + self->tree->language, + subtree_symbol(sibling, structural_child_index) + ); + if (sibling_metadata.visible) { *has_later_siblings = true; if (*has_later_named_siblings) break; - if (sibling.ptr->named_child_count > 0) { + if (sibling_metadata.named) { *has_later_named_siblings = true; break; } - } - TSSymbol visible_symbol = subtree_visible_symbol(sibling, structural_child_index); - if (visible_symbol) { + } else if (ts_subtree_visible_child_count(sibling) > 0) { *has_later_siblings = true; if (*has_later_named_siblings) break; - if (ts_language_symbol_metadata(self->tree->language, visible_symbol).named) { + if (sibling.ptr->named_child_count > 0) { *has_later_named_siblings = true; break; } @@ -316,7 +330,7 @@ TSFieldId ts_tree_cursor_current_status( } } - #undef subtree_visible_symbol + #undef subtree_metadata if (!ts_subtree_extra(*entry->subtree)) { const TSFieldMapEntry *field_map, *field_map_end; @@ -327,10 +341,10 @@ TSFieldId ts_tree_cursor_current_status( ); // Look for a field name associated with the current node. - if (!result) { + if (!*field_id) { for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) { if (!i->inherited && i->child_index == entry->structural_child_index) { - result = i->field_id; + *field_id = i->field_id; *can_have_later_siblings_with_this_field = false; break; } @@ -338,9 +352,9 @@ TSFieldId ts_tree_cursor_current_status( } // Determine if the current node can have later siblings with the same field name. - if (result) { + if (*field_id) { for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) { - if (i->field_id == result && i->child_index > entry->structural_child_index) { + if (i->field_id == *field_id && i->child_index > entry->structural_child_index) { *can_have_later_siblings_with_this_field = true; break; } @@ -348,52 +362,6 @@ TSFieldId ts_tree_cursor_current_status( } } } - - return result; -} - -bool ts_tree_cursor_has_supertype( - const TSTreeCursor *_self, - TSSymbol supertype_symbol -) { - const TreeCursor *self = (const TreeCursor *)_self; - - // Walk up the tree, visiting the current node and its invisible ancestors, - // because fields can refer to nodes through invisible *wrapper* nodes, - for (unsigned i = self->stack.size - 1; i > 0; i--) { - TreeCursorEntry *entry = &self->stack.contents[i]; - TreeCursorEntry *parent_entry = &self->stack.contents[i - 1]; - - const TSSymbol *alias_sequence = ts_language_alias_sequence( - self->tree->language, - parent_entry->subtree->ptr->production_id - ); - - // If the subtree is visible, return its public-facing symbol. - // Otherwise, return zero. - #define subtree_visible_symbol(subtree, structural_child_index) \ - (( \ - !ts_subtree_extra(subtree) && \ - alias_sequence && \ - alias_sequence[structural_child_index] \ - ) ? \ - alias_sequence[structural_child_index] : \ - ts_subtree_visible(subtree) ? \ - ts_subtree_symbol(subtree) : \ - 0) \ - - // Stop walking up when a visible ancestor is found. - if ( - i != self->stack.size - 1 && - subtree_visible_symbol(*entry->subtree, entry->structural_child_index) - ) break; - - if (ts_subtree_symbol(*entry->subtree) == supertype_symbol) { - return true; - } - } - - return false; } TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *_self) { diff --git a/lib/src/tree_cursor.h b/lib/src/tree_cursor.h index 7829e8b9..7c9c05d5 100644 --- a/lib/src/tree_cursor.h +++ b/lib/src/tree_cursor.h @@ -16,7 +16,14 @@ typedef struct { } TreeCursor; void ts_tree_cursor_init(TreeCursor *, TSNode); -TSFieldId ts_tree_cursor_current_status(const TSTreeCursor *, bool *, bool *, bool *); -bool ts_tree_cursor_has_supertype(const TSTreeCursor *, TSSymbol); +void ts_tree_cursor_current_status( + const TSTreeCursor *, + TSFieldId *, + bool *, + bool *, + bool *, + TSSymbol *, + unsigned * +); #endif // TREE_SITTER_TREE_CURSOR_H_