From 35ed21139c562262d793ab0143537e8f5e720114 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 21 Jun 2018 12:53:17 -0700 Subject: [PATCH 1/4] Declare the `tree` field of `TSNode` with a type of `TSTree` This field doesn't need to be treated as opaque. Co-Authored-By: Ashi Krishnan --- include/tree_sitter/runtime.h | 2 +- src/runtime/node.c | 33 ++++++++++++--------------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index a4dbedc9..f51c1e88 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -68,7 +68,7 @@ typedef struct { typedef struct { uint32_t context[4]; const void *id; - const void *tree; + const TSTree *tree; } TSNode; typedef struct { diff --git a/src/runtime/node.c b/src/runtime/node.c index 0855ec66..f64703b7 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -44,21 +44,16 @@ static inline const Subtree *ts_node__subtree(TSNode self) { return self.id; } -static inline const TSTree *ts_node__tree(const TSNode *self) { - return self->tree; -} - // ChildIterator 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, + node->tree->language, subtree->alias_sequence_id ); return (ChildIterator) { - .tree = tree, + .tree = node->tree, .parent = subtree, .position = {ts_node_start_byte(*node), ts_node_start_point(*node)}, .child_index = 0, @@ -103,7 +98,7 @@ static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) { ( ts_node__alias(&self) && ts_language_symbol_metadata( - ts_node__tree(&self)->language, + self.tree->language, ts_node__alias(&self) ).named ) @@ -125,7 +120,6 @@ static inline uint32_t ts_node__relevant_child_count(TSNode self, bool include_a } static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool include_anonymous) { - const TSTree *tree = ts_node__tree(&self); TSNode result = self; bool did_descend = true; @@ -138,7 +132,7 @@ static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool incl while (ts_node_child_iterator_next(&iterator, &child)) { if (ts_node__is_relevant(child, include_anonymous)) { if (index == child_index) { - ts_tree_set_cached_parent(tree, &child, &self); + ts_tree_set_cached_parent(self.tree, &child, &self); return child; } index++; @@ -294,7 +288,6 @@ static inline TSNode ts_node__descendant_for_byte_range(TSNode self, uint32_t mi bool include_anonymous) { TSNode node = self; TSNode last_visible_node = self; - const TSTree *tree = ts_node__tree(&self); bool did_descend = true; while (did_descend) { @@ -307,7 +300,7 @@ static inline TSNode ts_node__descendant_for_byte_range(TSNode self, uint32_t mi if (ts_node_start_byte(child) > min) break; node = child; if (ts_node__is_relevant(node, include_anonymous)) { - ts_tree_set_cached_parent(tree, &child, &last_visible_node); + ts_tree_set_cached_parent(self.tree, &child, &last_visible_node); last_visible_node = node; } did_descend = true; @@ -324,7 +317,6 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi bool include_anonymous) { TSNode node = self; TSNode last_visible_node = self; - const TSTree *tree = ts_node__tree(&self); bool did_descend = true; while (did_descend) { @@ -337,7 +329,7 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi if (point_gt(ts_node_start_point(child), min)) break; node = child; if (ts_node__is_relevant(node, include_anonymous)) { - ts_tree_set_cached_parent(tree, &child, &last_visible_node); + ts_tree_set_cached_parent(self.tree, &child, &last_visible_node); last_visible_node = node; } did_descend = true; @@ -365,11 +357,11 @@ TSSymbol ts_node_symbol(TSNode self) { } const char *ts_node_type(TSNode self) { - return ts_language_symbol_name(ts_node__tree(&self)->language, ts_node_symbol(self)); + return ts_language_symbol_name(self.tree->language, ts_node_symbol(self)); } char *ts_node_string(TSNode self) { - return ts_subtree_string(ts_node__subtree(self), ts_node__tree(&self)->language, false); + return ts_subtree_string(ts_node__subtree(self), self.tree->language, false); } bool ts_node_eq(TSNode self, TSNode other) { @@ -383,7 +375,7 @@ bool ts_node_is_null(TSNode self) { bool ts_node_is_named(TSNode self) { const Subtree *tree = ts_node__subtree(self); return ts_node__alias(&self) - ? ts_language_symbol_metadata(ts_node__tree(&self)->language, ts_node__alias(&self)).named + ? ts_language_symbol_metadata(self.tree->language, ts_node__alias(&self)).named : tree->named; } @@ -401,11 +393,10 @@ bool ts_node_has_error(TSNode self) { } TSNode ts_node_parent(TSNode self) { - const TSTree *tree = ts_node__tree(&self); - TSNode node = ts_tree_get_cached_parent(tree, &self); + TSNode node = ts_tree_get_cached_parent(self.tree, &self); if (node.id) return node; - node = ts_tree_root_node(tree); + node = ts_tree_root_node(self.tree); uint32_t end_byte = ts_node_end_byte(self); if (ts_node__subtree(node) == ts_node__subtree(self)) return ts_node__null(); @@ -424,7 +415,7 @@ TSNode ts_node_parent(TSNode self) { if (iterator.position.bytes >= end_byte) { node = child; if (ts_node__is_relevant(child, true)) { - ts_tree_set_cached_parent(tree, &node, &last_visible_node); + ts_tree_set_cached_parent(self.tree, &node, &last_visible_node); last_visible_node = node; } did_descend = true; From 89b6a14d9ff5b46b47ab65faa0751f1bc64f335c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 21 Jun 2018 12:54:04 -0700 Subject: [PATCH 2/4] Allow creating a tree cursor starting at any node, not just the root Co-Authored-By: Ashi Krishnan --- include/tree_sitter/runtime.h | 2 +- src/runtime/tree.c | 5 +++-- src/runtime/tree_cursor.c | 29 ++++++++++++++++++++--------- src/runtime/tree_cursor.h | 2 +- test/runtime/node_test.cc | 4 ++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index f51c1e88..e90c25fd 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -131,7 +131,7 @@ TSNode ts_node_named_descendant_for_byte_range(TSNode, uint32_t, uint32_t); TSNode ts_node_descendant_for_point_range(TSNode, TSPoint, TSPoint); TSNode ts_node_named_descendant_for_point_range(TSNode, TSPoint, TSPoint); -TSTreeCursor ts_tree_cursor_new(const TSTree *); +TSTreeCursor ts_tree_cursor_new(TSNode); void ts_tree_cursor_delete(TSTreeCursor *); bool ts_tree_cursor_goto_first_child(TSTreeCursor *); int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *, uint32_t); diff --git a/src/runtime/tree.c b/src/runtime/tree.c index 72fba7a8..866b93b4 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -43,8 +43,9 @@ void ts_tree_edit(TSTree *self, const TSInputEdit *edit) { TSRange *ts_tree_get_changed_ranges(const TSTree *self, const TSTree *other, uint32_t *count) { TSRange *result; TreeCursor cursor1, cursor2; - ts_tree_cursor_init(&cursor1, self); - ts_tree_cursor_init(&cursor2, self); + TSNode root = ts_tree_root_node(self); + ts_tree_cursor_init(&cursor1, root); + ts_tree_cursor_init(&cursor2, root); *count = ts_subtree_get_changed_ranges( self->root, other->root, &cursor1, &cursor2, self->language, &result diff --git a/src/runtime/tree_cursor.c b/src/runtime/tree_cursor.c index 73c08672..83a32927 100644 --- a/src/runtime/tree_cursor.c +++ b/src/runtime/tree_cursor.c @@ -46,26 +46,36 @@ static inline bool ts_tree_cursor_child_iterator_next(ChildIterator *self, 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->position = length_add(self->position, child->size); 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]; + self->position = length_add(self->position, child->padding); + } + return true; } // TSTreeCursor - lifecycle -TSTreeCursor ts_tree_cursor_new(const TSTree *tree) { +TSTreeCursor ts_tree_cursor_new(TSNode node) { TSTreeCursor self; - ts_tree_cursor_init((TreeCursor *)&self, tree); + ts_tree_cursor_init((TreeCursor *)&self, node); return self; } -void ts_tree_cursor_init(TreeCursor *self, const TSTree *tree) { - self->tree = tree; +void ts_tree_cursor_init(TreeCursor *self, TSNode node) { + self->tree = node.tree; array_init(&self->stack); array_push(&self->stack, ((TreeCursorEntry) { - .subtree = tree->root, - .position = length_zero(), + .subtree = (const Subtree *)node.id, + .position = { + ts_node_start_byte(node), + ts_node_start_point(node) + }, .child_index = 0, .structural_child_index = 0, })); @@ -118,7 +128,8 @@ int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *_self, uint32_t g 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 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 ? entry.subtree->visible_child_count : 0; @@ -208,7 +219,7 @@ TSNode ts_tree_cursor_current_node(const TSTreeCursor *_self) { return ts_node_new( self->tree, last_entry->subtree, - length_add(last_entry->position, last_entry->subtree->padding), + last_entry->position, alias_symbol ); } diff --git a/src/runtime/tree_cursor.h b/src/runtime/tree_cursor.h index 0fa1b167..0df79d5e 100644 --- a/src/runtime/tree_cursor.h +++ b/src/runtime/tree_cursor.h @@ -15,6 +15,6 @@ typedef struct { const TSTree *tree; } TreeCursor; -void ts_tree_cursor_init(TreeCursor *, const TSTree *); +void ts_tree_cursor_init(TreeCursor *, TSNode); #endif // RUNTIME_TREE_CURSOR_H_ diff --git a/test/runtime/node_test.cc b/test/runtime/node_test.cc index f1097916..1c59e60b 100644 --- a/test/runtime/node_test.cc +++ b/test/runtime/node_test.cc @@ -556,7 +556,7 @@ describe("TreeCursor", [&]() { parser = ts_parser_new(); ts_parser_set_language(parser, load_real_language("json")); tree = ts_parser_parse_string(parser, nullptr, json_string.c_str(), json_string.size()); - cursor = ts_tree_cursor_new(tree); + cursor = ts_tree_cursor_new(ts_tree_root_node(tree)); }); after_each([&]() { @@ -728,7 +728,7 @@ describe("TreeCursor", [&]() { ts_tree_delete(tree); tree = ts_parser_parse_string(parser, nullptr, "b ... b ... c", 13); - cursor = ts_tree_cursor_new(tree); + cursor = ts_tree_cursor_new(ts_tree_root_node(tree)); TSNode node = ts_tree_cursor_current_node(&cursor); AssertThat(ts_node_type(node), Equals("a")); From fae74605413a969ebdf8acbcd990e40e0d7f9204 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 21 Jun 2018 12:54:19 -0700 Subject: [PATCH 3/4] Add ts_tree_language function Co-Authored-By: Ashi Krishnan --- include/tree_sitter/runtime.h | 1 + src/runtime/tree.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index e90c25fd..361bbbef 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -101,6 +101,7 @@ TSNode ts_tree_root_node(const TSTree *); void ts_tree_edit(TSTree *, const TSInputEdit *); TSRange *ts_tree_get_changed_ranges(const TSTree *, const TSTree *, uint32_t *); void ts_tree_print_dot_graph(const TSTree *, FILE *); +const TSLanguage *ts_tree_language(const TSTree *); uint32_t ts_node_start_byte(TSNode); TSPoint ts_node_start_point(TSNode); diff --git a/src/runtime/tree.c b/src/runtime/tree.c index 866b93b4..1345f065 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -34,6 +34,10 @@ TSNode ts_tree_root_node(const TSTree *self) { return ts_node_new(self, self->root, self->root->padding, 0); } +const TSLanguage *ts_tree_language(const TSTree *self) { + return self->language; +} + void ts_tree_edit(TSTree *self, const TSInputEdit *edit) { SubtreePool pool = ts_subtree_pool_new(0); self->root = ts_subtree_edit(self->root, edit, &pool); From 10c12aaa3b4518459e6c1a543437f77837e00661 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 21 Jun 2018 12:54:32 -0700 Subject: [PATCH 4/4] Add ts_language_symbol_for_name function Co-Authored-By: Ashi Krishnan --- include/tree_sitter/runtime.h | 1 + src/runtime/language.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index 361bbbef..3c50c3f2 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -142,6 +142,7 @@ TSNode ts_tree_cursor_current_node(const TSTreeCursor *); uint32_t ts_language_symbol_count(const TSLanguage *); const char *ts_language_symbol_name(const TSLanguage *, TSSymbol); +TSSymbol ts_language_symbol_for_name(const TSLanguage *, const char *); TSSymbolType ts_language_symbol_type(const TSLanguage *, TSSymbol); uint32_t ts_language_version(const TSLanguage *); diff --git a/src/runtime/language.c b/src/runtime/language.c index 75e7da8b..c8e0bfc1 100644 --- a/src/runtime/language.c +++ b/src/runtime/language.c @@ -1,6 +1,7 @@ #include "runtime/language.h" #include "runtime/subtree.h" #include "runtime/error_costs.h" +#include void ts_language_table_entry(const TSLanguage *self, TSStateId state, TSSymbol symbol, TableEntry *result) { @@ -46,6 +47,15 @@ const char *ts_language_symbol_name(const TSLanguage *language, TSSymbol symbol) } } +TSSymbol ts_language_symbol_for_name(const TSLanguage *self, const char *name) { + for (TSSymbol i = 0; i < self->symbol_count; i++) { + if (!strcmp(self->symbol_names[i], name)) { + return i; + } + } + return 0; +} + TSSymbolType ts_language_symbol_type(const TSLanguage *language, TSSymbol symbol) { TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol); if (metadata.named) {