From 973e4a44f0ade679598bc7499be2d2820bcfd355 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 9 May 2018 10:16:10 -0700 Subject: [PATCH] Start work on removing parent pointers Co-Authored-By: Rick Winfrey --- include/tree_sitter/runtime.h | 8 +- src/runtime/array.h | 9 + src/runtime/document.c | 8 +- src/runtime/node.c | 307 +++++++++++------- src/runtime/node.h | 8 - src/runtime/parser.c | 54 +-- src/runtime/reusable_node.h | 95 ++++-- src/runtime/tree.c | 138 ++++---- src/runtime/tree.h | 14 +- .../prepare_grammar/extract_tokens_test.cc | 22 +- test/helpers/tree_helpers.cc | 25 +- test/runtime/document_test.cc | 2 +- test/runtime/node_test.cc | 40 +-- test/runtime/tree_test.cc | 4 +- 14 files changed, 410 insertions(+), 324 deletions(-) delete mode 100644 src/runtime/node.h diff --git a/include/tree_sitter/runtime.h b/include/tree_sitter/runtime.h index c3bef506..c4bc8ab5 100644 --- a/include/tree_sitter/runtime.h +++ b/include/tree_sitter/runtime.h @@ -63,8 +63,11 @@ typedef struct { } TSRange; typedef struct { - const void *data; - uint32_t offset[2]; + const void *subtree; + const TSDocument *document; + TSPoint position; + uint32_t byte; + TSSymbol alias_symbol; } TSNode; uint32_t ts_node_start_byte(TSNode); @@ -84,7 +87,6 @@ TSNode ts_node_child(TSNode, uint32_t); TSNode ts_node_named_child(TSNode, uint32_t); uint32_t ts_node_child_count(TSNode); uint32_t ts_node_named_child_count(TSNode); -uint32_t ts_node_child_index(TSNode); TSNode ts_node_next_sibling(TSNode); TSNode ts_node_next_named_sibling(TSNode); TSNode ts_node_prev_sibling(TSNode); diff --git a/src/runtime/array.h b/src/runtime/array.h index 4d2f478b..45b3adaa 100644 --- a/src/runtime/array.h +++ b/src/runtime/array.h @@ -58,6 +58,9 @@ extern "C" { #define array_pop(self) ((self)->contents[--(self)->size]) +#define array_assign(self, other) \ + array__assign((VoidArray *)(self), (const VoidArray *)(other), array__elem_size(self)) + // Private typedef Array(void) VoidArray; @@ -91,6 +94,12 @@ static inline void array__reserve(VoidArray *self, size_t element_size, uint32_t } } +static inline void array__assign(VoidArray *self, const VoidArray *other, size_t element_size) { + array__reserve(self, element_size, other->size); + self->size = other->size; + memcpy(self->contents, other->contents, self->size * element_size); +} + static inline void array__grow(VoidArray *self, size_t element_size) { if (self->size == self->capacity) { size_t new_capacity = self->capacity * 2; diff --git a/src/runtime/document.c b/src/runtime/document.c index d611d989..ddd89b43 100644 --- a/src/runtime/document.c +++ b/src/runtime/document.c @@ -1,5 +1,4 @@ #include "runtime/alloc.h" -#include "runtime/node.h" #include "runtime/tree.h" #include "runtime/parser.h" #include "runtime/string_input.h" @@ -171,7 +170,12 @@ void ts_document_invalidate(TSDocument *self) { } TSNode ts_document_root_node(const TSDocument *self) { - return ts_node_make(self->tree, 0, 0); + return (TSNode) { + .subtree = self->tree, + .document = self, + .position = {0, 0}, + .byte = 0, + }; } uint32_t ts_document_parse_count(const TSDocument *self) { diff --git a/src/runtime/node.c b/src/runtime/node.c index c825a104..246cd290 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -1,43 +1,91 @@ #include -#include "runtime/node.h" #include "runtime/tree.h" #include "runtime/document.h" +#include "runtime/language.h" -TSNode ts_node_make(const Tree *tree, uint32_t byte, uint32_t row) { - return (TSNode){.data = tree, .offset = { byte, row } }; -} +// NodeChildIterator -/* - * Private - */ +typedef struct { + const Tree *parent; + const TSDocument *document; + Length position; + uint32_t child_index; + uint32_t structural_child_index; + const TSSymbol *alias_sequence; +} NodeChildIterator; + +// TSNode - Private static inline TSNode ts_node__null() { - return ts_node_make(NULL, 0, 0); + return (TSNode) { + .subtree = NULL, + .document = NULL, + .position = {0, 0}, + .byte = 0, + }; } static inline const Tree *ts_node__tree(TSNode self) { - return self.data; + return self.subtree; } -static inline uint32_t ts_node__offset_byte(TSNode self) { - return self.offset[0]; +static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) { + const Tree *tree = ts_node__tree(*node); + const TSSymbol *alias_sequence = ts_language_alias_sequence( + node->document->parser.language, + tree->alias_sequence_id + ); + return (NodeChildIterator) { + .parent = tree, + .document = node->document, + .position = {node->byte, node->position}, + .child_index = 0, + .structural_child_index = 0, + .alias_sequence = alias_sequence, + }; } -static inline uint32_t ts_node__offset_row(TSNode self) { - return self.offset[1]; +static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) { + if (self->child_index == self->parent->children.size) return false; + Tree *child = self->parent->children.contents[self->child_index]; + TSSymbol alias_symbol = 0; + if (!child->extra) { + if (self->alias_sequence) { + alias_symbol = self->alias_sequence[self->structural_child_index]; + } + self->structural_child_index++; + } + *result = (TSNode) { + .subtree = child, + .document = self->document, + .position = self->position.extent, + .byte = self->position.bytes, + .alias_symbol = alias_symbol, + }; + self->position = length_add(self->position, ts_tree_total_size(child)); + self->child_index++; + return true; } static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) { const Tree *tree = ts_node__tree(self); if (include_anonymous) { - return tree->context.alias_symbol || tree->visible; + return tree->visible || self.alias_symbol; } else { - return tree->context.alias_is_named || (tree->visible && tree->named); + return ( + (tree->visible && tree->named) || + ( + self.alias_symbol && + ts_language_symbol_metadata( + self.document->parser.language, + self.alias_symbol + ).named + ) + ); } } -static inline uint32_t ts_node__relevant_child_count(TSNode self, - bool include_anonymous) { +static inline uint32_t ts_node__relevant_child_count(TSNode self, bool include_anonymous) { const Tree *tree = ts_node__tree(self); if (tree->children.size > 0) { if (include_anonymous) { @@ -50,44 +98,23 @@ static inline uint32_t ts_node__relevant_child_count(TSNode self, } } -static inline TSNode ts_node__direct_parent(TSNode self, uint32_t *index) { - const Tree *tree = ts_node__tree(self); - *index = tree->context.index; - return ts_node_make( - tree->context.parent, - ts_node__offset_byte(self) - tree->context.offset.bytes, - ts_node__offset_row(self) - tree->context.offset.extent.row - ); -} - -static inline TSNode ts_node__direct_child(TSNode self, uint32_t i) { - const Tree *child_tree = ts_node__tree(self)->children.contents[i]; - return ts_node_make( - child_tree, - ts_node__offset_byte(self) + child_tree->context.offset.bytes, - ts_node__offset_row(self) + child_tree->context.offset.extent.row - ); -} - -static inline TSNode ts_node__child(TSNode self, uint32_t child_index, - bool include_anonymous) { +static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool include_anonymous) { TSNode result = self; bool did_descend = true; while (did_descend) { did_descend = false; + TSNode child; uint32_t index = 0; - for (uint32_t i = 0; i < ts_node__tree(result)->children.size; i++) { - TSNode child = ts_node__direct_child(result, i); + NodeChildIterator iterator = ts_node_child_iterator_begin(&result); + while (ts_node_child_iterator_next(&iterator, &child)) { if (ts_node__is_relevant(child, include_anonymous)) { - if (index == child_index) - return child; + if (index == child_index) return child; index++; } else { uint32_t grandchild_index = child_index - index; - uint32_t grandchild_count = - ts_node__relevant_child_count(child, include_anonymous); + uint32_t grandchild_count = ts_node__relevant_child_count(child, include_anonymous); if (grandchild_index < grandchild_count) { did_descend = true; result = child; @@ -102,48 +129,80 @@ static inline TSNode ts_node__child(TSNode self, uint32_t child_index, return ts_node__null(); } -static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous) { - TSNode result = self; - - do { - uint32_t index; - result = ts_node__direct_parent(result, &index); - if (!result.data) +static inline bool ts_node__last_child_before(TSNode self, TSNode target, + bool include_anonymous, TSNode *result) { + TSNode child; + TSNode earlier_child = ts_node__null(); + bool earlier_child_is_relevant = false; + bool found_child_containing_target = false; + NodeChildIterator iterator = ts_node_child_iterator_begin(&self); + uint32_t target_end_byte = ts_node_end_byte(target); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (iterator.position.bytes >= target_end_byte) { + found_child_containing_target = true; break; - - for (uint32_t i = index - 1; i + 1 > 0; i--) { - TSNode child = ts_node__direct_child(result, i); - if (ts_node__is_relevant(child, include_anonymous)) - return child; - uint32_t grandchild_count = - ts_node__relevant_child_count(child, include_anonymous); - if (grandchild_count > 0) - return ts_node__child(child, grandchild_count - 1, include_anonymous); } - } while (!ts_node__tree(result)->visible); - return ts_node__null(); + if (ts_node__is_relevant(child, include_anonymous)) { + earlier_child = child; + earlier_child_is_relevant = true; + } else if (ts_node__relevant_child_count(child, include_anonymous) > 0) { + earlier_child = child; + earlier_child_is_relevant = false; + } + } + + if (found_child_containing_target && child.subtree != target.subtree) { + if (ts_node__last_child_before(child, target, include_anonymous, result)) { + return true; + } + } + + if (earlier_child_is_relevant) { + *result = earlier_child; + return true; + } + + if (earlier_child.subtree) { + return ts_node__last_child_before(earlier_child, target, include_anonymous, result); + } + + return false; +} + +static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous) { + TSNode result = ts_node__null(); + TSNode parent = ts_node_parent(self); + if (parent.subtree) { + ts_node__last_child_before(parent, self, include_anonymous, &result); + } + return result; } static inline TSNode ts_node__next_sibling(TSNode self, bool include_anonymous) { - TSNode result = self; + TSNode node = ts_node_parent(self); + if (!node.subtree) return ts_node__null(); + uint32_t end_byte = ts_node_end_byte(self); - do { - uint32_t index; - result = ts_node__direct_parent(result, &index); - if (!result.data) - break; + bool did_descend = true; + while (did_descend) { + did_descend = false; - for (uint32_t i = index + 1; i < ts_node__tree(result)->children.size; i++) { - TSNode child = ts_node__direct_child(result, i); - if (ts_node__is_relevant(child, include_anonymous)) - return child; - uint32_t grandchild_count = - ts_node__relevant_child_count(child, include_anonymous); - if (grandchild_count > 0) - return ts_node__child(child, 0, include_anonymous); + TSNode child; + NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (iterator.position.bytes > end_byte && child.subtree != self.subtree) { + if (ts_node__is_relevant(child, include_anonymous)) { + return child; + } + if (ts_node__relevant_child_count(child, include_anonymous) > 0) { + node = child; + did_descend = true; + break; + } + } } - } while (!ts_node__tree(result)->visible); + } return ts_node__null(); } @@ -160,8 +219,9 @@ static inline TSNode ts_node__first_child_for_byte(TSNode self, uint32_t goal, while (did_descend) { did_descend = false; - for (uint32_t i = 0; i < ts_node__tree(node)->children.size; i++) { - TSNode child = ts_node__direct_child(node, i); + TSNode child; + NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { if (ts_node_end_byte(child) > goal) { if (ts_node__is_relevant(child, include_anonymous)) { return child; @@ -187,10 +247,11 @@ static inline TSNode ts_node__descendant_for_byte_range(TSNode self, uint32_t mi while (did_descend) { did_descend = false; - for (uint32_t i = 0, n = ts_node__tree(node)->children.size; i < n; i++) { - TSNode child = ts_node__direct_child(node, i); - if (ts_node_end_byte(child) > max) { - if (ts_node_start_byte(child) > min) break; + TSNode child; + NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (iterator.position.bytes > max) { + if (child.byte > min) break; node = child; if (ts_node__is_relevant(node, include_anonymous)) last_visible_node = node; did_descend = true; @@ -214,10 +275,13 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi while (did_descend) { did_descend = false; - for (uint32_t i = 0, n = ts_node__tree(node)->children.size; i < n; i++) { - TSNode child = ts_node__direct_child(node, i); + TSNode child; + NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { const Tree *child_tree = ts_node__tree(child); - if (i > 0) start_position = point_add(start_position, child_tree->padding.extent); + if (iterator.child_index != 1) { + start_position = point_add(start_position, child_tree->padding.extent); + } end_position = point_add(start_position, child_tree->size.extent); if (point_gt(end_position, max)) { if (point_gt(start_position, min)) break; @@ -233,12 +297,10 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi return last_visible_node; } -/* - * Public - */ +// TSNode - Public uint32_t ts_node_start_byte(TSNode self) { - return ts_node__offset_byte(self) + ts_node__tree(self)->padding.bytes; + return self.byte + ts_node__tree(self)->padding.bytes; } uint32_t ts_node_end_byte(TSNode self) { @@ -246,21 +308,16 @@ uint32_t ts_node_end_byte(TSNode self) { } TSPoint ts_node_start_point(TSNode self) { - const Tree *tree = ts_node__tree(self); - return (TSPoint){ ts_node__offset_row(self) + tree->padding.extent.row, - ts_tree_start_column(tree) }; + return point_add(self.position, ts_node__tree(self)->padding.extent); } TSPoint ts_node_end_point(TSNode self) { - const Tree *tree = ts_node__tree(self); - return (TSPoint){ ts_node__offset_row(self) + tree->padding.extent.row + - tree->size.extent.row, - ts_tree_end_column(tree) }; + return point_add(ts_node_start_point(self), ts_node__tree(self)->size.extent); } TSSymbol ts_node_symbol(TSNode self) { const Tree *tree = ts_node__tree(self); - return tree->context.alias_symbol ? tree->context.alias_symbol : tree->symbol; + return self.alias_symbol ? self.alias_symbol : tree->symbol; } const char *ts_node_type(TSNode self, const TSDocument *document) { @@ -272,15 +329,17 @@ char *ts_node_string(TSNode self, const TSDocument *document) { } bool ts_node_eq(TSNode self, TSNode other) { - return + return ( ts_tree_eq(ts_node__tree(self), ts_node__tree(other)) && - self.offset[0] == other.offset[0] && - self.offset[1] == other.offset[1]; + self.byte == other.byte + ); } bool ts_node_is_named(TSNode self) { const Tree *tree = ts_node__tree(self); - return tree->context.alias_symbol ? tree->context.alias_is_named : tree->named; + return self.alias_symbol + ? ts_language_symbol_metadata(self.document->parser.language, self.alias_symbol).named + : tree->named; } bool ts_node_is_missing(TSNode self) { @@ -297,35 +356,31 @@ bool ts_node_has_error(TSNode self) { } TSNode ts_node_parent(TSNode self) { - TSNode result = self; - uint32_t index; + TSNode node = ts_document_root_node(self.document); + uint32_t end_byte = ts_node_end_byte(self); + if (node.subtree == self.subtree) return ts_node__null(); - do { - result = ts_node__direct_parent(result, &index); - if (!result.data) - return ts_node__null(); - } while (!ts_node__tree(result)->visible); + TSNode last_visible_node = node; + bool did_descend = true; + while (did_descend) { + did_descend = false; - return result; -} - -uint32_t ts_node_child_index(TSNode self) { - const Tree *tree = ts_node__tree(self); - uint32_t result = 0; - - for (;;) { - const Tree *parent = tree->context.parent; - uint32_t index = tree->context.index; - if (!parent) return UINT32_MAX; - for (uint32_t i = 0; i < index; i++) { - Tree *child = parent->children.contents[i]; - result += child->visible ? 1 : child->visible_child_count; + TSNode child; + NodeChildIterator iterator = ts_node_child_iterator_begin(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (child.byte > self.byte || child.subtree == self.subtree) break; + if (iterator.position.bytes >= end_byte) { + node = child; + if (ts_node__is_relevant(child, true)) { + last_visible_node = node; + } + did_descend = true; + break; + } } - if (parent->visible) break; - tree = parent; } - return result; + return last_visible_node; } TSNode ts_node_child(TSNode self, uint32_t child_index) { diff --git a/src/runtime/node.h b/src/runtime/node.h deleted file mode 100644 index ee184c9a..00000000 --- a/src/runtime/node.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RUNTIME_NODE_H_ -#define RUNTIME_NODE_H_ - -#include "runtime/tree.h" - -TSNode ts_node_make(const Tree *, uint32_t byte, uint32_t row); - -#endif diff --git a/src/runtime/parser.c b/src/runtime/parser.c index ff194936..cac6c9e1 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -119,16 +119,19 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) { static void parser__breakdown_lookahead(Parser *self, Tree **lookahead, TSStateId state, ReusableNode *reusable_node) { - bool did_break_down = false; - while (reusable_node->tree->children.size > 0 && reusable_node->tree->parse_state != state) { - LOG("state_mismatch sym:%s", SYM_NAME(reusable_node->tree->symbol)); - reusable_node_breakdown(reusable_node); - did_break_down = true; + bool did_descend = false; + Tree *tree = reusable_node_tree(reusable_node); + while (tree->children.size > 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); + did_descend = true; } - if (did_break_down) { + if (did_descend) { ts_tree_release(&self->tree_pool, *lookahead); - ts_tree_retain(*lookahead = reusable_node->tree); + *lookahead = tree; + ts_tree_retain(*lookahead); } } @@ -419,21 +422,22 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId Tree *last_external_token = ts_stack_last_external_token(self->stack, version); Tree *result; - while ((result = reusable_node->tree)) { - if (reusable_node->byte_index > position.bytes) { + while ((result = reusable_node_tree(reusable_node))) { + uint32_t byte_offset = reusable_node_byte_offset(reusable_node); + if (byte_offset > position.bytes) { LOG("before_reusable_node symbol:%s", SYM_NAME(result->symbol)); break; } - if (reusable_node->byte_index < position.bytes) { + if (byte_offset < position.bytes) { LOG("past_reusable_node symbol:%s", SYM_NAME(result->symbol)); - reusable_node_pop(reusable_node); + reusable_node_advance(reusable_node); continue; } if (!ts_tree_external_token_state_eq(reusable_node->last_external_token, last_external_token)) { LOG("reusable_node_has_different_external_scanner_state symbol:%s", SYM_NAME(result->symbol)); - reusable_node_pop(reusable_node); + reusable_node_advance(reusable_node); continue; } @@ -452,8 +456,8 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId if (reason) { LOG("cant_reuse_node_%s tree:%s", reason, SYM_NAME(result->symbol)); - if (!reusable_node_breakdown(reusable_node)) { - reusable_node_pop(reusable_node); + if (!reusable_node_descend(reusable_node)) { + reusable_node_advance(reusable_node); parser__breakdown_top_of_stack(self, version); *state = ts_stack_state(self->stack, version); } @@ -467,7 +471,7 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId SYM_NAME(result->symbol), SYM_NAME(result->first_leaf.symbol) ); - reusable_node_pop_leaf(reusable_node); + reusable_node_advance_past_leaf(reusable_node); break; } @@ -678,7 +682,7 @@ static void parser__start(Parser *self, TSInput input, Tree *previous_tree) { ts_lexer_set_input(&self->lexer, input); ts_stack_clear(self->stack); - self->reusable_node = reusable_node_new(previous_tree); + reusable_node_reset(&self->reusable_node, previous_tree); self->finished_tree = NULL; self->accept_count = 0; self->in_ambiguity = false; @@ -1106,7 +1110,9 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re } parser__shift(self, version, next_state, lookahead, action.params.extra); - if (lookahead == reusable_node->tree) reusable_node_pop(reusable_node); + if (lookahead == reusable_node_tree(reusable_node)) { + reusable_node_advance(reusable_node); + } ts_tree_release(&self->tree_pool, lookahead); return; } @@ -1136,7 +1142,9 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re parser__breakdown_lookahead(self, &lookahead, state, reusable_node); } parser__recover(self, version, lookahead); - if (lookahead == reusable_node->tree) reusable_node_pop(reusable_node); + if (lookahead == reusable_node_tree(reusable_node)) { + reusable_node_advance(reusable_node); + } ts_tree_release(&self->tree_pool, lookahead); return; } @@ -1255,6 +1263,7 @@ bool parser_init(Parser *self) { ts_tree_pool_init(&self->tree_pool); self->stack = ts_stack_new(&self->tree_pool); self->finished_tree = NULL; + self->reusable_node = reusable_node_new(); parser__set_cached_token(self, 0, NULL, NULL); return true; } @@ -1277,6 +1286,7 @@ void parser_destroy(Parser *self) { if (self->reduce_actions.contents) array_delete(&self->reduce_actions); ts_tree_pool_delete(&self->tree_pool); + reusable_node_delete(&self->reusable_node); parser_set_language(self, NULL); } @@ -1285,11 +1295,12 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err StackVersion version = STACK_VERSION_NONE; uint32_t position = 0, last_position = 0; - ReusableNode reusable_node; + ReusableNode reusable_node = reusable_node_new(); + reusable_node_assign(&reusable_node, &self->reusable_node); do { for (version = 0; version < ts_stack_version_count(self->stack); version++) { - reusable_node = self->reusable_node; + reusable_node_assign(&reusable_node, &self->reusable_node); while (ts_stack_is_active(self->stack, version)) { LOG("process version:%d, version_count:%u, state:%d, row:%u, col:%u", @@ -1309,7 +1320,7 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err } } - self->reusable_node = reusable_node; + reusable_node_assign(&self->reusable_node, &reusable_node); unsigned min_error_cost = parser__condense_stack(self); if (self->finished_tree && self->finished_tree->error_cost < min_error_cost) { @@ -1322,6 +1333,7 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err self->in_ambiguity = version > 1; } while (version != 0); + reusable_node_delete(&reusable_node); ts_stack_clear(self->stack); parser__set_cached_token(self, 0, NULL, NULL); ts_tree_assign_parents(self->finished_tree, &self->tree_pool, self->language); diff --git a/src/runtime/reusable_node.h b/src/runtime/reusable_node.h index 4a6290f4..803304de 100644 --- a/src/runtime/reusable_node.h +++ b/src/runtime/reusable_node.h @@ -2,44 +2,81 @@ typedef struct { Tree *tree; - uint32_t byte_index; + uint32_t child_index; + uint32_t byte_offset; +} StackEntry; + +typedef struct { + Array(StackEntry) stack; Tree *last_external_token; } ReusableNode; -static inline ReusableNode reusable_node_new(Tree *tree) { - ReusableNode result = {tree, 0, NULL}; - return result; +static inline ReusableNode reusable_node_new() { + return (ReusableNode) {array_new(), NULL}; } -static inline void reusable_node_pop(ReusableNode *self) { - self->byte_index += ts_tree_total_bytes(self->tree); - if (self->tree->has_external_tokens) { - self->last_external_token = ts_tree_last_external_token(self->tree); - } - - while (self->tree) { - Tree *parent = self->tree->context.parent; - uint32_t next_index = self->tree->context.index + 1; - if (parent && parent->children.size > next_index) { - self->tree = parent->children.contents[next_index]; - return; - } - self->tree = parent; - } +static inline void reusable_node_reset(ReusableNode *self, Tree *tree) { + array_clear(&self->stack); + array_push(&self->stack, ((StackEntry) { + .tree = tree, + .child_index = 0, + .byte_offset = 0, + })); } -static inline void reusable_node_pop_leaf(ReusableNode *self) { - while (self->tree->children.size > 0) { - self->tree = self->tree->children.contents[0]; - } - reusable_node_pop(self); +static inline Tree *reusable_node_tree(ReusableNode *self) { + return array_back(&self->stack)->tree; } -static inline bool reusable_node_breakdown(ReusableNode *self) { - if (self->tree->children.size == 0) { - return false; - } else { - self->tree = self->tree->children.contents[0]; +static inline uint32_t reusable_node_byte_offset(ReusableNode *self) { + return array_back(&self->stack)->byte_offset; +} + +static inline void reusable_node_delete(ReusableNode *self) { + array_delete(&self->stack); +} + +static inline void reusable_node_assign(ReusableNode *self, const ReusableNode *other) { + array_assign(&self->stack, &other->stack); +} + +static inline void reusable_node_advance(ReusableNode *self) { + StackEntry last_entry = *array_back(&self->stack); + uint32_t byte_offset = last_entry.byte_offset + ts_tree_total_bytes(last_entry.tree); + if (last_entry.tree->has_external_tokens) { + self->last_external_token = ts_tree_last_external_token(last_entry.tree); + } + + Tree *tree; + uint32_t next_index; + do { + StackEntry popped_entry = array_pop(&self->stack); + next_index = popped_entry.child_index + 1; + tree = array_back(&self->stack)->tree; + } while (tree->children.size <= next_index); + + array_push(&self->stack, ((StackEntry) { + .tree = tree->children.contents[next_index], + .child_index = next_index, + .byte_offset = byte_offset, + })); +} + +static inline bool reusable_node_descend(ReusableNode *self) { + StackEntry last_entry = *array_back(&self->stack); + if (last_entry.tree->children.size > 0) { + array_push(&self->stack, ((StackEntry) { + .tree = last_entry.tree->children.contents[0], + .child_index = 0, + .byte_offset = last_entry.byte_offset, + })); return true; + } else { + return false; } } + +static inline void reusable_node_advance_past_leaf(ReusableNode *self) { + while (reusable_node_descend(self)) {} + reusable_node_advance(self); +} diff --git a/src/runtime/tree.c b/src/runtime/tree.c index c1ada974..fcb534dd 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -169,7 +169,9 @@ Tree *ts_tree_make_copy(TreePool *pool, Tree *self) { return result; } -static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *language) { +static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *language, TreeArray *stack) { + unsigned initial_stack_size = stack->size; + Tree *tree = self; for (unsigned i = 0; i < count; i++) { if (tree->ref_count > 1 || tree->children.size != 2) break; @@ -189,22 +191,14 @@ static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *lang ) break; tree->children.contents[0] = grandchild; - grandchild->context.parent = tree; - grandchild->context.index = -1; - child->children.contents[0] = grandchild->children.contents[1]; - child->children.contents[0]->context.parent = child; - child->children.contents[0]->context.index = -1; - grandchild->children.contents[1] = child; - grandchild->children.contents[1]->context.parent = grandchild; - grandchild->children.contents[1]->context.index = -1; - + array_push(stack, tree); tree = grandchild; } - while (tree != self) { - tree = tree->context.parent; + while (stack->size > initial_stack_size) { + tree = array_pop(stack); Tree *child = tree->children.contents[0]; Tree *grandchild = child->children.contents[1]; ts_tree_set_children(grandchild, &grandchild->children, language); @@ -213,50 +207,30 @@ static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *lang } } -void ts_tree__balance(Tree *self, const TSLanguage *language) { - if (self->children.contents[0]->repeat_depth > self->children.contents[1]->repeat_depth) { - unsigned n = self->children.contents[0]->repeat_depth - self->children.contents[1]->repeat_depth; - for (unsigned i = n / 2; i > 0; i /= 2) { - ts_tree__compress(self, i, language); - n -= i; - } - } -} - void ts_tree_assign_parents(Tree *self, TreePool *pool, const TSLanguage *language) { - self->context.parent = NULL; array_clear(&pool->tree_stack); array_push(&pool->tree_stack, self); while (pool->tree_stack.size > 0) { Tree *tree = array_pop(&pool->tree_stack); if (tree->repeat_depth > 0) { - ts_tree__balance(tree, language); + if (tree->children.contents[0]->repeat_depth > tree->children.contents[1]->repeat_depth) { + unsigned n = ( + tree->children.contents[0]->repeat_depth - + tree->children.contents[1]->repeat_depth + ); + for (unsigned i = n / 2; i > 0; i /= 2) { + ts_tree__compress(tree, i, language, &pool->tree_stack); + n -= i; + } + } } - Length offset = length_zero(); - const TSSymbol *alias_sequence = ts_language_alias_sequence(language, tree->alias_sequence_id); - uint32_t non_extra_index = 0; - bool earlier_child_was_changed = false; for (uint32_t i = 0; i < tree->children.size; i++) { Tree *child = tree->children.contents[i]; - if (earlier_child_was_changed || child->context.parent != tree || child->context.index != i) { - earlier_child_was_changed = true; - child->context.parent = tree; - child->context.index = i; - child->context.offset = offset; - if (!child->extra && alias_sequence && alias_sequence[non_extra_index] != 0) { - TSSymbolMetadata metadata = ts_language_symbol_metadata(language, alias_sequence[non_extra_index]); - child->context.alias_symbol = alias_sequence[non_extra_index]; - child->context.alias_is_named = metadata.named; - } else { - child->context.alias_symbol = 0; - child->context.alias_is_named = false; - } + if (child->ref_count == 1) { array_push(&pool->tree_stack, child); } - offset = length_add(offset, ts_tree_total_size(child)); - if (!child->extra) non_extra_index++; } } } @@ -407,25 +381,6 @@ void ts_tree_release(TreePool *pool, Tree *self) { } } -uint32_t ts_tree_start_column(const Tree *self) { - uint32_t column = self->padding.extent.column; - if (self->padding.extent.row > 0) - return column; - for (const Tree *tree = self; tree != NULL; tree = tree->context.parent) { - column += tree->context.offset.extent.column; - if (tree->context.offset.extent.row > 0) - break; - } - return column; -} - -uint32_t ts_tree_end_column(const Tree *self) { - uint32_t result = self->size.extent.column; - if (self->size.extent.row == 0) - result += ts_tree_start_column(self); - return result; -} - bool ts_tree_eq(const Tree *self, const Tree *other) { if (self) { if (!other) return false; @@ -577,7 +532,6 @@ void ts_tree_edit(Tree *self, const TSInputEdit *edit) { } child_right = length_add(child_left, ts_tree_total_size(child)); - child->context.offset = child_left; } } @@ -612,9 +566,10 @@ static size_t ts_tree__write_char_to_string(char *s, size_t n, int32_t c) { return snprintf(s, n, "%d", c); } -static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *language, - char *string, size_t limit, bool is_root, - bool include_all) { +static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t limit, + const TSLanguage *language, bool is_root, + bool include_all, TSSymbol alias_symbol, + bool alias_is_named) { if (!self) return snprintf(string, limit, "(NULL)"); char *cursor = string; @@ -624,7 +579,7 @@ static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *langu is_root || self->is_missing || (self->visible && self->named) || - self->context.alias_is_named; + alias_is_named; if (visible && !is_root) { cursor += snprintf(*writer, limit, " "); @@ -637,15 +592,35 @@ static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *langu } else if (self->is_missing) { cursor += snprintf(*writer, limit, "(MISSING"); } else { - TSSymbol symbol = self->context.alias_symbol ? self->context.alias_symbol : self->symbol; + TSSymbol symbol = alias_symbol ? alias_symbol : self->symbol; const char *symbol_name = ts_language_symbol_name(language, symbol); cursor += snprintf(*writer, limit, "(%s", symbol_name); } } + 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++) { Tree *child = self->children.contents[i]; - cursor += ts_tree__write_to_string(child, language, *writer, limit, false, include_all); + if (child->extra) { + cursor += ts_tree__write_to_string( + child, *writer, limit, + language, false, include_all, + 0, false + ); + } else { + cursor += ts_tree__write_to_string( + child, *writer, limit, + language, false, include_all, + alias_sequence + ? alias_sequence[structural_child_index] + : 0, + alias_sequence + ? ts_language_symbol_metadata(language, alias_sequence[structural_child_index]).named + : false + ); + structural_child_index++; + } } if (visible) cursor += snprintf(*writer, limit, ")"); @@ -655,15 +630,19 @@ static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *langu char *ts_tree_string(const Tree *self, const TSLanguage *language, bool include_all) { char scratch_string[1]; - size_t size = ts_tree__write_to_string(self, language, scratch_string, 0, true, include_all) + 1; + size_t size = ts_tree__write_to_string( + self, scratch_string, 0, + language, true, + include_all, 0, false + ) + 1; char *result = ts_malloc(size * sizeof(char)); - ts_tree__write_to_string(self, language, result, size, true, include_all); + ts_tree__write_to_string(self, result, size, language, true, include_all, 0, false); return result; } void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset, - const TSLanguage *language, FILE *f) { - TSSymbol symbol = self->context.alias_symbol ? self->context.alias_symbol : self->symbol; + const TSLanguage *language, TSSymbol alias_symbol, FILE *f) { + 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) @@ -674,9 +653,18 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset, fprintf(f, ", tooltip=\"address:%p\nrange:%u - %u\nstate:%d\nerror-cost:%u\nrepeat-depth:%u\"]\n", self, byte_offset, byte_offset + ts_tree_total_bytes(self), self->parse_state, self->error_cost, self->repeat_depth); + + 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 Tree *child = self->children.contents[i]; - ts_tree__print_dot_graph(child, byte_offset, language, f); + if (child->extra) { + ts_tree__print_dot_graph(child, byte_offset, language, 0, f); + } else { + TSSymbol alias_symbol = alias_sequence ? alias_sequence[structural_child_index] : 0; + ts_tree__print_dot_graph(child, byte_offset, language, alias_symbol, f); + structural_child_index++; + } fprintf(f, "tree_%p -> tree_%p [tooltip=%u]\n", self, child, i); byte_offset += ts_tree_total_bytes(child); } @@ -685,7 +673,7 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset, void ts_tree_print_dot_graph(const Tree *self, const TSLanguage *language, FILE *f) { fprintf(f, "digraph tree {\n"); fprintf(f, "edge [arrowhead=none]\n"); - ts_tree__print_dot_graph(self, 0, language, f); + ts_tree__print_dot_graph(self, 0, language, 0, f); fprintf(f, "}\n"); } diff --git a/src/runtime/tree.h b/src/runtime/tree.h index f416516d..da5f1e90 100644 --- a/src/runtime/tree.h +++ b/src/runtime/tree.h @@ -27,14 +27,6 @@ typedef struct Tree Tree; typedef Array(Tree *) TreeArray; struct Tree { - struct { - struct Tree *parent; - uint32_t index; - Length offset; - TSSymbol alias_symbol : 15; - bool alias_is_named : 1; - } context; - Length padding; Length size; uint32_t ref_count; @@ -106,8 +98,6 @@ void ts_tree_retain(Tree *tree); void ts_tree_release(TreePool *, Tree *tree); bool ts_tree_eq(const Tree *tree1, const Tree *tree2); int ts_tree_compare(const Tree *tree1, const Tree *tree2); -uint32_t ts_tree_start_column(const Tree *self); -uint32_t ts_tree_end_column(const Tree *self); void ts_tree_set_children(Tree *, TreeArray *, const TSLanguage *); void ts_tree_assign_parents(Tree *, TreePool *, const TSLanguage *); void ts_tree_edit(Tree *, const TSInputEdit *edit); @@ -120,6 +110,10 @@ static inline uint32_t ts_tree_total_bytes(const Tree *self) { return self->padding.bytes + self->size.bytes; } +static inline uint32_t ts_tree_total_rows(const Tree *self) { + return self->padding.extent.row + self->size.extent.row; +} + static inline Length ts_tree_total_size(const Tree *self) { return length_add(self->padding, self->size); } diff --git a/test/compiler/prepare_grammar/extract_tokens_test.cc b/test/compiler/prepare_grammar/extract_tokens_test.cc index 0f9be780..da2ae60a 100644 --- a/test/compiler/prepare_grammar/extract_tokens_test.cc +++ b/test/compiler/prepare_grammar/extract_tokens_test.cc @@ -48,7 +48,7 @@ describe("extract_tokens", []() { Repeat{Symbol::non_terminal(3)} }, }, - {}, {}, {}, {} + {}, {}, {}, {}, {} }); InitialSyntaxGrammar &syntax_grammar = get<0>(result); @@ -156,7 +156,7 @@ describe("extract_tokens", []() { }) }, }, - {}, {}, {}, {} + {}, {}, {}, {}, {} }); InitialSyntaxGrammar &syntax_grammar = get<0>(result); @@ -203,7 +203,7 @@ describe("extract_tokens", []() { Rule::seq({ String{"ef"}, String{"cd"} }) }, }, - {}, {}, {}, {} + {}, {}, {}, {}, {} }); InitialSyntaxGrammar &syntax_grammar = get<0>(result); @@ -258,7 +258,7 @@ describe("extract_tokens", []() { String{"a"} }, }, - {}, {}, {}, {} + {}, {}, {}, {}, {} }); InitialSyntaxGrammar &syntax_grammar = get<0>(result); @@ -298,7 +298,7 @@ describe("extract_tokens", []() { { { Symbol::non_terminal(2), Symbol::non_terminal(3) } }, - {}, {} + {}, {}, {} }); InitialSyntaxGrammar &syntax_grammar = get<0>(result); @@ -319,7 +319,7 @@ describe("extract_tokens", []() { String{"y"}, Pattern{" "}, }, - {}, {}, {} + {}, {}, {}, {} }); AssertThat(get<2>(result), Equals(CompileError::none())); @@ -340,7 +340,7 @@ describe("extract_tokens", []() { { String{"y"}, }, - {}, {}, {} + {}, {}, {}, {} }); AssertThat(get<2>(result), Equals(CompileError::none())); @@ -370,7 +370,7 @@ describe("extract_tokens", []() { { Symbol::non_terminal(2), }, - {}, {}, {} + {}, {}, {}, {} }); AssertThat(get<2>(result), Equals(CompileError::none())); @@ -399,7 +399,7 @@ describe("extract_tokens", []() { { Symbol::non_terminal(1) }, - {}, {}, {} + {}, {}, {}, {} }); AssertThat(get<2>(result), Equals(CompileError( @@ -417,7 +417,7 @@ describe("extract_tokens", []() { { Rule::choice({ Symbol::non_terminal(1), Blank{} }) }, - {}, {}, {} + {}, {}, {}, {} }); AssertThat(get<2>(result), Equals(CompileError( @@ -446,7 +446,7 @@ describe("extract_tokens", []() { { Variable{"rule_A", VariableTypeNamed, Symbol::non_terminal(0)} }, - {} + {}, {} }); AssertThat(get<2>(result), Equals(CompileError( diff --git a/test/helpers/tree_helpers.cc b/test/helpers/tree_helpers.cc index 5142ca8d..8fedb560 100644 --- a/test/helpers/tree_helpers.cc +++ b/test/helpers/tree_helpers.cc @@ -1,8 +1,7 @@ -#include "bandit/bandit.h" +#include "test_helper.h" #include "helpers/tree_helpers.h" #include "helpers/point_helpers.h" #include "runtime/document.h" -#include "runtime/node.h" #include using std::string; @@ -21,24 +20,30 @@ TreeArray *tree_array(std::vector trees) { result.capacity = trees.size(); result.size = trees.size(); result.contents = (Tree **)calloc(trees.size(), sizeof(Tree *)); - for (size_t i = 0; i < trees.size(); i++) + for (size_t i = 0; i < trees.size(); i++) { result.contents[i] = trees[i]; + } return &result; } ostream &operator<<(std::ostream &stream, const Tree *tree) { static TSLanguage DUMMY_LANGUAGE = {}; - static TSDocument DUMMY_DOCUMENT = {}; - DUMMY_DOCUMENT.parser.language = &DUMMY_LANGUAGE; DUMMY_LANGUAGE.symbol_names = symbol_names; - TSNode node; - node.data = tree; - return stream << string(ts_node_string(node, &DUMMY_DOCUMENT)); + char *string = ts_tree_string(tree, &DUMMY_LANGUAGE, false); + stream << string; + ts_free(string); + return stream; } ostream &operator<<(ostream &stream, const TSNode &node) { - return stream << string("{") << (const Tree *)node.data << - string(", ") << to_string(ts_node_start_byte(node)) << string("}"); + if (node.subtree) { + char *string = ts_node_string(node, node.document); + stream << "{" << string << ", " << to_string(ts_node_start_byte(node)) << "}"; + ts_free(string); + return stream; + } else { + return stream << "NULL"; + } } bool operator==(const TSNode &left, const TSNode &right) { diff --git a/test/runtime/document_test.cc b/test/runtime/document_test.cc index 0be03657..97aa4fe2 100644 --- a/test/runtime/document_test.cc +++ b/test/runtime/document_test.cc @@ -182,7 +182,7 @@ describe("Document", [&]() { ts_document_parse(document); ts_document_set_language(document, load_real_language("javascript")); - AssertThat(ts_document_root_node(document).data, Equals(nullptr)); + AssertThat(ts_document_root_node(document).subtree, Equals(nullptr)); ts_document_parse(document); root = ts_document_root_node(document); diff --git a/test/runtime/node_test.cc b/test/runtime/node_test.cc index ff12169f..22196ec5 100644 --- a/test/runtime/node_test.cc +++ b/test/runtime/node_test.cc @@ -71,6 +71,7 @@ describe("Node", [&]() { document = ts_document_new(); ts_document_set_language(document, load_real_language("json")); ts_document_set_input_string(document, json_string.c_str()); + // ts_document_print_debugging_graphs(document, true); ts_document_parse(document); root_node = ts_node_child(ts_document_root_node(document), 0); }); @@ -157,7 +158,7 @@ describe("Node", [&]() { AssertThat(ts_node_parent(number_node), Equals(root_node)); AssertThat(ts_node_parent(false_node), Equals(root_node)); AssertThat(ts_node_parent(object_node), Equals(root_node)); - AssertThat(ts_node_parent(ts_document_root_node(document)).data, Equals(nullptr)); + AssertThat(ts_node_parent(ts_document_root_node(document)).subtree, Equals(nullptr)); }); it("works correctly when the node contains aliased children and extras", [&]() { @@ -239,19 +240,7 @@ describe("Node", [&]() { child = ts_node_first_named_child_for_byte(root_node, object_index + 1); AssertThat(ts_node_type(child, document), Equals("object")); child = ts_node_first_named_child_for_byte(root_node, object_end_index); - AssertThat(child.data, Equals(nullptr)); - }); - }); - - describe("child_index()", [&]() { - it("returns the index of the node within its parent", [&]() { - AssertThat(ts_node_child_index(ts_node_child(root_node, 0)), Equals(0u)); - AssertThat(ts_node_child_index(ts_node_child(root_node, 1)), Equals(1u)); - AssertThat(ts_node_child_index(ts_node_child(root_node, 2)), Equals(2u)); - AssertThat(ts_node_child_index(ts_node_child(root_node, 3)), Equals(3u)); - AssertThat(ts_node_child_index(ts_node_child(root_node, 4)), Equals(4u)); - AssertThat(ts_node_child_index(ts_node_child(root_node, 5)), Equals(5u)); - AssertThat(ts_node_child_index(ts_node_child(root_node, 6)), Equals(6u)); + AssertThat(child.subtree, Equals(nullptr)); }); }); @@ -335,7 +324,7 @@ describe("Node", [&]() { AssertThat(ts_node_parent(child5), Equals(root_node)); AssertThat(ts_node_parent(child6), Equals(root_node)); AssertThat(ts_node_parent(child7), Equals(root_node)); - AssertThat(ts_node_parent(ts_document_root_node(document)).data, Equals(nullptr)); + AssertThat(ts_node_parent(ts_document_root_node(document)).subtree, Equals(nullptr)); }); }); @@ -355,15 +344,16 @@ describe("Node", [&]() { TSNode brace_node2 = ts_node_child(object_node, 2); TSNode bracket_node2 = ts_node_child(root_node, 6); + AssertThat(ts_node_parent(bracket_node1), Equals(root_node)); AssertThat(ts_node_next_sibling(bracket_node1), Equals(number_node)); AssertThat(ts_node_next_sibling(number_node), Equals(array_comma_node1)); AssertThat(ts_node_next_sibling(array_comma_node1), Equals(false_node)); AssertThat(ts_node_next_sibling(false_node), Equals(array_comma_node2)); AssertThat(ts_node_next_sibling(array_comma_node2), Equals(object_node)); AssertThat(ts_node_next_sibling(object_node), Equals(bracket_node2)); - AssertThat(ts_node_next_sibling(bracket_node2).data, Equals(nullptr)); + AssertThat(ts_node_next_sibling(bracket_node2).subtree, Equals(nullptr)); - AssertThat(ts_node_prev_sibling(bracket_node1).data, Equals(nullptr)); + AssertThat(ts_node_prev_sibling(bracket_node1).subtree, Equals(nullptr)); AssertThat(ts_node_prev_sibling(number_node), Equals(bracket_node1)); AssertThat(ts_node_prev_sibling(array_comma_node1), Equals(number_node)); AssertThat(ts_node_prev_sibling(false_node), Equals(array_comma_node1)); @@ -373,24 +363,24 @@ describe("Node", [&]() { AssertThat(ts_node_next_sibling(brace_node1), Equals(pair_node)); AssertThat(ts_node_next_sibling(pair_node), Equals(brace_node2)); - AssertThat(ts_node_next_sibling(brace_node2).data, Equals(nullptr)); + AssertThat(ts_node_next_sibling(brace_node2).subtree, Equals(nullptr)); - AssertThat(ts_node_prev_sibling(brace_node1).data, Equals(nullptr)); + AssertThat(ts_node_prev_sibling(brace_node1).subtree, Equals(nullptr)); AssertThat(ts_node_prev_sibling(pair_node), Equals(brace_node1)); AssertThat(ts_node_prev_sibling(brace_node2), Equals(pair_node)); AssertThat(ts_node_next_sibling(string_node), Equals(colon_node)); AssertThat(ts_node_next_sibling(colon_node), Equals(null_node)); - AssertThat(ts_node_next_sibling(null_node).data, Equals(nullptr)); + AssertThat(ts_node_next_sibling(null_node).subtree, Equals(nullptr)); - AssertThat(ts_node_prev_sibling(string_node).data, Equals(nullptr)); + AssertThat(ts_node_prev_sibling(string_node).subtree, Equals(nullptr)); AssertThat(ts_node_prev_sibling(colon_node), Equals(string_node)); AssertThat(ts_node_prev_sibling(null_node), Equals(colon_node)); }); it("returns null when the node has no parent", [&]() { - AssertThat(ts_node_next_named_sibling(root_node).data, Equals(nullptr)); - AssertThat(ts_node_prev_named_sibling(root_node).data, Equals(nullptr)); + AssertThat(ts_node_next_named_sibling(root_node).subtree, Equals(nullptr)); + AssertThat(ts_node_prev_named_sibling(root_node).subtree, Equals(nullptr)); }); }); @@ -412,8 +402,8 @@ describe("Node", [&]() { }); it("returns null when the node has no parent", [&]() { - AssertThat(ts_node_next_named_sibling(root_node).data, Equals(nullptr)); - AssertThat(ts_node_prev_named_sibling(root_node).data, Equals(nullptr)); + AssertThat(ts_node_next_named_sibling(root_node).subtree, Equals(nullptr)); + AssertThat(ts_node_prev_named_sibling(root_node).subtree, Equals(nullptr)); }); }); diff --git a/test/runtime/tree_test.cc b/test/runtime/tree_test.cc index 8669b6c1..262572b1 100644 --- a/test/runtime/tree_test.cc +++ b/test/runtime/tree_test.cc @@ -5,14 +5,12 @@ #include "runtime/length.h" void assert_consistent(const Tree *tree) { - if (tree->child_count == 0) - return; + if (tree->child_count == 0) return; AssertThat(tree->children.contents[0]->padding, Equals(tree->padding)); Length total_children_size = length_zero(); for (size_t i = 0; i < tree->children.size; i++) { Tree *child = tree->children.contents[i]; - AssertThat(child->context.offset, Equals(total_children_size)); assert_consistent(child); total_children_size = length_add(total_children_size, ts_tree_total_size(child)); }