From 46ec0804f8ccaa199c2a8fefde0a3c99f3324f11 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 4 Aug 2017 11:03:14 -0700 Subject: [PATCH] Move tree comparison function to a separate translation unit --- project.gyp | 1 + src/runtime/document.c | 11 +- .../{tree_path.h => get_changed_ranges.c} | 157 ++++++++++-------- src/runtime/get_changed_ranges.h | 11 ++ 4 files changed, 108 insertions(+), 72 deletions(-) rename src/runtime/{tree_path.h => get_changed_ranges.c} (62%) create mode 100644 src/runtime/get_changed_ranges.h diff --git a/project.gyp b/project.gyp index 9bee27cc..f1efaeef 100644 --- a/project.gyp +++ b/project.gyp @@ -91,6 +91,7 @@ 'sources': [ 'src/runtime/document.c', 'src/runtime/error_costs.c', + 'src/runtime/get_changed_ranges.c', 'src/runtime/language.c', 'src/runtime/lexer.c', 'src/runtime/node.c', diff --git a/src/runtime/document.c b/src/runtime/document.c index 1311cb49..ed4b2b62 100644 --- a/src/runtime/document.c +++ b/src/runtime/document.c @@ -4,7 +4,7 @@ #include "runtime/parser.h" #include "runtime/string_input.h" #include "runtime/document.h" -#include "runtime/tree_path.h" +#include "runtime/get_changed_ranges.h" TSDocument *ts_document_new() { TSDocument *self = ts_calloc(1, sizeof(TSDocument)); @@ -140,11 +140,10 @@ void ts_document_parse_with_options(TSDocument *self, TSParseOptions options) { self->tree = tree; if (options.changed_ranges && options.changed_range_count) { - tree_path_init(&self->parser.tree_path1, old_tree); - tree_path_init(&self->parser.tree_path2, tree); - tree_path_get_changes(&self->parser.tree_path1, &self->parser.tree_path2, - options.changed_ranges, options.changed_range_count, - self->parser.language); + *options.changed_range_count = ts_tree_get_changed_ranges( + old_tree, tree, &self->parser.tree_path1, &self->parser.tree_path2, + self->parser.language, options.changed_ranges + ); } ts_tree_release(old_tree); diff --git a/src/runtime/tree_path.h b/src/runtime/get_changed_ranges.c similarity index 62% rename from src/runtime/tree_path.h rename to src/runtime/get_changed_ranges.c index cbddd245..b48afcde 100644 --- a/src/runtime/tree_path.h +++ b/src/runtime/get_changed_ranges.c @@ -1,10 +1,10 @@ -#ifndef RUNTIME_TREE_PATH_H_ -#define RUNTIME_TREE_PATH_H_ - +#include "runtime/get_changed_ranges.h" #include "runtime/tree.h" #include "runtime/language.h" #include "runtime/error_costs.h" +#include + typedef Array(TSRange) RangeArray; static void range_array_add(RangeArray *results, TSPoint start, TSPoint end) { @@ -22,7 +22,35 @@ static void range_array_add(RangeArray *results, TSPoint start, TSPoint end) { } } -static bool tree_path_descend(TreePath *path, Length position) { +static bool tree_is_visible( + const Tree *tree, + const Tree *parent, + uint32_t child_index, + const TSLanguage *language +) { + if (tree->visible) return true; + + // if (parent) { + // const TSSymbol *alias_sequence = ts_language_alias_sequence(language, parent->alias_sequence_id); + // return alias_sequence && alias_sequence[child_index] != 0; + // } + + return false; +} + +static void tree_path_ascend(TreePath *path, uint32_t count, const TSLanguage *language) { + for (uint32_t i = 0; i < count; i++) { + while (path->size > 0) { + path->size--; + if (path->size == 0) return; + TreePathEntry *entry = array_back(path); + Tree *parent = path->size > 1 ? path->contents[path->size - 2].tree : NULL; + if (tree_is_visible(entry->tree, parent, entry->child_index, language)) break; + } + } +} + +static bool tree_path_descend(TreePath *path, Length position, const TSLanguage *language) { uint32_t original_size = path->size; bool did_descend; @@ -30,21 +58,29 @@ static bool tree_path_descend(TreePath *path, Length position) { did_descend = false; TreePathEntry entry = *array_back(path); Length child_left = entry.position; + uint32_t structural_child_index = 0; for (uint32_t i = 0; i < entry.tree->child_count; i++) { Tree *child = entry.tree->children[i]; Length child_right = length_add(child_left, ts_tree_total_size(child)); if (position.bytes < child_right.bytes) { - TreePathEntry child_entry = { child, child_left, i }; - if (child->visible || child->child_count == 0) { + TreePathEntry child_entry = { + .tree = child, + .position = child_left, + .child_index = i, + .structural_child_index = structural_child_index, + }; + if (tree_is_visible(child, entry.tree, structural_child_index, language) || child->child_count == 0) { array_push(path, child_entry); return true; - } else if (child->visible_child_count > 0) { + } + if (child->visible_child_count > 0) { array_push(path, child_entry); did_descend = true; break; } } child_left = child_right; + if (!child->extra) structural_child_index++; } } while (did_descend); @@ -52,7 +88,7 @@ static bool tree_path_descend(TreePath *path, Length position) { return false; } -static uint32_t tree_path_advance(TreePath *path) { +static uint32_t tree_path_advance(TreePath *path, const TSLanguage *language) { uint32_t ascend_count = 0; while (path->size > 0) { @@ -62,55 +98,44 @@ static uint32_t tree_path_advance(TreePath *path) { if (parent_entry.tree->visible) ascend_count++; Length position = length_add(entry.position, ts_tree_total_size(entry.tree)); + uint32_t structural_child_index = entry.structural_child_index; + if (!entry.tree->extra) structural_child_index++; + for (uint32_t i = entry.child_index + 1; i < parent_entry.tree->child_count; i++) { Tree *next_child = parent_entry.tree->children[i]; - if (next_child->visible || + bool is_visible = tree_is_visible(next_child, entry.tree, structural_child_index, language); + if (is_visible || next_child->child_count == 0 || next_child->visible_child_count > 0) { if (parent_entry.tree->visible) ascend_count--; array_push(path, ((TreePathEntry){ .tree = next_child, - .child_index = i, .position = position, + .child_index = i, + .structural_child_index = structural_child_index, })); - if (!next_child->visible) { - tree_path_descend(path, length_zero()); + if (!is_visible) { + tree_path_descend(path, length_zero(), language); } return ascend_count; } position = length_add(position, ts_tree_total_size(next_child)); + if (!next_child->extra) structural_child_index++; } } return ascend_count; } -static void tree_path_ascend(TreePath *path, uint32_t count) { - for (uint32_t i = 0; i < count; i++) { - do { - path->size--; - } while (path->size > 0 && !array_back(path)->tree->visible); - } -} - -static void tree_path_init(TreePath *path, Tree *tree) { +static void tree_path_init(TreePath *path, Tree *tree, const TSLanguage *language) { array_clear(path); array_push(path, ((TreePathEntry){ .tree = tree, .position = { 0, 0, { 0, 0 } }, .child_index = 0, + .structural_child_index = 0, })); - if (!tree->visible) { - tree_path_descend(path, length_zero()); - } -} - -Tree *tree_path_visible_tree(TreePath *self) { - for (uint32_t i = self->size - 1; i + 1 > 0; i--) { - Tree *tree = self->contents[i].tree; - if (tree->visible) return tree; - } - return NULL; + if (!tree->visible) tree_path_descend(path, length_zero(), language); } Length tree_path_start_position(TreePath *self) { @@ -139,12 +164,10 @@ TreePathComparison tree_path_compare(const TreePath *old_path, old_tree = old_path->contents[i].tree; old_start = old_path->contents[i].position; if (i > 0) { - const TSSymbol *alias_sequence = ts_language_alias_sequence( - language, - old_path->contents[i - 1].tree->alias_sequence_id - ); + Tree *parent = old_path->contents[i - 1].tree; + const TSSymbol *alias_sequence = ts_language_alias_sequence(language, parent->alias_sequence_id); if (alias_sequence) { - old_alias_symbol = alias_sequence[old_path->contents[i].child_index]; + old_alias_symbol = alias_sequence[old_path->contents[i].structural_child_index]; } } @@ -158,12 +181,10 @@ TreePathComparison tree_path_compare(const TreePath *old_path, new_tree = new_path->contents[i].tree; new_start = old_path->contents[i].position; if (i > 0) { - const TSSymbol *alias_sequence = ts_language_alias_sequence( - language, - new_path->contents[i - 1].tree->alias_sequence_id - ); + Tree *parent = new_path->contents[i - 1].tree; + const TSSymbol *alias_sequence = ts_language_alias_sequence(language, parent->alias_sequence_id); if (alias_sequence) { - new_alias_symbol = alias_sequence[new_path->contents[i].child_index]; + new_alias_symbol = alias_sequence[new_path->contents[i].structural_child_index]; } } @@ -191,9 +212,13 @@ TreePathComparison tree_path_compare(const TreePath *old_path, return TreePathNotEq; } -static void tree_path_get_changes(TreePath *old_path, TreePath *new_path, - TSRange **ranges, uint32_t *range_count, - const TSLanguage *language) { +unsigned ts_tree_get_changed_ranges( + Tree *old_tree, Tree *new_tree, + TreePath *old_path, TreePath *new_path, + const TSLanguage *language, TSRange **ranges +) { + tree_path_init(old_path, old_tree, language); + tree_path_init(new_path, new_tree, language); Length position = length_zero(); RangeArray results = array_new(); @@ -206,11 +231,11 @@ static void tree_path_get_changes(TreePath *old_path, TreePath *new_path, Length old_end = tree_path_end_position(old_path); Length new_end = tree_path_end_position(new_path); - // #define NAME(t) (ts_language_symbol_name(language, ((Tree *)(t))->symbol)) - // printf("At [%-2u, %-2u] Compare (%-20s\t [%-2u, %-2u] - [%u, %u])\tvs\t(%-20s\t [%u, %u] - [%u, %u])\n", + // #define NAME(tree) (ts_language_symbol_name(language, ((Tree *)(tree))->symbol)) + // printf("At [%-2u, %-2u] Compare (%-20s\t [%u, %u] - [%u, %u])\tvs\t(%-20s\t [%u, %u] - [%u, %u])\t", // position.extent.row, position.extent.column, - // NAME(old_tree), old_start.extent.row, old_start.extent.column, old_end.extent.row, old_end.extent.column, - // NAME(new_tree), new_start.extent.row, new_start.extent.column, new_end.extent.row, new_end.extent.column); + // NAME(array_back(old_path)->tree), old_start.extent.row, old_start.extent.column, old_end.extent.row, old_end.extent.column, + // NAME(array_back(old_path)->tree), new_start.extent.row, new_start.extent.column, new_end.extent.row, new_end.extent.column); if (position.bytes < old_start.bytes) { if (position.bytes < new_start.bytes) { @@ -229,14 +254,14 @@ static void tree_path_get_changes(TreePath *old_path, TreePath *new_path, break; case TreePathCanEq: - if (tree_path_descend(old_path, position)) { - if (!tree_path_descend(new_path, position)) { - tree_path_ascend(old_path, 1); + if (tree_path_descend(old_path, position, language)) { + if (!tree_path_descend(new_path, position, language)) { + tree_path_ascend(old_path, 1, language); is_changed = true; next_position = new_end; } - } else if (tree_path_descend(new_path, position)) { - tree_path_ascend(new_path, 1); + } else if (tree_path_descend(new_path, position, language)) { + tree_path_ascend(new_path, 1, language); is_changed = true; next_position = old_end; } else { @@ -255,27 +280,27 @@ static void tree_path_get_changes(TreePath *old_path, TreePath *new_path, bool at_new_end = new_end.bytes <= next_position.bytes; if (at_new_end && at_old_end) { - uint32_t old_ascend_count = tree_path_advance(old_path); - uint32_t new_ascend_count = tree_path_advance(new_path); + uint32_t old_ascend_count = tree_path_advance(old_path, language); + uint32_t new_ascend_count = tree_path_advance(new_path, language); if (old_ascend_count > new_ascend_count) { - tree_path_ascend(new_path, old_ascend_count - new_ascend_count); + tree_path_ascend(new_path, old_ascend_count - new_ascend_count, language); } else if (new_ascend_count > old_ascend_count) { - tree_path_ascend(old_path, new_ascend_count - old_ascend_count); + tree_path_ascend(old_path, new_ascend_count - old_ascend_count, language); } } else if (at_new_end) { - uint32_t ascend_count = tree_path_advance(new_path); - tree_path_ascend(old_path, ascend_count); + uint32_t ascend_count = tree_path_advance(new_path, language); + tree_path_ascend(old_path, ascend_count, language); } else if (at_old_end) { - uint32_t ascend_count = tree_path_advance(old_path); - tree_path_ascend(new_path, ascend_count); + uint32_t ascend_count = tree_path_advance(old_path, language); + tree_path_ascend(new_path, ascend_count, language); } - if (is_changed) range_array_add(&results, position.extent, next_position.extent); + if (is_changed) { + range_array_add(&results, position.extent, next_position.extent); + } position = next_position; } *ranges = results.contents; - *range_count = results.size; + return results.size; } - -#endif // RUNTIME_TREE_PATH_H_ diff --git a/src/runtime/get_changed_ranges.h b/src/runtime/get_changed_ranges.h new file mode 100644 index 00000000..cfff44f4 --- /dev/null +++ b/src/runtime/get_changed_ranges.h @@ -0,0 +1,11 @@ +#ifndef RUNTIME_GET_CHANGED_RANGES_H_ +#define RUNTIME_GET_CHANGED_RANGES_H_ + +#include "runtime/tree.h" + +unsigned ts_tree_get_changed_ranges( + Tree *old_tree, Tree *new_tree, TreePath *tree_path1, TreePath *tree_path2, + const TSLanguage *language, TSRange **ranges +); + +#endif // RUNTIME_GET_CHANGED_RANGES_H_