Rename Tree -> Subtree

This commit is contained in:
Max Brunsfeld 2018-05-10 15:11:14 -07:00
parent 61327b627a
commit 35510a612d
25 changed files with 724 additions and 719 deletions

View file

@ -95,7 +95,7 @@
'src/runtime/stack.c',
'src/runtime/parser.c',
'src/runtime/string_input.c',
'src/runtime/tree.c',
'src/runtime/subtree.c',
'src/runtime/tree_cursor.c',
'src/runtime/utf16.c',
'externals/utf8proc/utf8proc.c',

View file

@ -1,5 +1,5 @@
#include "runtime/alloc.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/parser.h"
#include "runtime/string_input.h"
#include "runtime/document.h"
@ -19,7 +19,7 @@ TSDocument *ts_document_new() {
}
void ts_document_free(TSDocument *self) {
if (self->tree) ts_tree_release(&self->parser.tree_pool, self->tree);
if (self->tree) ts_subtree_release(&self->parser.tree_pool, self->tree);
if (self->cursor1.stack.contents) array_delete(&self->cursor1.stack);
if (self->cursor2.stack.contents) array_delete(&self->cursor2.stack);
parser_destroy(&self->parser);
@ -41,7 +41,7 @@ void ts_document_set_language(TSDocument *self, const TSLanguage *language) {
ts_document_invalidate(self);
parser_set_language(&self->parser, language);
if (self->tree) {
ts_tree_release(&self->parser.tree_pool, self->tree);
ts_subtree_release(&self->parser.tree_pool, self->tree);
self->tree = NULL;
}
}
@ -91,16 +91,16 @@ void ts_document_edit(TSDocument *self, TSInputEdit edit) {
if (!self->tree)
return;
uint32_t max_bytes = ts_tree_total_bytes(self->tree);
uint32_t max_bytes = ts_subtree_total_bytes(self->tree);
if (edit.start_byte > max_bytes)
return;
if (edit.bytes_removed > max_bytes - edit.start_byte)
edit.bytes_removed = max_bytes - edit.start_byte;
self->tree = ts_tree_edit(self->tree, &edit, &self->parser.tree_pool);
self->tree = ts_subtree_edit(self->tree, &edit, &self->parser.tree_pool);
if (self->parser.print_debugging_graphs) {
ts_tree_print_dot_graph(self->tree, self->parser.language, stderr);
ts_subtree_print_dot_graph(self->tree, self->parser.language, stderr);
}
}
@ -130,18 +130,18 @@ void ts_document_parse_with_options(TSDocument *self, TSParseOptions options) {
if (!self->input.read || !self->parser.language)
return;
Tree *reusable_tree = self->valid ? self->tree : NULL;
Subtree *reusable_tree = self->valid ? self->tree : NULL;
if (reusable_tree && !reusable_tree->has_changes)
return;
Tree *tree = parser_parse(&self->parser, self->input, reusable_tree, options.halt_on_error);
Subtree *tree = parser_parse(&self->parser, self->input, reusable_tree, options.halt_on_error);
if (self->tree) {
Tree *old_tree = self->tree;
Subtree *old_tree = self->tree;
self->tree = tree;
if (options.changed_ranges && options.changed_range_count) {
*options.changed_range_count = ts_tree_get_changed_ranges(
*options.changed_range_count = ts_subtree_get_changed_ranges(
old_tree, tree, &self->cursor1, &self->cursor2,
self->parser.language, options.changed_ranges
);
@ -158,7 +158,7 @@ void ts_document_parse_with_options(TSDocument *self, TSParseOptions options) {
}
}
ts_tree_release(&self->parser.tree_pool, old_tree);
ts_subtree_release(&self->parser.tree_pool, old_tree);
}
self->tree = tree;

View file

@ -2,14 +2,14 @@
#define RUNTIME_DOCUMENT_H_
#include "runtime/parser.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/tree_cursor.h"
#include <stdbool.h>
struct TSDocument {
Parser parser;
TSInput input;
Tree *tree;
Subtree *tree;
TSTreeCursor cursor1;
TSTreeCursor cursor2;
size_t parse_count;

View file

@ -1,5 +1,5 @@
#include "runtime/get_changed_ranges.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/language.h"
#include "runtime/error_costs.h"
#include "runtime/tree_cursor.h"
@ -31,7 +31,7 @@ typedef struct {
bool in_padding;
} Iterator;
static Iterator iterator_new(TSTreeCursor *cursor, Tree *tree, const TSLanguage *language) {
static Iterator iterator_new(TSTreeCursor *cursor, Subtree *tree, const TSLanguage *language) {
array_clear(&cursor->stack);
array_push(&cursor->stack, ((TreeCursorEntry){
.tree = tree,
@ -74,14 +74,14 @@ static bool iterator_tree_is_visible(const Iterator *self) {
TreeCursorEntry entry = *array_back(&self->cursor.stack);
if (entry.tree->visible) return true;
if (self->cursor.stack.size > 1) {
Tree *parent = self->cursor.stack.contents[self->cursor.stack.size - 2].tree;
Subtree *parent = self->cursor.stack.contents[self->cursor.stack.size - 2].tree;
const TSSymbol *alias_sequence = ts_language_alias_sequence(self->language, parent->alias_sequence_id);
return alias_sequence && alias_sequence[entry.structural_child_index] != 0;
}
return false;
}
static void iterator_get_visible_state(const Iterator *self, Tree **tree,
static void iterator_get_visible_state(const Iterator *self, Subtree **tree,
TSSymbol *alias_symbol, uint32_t *start_byte) {
uint32_t i = self->cursor.stack.size - 1;
@ -94,7 +94,7 @@ static void iterator_get_visible_state(const Iterator *self, Tree **tree,
TreeCursorEntry entry = self->cursor.stack.contents[i];
if (i > 0) {
Tree *parent = self->cursor.stack.contents[i - 1].tree;
Subtree *parent = self->cursor.stack.contents[i - 1].tree;
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->language,
parent->alias_sequence_id
@ -129,7 +129,7 @@ static bool iterator_descend(Iterator *self, uint32_t goal_position) {
Length position = entry.position;
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < entry.tree->children.size; i++) {
Tree *child = entry.tree->children.contents[i];
Subtree *child = entry.tree->children.contents[i];
Length child_left = length_add(position, child->padding);
Length child_right = length_add(child_left, child->size);
@ -178,13 +178,13 @@ static void iterator_advance(Iterator *self) {
TreeCursorEntry entry = array_pop(&self->cursor.stack);
if (iterator_done(self)) return;
Tree *parent = array_back(&self->cursor.stack)->tree;
Subtree *parent = array_back(&self->cursor.stack)->tree;
uint32_t child_index = entry.child_index + 1;
if (parent->children.size > child_index) {
Length position = length_add(entry.position, ts_tree_total_size(entry.tree));
Length position = length_add(entry.position, ts_subtree_total_size(entry.tree));
uint32_t structural_child_index = entry.structural_child_index;
if (!entry.tree->extra) structural_child_index++;
Tree *next_child = parent->children.contents[child_index];
Subtree *next_child = parent->children.contents[child_index];
array_push(&self->cursor.stack, ((TreeCursorEntry){
.tree = next_child,
@ -214,7 +214,7 @@ typedef enum {
} IteratorComparison;
IteratorComparison iterator_compare(const Iterator *old_iter, const Iterator *new_iter) {
Tree *old_tree = NULL, *new_tree = NULL;
Subtree *old_tree = NULL, *new_tree = NULL;
uint32_t old_start = 0, new_start = 0;
TSSymbol old_alias_symbol = 0, new_alias_symbol = 0;
iterator_get_visible_state(old_iter, &old_tree, &old_alias_symbol, &old_start);
@ -261,7 +261,7 @@ static inline void iterator_print_state(Iterator *self) {
}
#endif
unsigned ts_tree_get_changed_ranges(Tree *old_tree, Tree *new_tree,
unsigned ts_subtree_get_changed_ranges(Subtree *old_tree, Subtree *new_tree,
TSTreeCursor *cursor1, TSTreeCursor *cursor2,
const TSLanguage *language, TSRange **ranges) {
RangeArray results = array_new();

View file

@ -1,10 +1,10 @@
#ifndef RUNTIME_GET_CHANGED_RANGES_H_
#define RUNTIME_GET_CHANGED_RANGES_H_
#include "runtime/tree.h"
#include "runtime/subtree.h"
unsigned ts_tree_get_changed_ranges(
Tree *old_tree, Tree *new_tree, TSTreeCursor *cursor1, TSTreeCursor *cursor2,
unsigned ts_subtree_get_changed_ranges(
Subtree *old_tree, Subtree *new_tree, TSTreeCursor *cursor1, TSTreeCursor *cursor2,
const TSLanguage *language, TSRange **ranges
);

View file

@ -1,5 +1,5 @@
#include "runtime/language.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/error_costs.h"
void ts_language_table_entry(const TSLanguage *self, TSStateId state,

View file

@ -6,7 +6,7 @@ extern "C" {
#endif
#include "tree_sitter/parser.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#define ts_builtin_sym_error_repeat (ts_builtin_sym_error - 1)

View file

@ -1,6 +1,6 @@
#include <stdio.h>
#include "runtime/lexer.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/length.h"
#include "runtime/utf16.h"
#include "utf8proc.h"

View file

@ -8,7 +8,7 @@ extern "C" {
#include "tree_sitter/parser.h"
#include "tree_sitter/runtime.h"
#include "runtime/length.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
typedef struct {
TSLexer data;

View file

@ -1,12 +1,12 @@
#include <stdbool.h>
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/document.h"
#include "runtime/language.h"
// NodeChildIterator
typedef struct {
const Tree *parent;
const Subtree *parent;
const TSDocument *document;
Length position;
uint32_t child_index;
@ -25,12 +25,12 @@ static inline TSNode ts_node__null() {
};
}
static inline const Tree *ts_node__tree(TSNode self) {
static inline const Subtree *ts_node__tree(TSNode self) {
return self.subtree;
}
static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) {
const Tree *tree = ts_node__tree(*node);
const Subtree *tree = ts_node__tree(*node);
const TSSymbol *alias_sequence = ts_language_alias_sequence(
node->document->parser.language,
tree->alias_sequence_id
@ -47,7 +47,7 @@ static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node)
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];
Subtree *child = self->parent->children.contents[self->child_index];
TSSymbol alias_symbol = 0;
if (!child->extra) {
if (self->alias_sequence) {
@ -62,13 +62,13 @@ static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *
.byte = self->position.bytes,
.alias_symbol = alias_symbol,
};
self->position = length_add(self->position, ts_tree_total_size(child));
self->position = length_add(self->position, ts_subtree_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);
const Subtree *tree = ts_node__tree(self);
if (include_anonymous) {
return tree->visible || self.alias_symbol;
} else {
@ -86,7 +86,7 @@ static inline bool ts_node__is_relevant(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);
const Subtree *tree = ts_node__tree(self);
if (tree->children.size > 0) {
if (include_anonymous) {
return tree->visible_child_count;
@ -300,7 +300,7 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi
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);
const Subtree *child_tree = ts_node__tree(child);
if (iterator.child_index != 1) {
start_position = point_add(start_position, child_tree->padding.extent);
}
@ -338,7 +338,7 @@ TSPoint ts_node_end_point(TSNode self) {
}
TSSymbol ts_node_symbol(TSNode self) {
const Tree *tree = ts_node__tree(self);
const Subtree *tree = ts_node__tree(self);
return self.alias_symbol ? self.alias_symbol : tree->symbol;
}
@ -347,25 +347,25 @@ const char *ts_node_type(TSNode self) {
}
char *ts_node_string(TSNode self) {
return ts_tree_string(ts_node__tree(self), self.document->parser.language, false);
return ts_subtree_string(ts_node__tree(self), self.document->parser.language, false);
}
bool ts_node_eq(TSNode self, TSNode other) {
return (
ts_tree_eq(ts_node__tree(self), ts_node__tree(other)) &&
ts_subtree_eq(ts_node__tree(self), ts_node__tree(other)) &&
self.byte == other.byte
);
}
bool ts_node_is_named(TSNode self) {
const Tree *tree = ts_node__tree(self);
const Subtree *tree = ts_node__tree(self);
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) {
const Tree *tree = ts_node__tree(self);
const Subtree *tree = ts_node__tree(self);
return tree->is_missing;
}
@ -414,7 +414,7 @@ TSNode ts_node_named_child(TSNode self, uint32_t child_index) {
}
uint32_t ts_node_child_count(TSNode self) {
const Tree *tree = ts_node__tree(self);
const Subtree *tree = ts_node__tree(self);
if (tree->children.size > 0) {
return tree->visible_child_count;
} else {
@ -423,7 +423,7 @@ uint32_t ts_node_child_count(TSNode self) {
}
uint32_t ts_node_named_child_count(TSNode self) {
const Tree *tree = ts_node__tree(self);
const Subtree *tree = ts_node__tree(self);
if (tree->children.size > 0) {
return tree->named_child_count;
} else {

View file

@ -4,7 +4,7 @@
#include <limits.h>
#include <stdbool.h>
#include "tree_sitter/runtime.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/lexer.h"
#include "runtime/length.h"
#include "runtime/array.h"
@ -27,7 +27,7 @@
#define LOG_TREE() \
if (self->print_debugging_graphs) { \
ts_tree_print_dot_graph(self->finished_tree, self->language, stderr); \
ts_subtree_print_dot_graph(self->finished_tree, self->language, stderr); \
fputs("\n", stderr); \
}
@ -84,10 +84,10 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
for (uint32_t i = 0; i < pop.size; i++) {
StackSlice slice = pop.contents[i];
TSStateId state = ts_stack_state(self->stack, slice.version);
Tree *parent = *array_front(&slice.trees);
Subtree *parent = *array_front(&slice.subtrees);
for (uint32_t j = 0; j < parent->children.size; j++) {
Tree *child = parent->children.contents[j];
Subtree *child = parent->children.contents[j];
pending = child->children.size > 0;
if (child->symbol == ts_builtin_sym_error) {
@ -96,17 +96,17 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
state = ts_language_next_state(self->language, state, child->symbol);
}
ts_tree_retain(child);
ts_subtree_retain(child);
ts_stack_push(self->stack, slice.version, child, pending, state);
}
for (uint32_t j = 1; j < slice.trees.size; j++) {
Tree *tree = slice.trees.contents[j];
for (uint32_t j = 1; j < slice.subtrees.size; j++) {
Subtree *tree = slice.subtrees.contents[j];
ts_stack_push(self->stack, slice.version, tree, false, state);
}
ts_tree_release(&self->tree_pool, parent);
array_delete(&slice.trees);
ts_subtree_release(&self->tree_pool, parent);
array_delete(&slice.subtrees);
LOG("breakdown_top_of_stack tree:%s", SYM_NAME(parent->symbol));
LOG_STACK();
@ -116,11 +116,11 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
return did_break_down;
}
static void parser__breakdown_lookahead(Parser *self, Tree **lookahead,
static void parser__breakdown_lookahead(Parser *self, Subtree **lookahead,
TSStateId state,
ReusableNode *reusable_node) {
bool did_descend = false;
Tree *tree = reusable_node_tree(reusable_node);
Subtree *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);
@ -129,9 +129,9 @@ static void parser__breakdown_lookahead(Parser *self, Tree **lookahead,
}
if (did_descend) {
ts_tree_release(&self->tree_pool, *lookahead);
ts_subtree_release(&self->tree_pool, *lookahead);
*lookahead = tree;
ts_tree_retain(*lookahead);
ts_subtree_retain(*lookahead);
}
}
@ -215,7 +215,7 @@ static bool parser__better_version_exists(Parser *self, StackVersion version,
return false;
}
static void parser__restore_external_scanner(Parser *self, Tree *external_token) {
static void parser__restore_external_scanner(Parser *self, Subtree *external_token) {
if (external_token) {
self->language->external_scanner.deserialize(
self->external_scanner_payload,
@ -227,9 +227,9 @@ static void parser__restore_external_scanner(Parser *self, Tree *external_token)
}
}
static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_state) {
static Subtree *parser__lex(Parser *self, StackVersion version, TSStateId parse_state) {
Length start_position = ts_stack_position(self->stack, version);
Tree *external_token = ts_stack_last_external_token(self->stack, version);
Subtree *external_token = ts_stack_last_external_token(self->stack, version);
TSLexMode lex_mode = self->language->lex_modes[parse_state];
const bool *valid_external_tokens = ts_language_enabled_external_tokens(
self->language,
@ -326,11 +326,11 @@ static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_sta
last_byte_scanned = self->lexer.current_position.bytes;
}
Tree *result;
Subtree *result;
if (skipped_error) {
Length padding = length_sub(error_start_position, start_position);
Length size = length_sub(error_end_position, error_start_position);
result = ts_tree_make_error(&self->tree_pool, size, padding, first_error_character, self->language);
result = ts_subtree_make_error(&self->tree_pool, size, padding, first_error_character, self->language);
} else {
if (self->lexer.token_end_position.bytes < self->lexer.token_start_position.bytes) {
self->lexer.token_start_position = self->lexer.token_end_position;
@ -355,7 +355,7 @@ static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_sta
}
}
result = ts_tree_make_leaf(&self->tree_pool, symbol, padding, size, self->language);
result = ts_subtree_make_leaf(&self->tree_pool, symbol, padding, size, self->language);
if (found_external_token) {
result->has_external_tokens = true;
@ -375,30 +375,30 @@ static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_sta
return result;
}
static Tree *parser__get_cached_token(Parser *self, size_t byte_index, Tree *last_external_token) {
static Subtree *parser__get_cached_token(Parser *self, size_t byte_index, Subtree *last_external_token) {
TokenCache *cache = &self->token_cache;
if (cache->token &&
cache->byte_index == byte_index &&
ts_tree_external_token_state_eq(cache->last_external_token, last_external_token)) {
ts_subtree_external_token_state_eq(cache->last_external_token, last_external_token)) {
return cache->token;
} else {
return NULL;
}
}
static void parser__set_cached_token(Parser *self, size_t byte_index, Tree *last_external_token,
Tree *token) {
static void parser__set_cached_token(Parser *self, size_t byte_index, Subtree *last_external_token,
Subtree *token) {
TokenCache *cache = &self->token_cache;
if (token) ts_tree_retain(token);
if (last_external_token) ts_tree_retain(last_external_token);
if (cache->token) ts_tree_release(&self->tree_pool, cache->token);
if (cache->last_external_token) ts_tree_release(&self->tree_pool, cache->last_external_token);
if (token) ts_subtree_retain(token);
if (last_external_token) ts_subtree_retain(last_external_token);
if (cache->token) ts_subtree_release(&self->tree_pool, cache->token);
if (cache->last_external_token) ts_subtree_release(&self->tree_pool, cache->last_external_token);
cache->token = token;
cache->byte_index = byte_index;
cache->last_external_token = last_external_token;
}
static bool parser__can_reuse_first_leaf(Parser *self, TSStateId state, Tree *tree,
static bool parser__can_reuse_first_leaf(Parser *self, TSStateId state, Subtree *tree,
TableEntry *table_entry) {
TSLexMode current_lex_mode = self->language->lex_modes[state];
@ -416,12 +416,12 @@ static bool parser__can_reuse_first_leaf(Parser *self, TSStateId state, Tree *tr
return current_lex_mode.external_lex_state == 0 && table_entry->is_reusable;
}
static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId *state,
static Subtree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId *state,
ReusableNode *reusable_node, TableEntry *table_entry) {
Length position = ts_stack_position(self->stack, version);
Tree *last_external_token = ts_stack_last_external_token(self->stack, version);
Subtree *last_external_token = ts_stack_last_external_token(self->stack, version);
Tree *result;
Subtree *result;
while ((result = reusable_node_tree(reusable_node))) {
uint32_t byte_offset = reusable_node_byte_offset(reusable_node);
if (byte_offset > position.bytes) {
@ -435,7 +435,7 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
continue;
}
if (!ts_tree_external_token_state_eq(reusable_node->last_external_token, last_external_token)) {
if (!ts_subtree_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_advance(reusable_node);
continue;
@ -476,14 +476,14 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
}
LOG("reuse_node symbol:%s", SYM_NAME(result->symbol));
ts_tree_retain(result);
ts_subtree_retain(result);
return result;
}
if ((result = parser__get_cached_token(self, position.bytes, last_external_token))) {
ts_language_table_entry(self->language, *state, result->first_leaf.symbol, table_entry);
if (parser__can_reuse_first_leaf(self, *state, result, table_entry)) {
ts_tree_retain(result);
ts_subtree_retain(result);
return result;
}
}
@ -494,7 +494,7 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
return result;
}
static bool parser__select_tree(Parser *self, Tree *left, Tree *right) {
static bool parser__select_tree(Parser *self, Subtree *left, Subtree *right) {
if (!left) return true;
if (!right) return false;
@ -526,7 +526,7 @@ static bool parser__select_tree(Parser *self, Tree *left, Tree *right) {
if (left->error_cost > 0) return true;
int comparison = ts_tree_compare(left, right);
int comparison = ts_subtree_compare(left, right);
switch (comparison) {
case -1:
LOG("select_earlier symbol:%s, over_symbol:%s", SYM_NAME(left->symbol),
@ -545,31 +545,31 @@ static bool parser__select_tree(Parser *self, Tree *left, Tree *right) {
}
static void parser__shift(Parser *self, StackVersion version, TSStateId state,
Tree *lookahead, bool extra) {
Subtree *lookahead, bool extra) {
if (extra != lookahead->extra) {
if (ts_stack_version_count(self->stack) > 1) {
lookahead = ts_tree_make_copy(&self->tree_pool, lookahead);
lookahead = ts_subtree_make_copy(&self->tree_pool, lookahead);
} else {
ts_tree_retain(lookahead);
ts_subtree_retain(lookahead);
}
lookahead->extra = extra;
} else {
ts_tree_retain(lookahead);
ts_subtree_retain(lookahead);
}
bool is_pending = lookahead->children.size > 0;
ts_stack_push(self->stack, version, lookahead, is_pending, state);
if (lookahead->has_external_tokens) {
ts_stack_set_last_external_token(
self->stack, version, ts_tree_last_external_token(lookahead)
self->stack, version, ts_subtree_last_external_token(lookahead)
);
}
}
static bool parser__replace_children(Parser *self, Tree *tree, TreeArray *children) {
static bool parser__replace_children(Parser *self, Subtree *tree, SubtreeArray *children) {
self->scratch_tree = *tree;
self->scratch_tree.children.size = 0;
ts_tree_set_children(&self->scratch_tree, children, self->language);
ts_subtree_set_children(&self->scratch_tree, children, self->language);
if (parser__select_tree(self, tree, &self->scratch_tree)) {
*tree = self->scratch_tree;
return true;
@ -591,12 +591,12 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
// Extra tokens on top of the stack should not be included in this new parent
// node. They will be re-pushed onto the stack after the parent node is
// created and pushed.
TreeArray children = slice.trees;
SubtreeArray children = slice.subtrees;
while (children.size > 0 && children.contents[children.size - 1]->extra) {
children.size--;
}
Tree *parent = ts_tree_make_node(&self->tree_pool,
Subtree *parent = ts_subtree_make_node(&self->tree_pool,
symbol, &children, alias_sequence_id, self->language
);
@ -609,16 +609,16 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
if (next_slice.version != slice.version) break;
i++;
TreeArray children = next_slice.trees;
SubtreeArray children = next_slice.subtrees;
while (children.size > 0 && children.contents[children.size - 1]->extra) {
children.size--;
}
if (parser__replace_children(self, parent, &children)) {
ts_tree_array_delete(&self->tree_pool, &slice.trees);
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
slice = next_slice;
} else {
ts_tree_array_delete(&self->tree_pool, &next_slice.trees);
ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees);
}
}
@ -638,15 +638,15 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
// Push the parent node onto the stack, along with any extra tokens that
// were previously on top of the stack.
ts_stack_push(self->stack, slice.version, parent, false, next_state);
for (uint32_t j = parent->children.size; j < slice.trees.size; j++) {
ts_stack_push(self->stack, slice.version, slice.trees.contents[j], false, next_state);
for (uint32_t j = parent->children.size; j < slice.subtrees.size; j++) {
ts_stack_push(self->stack, slice.version, slice.subtrees.contents[j], false, next_state);
}
if (ts_stack_version_count(self->stack) > MAX_VERSION_COUNT) {
i++;
while (i < pop.size) {
StackSlice slice = pop.contents[i];
ts_tree_array_delete(&self->tree_pool, &slice.trees);
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
ts_stack_halt(self->stack, slice.version);
i++;
}
@ -669,7 +669,7 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
return pop;
}
static void parser__start(Parser *self, TSInput input, Tree *previous_tree) {
static void parser__start(Parser *self, TSInput input, Subtree *previous_tree) {
if (previous_tree) {
LOG("parse_after_edit");
} else {
@ -688,29 +688,29 @@ static void parser__start(Parser *self, TSInput input, Tree *previous_tree) {
self->in_ambiguity = false;
}
static void parser__accept(Parser *self, StackVersion version, Tree *lookahead) {
static void parser__accept(Parser *self, StackVersion version, Subtree *lookahead) {
lookahead->extra = true;
assert(lookahead->symbol == ts_builtin_sym_end);
ts_tree_retain(lookahead);
ts_subtree_retain(lookahead);
ts_stack_push(self->stack, version, lookahead, false, 1);
StackSliceArray pop = ts_stack_pop_all(self->stack, version);
for (uint32_t i = 0; i < pop.size; i++) {
TreeArray trees = pop.contents[i].trees;
SubtreeArray trees = pop.contents[i].subtrees;
Tree *root = NULL;
Subtree *root = NULL;
for (uint32_t j = trees.size - 1; j + 1 > 0; j--) {
Tree *child = trees.contents[j];
Subtree *child = trees.contents[j];
if (!child->extra) {
for (uint32_t k = 0; k < child->children.size; k++) {
ts_tree_retain(child->children.contents[k]);
ts_subtree_retain(child->children.contents[k]);
}
array_splice(&trees, j, 1, &child->children);
root = ts_tree_make_node(
root = ts_subtree_make_node(
&self->tree_pool, child->symbol, &trees,
child->alias_sequence_id, self->language
);
ts_tree_release(&self->tree_pool, child);
ts_subtree_release(&self->tree_pool, child);
break;
}
}
@ -720,10 +720,10 @@ static void parser__accept(Parser *self, StackVersion version, Tree *lookahead)
if (self->finished_tree) {
if (parser__select_tree(self, self->finished_tree, root)) {
ts_tree_release(&self->tree_pool, self->finished_tree);
ts_subtree_release(&self->tree_pool, self->finished_tree);
self->finished_tree = root;
} else {
ts_tree_release(&self->tree_pool, root);
ts_subtree_release(&self->tree_pool, root);
}
} else {
self->finished_tree = root;
@ -845,7 +845,7 @@ static void parser__handle_error(Parser *self, StackVersion version, TSSymbol lo
lookahead_symbol
)) {
StackVersion version_with_missing_tree = ts_stack_copy_version(self->stack, v);
Tree *missing_tree = ts_tree_make_missing_leaf(&self->tree_pool, missing_symbol, self->language);
Subtree *missing_tree = ts_subtree_make_missing_leaf(&self->tree_pool, missing_symbol, self->language);
ts_stack_push(
self->stack, version_with_missing_tree,
missing_tree, false,
@ -890,17 +890,17 @@ static void parser__halt_parse(Parser *self) {
ts_stack_position(self->stack, 0)
);
Tree *filler_node = ts_tree_make_error(&self->tree_pool, remaining_length, length_zero(), 0, self->language);
Subtree *filler_node = ts_subtree_make_error(&self->tree_pool, remaining_length, length_zero(), 0, self->language);
filler_node->visible = false;
ts_stack_push(self->stack, 0, filler_node, false, 0);
TreeArray children = array_new();
Tree *root_error = ts_tree_make_error_node(&self->tree_pool, &children, self->language);
SubtreeArray children = array_new();
Subtree *root_error = ts_subtree_make_error_node(&self->tree_pool, &children, self->language);
ts_stack_push(self->stack, 0, root_error, false, 0);
Tree *eof = ts_tree_make_leaf(&self->tree_pool, ts_builtin_sym_end, length_zero(), length_zero(), self->language);
Subtree *eof = ts_subtree_make_leaf(&self->tree_pool, ts_builtin_sym_end, length_zero(), length_zero(), self->language);
parser__accept(self, 0, eof);
ts_tree_release(&self->tree_pool, eof);
ts_subtree_release(&self->tree_pool, eof);
}
static bool parser__recover_to_state(Parser *self, StackVersion version, unsigned depth,
@ -912,40 +912,40 @@ static bool parser__recover_to_state(Parser *self, StackVersion version, unsigne
StackSlice slice = pop.contents[i];
if (slice.version == previous_version) {
ts_tree_array_delete(&self->tree_pool, &slice.trees);
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
array_erase(&pop, i--);
continue;
}
if (ts_stack_state(self->stack, slice.version) != goal_state) {
ts_stack_halt(self->stack, slice.version);
ts_tree_array_delete(&self->tree_pool, &slice.trees);
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
array_erase(&pop, i--);
continue;
}
TreeArray error_trees = ts_stack_pop_error(self->stack, slice.version);
SubtreeArray error_trees = ts_stack_pop_error(self->stack, slice.version);
if (error_trees.size > 0) {
assert(error_trees.size == 1);
array_splice(&slice.trees, 0, 0, &error_trees.contents[0]->children);
array_splice(&slice.subtrees, 0, 0, &error_trees.contents[0]->children);
for (unsigned j = 0; j < error_trees.contents[0]->children.size; j++) {
ts_tree_retain(slice.trees.contents[j]);
ts_subtree_retain(slice.subtrees.contents[j]);
}
ts_tree_array_delete(&self->tree_pool, &error_trees);
ts_subtree_array_delete(&self->tree_pool, &error_trees);
}
TreeArray trailing_extras = ts_tree_array_remove_trailing_extras(&slice.trees);
SubtreeArray trailing_extras = ts_subtree_array_remove_trailing_extras(&slice.subtrees);
if (slice.trees.size > 0) {
Tree *error = ts_tree_make_error_node(&self->tree_pool, &slice.trees, self->language);
if (slice.subtrees.size > 0) {
Subtree *error = ts_subtree_make_error_node(&self->tree_pool, &slice.subtrees, self->language);
error->extra = true;
ts_stack_push(self->stack, slice.version, error, false, goal_state);
} else {
array_delete(&slice.trees);
array_delete(&slice.subtrees);
}
for (unsigned j = 0; j < trailing_extras.size; j++) {
Tree *tree = trailing_extras.contents[j];
Subtree *tree = trailing_extras.contents[j];
ts_stack_push(self->stack, slice.version, tree, false, goal_state);
}
@ -956,7 +956,7 @@ static bool parser__recover_to_state(Parser *self, StackVersion version, unsigne
return previous_version != STACK_VERSION_NONE;
}
static void parser__recover(Parser *self, StackVersion version, Tree *lookahead) {
static void parser__recover(Parser *self, StackVersion version, Subtree *lookahead) {
bool did_recover = false;
unsigned previous_version_count = ts_stack_version_count(self->stack);
Length position = ts_stack_position(self->stack, version);
@ -1017,8 +1017,8 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
if (lookahead->symbol == ts_builtin_sym_end) {
LOG("recover_eof");
TreeArray children = array_new();
Tree *parent = ts_tree_make_error_node(&self->tree_pool, &children, self->language);
SubtreeArray children = array_new();
Subtree *parent = ts_subtree_make_error_node(&self->tree_pool, &children, self->language);
ts_stack_push(self->stack, version, parent, false, 1);
parser__accept(self, version, lookahead);
return;
@ -1026,8 +1026,8 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
unsigned new_cost =
current_error_cost + ERROR_COST_PER_SKIPPED_TREE +
ts_tree_total_bytes(lookahead) * ERROR_COST_PER_SKIPPED_CHAR +
ts_tree_total_size(lookahead).extent.row * ERROR_COST_PER_SKIPPED_LINE;
ts_subtree_total_bytes(lookahead) * ERROR_COST_PER_SKIPPED_CHAR +
ts_subtree_total_size(lookahead).extent.row * ERROR_COST_PER_SKIPPED_LINE;
if (parser__better_version_exists(self, version, false, new_cost)) {
ts_stack_halt(self->stack, version);
@ -1041,11 +1041,11 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
}
LOG("skip_token symbol:%s", SYM_NAME(lookahead->symbol));
ts_tree_retain(lookahead);
TreeArray children = array_new();
ts_subtree_retain(lookahead);
SubtreeArray children = array_new();
array_reserve(&children, 1);
array_push(&children, lookahead);
Tree *error_repeat = ts_tree_make_node(
Subtree *error_repeat = ts_subtree_make_node(
&self->tree_pool,
ts_builtin_sym_error_repeat,
&children,
@ -1056,13 +1056,13 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
if (node_count_since_error > 0) {
StackSliceArray pop = ts_stack_pop_count(self->stack, version, 1);
assert(pop.size == 1);
assert(pop.contents[0].trees.size == 1);
assert(pop.contents[0].subtrees.size == 1);
ts_stack_renumber_version(self->stack, pop.contents[0].version, version);
array_push(&pop.contents[0].trees, error_repeat);
error_repeat = ts_tree_make_node(
array_push(&pop.contents[0].subtrees, error_repeat);
error_repeat = ts_subtree_make_node(
&self->tree_pool,
ts_builtin_sym_error_repeat,
&pop.contents[0].trees,
&pop.contents[0].subtrees,
0,
self->language
);
@ -1072,7 +1072,7 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
if (lookahead->has_external_tokens) {
ts_stack_set_last_external_token(
self->stack, version, ts_tree_last_external_token(lookahead)
self->stack, version, ts_subtree_last_external_token(lookahead)
);
}
}
@ -1080,7 +1080,7 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
static void parser__advance(Parser *self, StackVersion version, ReusableNode *reusable_node) {
TSStateId state = ts_stack_state(self->stack, version);
TableEntry table_entry;
Tree *lookahead = parser__get_lookahead(self, version, &state, reusable_node, &table_entry);
Subtree *lookahead = parser__get_lookahead(self, version, &state, reusable_node, &table_entry);
for (;;) {
StackVersion last_reduction_version = STACK_VERSION_NONE;
@ -1113,7 +1113,7 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
if (lookahead == reusable_node_tree(reusable_node)) {
reusable_node_advance(reusable_node);
}
ts_tree_release(&self->tree_pool, lookahead);
ts_subtree_release(&self->tree_pool, lookahead);
return;
}
@ -1133,7 +1133,7 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
case TSParseActionTypeAccept: {
LOG("accept");
parser__accept(self, version, lookahead);
ts_tree_release(&self->tree_pool, lookahead);
ts_subtree_release(&self->tree_pool, lookahead);
return;
}
@ -1145,7 +1145,7 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
if (lookahead == reusable_node_tree(reusable_node)) {
reusable_node_advance(reusable_node);
}
ts_tree_release(&self->tree_pool, lookahead);
ts_subtree_release(&self->tree_pool, lookahead);
return;
}
}
@ -1156,12 +1156,12 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
LOG_STACK();
} else if (state == ERROR_STATE) {
parser__recover(self, version, lookahead);
ts_tree_release(&self->tree_pool, lookahead);
ts_subtree_release(&self->tree_pool, lookahead);
return;
} else if (!parser__breakdown_top_of_stack(self, version)) {
LOG("detect_error");
ts_stack_pause(self->stack, version, lookahead->first_leaf.symbol);
ts_tree_release(&self->tree_pool, lookahead);
ts_subtree_release(&self->tree_pool, lookahead);
return;
}
@ -1260,7 +1260,7 @@ bool parser_init(Parser *self) {
ts_lexer_init(&self->lexer);
array_init(&self->reduce_actions);
array_reserve(&self->reduce_actions, 4);
ts_tree_pool_init(&self->tree_pool);
ts_subtree_pool_init(&self->tree_pool);
self->stack = ts_stack_new(&self->tree_pool);
self->finished_tree = NULL;
self->reusable_node = reusable_node_new();
@ -1285,12 +1285,12 @@ void parser_destroy(Parser *self) {
ts_stack_delete(self->stack);
if (self->reduce_actions.contents)
array_delete(&self->reduce_actions);
ts_tree_pool_delete(&self->tree_pool);
ts_subtree_pool_delete(&self->tree_pool);
reusable_node_delete(&self->reusable_node);
parser_set_language(self, NULL);
}
Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_error) {
Subtree *parser_parse(Parser *self, TSInput input, Subtree *old_tree, bool halt_on_error) {
parser__start(self, input, old_tree);
StackVersion version = STACK_VERSION_NONE;
@ -1336,7 +1336,7 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err
reusable_node_delete(&reusable_node);
ts_stack_clear(self->stack);
parser__set_cached_token(self, 0, NULL, NULL);
ts_tree_balance(self->finished_tree, &self->tree_pool, self->language);
ts_subtree_balance(self->finished_tree, &self->tree_pool, self->language);
LOG("done");
LOG_TREE();

View file

@ -10,22 +10,22 @@ extern "C" {
#include "runtime/lexer.h"
#include "runtime/reusable_node.h"
#include "runtime/reduce_action.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
typedef struct {
Tree *token;
Tree *last_external_token;
Subtree *token;
Subtree *last_external_token;
uint32_t byte_index;
} TokenCache;
typedef struct {
Lexer lexer;
Stack *stack;
TreePool tree_pool;
SubtreePool tree_pool;
const TSLanguage *language;
ReduceActionSet reduce_actions;
Tree *finished_tree;
Tree scratch_tree;
Subtree *finished_tree;
Subtree scratch_tree;
TokenCache token_cache;
ReusableNode reusable_node;
void *external_scanner_payload;
@ -36,7 +36,7 @@ typedef struct {
bool parser_init(Parser *);
void parser_destroy(Parser *);
Tree *parser_parse(Parser *, TSInput, Tree *, bool halt_on_error);
Subtree *parser_parse(Parser *, TSInput, Subtree *, bool halt_on_error);
void parser_set_language(Parser *, const TSLanguage *);
#ifdef __cplusplus

View file

@ -1,21 +1,21 @@
#include "runtime/tree.h"
#include "runtime/subtree.h"
typedef struct {
Tree *tree;
Subtree *tree;
uint32_t child_index;
uint32_t byte_offset;
} StackEntry;
typedef struct {
Array(StackEntry) stack;
Tree *last_external_token;
Subtree *last_external_token;
} ReusableNode;
static inline ReusableNode reusable_node_new() {
return (ReusableNode) {array_new(), NULL};
}
static inline void reusable_node_reset(ReusableNode *self, Tree *tree) {
static inline void reusable_node_reset(ReusableNode *self, Subtree *tree) {
array_clear(&self->stack);
array_push(&self->stack, ((StackEntry) {
.tree = tree,
@ -24,7 +24,7 @@ static inline void reusable_node_reset(ReusableNode *self, Tree *tree) {
}));
}
static inline Tree *reusable_node_tree(ReusableNode *self) {
static inline Subtree *reusable_node_tree(ReusableNode *self) {
return self->stack.size > 0
? self->stack.contents[self->stack.size - 1].tree
: NULL;
@ -46,12 +46,12 @@ static inline void reusable_node_assign(ReusableNode *self, const ReusableNode *
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);
uint32_t byte_offset = last_entry.byte_offset + ts_subtree_total_bytes(last_entry.tree);
if (last_entry.tree->has_external_tokens) {
self->last_external_token = ts_tree_last_external_token(last_entry.tree);
self->last_external_token = ts_subtree_last_external_token(last_entry.tree);
}
Tree *tree;
Subtree *tree;
uint32_t next_index;
do {
StackEntry popped_entry = array_pop(&self->stack);

View file

@ -1,6 +1,6 @@
#include "runtime/alloc.h"
#include "runtime/language.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/array.h"
#include "runtime/stack.h"
#include "runtime/length.h"
@ -21,7 +21,7 @@ typedef struct StackNode StackNode;
typedef struct {
StackNode *node;
Tree *tree;
Subtree *subtree;
bool is_pending;
} StackLink;
@ -38,8 +38,8 @@ struct StackNode {
typedef struct {
StackNode *node;
TreeArray trees;
uint32_t tree_count;
SubtreeArray subtrees;
uint32_t subtree_count;
bool is_pending;
} Iterator;
@ -58,7 +58,7 @@ typedef enum {
typedef struct {
StackNode *node;
Tree *last_external_token;
Subtree *last_external_token;
StackSummary *summary;
unsigned node_count_at_last_error;
TSSymbol lookahead_when_paused;
@ -71,7 +71,7 @@ struct Stack {
Array(Iterator) iterators;
StackNodeArray node_pool;
StackNode *base_node;
TreePool *tree_pool;
SubtreePool *subtree_pool;
};
typedef unsigned StackAction;
@ -91,7 +91,7 @@ static void stack_node_retain(StackNode *self) {
assert(self->ref_count != 0);
}
static void stack_node_release(StackNode *self, StackNodeArray *pool, TreePool *tree_pool) {
static void stack_node_release(StackNode *self, StackNodeArray *pool, SubtreePool *subtree_pool) {
recur:
assert(self->ref_count != 0);
self->ref_count--;
@ -100,10 +100,10 @@ recur:
StackNode *first_predecessor = NULL;
if (self->link_count > 0) {
for (unsigned i = self->link_count - 1; i > 0; i--) {
if (self->links[i].tree) ts_tree_release(tree_pool, self->links[i].tree);
stack_node_release(self->links[i].node, pool, tree_pool);
if (self->links[i].subtree) ts_subtree_release(subtree_pool, self->links[i].subtree);
stack_node_release(self->links[i].node, pool, subtree_pool);
}
if (self->links[0].tree) ts_tree_release(tree_pool, self->links[0].tree);
if (self->links[0].subtree) ts_subtree_release(subtree_pool, self->links[0].subtree);
first_predecessor = self->links[0].node;
}
@ -119,7 +119,7 @@ recur:
}
}
static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_pending,
static StackNode *stack_node_new(StackNode *previous_node, Subtree *subtree, bool is_pending,
TSStateId state, StackNodeArray *pool) {
StackNode *node = pool->size > 0 ?
array_pop(pool) :
@ -130,7 +130,7 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
node->link_count = 1;
node->links[0] = (StackLink){
.node = previous_node,
.tree = tree,
.subtree = subtree,
.is_pending = is_pending,
};
@ -139,11 +139,11 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
node->dynamic_precedence = previous_node->dynamic_precedence;
node->node_count = previous_node->node_count;
if (tree) {
node->error_cost += tree->error_cost;
node->position = length_add(node->position, ts_tree_total_size(tree));
node->dynamic_precedence += tree->dynamic_precedence;
if (!tree->extra) node->node_count += tree->node_count;
if (subtree) {
node->error_cost += subtree->error_cost;
node->position = length_add(node->position, ts_subtree_total_size(subtree));
node->dynamic_precedence += subtree->dynamic_precedence;
if (!subtree->extra) node->node_count += subtree->node_count;
}
} else {
node->position = length_zero();
@ -153,7 +153,7 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
return node;
}
static bool stack__tree_is_equivalent(const Tree *left, const Tree *right) {
static bool stack__subtree_is_equivalent(const Subtree *left, const Subtree *right) {
return
left == right ||
(left &&
@ -164,7 +164,7 @@ static bool stack__tree_is_equivalent(const Tree *left, const Tree *right) {
left->padding.bytes == right->padding.bytes &&
left->size.bytes == right->size.bytes &&
left->extra == right->extra &&
ts_tree_external_token_state_eq(left, right))));
ts_subtree_external_token_state_eq(left, right))));
}
static void stack_node_add_link(StackNode *self, StackLink link) {
@ -172,7 +172,7 @@ static void stack_node_add_link(StackNode *self, StackLink link) {
for (int i = 0; i < self->link_count; i++) {
StackLink existing_link = self->links[i];
if (stack__tree_is_equivalent(existing_link.tree, link.tree)) {
if (stack__subtree_is_equivalent(existing_link.subtree, link.subtree)) {
if (existing_link.node == link.node) return;
if (existing_link.node->state == link.node->state &&
existing_link.node->position.bytes == link.node->position.bytes) {
@ -187,24 +187,24 @@ static void stack_node_add_link(StackNode *self, StackLink link) {
if (self->link_count == MAX_LINK_COUNT) return;
stack_node_retain(link.node);
if (link.tree) ts_tree_retain(link.tree);
if (link.subtree) ts_subtree_retain(link.subtree);
self->links[self->link_count++] = link;
unsigned node_count = link.node->node_count;
if (link.tree) node_count += link.tree->node_count;
if (link.subtree) node_count += link.subtree->node_count;
if (node_count > self->node_count) self->node_count = node_count;
}
static void stack_head_delete(StackHead *self, StackNodeArray *pool, TreePool *tree_pool) {
static void stack_head_delete(StackHead *self, StackNodeArray *pool, SubtreePool *subtree_pool) {
if (self->node) {
if (self->last_external_token) {
ts_tree_release(tree_pool, self->last_external_token);
ts_subtree_release(subtree_pool, self->last_external_token);
}
if (self->summary) {
array_delete(self->summary);
ts_free(self->summary);
}
stack_node_release(self->node, pool, tree_pool);
stack_node_release(self->node, pool, subtree_pool);
}
}
@ -219,44 +219,44 @@ static StackVersion ts_stack__add_version(Stack *self, StackVersion original_ver
};
array_push(&self->heads, head);
stack_node_retain(node);
if (head.last_external_token) ts_tree_retain(head.last_external_token);
if (head.last_external_token) ts_subtree_retain(head.last_external_token);
return (StackVersion)(self->heads.size - 1);
}
static void ts_stack__add_slice(Stack *self, StackVersion original_version,
StackNode *node, TreeArray *trees) {
StackNode *node, SubtreeArray *subtrees) {
for (uint32_t i = self->slices.size - 1; i + 1 > 0; i--) {
StackVersion version = self->slices.contents[i].version;
if (self->heads.contents[version].node == node) {
StackSlice slice = {*trees, version};
StackSlice slice = {*subtrees, version};
array_insert(&self->slices, i + 1, slice);
return;
}
}
StackVersion version = ts_stack__add_version(self, original_version, node);
StackSlice slice = { *trees, version };
StackSlice slice = { *subtrees, version };
array_push(&self->slices, slice);
}
inline StackSliceArray stack__iter(Stack *self, StackVersion version,
StackCallback callback, void *payload,
int goal_tree_count) {
int goal_subtree_count) {
array_clear(&self->slices);
array_clear(&self->iterators);
StackHead *head = array_get(&self->heads, version);
Iterator iterator = {
.node = head->node,
.trees = array_new(),
.tree_count = 0,
.subtrees = array_new(),
.subtree_count = 0,
.is_pending = true,
};
bool include_trees = false;
if (goal_tree_count >= 0) {
include_trees = true;
array_reserve(&iterator.trees, goal_tree_count);
bool include_subtrees = false;
if (goal_subtree_count >= 0) {
include_subtrees = true;
array_reserve(&iterator.subtrees, goal_subtree_count);
}
array_push(&self->iterators, iterator);
@ -271,21 +271,21 @@ inline StackSliceArray stack__iter(Stack *self, StackVersion version,
bool should_stop = action & StackActionStop || node->link_count == 0;
if (should_pop) {
TreeArray trees = iterator->trees;
SubtreeArray subtrees = iterator->subtrees;
if (!should_stop)
ts_tree_array_copy(trees, &trees);
ts_tree_array_reverse(&trees);
ts_subtree_array_copy(subtrees, &subtrees);
ts_subtree_array_reverse(&subtrees);
ts_stack__add_slice(
self,
version,
node,
&trees
&subtrees
);
}
if (should_stop) {
if (!should_pop)
ts_tree_array_delete(self->tree_pool, &iterator->trees);
ts_subtree_array_delete(self->subtree_pool, &iterator->subtrees);
array_erase(&self->iterators, i);
i--, size--;
continue;
@ -303,24 +303,24 @@ inline StackSliceArray stack__iter(Stack *self, StackVersion version,
Iterator current_iterator = self->iterators.contents[i];
array_push(&self->iterators, current_iterator);
next_iterator = array_back(&self->iterators);
ts_tree_array_copy(next_iterator->trees, &next_iterator->trees);
ts_subtree_array_copy(next_iterator->subtrees, &next_iterator->subtrees);
}
next_iterator->node = link.node;
if (link.tree) {
if (include_trees) {
array_push(&next_iterator->trees, link.tree);
ts_tree_retain(link.tree);
if (link.subtree) {
if (include_subtrees) {
array_push(&next_iterator->subtrees, link.subtree);
ts_subtree_retain(link.subtree);
}
if (!link.tree->extra) {
next_iterator->tree_count++;
if (!link.subtree->extra) {
next_iterator->subtree_count++;
if (!link.is_pending) {
next_iterator->is_pending = false;
}
}
} else {
next_iterator->tree_count++;
next_iterator->subtree_count++;
next_iterator->is_pending = false;
}
}
@ -330,7 +330,7 @@ inline StackSliceArray stack__iter(Stack *self, StackVersion version,
return self->slices;
}
Stack *ts_stack_new(TreePool *tree_pool) {
Stack *ts_stack_new(SubtreePool *subtree_pool) {
Stack *self = ts_calloc(1, sizeof(Stack));
array_init(&self->heads);
@ -342,7 +342,7 @@ Stack *ts_stack_new(TreePool *tree_pool) {
array_reserve(&self->iterators, 4);
array_reserve(&self->node_pool, MAX_NODE_POOL_SIZE);
self->tree_pool = tree_pool;
self->subtree_pool = subtree_pool;
self->base_node = stack_node_new(NULL, NULL, false, 1, &self->node_pool);
ts_stack_clear(self);
@ -354,9 +354,9 @@ void ts_stack_delete(Stack *self) {
array_delete(&self->slices);
if (self->iterators.contents)
array_delete(&self->iterators);
stack_node_release(self->base_node, &self->node_pool, self->tree_pool);
stack_node_release(self->base_node, &self->node_pool, self->subtree_pool);
for (uint32_t i = 0; i < self->heads.size; i++) {
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->tree_pool);
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->subtree_pool);
}
array_clear(&self->heads);
if (self->node_pool.contents) {
@ -380,14 +380,14 @@ Length ts_stack_position(const Stack *self, StackVersion version) {
return array_get(&self->heads, version)->node->position;
}
Tree *ts_stack_last_external_token(const Stack *self, StackVersion version) {
Subtree *ts_stack_last_external_token(const Stack *self, StackVersion version) {
return array_get(&self->heads, version)->last_external_token;
}
void ts_stack_set_last_external_token(Stack *self, StackVersion version, Tree *token) {
void ts_stack_set_last_external_token(Stack *self, StackVersion version, Subtree *token) {
StackHead *head = array_get(&self->heads, version);
if (token) ts_tree_retain(token);
if (head->last_external_token) ts_tree_release(self->tree_pool, head->last_external_token);
if (token) ts_subtree_retain(token);
if (head->last_external_token) ts_subtree_release(self->subtree_pool, head->last_external_token);
head->last_external_token = token;
}
@ -396,7 +396,7 @@ unsigned ts_stack_error_cost(const Stack *self, StackVersion version) {
unsigned result = head->node->error_cost;
if (
head->status == StackStatusPaused ||
(head->node->state == ERROR_STATE && !head->node->links[0].tree)) {
(head->node->state == ERROR_STATE && !head->node->links[0].subtree)) {
result += ERROR_COST_PER_RECOVERY;
}
return result;
@ -410,10 +410,10 @@ unsigned ts_stack_node_count_since_error(const Stack *self, StackVersion version
return head->node->node_count - head->node_count_at_last_error;
}
void ts_stack_push(Stack *self, StackVersion version, Tree *tree, bool pending, TSStateId state) {
void ts_stack_push(Stack *self, StackVersion version, Subtree *subtree, bool pending, TSStateId state) {
StackHead *head = array_get(&self->heads, version);
StackNode *new_node = stack_node_new(head->node, tree, pending, state, &self->node_pool);
if (!tree) head->node_count_at_last_error = new_node->node_count;
StackNode *new_node = stack_node_new(head->node, subtree, pending, state, &self->node_pool);
if (!subtree) head->node_count_at_last_error = new_node->node_count;
head->node = new_node;
}
@ -422,7 +422,7 @@ inline StackAction iterate_callback(void *payload, const Iterator *iterator) {
session->callback(
session->payload,
iterator->node->state,
iterator->tree_count
iterator->subtree_count
);
return StackActionNone;
}
@ -434,8 +434,8 @@ void ts_stack_iterate(Stack *self, StackVersion version,
}
inline StackAction pop_count_callback(void *payload, const Iterator *iterator) {
unsigned *goal_tree_count = payload;
if (iterator->tree_count == *goal_tree_count) {
unsigned *goal_subtree_count = payload;
if (iterator->subtree_count == *goal_subtree_count) {
return StackActionPop | StackActionStop;
} else {
return StackActionNone;
@ -447,7 +447,7 @@ StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t c
}
inline StackAction pop_pending_callback(void *payload, const Iterator *iterator) {
if (iterator->tree_count >= 1) {
if (iterator->subtree_count >= 1) {
if (iterator->is_pending) {
return StackActionPop | StackActionStop;
} else {
@ -468,9 +468,9 @@ StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version) {
}
inline StackAction pop_error_callback(void *payload, const Iterator *iterator) {
if (iterator->trees.size > 0) {
if (iterator->subtrees.size > 0) {
bool *found_error = payload;
if (!*found_error && iterator->trees.contents[0]->symbol == ts_builtin_sym_error) {
if (!*found_error && iterator->subtrees.contents[0]->symbol == ts_builtin_sym_error) {
*found_error = true;
return StackActionPop | StackActionStop;
} else {
@ -481,21 +481,21 @@ inline StackAction pop_error_callback(void *payload, const Iterator *iterator) {
}
}
TreeArray ts_stack_pop_error(Stack *self, StackVersion version) {
SubtreeArray ts_stack_pop_error(Stack *self, StackVersion version) {
StackNode *node = array_get(&self->heads, version)->node;
for (unsigned i = 0; i < node->link_count; i++) {
if (node->links[i].tree && node->links[i].tree->symbol == ts_builtin_sym_error) {
if (node->links[i].subtree && node->links[i].subtree->symbol == ts_builtin_sym_error) {
bool found_error = false;
StackSliceArray pop = stack__iter(self, version, pop_error_callback, &found_error, 1);
if (pop.size > 0) {
assert(pop.size == 1);
ts_stack_renumber_version(self, pop.contents[0].version, version);
return pop.contents[0].trees;
return pop.contents[0].subtrees;
}
break;
}
}
return (TreeArray){.size = 0};
return (SubtreeArray){.size = 0};
}
inline StackAction pop_all_callback(void *payload, const Iterator *iterator) {
@ -514,7 +514,7 @@ typedef struct {
inline StackAction summarize_stack_callback(void *payload, const Iterator *iterator) {
SummarizeStackSession *session = payload;
TSStateId state = iterator->node->state;
unsigned depth = iterator->tree_count;
unsigned depth = iterator->subtree_count;
if (depth > session->max_depth) return StackActionStop;
for (unsigned i = session->summary->size - 1; i + 1 > 0; i--) {
StackSummaryEntry entry = session->summary->contents[i];
@ -548,7 +548,7 @@ int ts_stack_dynamic_precedence(Stack *self, StackVersion version) {
}
void ts_stack_remove_version(Stack *self, StackVersion version) {
stack_head_delete(array_get(&self->heads, version), &self->node_pool, self->tree_pool);
stack_head_delete(array_get(&self->heads, version), &self->node_pool, self->subtree_pool);
array_erase(&self->heads, version);
}
@ -561,7 +561,7 @@ void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2) {
source_head->summary = target_head->summary;
target_head->summary = NULL;
}
stack_head_delete(target_head, &self->node_pool, self->tree_pool);
stack_head_delete(target_head, &self->node_pool, self->subtree_pool);
*target_head = *source_head;
array_erase(&self->heads, v1);
}
@ -577,7 +577,7 @@ StackVersion ts_stack_copy_version(Stack *self, StackVersion version) {
array_push(&self->heads, self->heads.contents[version]);
StackHead *head = array_back(&self->heads);
stack_node_retain(head->node);
if (head->last_external_token) ts_tree_retain(head->last_external_token);
if (head->last_external_token) ts_subtree_retain(head->last_external_token);
head->summary = NULL;
return self->heads.size - 1;
}
@ -605,7 +605,7 @@ bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version
head1->node->state == head2->node->state &&
head1->node->position.bytes == head2->node->position.bytes &&
head1->node->error_cost == head2->node->error_cost &&
ts_tree_external_token_state_eq(head1->last_external_token, head2->last_external_token);
ts_subtree_external_token_state_eq(head1->last_external_token, head2->last_external_token);
}
void ts_stack_halt(Stack *self, StackVersion version) {
@ -643,7 +643,7 @@ TSSymbol ts_stack_resume(Stack *self, StackVersion version) {
void ts_stack_clear(Stack *self) {
stack_node_retain(self->base_node);
for (uint32_t i = 0; i < self->heads.size; i++) {
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->tree_pool);
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->subtree_pool);
}
array_clear(&self->heads);
array_push(&self->heads, ((StackHead){
@ -715,8 +715,8 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
fprintf(f, "node_%p [", node);
if (node->state == ERROR_STATE)
fprintf(f, "label=\"?\"");
else if (node->link_count == 1 && node->links[0].tree &&
node->links[0].tree->extra)
else if (node->link_count == 1 && node->links[0].subtree &&
node->links[0].subtree->extra)
fprintf(f, "shape=point margin=0 label=\"\"");
else
fprintf(f, "label=\"%d\"", node->state);
@ -736,24 +736,24 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
fprintf(f, "node_%p -> node_%p [", node, link.node);
if (link.is_pending)
fprintf(f, "style=dashed ");
if (link.tree && link.tree->extra)
if (link.subtree && link.subtree->extra)
fprintf(f, "fontcolor=gray ");
if (!link.tree) {
if (!link.subtree) {
fprintf(f, "color=red");
} else {
fprintf(f, "label=\"");
if (link.tree->visible && !link.tree->named) fprintf(f, "'");
const char *name = ts_language_symbol_name(language, link.tree->symbol);
if (link.subtree->visible && !link.subtree->named) fprintf(f, "'");
const char *name = ts_language_symbol_name(language, link.subtree->symbol);
for (const char *c = name; *c; c++) {
if (*c == '\"' || *c == '\\') fprintf(f, "\\");
fprintf(f, "%c", *c);
}
if (link.tree->visible && !link.tree->named) fprintf(f, "'");
if (link.subtree->visible && !link.subtree->named) fprintf(f, "'");
fprintf(f, "\"");
fprintf(f, "labeltooltip=\"error_cost: %u\ndynamic_precedence: %u\"",
link.tree->error_cost,
link.tree->dynamic_precedence);
link.subtree->error_cost,
link.subtree->dynamic_precedence);
}
fprintf(f, "];\n");

View file

@ -6,7 +6,7 @@ extern "C" {
#endif
#include "runtime/array.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/error_costs.h"
#include <stdio.h>
@ -16,7 +16,7 @@ typedef unsigned StackVersion;
#define STACK_VERSION_NONE ((StackVersion)-1)
typedef struct {
TreeArray trees;
SubtreeArray subtrees;
StackVersion version;
} StackSlice;
typedef Array(StackSlice) StackSliceArray;
@ -29,7 +29,7 @@ typedef struct {
typedef Array(StackSummaryEntry) StackSummary;
// Create a stack.
Stack *ts_stack_new(TreePool *);
Stack *ts_stack_new(SubtreePool *);
// Release the memory reserved for a given stack.
void ts_stack_delete(Stack *);
@ -42,10 +42,10 @@ uint32_t ts_stack_version_count(const Stack *);
TSStateId ts_stack_state(const Stack *, StackVersion);
// Get the last external token associated with a given version of the stack.
Tree *ts_stack_last_external_token(const Stack *, StackVersion);
Subtree *ts_stack_last_external_token(const Stack *, StackVersion);
// Set the last external token associated with a given version of the stack.
void ts_stack_set_last_external_token(Stack *, StackVersion, Tree *);
void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree *);
// Get the position of the given version of the stack within the document.
Length ts_stack_position(const Stack *, StackVersion);
@ -55,7 +55,7 @@ Length ts_stack_position(const Stack *, StackVersion);
// This transfers ownership of the tree to the Stack. Callers that
// need to retain ownership of the tree for their own purposes should
// first retain the tree.
void ts_stack_push(Stack *, StackVersion, Tree *, bool, TSStateId);
void ts_stack_push(Stack *, StackVersion, Subtree *, bool, TSStateId);
// Pop the given number of entries from the given version of the stack. This
// operation can increase the number of stack versions by revealing multiple
@ -65,7 +65,7 @@ void ts_stack_push(Stack *, StackVersion, Tree *, bool, TSStateId);
StackSliceArray ts_stack_pop_count(Stack *, StackVersion, uint32_t count);
// Remove an error at the top of the given version of the stack.
TreeArray ts_stack_pop_error(Stack *, StackVersion);
SubtreeArray ts_stack_pop_error(Stack *, StackVersion);
// Remove any pending trees from the top of the given version of the stack.
StackSliceArray ts_stack_pop_pending(Stack *, StackVersion);

View file

@ -6,7 +6,7 @@
#include <stdio.h>
#include "runtime/alloc.h"
#include "runtime/atomic.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/length.h"
#include "runtime/language.h"
#include "runtime/error_costs.h"
@ -51,15 +51,15 @@ bool ts_external_token_state_eq(const TSExternalTokenState *a, const TSExternalT
memcmp(ts_external_token_state_data(a), ts_external_token_state_data(b), a->length) == 0);
}
// TreeArray
// SubtreeArray
bool ts_tree_array_copy(TreeArray self, TreeArray *dest) {
Tree **contents = NULL;
bool ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest) {
Subtree **contents = NULL;
if (self.capacity > 0) {
contents = ts_calloc(self.capacity, sizeof(Tree *));
memcpy(contents, self.contents, self.size * sizeof(Tree *));
contents = ts_calloc(self.capacity, sizeof(Subtree *));
memcpy(contents, self.contents, self.size * sizeof(Subtree *));
for (uint32_t i = 0; i < self.size; i++) {
ts_tree_retain(contents[i]);
ts_subtree_retain(contents[i]);
}
}
@ -69,47 +69,47 @@ bool ts_tree_array_copy(TreeArray self, TreeArray *dest) {
return true;
}
void ts_tree_array_delete(TreePool *pool, TreeArray *self) {
void ts_subtree_array_delete(SubtreePool *pool, SubtreeArray *self) {
for (uint32_t i = 0; i < self->size; i++) {
ts_tree_release(pool, self->contents[i]);
ts_subtree_release(pool, self->contents[i]);
}
array_delete(self);
}
TreeArray ts_tree_array_remove_trailing_extras(TreeArray *self) {
TreeArray result = array_new();
SubtreeArray ts_subtree_array_remove_trailing_extras(SubtreeArray *self) {
SubtreeArray result = array_new();
uint32_t i = self->size - 1;
for (; i + 1 > 0; i--) {
Tree *child = self->contents[i];
Subtree *child = self->contents[i];
if (!child->extra) break;
array_push(&result, child);
}
self->size = i + 1;
ts_tree_array_reverse(&result);
ts_subtree_array_reverse(&result);
return result;
}
void ts_tree_array_reverse(TreeArray *self) {
void ts_subtree_array_reverse(SubtreeArray *self) {
for (uint32_t i = 0, limit = self->size / 2; i < limit; i++) {
size_t reverse_index = self->size - 1 - i;
Tree *swap = self->contents[i];
Subtree *swap = self->contents[i];
self->contents[i] = self->contents[reverse_index];
self->contents[reverse_index] = swap;
}
}
// TreePool
// SubtreePool
static const uint32_t MAX_TREE_POOL_SIZE = 1024;
void ts_tree_pool_init(TreePool *self) {
void ts_subtree_pool_init(SubtreePool *self) {
array_init(&self->free_trees);
array_init(&self->tree_stack);
}
void ts_tree_pool_delete(TreePool *self) {
void ts_subtree_pool_delete(SubtreePool *self) {
if (self->free_trees.contents) {
for (unsigned i = 0; i < self->free_trees.size; i++) {
ts_free(self->free_trees.contents[i]);
@ -119,15 +119,15 @@ void ts_tree_pool_delete(TreePool *self) {
if (self->tree_stack.contents) array_delete(&self->tree_stack);
}
Tree *ts_tree_pool_allocate(TreePool *self) {
Subtree *ts_subtree_pool_allocate(SubtreePool *self) {
if (self->free_trees.size > 0) {
return array_pop(&self->free_trees);
} else {
return ts_malloc(sizeof(Tree));
return ts_malloc(sizeof(Subtree));
}
}
void ts_tree_pool_free(TreePool *self, Tree *tree) {
void ts_subtree_pool_free(SubtreePool *self, Subtree *tree) {
if (self->free_trees.size < MAX_TREE_POOL_SIZE) {
array_push(&self->free_trees, tree);
} else {
@ -135,12 +135,13 @@ void ts_tree_pool_free(TreePool *self, Tree *tree) {
}
}
// Tree
// Subtree
Tree *ts_tree_make_leaf(TreePool *pool, TSSymbol symbol, Length padding, Length size, const TSLanguage *language) {
Subtree *ts_subtree_make_leaf(SubtreePool *pool, TSSymbol symbol, Length padding, Length size,
const TSLanguage *language) {
TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
Tree *result = ts_tree_pool_allocate(pool);
*result = (Tree){
Subtree *result = ts_subtree_pool_allocate(pool);
*result = (Subtree){
.ref_count = 1,
.symbol = symbol,
.size = size,
@ -161,50 +162,51 @@ Tree *ts_tree_make_leaf(TreePool *pool, TSSymbol symbol, Length padding, Length
return result;
}
Tree *ts_tree_make_error(TreePool *pool, Length size, Length padding, int32_t lookahead_char,
const TSLanguage *language) {
Tree *result = ts_tree_make_leaf(pool, ts_builtin_sym_error, padding, size, language);
Subtree *ts_subtree_make_error(SubtreePool *pool, Length size, Length padding,
int32_t lookahead_char, const TSLanguage *language) {
Subtree *result = ts_subtree_make_leaf(pool, ts_builtin_sym_error, padding, size, language);
result->fragile_left = true;
result->fragile_right = true;
result->lookahead_char = lookahead_char;
return result;
}
Tree *ts_tree_make_copy(TreePool *pool, Tree *self) {
Tree *result = ts_tree_pool_allocate(pool);
Subtree *ts_subtree_make_copy(SubtreePool *pool, Subtree *self) {
Subtree *result = ts_subtree_pool_allocate(pool);
*result = *self;
if (result->children.size > 0) {
ts_tree_array_copy(self->children, &result->children);
ts_subtree_array_copy(self->children, &result->children);
}
result->ref_count = 1;
return result;
}
static Tree *ts_tree_make_mut(TreePool *pool, Tree *self) {
static Subtree *ts_subtree_make_mut(SubtreePool *pool, Subtree *self) {
if (self->ref_count == 1) {
return self;
} else {
Tree *result = ts_tree_make_copy(pool, self);
ts_tree_release(pool, self);
Subtree *result = ts_subtree_make_copy(pool, self);
ts_subtree_release(pool, self);
return result;
}
}
static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *language, TreeArray *stack) {
static void ts_subtree__compress(Subtree *self, unsigned count, const TSLanguage *language,
SubtreeArray *stack) {
unsigned initial_stack_size = stack->size;
Tree *tree = self;
Subtree *tree = self;
for (unsigned i = 0; i < count; i++) {
if (tree->ref_count > 1 || tree->children.size != 2) break;
Tree *child = tree->children.contents[0];
Subtree *child = tree->children.contents[0];
if (
child->ref_count > 1 ||
child->children.size != 2 ||
child->symbol != tree->symbol
) break;
Tree *grandchild = child->children.contents[0];
Subtree *grandchild = child->children.contents[0];
if (
grandchild->ref_count > 1 ||
grandchild->children.size != 2 ||
@ -221,19 +223,19 @@ static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *lang
while (stack->size > initial_stack_size) {
tree = array_pop(stack);
assert(tree);
Tree *child = tree->children.contents[0];
Tree *grandchild = child->children.contents[1];
ts_tree_set_children(grandchild, &grandchild->children, language);
ts_tree_set_children(child, &child->children, language);
ts_tree_set_children(tree, &tree->children, language);
Subtree *child = tree->children.contents[0];
Subtree *grandchild = child->children.contents[1];
ts_subtree_set_children(grandchild, &grandchild->children, language);
ts_subtree_set_children(child, &child->children, language);
ts_subtree_set_children(tree, &tree->children, language);
}
}
void ts_tree_balance(Tree *self, TreePool *pool, const TSLanguage *language) {
void ts_subtree_balance(Subtree *self, SubtreePool *pool, const TSLanguage *language) {
array_clear(&pool->tree_stack);
array_push(&pool->tree_stack, self);
while (pool->tree_stack.size > 0) {
Tree *tree = array_pop(&pool->tree_stack);
Subtree *tree = array_pop(&pool->tree_stack);
assert(tree);
if (tree->repeat_depth > 0) {
@ -243,14 +245,14 @@ void ts_tree_balance(Tree *self, TreePool *pool, const TSLanguage *language) {
tree->children.contents[1]->repeat_depth
);
for (unsigned i = n / 2; i > 0; i /= 2) {
ts_tree__compress(tree, i, language, &pool->tree_stack);
ts_subtree__compress(tree, i, language, &pool->tree_stack);
n -= i;
}
}
}
for (uint32_t i = 0; i < tree->children.size; i++) {
Tree *child = tree->children.contents[i];
Subtree *child = tree->children.contents[i];
if (child->ref_count == 1) {
array_push(&pool->tree_stack, child);
}
@ -258,7 +260,7 @@ void ts_tree_balance(Tree *self, TreePool *pool, const TSLanguage *language) {
}
}
void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *language) {
void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLanguage *language) {
if (self->children.size > 0 && children->contents != self->children.contents) {
array_delete(&self->children);
}
@ -276,16 +278,16 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id);
for (uint32_t i = 0; i < self->children.size; i++) {
Tree *child = self->children.contents[i];
Subtree *child = self->children.contents[i];
if (i == 0) {
self->padding = child->padding;
self->size = child->size;
self->bytes_scanned = child->bytes_scanned;
} else {
uint32_t bytes_scanned = ts_tree_total_bytes(self) + child->bytes_scanned;
uint32_t bytes_scanned = ts_subtree_total_bytes(self) + child->bytes_scanned;
if (bytes_scanned > self->bytes_scanned) self->bytes_scanned = bytes_scanned;
self->size = length_add(self->size, ts_tree_total_size(child));
self->size = length_add(self->size, ts_subtree_total_size(child));
}
if (child->symbol != ts_builtin_sym_error_repeat) {
@ -322,7 +324,7 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
ERROR_COST_PER_SKIPPED_CHAR * self->size.bytes +
ERROR_COST_PER_SKIPPED_LINE * self->size.extent.row;
for (uint32_t i = 0; i < self->children.size; i++) {
Tree *child = self->children.contents[i];
Subtree *child = self->children.contents[i];
if (child->extra) continue;
if (child->symbol == ts_builtin_sym_error && child->children.size == 0) continue;
if (child->visible) {
@ -334,8 +336,8 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
}
if (self->children.size > 0) {
Tree *first_child = self->children.contents[0];
Tree *last_child = self->children.contents[self->children.size - 1];
Subtree *first_child = self->children.contents[0];
Subtree *last_child = self->children.contents[self->children.size - 1];
self->first_leaf = first_child->first_leaf;
if (first_child->fragile_left) self->fragile_left = true;
if (last_child->fragile_right) self->fragile_right = true;
@ -354,40 +356,42 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
}
}
Tree *ts_tree_make_node(TreePool *pool, TSSymbol symbol, TreeArray *children,
Subtree *ts_subtree_make_node(SubtreePool *pool, TSSymbol symbol, SubtreeArray *children,
unsigned alias_sequence_id, const TSLanguage *language) {
Tree *result = ts_tree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
Subtree *result = ts_subtree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
result->alias_sequence_id = alias_sequence_id;
if (symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat) {
result->fragile_left = true;
result->fragile_right = true;
}
ts_tree_set_children(result, children, language);
ts_subtree_set_children(result, children, language);
return result;
}
Tree *ts_tree_make_error_node(TreePool *pool, TreeArray *children, const TSLanguage *language) {
return ts_tree_make_node(pool, ts_builtin_sym_error, children, 0, language);
Subtree *ts_subtree_make_error_node(SubtreePool *pool, SubtreeArray *children,
const TSLanguage *language) {
return ts_subtree_make_node(pool, ts_builtin_sym_error, children, 0, language);
}
Tree *ts_tree_make_missing_leaf(TreePool *pool, TSSymbol symbol, const TSLanguage *language) {
Tree *result = ts_tree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
Subtree *ts_subtree_make_missing_leaf(SubtreePool *pool, TSSymbol symbol,
const TSLanguage *language) {
Subtree *result = ts_subtree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
result->is_missing = true;
result->error_cost = ERROR_COST_PER_MISSING_TREE + ERROR_COST_PER_RECOVERY;
return result;
}
void ts_tree_retain(Tree *self) {
void ts_subtree_retain(Subtree *self) {
assert(self->ref_count > 0);
atomic_inc(&self->ref_count);
assert(self->ref_count != 0);
}
void ts_tree_release(TreePool *pool, Tree *self) {
void ts_subtree_release(SubtreePool *pool, Subtree *self) {
array_clear(&pool->tree_stack);
array_push(&pool->tree_stack, self);
while (pool->tree_stack.size > 0) {
Tree *tree = array_pop(&pool->tree_stack);
Subtree *tree = array_pop(&pool->tree_stack);
assert(tree->ref_count > 0);
if (atomic_dec(&tree->ref_count) == 0) {
if (tree->children.size > 0) {
@ -398,12 +402,12 @@ void ts_tree_release(TreePool *pool, Tree *self) {
} else if (tree->has_external_tokens) {
ts_external_token_state_delete(&tree->external_token_state);
}
ts_tree_pool_free(pool, tree);
ts_subtree_pool_free(pool, tree);
}
}
}
bool ts_tree_eq(const Tree *self, const Tree *other) {
bool ts_subtree_eq(const Subtree *self, const Subtree *other) {
if (self) {
if (!other) return false;
} else {
@ -421,14 +425,14 @@ bool ts_tree_eq(const Tree *self, const Tree *other) {
if (self->named_child_count != other->named_child_count) return false;
for (uint32_t i = 0; i < self->children.size; i++) {
if (!ts_tree_eq(self->children.contents[i], other->children.contents[i])) {
if (!ts_subtree_eq(self->children.contents[i], other->children.contents[i])) {
return false;
}
}
return true;
}
int ts_tree_compare(const Tree *left, const Tree *right) {
int ts_subtree_compare(const Subtree *left, const Subtree *right) {
if (left->symbol < right->symbol)
return -1;
if (right->symbol < left->symbol)
@ -438,9 +442,9 @@ int ts_tree_compare(const Tree *left, const Tree *right) {
if (right->children.size < left->children.size)
return 1;
for (uint32_t i = 0; i < left->children.size; i++) {
Tree *left_child = left->children.contents[i];
Tree *right_child = right->children.contents[i];
switch (ts_tree_compare(left_child, right_child)) {
Subtree *left_child = left->children.contents[i];
Subtree *right_child = right->children.contents[i];
switch (ts_subtree_compare(left_child, right_child)) {
case -1:
return -1;
case 1:
@ -452,30 +456,31 @@ int ts_tree_compare(const Tree *left, const Tree *right) {
return 0;
}
Tree *ts_tree_invalidate_lookahead(Tree *self, uint32_t edit_byte_offset, TreePool *pool) {
Subtree *ts_subtree_invalidate_lookahead(Subtree *self, uint32_t edit_byte_offset,
SubtreePool *pool) {
if (edit_byte_offset >= self->bytes_scanned) return self;
Tree *result = ts_tree_make_mut(pool, self);
Subtree *result = ts_subtree_make_mut(pool, self);
result->has_changes = true;
if (result->children.size > 0) {
uint32_t child_start_byte = 0;
for (uint32_t i = 0; i < result->children.size; i++) {
Tree **child = &result->children.contents[i];
Subtree **child = &result->children.contents[i];
if (child_start_byte > edit_byte_offset) break;
*child = ts_tree_invalidate_lookahead(*child, edit_byte_offset - child_start_byte, pool);
child_start_byte += ts_tree_total_bytes(*child);
*child = ts_subtree_invalidate_lookahead(*child, edit_byte_offset - child_start_byte, pool);
child_start_byte += ts_subtree_total_bytes(*child);
}
}
return result;
}
Tree *ts_tree__edit(Tree *self, Edit edit, TreePool *pool) {
Subtree *ts_subtree__edit(Subtree *self, Edit edit, SubtreePool *pool) {
Length new_end = length_add(edit.start, edit.added);
Length old_end = length_add(edit.start, edit.removed);
Tree *result = ts_tree_make_mut(pool, self);
Subtree *result = ts_subtree_make_mut(pool, self);
result->has_changes = true;
if (old_end.bytes <= result->padding.bytes) {
@ -486,14 +491,14 @@ Tree *ts_tree__edit(Tree *self, Edit edit, TreePool *pool) {
} else if (edit.start.bytes == result->padding.bytes && edit.removed.bytes == 0) {
result->padding = length_add(result->padding, edit.added);
} else {
Length new_total_size = length_add(new_end, length_sub(ts_tree_total_size(result), old_end));
Length new_total_size = length_add(new_end, length_sub(ts_subtree_total_size(result), old_end));
result->size = length_sub(new_total_size, result->padding);
}
Length child_left, child_right = length_zero();
for (uint32_t i = 0; i < result->children.size; i++) {
Tree **child = &result->children.contents[i];
Length child_size = ts_tree_total_size(*child);
Subtree **child = &result->children.contents[i];
Length child_size = ts_subtree_total_size(*child);
child_left = child_right;
child_right = length_add(child_left, child_size);
@ -519,28 +524,28 @@ Tree *ts_tree__edit(Tree *self, Edit edit, TreePool *pool) {
edit.added = length_zero();
edit.removed = length_sub(edit.removed, child_edit.removed);
*child = ts_tree__edit(*child, child_edit, pool);
*child = ts_subtree__edit(*child, child_edit, pool);
} else if (child_left.bytes <= edit.start.bytes) {
*child = ts_tree_invalidate_lookahead(*child, edit.start.bytes - child_left.bytes, pool);
*child = ts_subtree_invalidate_lookahead(*child, edit.start.bytes - child_left.bytes, pool);
}
}
return result;
}
Tree *ts_tree_edit(Tree *self, const TSInputEdit *edit, TreePool *pool) {
return ts_tree__edit(self, (Edit) {
Subtree *ts_subtree_edit(Subtree *self, const TSInputEdit *edit, SubtreePool *pool) {
return ts_subtree__edit(self, (Edit) {
.start = {edit->start_byte, edit->start_point},
.added = {edit->bytes_added, edit->extent_added},
.removed = {edit->bytes_removed, edit->extent_removed},
}, pool);
}
Tree *ts_tree_last_external_token(Tree *tree) {
Subtree *ts_subtree_last_external_token(Subtree *tree) {
if (!tree->has_external_tokens) return NULL;
while (tree->children.size > 0) {
for (uint32_t i = tree->children.size - 1; i + 1 > 0; i--) {
Tree *child = tree->children.contents[i];
Subtree *child = tree->children.contents[i];
if (child->has_external_tokens) {
tree = child;
break;
@ -550,7 +555,7 @@ Tree *ts_tree_last_external_token(Tree *tree) {
return tree;
}
static size_t ts_tree__write_char_to_string(char *s, size_t n, int32_t c) {
static size_t ts_subtree__write_char_to_string(char *s, size_t n, int32_t c) {
if (c == 0)
return snprintf(s, n, "EOF");
if (c == -1)
@ -567,7 +572,7 @@ 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, char *string, size_t limit,
static size_t ts_subtree__write_to_string(const Subtree *self, char *string, size_t limit,
const TSLanguage *language, bool is_root,
bool include_all, TSSymbol alias_symbol,
bool alias_is_named) {
@ -589,7 +594,7 @@ static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t li
if (visible) {
if (self->symbol == ts_builtin_sym_error && self->children.size == 0 && self->size.bytes > 0) {
cursor += snprintf(*writer, limit, "(UNEXPECTED ");
cursor += ts_tree__write_char_to_string(*writer, limit, self->lookahead_char);
cursor += ts_subtree__write_char_to_string(*writer, limit, self->lookahead_char);
} else if (self->is_missing) {
cursor += snprintf(*writer, limit, "(MISSING");
} else {
@ -602,16 +607,16 @@ static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t li
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];
Subtree *child = self->children.contents[i];
if (child->extra) {
cursor += ts_tree__write_to_string(
cursor += ts_subtree__write_to_string(
child, *writer, limit,
language, false, include_all,
0, false
);
} else {
TSSymbol alias_symbol = alias_sequence ? alias_sequence[structural_child_index] : 0;
cursor += ts_tree__write_to_string(
cursor += ts_subtree__write_to_string(
child, *writer, limit,
language, false, include_all,
alias_symbol,
@ -626,19 +631,19 @@ static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t li
return cursor - string;
}
char *ts_tree_string(const Tree *self, const TSLanguage *language, bool include_all) {
char *ts_subtree_string(const Subtree *self, const TSLanguage *language, bool include_all) {
char scratch_string[1];
size_t size = ts_tree__write_to_string(
size_t size = ts_subtree__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, result, size, language, true, include_all, 0, false);
ts_subtree__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,
void ts_subtree__print_dot_graph(const Subtree *self, uint32_t byte_offset,
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));
@ -656,7 +661,7 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
"repeat-depth:%u\n"
"bytes-scanned:%u\"]\n",
self,
byte_offset, byte_offset + ts_tree_total_bytes(self),
byte_offset, byte_offset + ts_subtree_total_bytes(self),
self->parse_state,
self->error_cost,
self->repeat_depth,
@ -666,29 +671,29 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
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];
const Subtree *child = self->children.contents[i];
if (child->extra) {
ts_tree__print_dot_graph(child, byte_offset, language, 0, f);
ts_subtree__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);
ts_subtree__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);
byte_offset += ts_subtree_total_bytes(child);
}
}
void ts_tree_print_dot_graph(const Tree *self, const TSLanguage *language, FILE *f) {
void ts_subtree_print_dot_graph(const Subtree *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, 0, f);
ts_subtree__print_dot_graph(self, 0, language, 0, f);
fprintf(f, "}\n");
}
static const TSExternalTokenState empty_state = {.length = 0, .short_data = {0}};
bool ts_tree_external_token_state_eq(const Tree *self, const Tree *other) {
bool ts_subtree_external_token_state_eq(const Subtree *self, const Subtree *other) {
const TSExternalTokenState *state1 = &empty_state;
const TSExternalTokenState *state2 = &empty_state;
if (self && self->has_external_tokens) state1 = &self->external_token_state;

125
src/runtime/subtree.h Normal file
View file

@ -0,0 +1,125 @@
#ifndef RUNTIME_TREE_H_
#define RUNTIME_TREE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "tree_sitter/parser.h"
#include "tree_sitter/runtime.h"
#include "runtime/length.h"
#include "runtime/array.h"
#include <stdio.h>
extern TSStateId TS_TREE_STATE_NONE;
typedef struct {
union {
char *long_data;
char short_data[sizeof(char *) + sizeof(uint32_t)];
};
uint32_t length;
} TSExternalTokenState;
typedef struct Subtree Subtree;
typedef Array(Subtree *) SubtreeArray;
struct Subtree {
Length padding;
Length size;
volatile uint32_t ref_count;
uint32_t bytes_scanned;
uint32_t error_cost;
uint32_t node_count;
uint32_t repeat_depth;
uint32_t child_count;
int32_t dynamic_precedence;
bool visible : 1;
bool named : 1;
bool extra : 1;
bool fragile_left : 1;
bool fragile_right : 1;
bool has_changes : 1;
bool has_external_tokens : 1;
bool is_missing : 1;
TSSymbol symbol;
TSStateId parse_state;
struct {
TSSymbol symbol;
TSLexMode lex_mode;
} first_leaf;
union {
struct {
SubtreeArray children;
uint32_t visible_child_count;
uint32_t named_child_count;
uint16_t alias_sequence_id;
};
struct {
uint32_t _2;
TSExternalTokenState external_token_state;
};
struct {
uint32_t _1;
int32_t lookahead_char;
};
};
};
typedef struct {
SubtreeArray free_trees;
SubtreeArray tree_stack;
} SubtreePool;
void ts_external_token_state_init(TSExternalTokenState *, const char *, unsigned);
const char *ts_external_token_state_data(const TSExternalTokenState *);
bool ts_subtree_array_copy(SubtreeArray, SubtreeArray *);
void ts_subtree_array_delete(SubtreePool *, SubtreeArray *);
SubtreeArray ts_subtree_array_remove_trailing_extras(SubtreeArray *);
void ts_subtree_array_reverse(SubtreeArray *);
void ts_subtree_pool_init(SubtreePool *);
void ts_subtree_pool_delete(SubtreePool *);
Subtree *ts_subtree_pool_allocate(SubtreePool *);
void ts_subtree_pool_free(SubtreePool *, Subtree *);
Subtree *ts_subtree_make_leaf(SubtreePool *, TSSymbol, Length, Length, const TSLanguage *);
Subtree *ts_subtree_make_node(SubtreePool *, TSSymbol, SubtreeArray *, unsigned, const TSLanguage *);
Subtree *ts_subtree_make_copy(SubtreePool *, Subtree *child);
Subtree *ts_subtree_make_error_node(SubtreePool *, SubtreeArray *, const TSLanguage *);
Subtree *ts_subtree_make_error(SubtreePool *, Length, Length, int32_t, const TSLanguage *);
Subtree *ts_subtree_make_missing_leaf(SubtreePool *, TSSymbol, const TSLanguage *);
void ts_subtree_retain(Subtree *tree);
void ts_subtree_release(SubtreePool *, Subtree *tree);
bool ts_subtree_eq(const Subtree *tree1, const Subtree *tree2);
int ts_subtree_compare(const Subtree *tree1, const Subtree *tree2);
void ts_subtree_set_children(Subtree *, SubtreeArray *, const TSLanguage *);
void ts_subtree_balance(Subtree *, SubtreePool *, const TSLanguage *);
Subtree *ts_subtree_edit(Subtree *, const TSInputEdit *edit, SubtreePool *);
char *ts_subtree_string(const Subtree *, const TSLanguage *, bool include_all);
void ts_subtree_print_dot_graph(const Subtree *, const TSLanguage *, FILE *);
Subtree *ts_subtree_last_external_token(Subtree *);
bool ts_subtree_external_token_state_eq(const Subtree *, const Subtree *);
static inline uint32_t ts_subtree_total_bytes(const Subtree *self) {
return self->padding.bytes + self->size.bytes;
}
static inline uint32_t ts_subtree_total_rows(const Subtree *self) {
return self->padding.extent.row + self->size.extent.row;
}
static inline Length ts_subtree_total_size(const Subtree *self) {
return length_add(self->padding, self->size);
}
#ifdef __cplusplus
}
#endif
#endif // RUNTIME_TREE_H_

View file

@ -1,125 +0,0 @@
#ifndef RUNTIME_TREE_H_
#define RUNTIME_TREE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "tree_sitter/parser.h"
#include "tree_sitter/runtime.h"
#include "runtime/length.h"
#include "runtime/array.h"
#include <stdio.h>
extern TSStateId TS_TREE_STATE_NONE;
typedef struct {
union {
char *long_data;
char short_data[sizeof(char *) + sizeof(uint32_t)];
};
uint32_t length;
} TSExternalTokenState;
typedef struct Tree Tree;
typedef Array(Tree *) TreeArray;
struct Tree {
Length padding;
Length size;
volatile uint32_t ref_count;
uint32_t bytes_scanned;
uint32_t error_cost;
uint32_t node_count;
uint32_t repeat_depth;
uint32_t child_count;
int32_t dynamic_precedence;
bool visible : 1;
bool named : 1;
bool extra : 1;
bool fragile_left : 1;
bool fragile_right : 1;
bool has_changes : 1;
bool has_external_tokens : 1;
bool is_missing : 1;
TSSymbol symbol;
TSStateId parse_state;
struct {
TSSymbol symbol;
TSLexMode lex_mode;
} first_leaf;
union {
struct {
TreeArray children;
uint32_t visible_child_count;
uint32_t named_child_count;
uint16_t alias_sequence_id;
};
struct {
uint32_t _2;
TSExternalTokenState external_token_state;
};
struct {
uint32_t _1;
int32_t lookahead_char;
};
};
};
typedef struct {
TreeArray free_trees;
TreeArray tree_stack;
} TreePool;
void ts_external_token_state_init(TSExternalTokenState *, const char *, unsigned);
const char *ts_external_token_state_data(const TSExternalTokenState *);
bool ts_tree_array_copy(TreeArray, TreeArray *);
void ts_tree_array_delete(TreePool *, TreeArray *);
TreeArray ts_tree_array_remove_trailing_extras(TreeArray *);
void ts_tree_array_reverse(TreeArray *);
void ts_tree_pool_init(TreePool *);
void ts_tree_pool_delete(TreePool *);
Tree *ts_tree_pool_allocate(TreePool *);
void ts_tree_pool_free(TreePool *, Tree *);
Tree *ts_tree_make_leaf(TreePool *, TSSymbol, Length, Length, const TSLanguage *);
Tree *ts_tree_make_node(TreePool *, TSSymbol, TreeArray *, unsigned, const TSLanguage *);
Tree *ts_tree_make_copy(TreePool *, Tree *child);
Tree *ts_tree_make_error_node(TreePool *, TreeArray *, const TSLanguage *);
Tree *ts_tree_make_error(TreePool *, Length, Length, int32_t, const TSLanguage *);
Tree *ts_tree_make_missing_leaf(TreePool *, TSSymbol, const TSLanguage *);
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);
void ts_tree_set_children(Tree *, TreeArray *, const TSLanguage *);
void ts_tree_balance(Tree *, TreePool *, const TSLanguage *);
Tree *ts_tree_edit(Tree *, const TSInputEdit *edit, TreePool *);
char *ts_tree_string(const Tree *, const TSLanguage *, bool include_all);
void ts_tree_print_dot_graph(const Tree *, const TSLanguage *, FILE *);
Tree *ts_tree_last_external_token(Tree *);
bool ts_tree_external_token_state_eq(const Tree *, const Tree *);
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);
}
#ifdef __cplusplus
}
#endif
#endif // RUNTIME_TREE_H_

View file

@ -24,7 +24,7 @@ void ts_tree_cursor_delete(TSTreeCursor *self) {
bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
TreeCursorEntry *last_entry = array_back(&self->stack);
Tree *tree = last_entry->tree;
Subtree *tree = last_entry->tree;
Length position = last_entry->position;
bool did_descend;
@ -33,7 +33,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < tree->children.size; i++) {
Tree *child = tree->children.contents[i];
Subtree *child = tree->children.contents[i];
if (child->visible || child->visible_child_count > 0) {
array_push(&self->stack, ((TreeCursorEntry) {
.tree = child,
@ -51,7 +51,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
}
}
if (!child->extra) structural_child_index++;
position = length_add(position, ts_tree_total_size(child));
position = length_add(position, ts_subtree_total_size(child));
}
} while (did_descend);
@ -64,15 +64,15 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
TreeCursorEntry *parent_entry = &self->stack.contents[i];
Tree *parent = parent_entry->tree;
Subtree *parent = parent_entry->tree;
uint32_t child_index = child_entry->child_index;
uint32_t structural_child_index = child_entry->structural_child_index;
Length position = child_entry->position;
Tree *child = parent->children.contents[child_index];
Subtree *child = parent->children.contents[child_index];
while (++child_index < parent->children.size) {
if (!child->extra) structural_child_index++;
position = length_add(position, ts_tree_total_size(child));
position = length_add(position, ts_subtree_total_size(child));
child = parent->children.contents[child_index];
if (child->visible || child->visible_child_count > 0) {

View file

@ -1,10 +1,10 @@
#ifndef RUNTIME_TREE_CURSOR_H_
#define RUNTIME_TREE_CURSOR_H_
#include "runtime/tree.h"
#include "runtime/subtree.h"
typedef struct {
Tree *tree;
Subtree *tree;
Length position;
uint32_t child_index;
uint32_t structural_child_index;

View file

@ -14,21 +14,21 @@ const char *symbol_names[24] = {
"twenty-two", "twenty-three"
};
TreeArray *tree_array(std::vector<Tree *> trees) {
static TreeArray result;
SubtreeArray *tree_array(std::vector<Subtree *> trees) {
static SubtreeArray result;
result.capacity = trees.size();
result.size = trees.size();
result.contents = (Tree **)calloc(trees.size(), sizeof(Tree *));
result.contents = (Subtree **)calloc(trees.size(), sizeof(Subtree *));
for (size_t i = 0; i < trees.size(); i++) {
result.contents[i] = trees[i];
}
return &result;
}
ostream &operator<<(std::ostream &stream, const Tree *tree) {
ostream &operator<<(std::ostream &stream, const Subtree *tree) {
static TSLanguage DUMMY_LANGUAGE = {};
DUMMY_LANGUAGE.symbol_names = symbol_names;
char *string = ts_tree_string(tree, &DUMMY_LANGUAGE, false);
char *string = ts_subtree_string(tree, &DUMMY_LANGUAGE, false);
stream << string;
ts_free(string);
return stream;
@ -49,7 +49,7 @@ bool operator==(const TSNode &left, const TSNode &right) {
return ts_node_eq(left, right);
}
bool operator==(const std::vector<Tree *> &vec, const TreeArray &array) {
bool operator==(const std::vector<Subtree *> &vec, const SubtreeArray &array) {
if (vec.size() != array.size)
return false;
for (size_t i = 0; i < array.size; i++)

View file

@ -1,17 +1,17 @@
#ifndef HELPERS_TREE_HELPERS_H_
#define HELPERS_TREE_HELPERS_H_
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include <vector>
#include <string>
extern const char *symbol_names[24];
TreeArray *tree_array(std::vector<Tree *> trees);
SubtreeArray *tree_array(std::vector<Subtree *> trees);
std::ostream &operator<<(std::ostream &stream, const Tree *tree);
std::ostream &operator<<(std::ostream &stream, const Subtree *tree);
std::ostream &operator<<(std::ostream &stream, const TSNode &node);
bool operator==(const TSNode &left, const TSNode &right);
bool operator==(const std::vector<Tree *> &right, const TreeArray &array);
bool operator==(const std::vector<Subtree *> &right, const SubtreeArray &array);
void assert_consistent_tree_sizes(TSNode node);

View file

@ -4,7 +4,7 @@
#include "helpers/record_alloc.h"
#include "helpers/stream_methods.h"
#include "runtime/stack.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/length.h"
#include "runtime/alloc.h"
@ -23,23 +23,23 @@ Length operator*(const Length &length, uint32_t factor) {
return {length.bytes * factor, {0, length.extent.column * factor}};
}
void free_slice_array(TreePool *pool, StackSliceArray *slices) {
void free_slice_array(SubtreePool *pool, StackSliceArray *slices) {
for (size_t i = 0; i < slices->size; i++) {
StackSlice slice = slices->contents[i];
bool matches_prior_trees = false;
for (size_t j = 0; j < i; j++) {
StackSlice prior_slice = slices->contents[j];
if (slice.trees.contents == prior_slice.trees.contents) {
if (slice.subtrees.contents == prior_slice.subtrees.contents) {
matches_prior_trees = true;
break;
}
}
if (!matches_prior_trees) {
for (size_t j = 0; j < slice.trees.size; j++)
ts_tree_release(pool, slice.trees.contents[j]);
array_delete(&slice.trees);
for (size_t j = 0; j < slice.subtrees.size; j++)
ts_subtree_release(pool, slice.subtrees.contents[j]);
array_delete(&slice.subtrees);
}
}
}
@ -54,9 +54,9 @@ vector<StackEntry> get_stack_entries(Stack *stack, StackVersion version) {
ts_stack_iterate(
stack,
version,
[](void *payload, TSStateId state, uint32_t tree_count) {
[](void *payload, TSStateId state, uint32_t subtree_count) {
auto entries = static_cast<vector<StackEntry> *>(payload);
StackEntry entry = {state, tree_count};
StackEntry entry = {state, subtree_count};
if (find(entries->begin(), entries->end(), entry) == entries->end()) {
entries->push_back(entry);
}
@ -68,39 +68,39 @@ START_TEST
describe("Stack", [&]() {
Stack *stack;
const size_t tree_count = 11;
Tree *trees[tree_count];
const size_t subtree_count = 11;
Subtree *subtrees[subtree_count];
Length tree_len = {3, {0, 3}};
TreePool pool;
SubtreePool pool;
before_each([&]() {
record_alloc::start();
ts_tree_pool_init(&pool);
ts_subtree_pool_init(&pool);
stack = ts_stack_new(&pool);
TSLanguage dummy_language;
TSSymbolMetadata symbol_metadata[50] = {};
dummy_language.symbol_metadata = symbol_metadata;
for (size_t i = 0; i < tree_count; i++) {
trees[i] = ts_tree_make_leaf(&pool, i, length_zero(), tree_len, &dummy_language);
for (size_t i = 0; i < subtree_count; i++) {
subtrees[i] = ts_subtree_make_leaf(&pool, i, length_zero(), tree_len, &dummy_language);
}
});
after_each([&]() {
ts_stack_delete(stack);
for (size_t i = 0; i < tree_count; i++) {
ts_tree_release(&pool, trees[i]);
for (size_t i = 0; i < subtree_count; i++) {
ts_subtree_release(&pool, subtrees[i]);
}
ts_tree_pool_delete(&pool);
ts_subtree_pool_delete(&pool);
record_alloc::stop();
AssertThat(record_alloc::outstanding_allocation_indices(), IsEmpty());
});
auto push = [&](StackVersion version, Tree *tree, TSStateId state) {
ts_tree_retain(tree);
auto push = [&](StackVersion version, Subtree *tree, TSStateId state) {
ts_subtree_retain(tree);
ts_stack_push(stack, version, tree, false, state);
};
@ -111,17 +111,17 @@ describe("Stack", [&]() {
AssertThat(ts_stack_position(stack, 0), Equals(length_zero()));
// . <──0── A*
push(0, trees[0], stateA);
push(0, subtrees[0], stateA);
AssertThat(ts_stack_state(stack, 0), Equals(stateA));
AssertThat(ts_stack_position(stack, 0), Equals(tree_len));
// . <──0── A <──1── B*
push(0, trees[1], stateB);
push(0, subtrees[1], stateB);
AssertThat(ts_stack_state(stack, 0), Equals(stateB));
AssertThat(ts_stack_position(stack, 0), Equals(tree_len * 2));
// . <──0── A <──1── B <──2── C*
push(0, trees[2], stateC);
push(0, subtrees[2], stateC);
AssertThat(ts_stack_state(stack, 0), Equals(stateC));
AssertThat(ts_stack_position(stack, 0), Equals(tree_len * 3));
@ -139,7 +139,7 @@ describe("Stack", [&]() {
// . <──0── A <─*
// ↑
// └───*
push(0, trees[0], stateA);
push(0, subtrees[0], stateA);
ts_stack_copy_version(stack, 0);
});
@ -147,10 +147,10 @@ describe("Stack", [&]() {
// . <──0── A <──1── B <──3── D*
// ↑
// └───2─── C <──4── D*
push(0, trees[1], stateB);
push(1, trees[2], stateC);
push(0, trees[3], stateD);
push(1, trees[4], stateD);
push(0, subtrees[1], stateB);
push(1, subtrees[2], stateC);
push(0, subtrees[3], stateD);
push(1, subtrees[4], stateD);
// . <──0── A <──1── B <──3── D*
// ↑ |
@ -170,8 +170,8 @@ describe("Stack", [&]() {
// . <──0── A <──1── B*
// ↑
// └───2─── C*
push(0, trees[1], stateB);
push(1, trees[2], stateC);
push(0, subtrees[1], stateB);
push(1, subtrees[2], stateC);
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
@ -181,11 +181,11 @@ describe("Stack", [&]() {
// . <──0── A <──1── B <────3──── D*
// ↑
// └───2─── C <──4── D*
trees[3]->size = tree_len * 3;
push(0, trees[1], stateB);
push(1, trees[2], stateC);
push(0, trees[3], stateD);
push(1, trees[4], stateD);
subtrees[3]->size = tree_len * 3;
push(0, subtrees[1], stateB);
push(1, subtrees[2], stateC);
push(0, subtrees[3], stateD);
push(1, subtrees[4], stateD);
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
@ -196,12 +196,12 @@ describe("Stack", [&]() {
// . <──0── A <──1── B <──3── D <──5── E*
// ↑
// └───2─── C <──4── D <──5── E*
push(0, trees[1], stateB);
push(1, trees[2], stateC);
push(0, trees[3], stateD);
push(1, trees[4], stateD);
push(0, trees[5], stateE);
push(1, trees[5], stateE);
push(0, subtrees[1], stateB);
push(1, subtrees[2], stateC);
push(0, subtrees[3], stateD);
push(1, subtrees[4], stateD);
push(0, subtrees[5], stateE);
push(1, subtrees[5], stateE);
// . <──0── A <──1── B <──3── D <──5── E*
// ↑ |
@ -224,12 +224,12 @@ describe("Stack", [&]() {
// . <──0── A <────1──── B*
// ↑
// └2─ A <──1── B*
trees[2]->extra = true;
trees[2]->size = tree_len * 0;
subtrees[2]->extra = true;
subtrees[2]->size = tree_len * 0;
push(0, trees[1], stateB);
push(1, trees[2], stateA);
push(1, trees[1], stateB);
push(0, subtrees[1], stateB);
push(1, subtrees[2], stateA);
push(1, subtrees[1], stateB);
// . <──0── A <──1── B*
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
@ -246,9 +246,9 @@ describe("Stack", [&]() {
describe("pop_count(version, count)", [&]() {
before_each([&]() {
// . <──0── A <──1── B <──2── C*
push(0, trees[0], stateA);
push(0, trees[1], stateB);
push(0, trees[2], stateC);
push(0, subtrees[0], stateA);
push(0, subtrees[1], stateB);
push(0, subtrees[2], stateC);
});
it("creates a new version with the given number of entries removed", [&]() {
@ -261,14 +261,14 @@ describe("Stack", [&]() {
StackSlice slice = pop.contents[0];
AssertThat(slice.version, Equals<StackVersion>(1));
AssertThat(slice.trees, Equals(vector<Tree *>({ trees[1], trees[2] })));
AssertThat(slice.subtrees, Equals(vector<Subtree *>({ subtrees[1], subtrees[2] })));
AssertThat(ts_stack_state(stack, 1), Equals(stateA));
free_slice_array(&pool,&pop);
});
it("does not count 'extra' trees toward the given count", [&]() {
trees[1]->extra = true;
it("does not count 'extra' subtrees toward the given count", [&]() {
subtrees[1]->extra = true;
// . <──0── A <──1── B <──2── C*
// ↑
@ -277,7 +277,7 @@ describe("Stack", [&]() {
AssertThat(pop.size, Equals<size_t>(1));
StackSlice slice = pop.contents[0];
AssertThat(slice.trees, Equals(vector<Tree *>({ trees[0], trees[1], trees[2] })));
AssertThat(slice.subtrees, Equals(vector<Subtree *>({ subtrees[0], subtrees[1], subtrees[2] })));
AssertThat(ts_stack_state(stack, 1), Equals(1));
free_slice_array(&pool,&pop);
@ -288,14 +288,14 @@ describe("Stack", [&]() {
// . <──0── A <──1── B <──2── C <──3── D <──10── I*
// ↑ |
// └───4─── E <──5── F <──6───┘
push(0, trees[3], stateD);
push(0, subtrees[3], stateD);
StackSliceArray pop = ts_stack_pop_count(stack, 0, 3);
free_slice_array(&pool,&pop);
push(1, trees[4], stateE);
push(1, trees[5], stateF);
push(1, trees[6], stateD);
push(1, subtrees[4], stateE);
push(1, subtrees[5], stateF);
push(1, subtrees[6], stateD);
ts_stack_merge(stack, 0, 1);
push(0, trees[10], stateI);
push(0, subtrees[10], stateI);
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
@ -322,11 +322,11 @@ describe("Stack", [&]() {
StackSlice slice1 = pop.contents[0];
AssertThat(slice1.version, Equals<StackVersion>(1));
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[2], trees[3], trees[10] })));
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[2], subtrees[3], subtrees[10] })));
StackSlice slice2 = pop.contents[1];
AssertThat(slice2.version, Equals<StackVersion>(2));
AssertThat(slice2.trees, Equals(vector<Tree *>({ trees[5], trees[6], trees[10] })));
AssertThat(slice2.subtrees, Equals(vector<Subtree *>({ subtrees[5], subtrees[6], subtrees[10] })));
AssertThat(ts_stack_version_count(stack), Equals<size_t>(3));
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
@ -366,7 +366,7 @@ describe("Stack", [&]() {
StackSlice slice1 = pop.contents[0];
AssertThat(slice1.version, Equals<StackVersion>(1));
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[10] })));
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[10] })));
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
AssertThat(ts_stack_state(stack, 0), Equals(stateI));
@ -388,11 +388,11 @@ describe("Stack", [&]() {
StackSlice slice1 = pop.contents[0];
AssertThat(slice1.version, Equals<StackVersion>(1));
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[1], trees[2], trees[3], trees[10] })));
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[1], subtrees[2], subtrees[3], subtrees[10] })));
StackSlice slice2 = pop.contents[1];
AssertThat(slice2.version, Equals<StackVersion>(1));
AssertThat(slice2.trees, Equals(vector<Tree *>({ trees[4], trees[5], trees[6], trees[10] })));
AssertThat(slice2.subtrees, Equals(vector<Subtree *>({ subtrees[4], subtrees[5], subtrees[6], subtrees[10] })));
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
AssertThat(ts_stack_state(stack, 0), Equals(stateI));
@ -403,7 +403,7 @@ describe("Stack", [&]() {
});
describe("when there are three paths that lead to three different versions", [&]() {
it("returns three entries with different arrays of trees", [&]() {
it("returns three entries with different arrays of subtrees", [&]() {
// . <──0── A <──1── B <──2── C <──3── D <──10── I*
// ↑ |
// ├───4─── E <──5── F <──6───┘
@ -411,10 +411,10 @@ describe("Stack", [&]() {
// └───7─── G <──8── H <──9───┘
StackSliceArray pop = ts_stack_pop_count(stack, 0, 4);
free_slice_array(&pool,&pop);
push(1, trees[7], stateG);
push(1, trees[8], stateH);
push(1, trees[9], stateD);
push(1, trees[10], stateI);
push(1, subtrees[7], stateG);
push(1, subtrees[8], stateH);
push(1, subtrees[9], stateD);
push(1, subtrees[10], stateI);
ts_stack_merge(stack, 0, 1);
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
@ -443,15 +443,15 @@ describe("Stack", [&]() {
StackSlice slice1 = pop.contents[0];
AssertThat(slice1.version, Equals<StackVersion>(1));
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[3], trees[10] })));
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[3], subtrees[10] })));
StackSlice slice2 = pop.contents[1];
AssertThat(slice2.version, Equals<StackVersion>(2));
AssertThat(slice2.trees, Equals(vector<Tree *>({ trees[6], trees[10] })));
AssertThat(slice2.subtrees, Equals(vector<Subtree *>({ subtrees[6], subtrees[10] })));
StackSlice slice3 = pop.contents[2];
AssertThat(slice3.version, Equals<StackVersion>(3));
AssertThat(slice3.trees, Equals(vector<Tree *>({ trees[9], trees[10] })));
AssertThat(slice3.subtrees, Equals(vector<Subtree *>({ subtrees[9], subtrees[10] })));
AssertThat(ts_stack_version_count(stack), Equals<size_t>(4));
AssertThat(ts_stack_state(stack, 0), Equals(stateI));
@ -467,12 +467,12 @@ describe("Stack", [&]() {
describe("pop_pending(version)", [&]() {
before_each([&]() {
push(0, trees[0], stateA);
push(0, subtrees[0], stateA);
});
it("removes the top node from the stack if it was pushed in pending mode", [&]() {
ts_stack_push(stack, 0, trees[1], true, stateB);
ts_tree_retain(trees[1]);
ts_stack_push(stack, 0, subtrees[1], true, stateB);
ts_subtree_retain(subtrees[1]);
StackSliceArray pop = ts_stack_pop_pending(stack, 0);
AssertThat(pop.size, Equals<size_t>(1));
@ -485,20 +485,20 @@ describe("Stack", [&]() {
free_slice_array(&pool,&pop);
});
it("skips entries whose trees are extra", [&]() {
ts_stack_push(stack, 0, trees[1], true, stateB);
ts_tree_retain(trees[1]);
it("skips entries whose subtrees are extra", [&]() {
ts_stack_push(stack, 0, subtrees[1], true, stateB);
ts_subtree_retain(subtrees[1]);
trees[2]->extra = true;
trees[3]->extra = true;
subtrees[2]->extra = true;
subtrees[3]->extra = true;
push(0, trees[2], stateB);
push(0, trees[3], stateB);
push(0, subtrees[2], stateB);
push(0, subtrees[3], stateB);
StackSliceArray pop = ts_stack_pop_pending(stack, 0);
AssertThat(pop.size, Equals<size_t>(1));
AssertThat(pop.contents[0].trees, Equals(vector<Tree *>({ trees[1], trees[2], trees[3] })));
AssertThat(pop.contents[0].subtrees, Equals(vector<Subtree *>({ subtrees[1], subtrees[2], subtrees[3] })));
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
{stateA, 0},
@ -509,7 +509,7 @@ describe("Stack", [&]() {
});
it("does nothing if the top node was not pushed in pending mode", [&]() {
push(0, trees[1], stateB);
push(0, subtrees[1], stateB);
StackSliceArray pop = ts_stack_pop_pending(stack, 0);
AssertThat(pop.size, Equals<size_t>(0));
@ -526,59 +526,59 @@ describe("Stack", [&]() {
describe("setting external token state", [&]() {
before_each([&]() {
trees[1]->has_external_tokens = true;
trees[2]->has_external_tokens = true;
ts_external_token_state_init(&trees[1]->external_token_state, NULL, 0);
ts_external_token_state_init(&trees[2]->external_token_state, NULL, 0);
subtrees[1]->has_external_tokens = true;
subtrees[2]->has_external_tokens = true;
ts_external_token_state_init(&subtrees[1]->external_token_state, NULL, 0);
ts_external_token_state_init(&subtrees[2]->external_token_state, NULL, 0);
});
it("allows the state to be retrieved", [&]() {
AssertThat(ts_stack_last_external_token(stack, 0), Equals<Tree *>(nullptr));
AssertThat(ts_stack_last_external_token(stack, 0), Equals<Subtree *>(nullptr));
ts_stack_set_last_external_token(stack, 0, trees[1]);
AssertThat(ts_stack_last_external_token(stack, 0), Equals(trees[1]));
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
AssertThat(ts_stack_last_external_token(stack, 0), Equals(subtrees[1]));
ts_stack_copy_version(stack, 0);
AssertThat(ts_stack_last_external_token(stack, 1), Equals(trees[1]));
AssertThat(ts_stack_last_external_token(stack, 1), Equals(subtrees[1]));
ts_stack_set_last_external_token(stack, 0, trees[2]);
AssertThat(ts_stack_last_external_token(stack, 0), Equals(trees[2]));
ts_stack_set_last_external_token(stack, 0, subtrees[2]);
AssertThat(ts_stack_last_external_token(stack, 0), Equals(subtrees[2]));
});
it("does not merge stack versions with different external token states", [&]() {
ts_external_token_state_init(&trees[1]->external_token_state, "abcd", 2);
ts_external_token_state_init(&trees[2]->external_token_state, "ABCD", 2);
ts_external_token_state_init(&subtrees[1]->external_token_state, "abcd", 2);
ts_external_token_state_init(&subtrees[2]->external_token_state, "ABCD", 2);
ts_stack_copy_version(stack, 0);
push(0, trees[0], 5);
push(1, trees[0], 5);
push(0, subtrees[0], 5);
push(1, subtrees[0], 5);
ts_stack_set_last_external_token(stack, 0, trees[1]);
ts_stack_set_last_external_token(stack, 1, trees[2]);
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
ts_stack_set_last_external_token(stack, 1, subtrees[2]);
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
});
it("merges stack versions with identical external token states", [&]() {
ts_external_token_state_init(&trees[1]->external_token_state, "abcd", 2);
ts_external_token_state_init(&trees[2]->external_token_state, "abcd", 2);
ts_external_token_state_init(&subtrees[1]->external_token_state, "abcd", 2);
ts_external_token_state_init(&subtrees[2]->external_token_state, "abcd", 2);
ts_stack_copy_version(stack, 0);
push(0, trees[0], 5);
push(1, trees[0], 5);
push(0, subtrees[0], 5);
push(1, subtrees[0], 5);
ts_stack_set_last_external_token(stack, 0, trees[1]);
ts_stack_set_last_external_token(stack, 1, trees[2]);
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
ts_stack_set_last_external_token(stack, 1, subtrees[2]);
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
});
it("does not distinguish between an *empty* external token state and *no* external token state", [&]() {
ts_stack_copy_version(stack, 0);
push(0, trees[0], 5);
push(1, trees[0], 5);
push(0, subtrees[0], 5);
push(1, subtrees[0], 5);
ts_stack_set_last_external_token(stack, 0, trees[1]);
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
});
@ -595,7 +595,7 @@ std::ostream &operator<<(std::ostream &stream, const StackEntry &entry) {
return stream << "{" << entry.state << ", " << entry.depth << "}";
}
std::ostream &operator<<(std::ostream &stream, const TreeArray &array) {
std::ostream &operator<<(std::ostream &stream, const SubtreeArray &array) {
stream << "[";
bool first = true;
for (size_t i = 0; i < array.size; i++) {

View file

@ -1,26 +1,26 @@
#include "test_helper.h"
#include "helpers/tree_helpers.h"
#include "helpers/point_helpers.h"
#include "runtime/tree.h"
#include "runtime/subtree.h"
#include "runtime/length.h"
void assert_consistent(const Tree *tree) {
void assert_consistent(const Subtree *tree) {
if (tree->child_count == 0) return;
AssertThat(tree->children.contents[0]->padding, Equals<Length>(tree->padding));
Length total_children_size = length_zero();
for (size_t i = 0; i < tree->children.size; i++) {
Tree *child = tree->children.contents[i];
Subtree *child = tree->children.contents[i];
assert_consistent(child);
total_children_size = length_add(total_children_size, ts_tree_total_size(child));
total_children_size = length_add(total_children_size, ts_subtree_total_size(child));
}
AssertThat(total_children_size, Equals<Length>(ts_tree_total_size(tree)));
AssertThat(total_children_size, Equals<Length>(ts_subtree_total_size(tree)));
};
START_TEST
describe("Tree", []() {
describe("Subtree", []() {
enum {
symbol1 = 1,
symbol2,
@ -38,29 +38,29 @@ describe("Tree", []() {
TSLanguage language;
language.symbol_metadata = metadata_list;
TreePool pool;
SubtreePool pool;
before_each([&]() {
ts_tree_pool_init(&pool);
ts_subtree_pool_init(&pool);
});
after_each([&]() {
ts_tree_pool_delete(&pool);
ts_subtree_pool_delete(&pool);
});
describe("make_leaf", [&]() {
it("does not mark the tree as fragile", [&]() {
Tree *tree = ts_tree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
Subtree *tree = ts_subtree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
AssertThat(tree->fragile_left, IsFalse());
AssertThat(tree->fragile_right, IsFalse());
ts_tree_release(&pool, tree);
ts_subtree_release(&pool, tree);
});
});
describe("make_error", [&]() {
it("marks the tree as fragile", [&]() {
Tree *error_tree = ts_tree_make_error(
Subtree *error_tree = ts_subtree_make_error(
&pool,
length_zero(),
length_zero(),
@ -71,29 +71,29 @@ describe("Tree", []() {
AssertThat(error_tree->fragile_left, IsTrue());
AssertThat(error_tree->fragile_right, IsTrue());
ts_tree_release(&pool, error_tree);
ts_subtree_release(&pool, error_tree);
});
});
describe("make_node", [&]() {
Tree *tree1, *tree2, *parent1;
Subtree *tree1, *tree2, *parent1;
before_each([&]() {
tree1 = ts_tree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
tree2 = ts_tree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
tree1 = ts_subtree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
tree2 = ts_subtree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
ts_tree_retain(tree1);
ts_tree_retain(tree2);
parent1 = ts_tree_make_node(&pool, symbol3, tree_array({
ts_subtree_retain(tree1);
ts_subtree_retain(tree2);
parent1 = ts_subtree_make_node(&pool, symbol3, tree_array({
tree1,
tree2,
}), 0, &language);
});
after_each([&]() {
ts_tree_release(&pool, tree1);
ts_tree_release(&pool, tree2);
ts_tree_release(&pool, parent1);
ts_subtree_release(&pool, tree1);
ts_subtree_release(&pool, tree2);
ts_subtree_release(&pool, parent1);
});
it("computes its size and padding based on its child nodes", [&]() {
@ -104,22 +104,22 @@ describe("Tree", []() {
});
describe("when the first node is fragile on the left side", [&]() {
Tree *parent;
Subtree *parent;
before_each([&]() {
tree1->fragile_left = true;
tree1->extra = true;
ts_tree_retain(tree1);
ts_tree_retain(tree2);
parent = ts_tree_make_node(&pool, symbol3, tree_array({
ts_subtree_retain(tree1);
ts_subtree_retain(tree2);
parent = ts_subtree_make_node(&pool, symbol3, tree_array({
tree1,
tree2,
}), 0, &language);
});
after_each([&]() {
ts_tree_release(&pool, parent);
ts_subtree_release(&pool, parent);
});
it("records that it is fragile on the left side", [&]() {
@ -128,22 +128,22 @@ describe("Tree", []() {
});
describe("when the last node is fragile on the right side", [&]() {
Tree *parent;
Subtree *parent;
before_each([&]() {
tree2->fragile_right = true;
tree2->extra = true;
ts_tree_retain(tree1);
ts_tree_retain(tree2);
parent = ts_tree_make_node(&pool, symbol3, tree_array({
ts_subtree_retain(tree1);
ts_subtree_retain(tree2);
parent = ts_subtree_make_node(&pool, symbol3, tree_array({
tree1,
tree2,
}), 0, &language);
});
after_each([&]() {
ts_tree_release(&pool, parent);
ts_subtree_release(&pool, parent);
});
it("records that it is fragile on the right side", [&]() {
@ -152,22 +152,22 @@ describe("Tree", []() {
});
describe("when the outer nodes aren't fragile on their outer side", [&]() {
Tree *parent;
Subtree *parent;
before_each([&]() {
tree1->fragile_right = true;
tree2->fragile_left = true;
ts_tree_retain(tree1);
ts_tree_retain(tree2);
parent = ts_tree_make_node(&pool, symbol3, tree_array({
ts_subtree_retain(tree1);
ts_subtree_retain(tree2);
parent = ts_subtree_make_node(&pool, symbol3, tree_array({
tree1,
tree2,
}), 0, &language);
});
after_each([&]() {
ts_tree_release(&pool, parent);
ts_subtree_release(&pool, parent);
});
it("records that it is not fragile", [&]() {
@ -178,13 +178,13 @@ describe("Tree", []() {
});
describe("edit", [&]() {
Tree *tree;
Subtree *tree;
before_each([&]() {
tree = ts_tree_make_node(&pool, symbol1, tree_array({
ts_tree_make_leaf(&pool, symbol2, {2, {0, 2}}, {3, {0, 3}}, &language),
ts_tree_make_leaf(&pool, symbol3, {2, {0, 2}}, {3, {0, 3}}, &language),
ts_tree_make_leaf(&pool, symbol4, {2, {0, 2}}, {3, {0, 3}}, &language),
tree = ts_subtree_make_node(&pool, symbol1, tree_array({
ts_subtree_make_leaf(&pool, symbol2, {2, {0, 2}}, {3, {0, 3}}, &language),
ts_subtree_make_leaf(&pool, symbol3, {2, {0, 2}}, {3, {0, 3}}, &language),
ts_subtree_make_leaf(&pool, symbol4, {2, {0, 2}}, {3, {0, 3}}, &language),
}), 0, &language);
AssertThat(tree->padding, Equals<Length>({2, {0, 2}}));
@ -192,7 +192,7 @@ describe("Tree", []() {
});
after_each([&]() {
ts_tree_release(&pool, tree);
ts_subtree_release(&pool, tree);
});
it("does not mutate the argument", [&]() {
@ -204,8 +204,8 @@ describe("Tree", []() {
edit.extent_removed = {0, 0};
edit.extent_added = {0, 1};
ts_tree_retain(tree);
Tree *new_tree = ts_tree_edit(tree, &edit, &pool);
ts_subtree_retain(tree);
Subtree *new_tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
assert_consistent(new_tree);
@ -221,7 +221,7 @@ describe("Tree", []() {
AssertThat(tree->children.contents[1]->padding, Equals<Length>({2, {0, 2}}));
AssertThat(tree->children.contents[1]->size, Equals<Length>({3, {0, 3}}));
ts_tree_release(&pool, new_tree);
ts_subtree_release(&pool, new_tree);
});
describe("edits within a tree's padding", [&]() {
@ -233,7 +233,7 @@ describe("Tree", []() {
edit.start_point = {0, 1};
edit.extent_removed = {0, 0};
edit.extent_added = {0, 1};
tree = ts_tree_edit(tree, &edit, &pool);
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
AssertThat(tree->has_changes, IsTrue());
@ -259,7 +259,7 @@ describe("Tree", []() {
edit.start_point = {0, 1};
edit.extent_removed = {0, 3};
edit.extent_added = {0, 4};
tree = ts_tree_edit(tree, &edit, &pool);
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
AssertThat(tree->has_changes, IsTrue());
@ -281,7 +281,7 @@ describe("Tree", []() {
edit.start_point = {0, 2};
edit.extent_removed = {0, 0};
edit.extent_added = {0, 2};
tree = ts_tree_edit(tree, &edit, &pool);
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
AssertThat(tree->has_changes, IsTrue());
@ -305,7 +305,7 @@ describe("Tree", []() {
edit.start_point = {0, 2};
edit.extent_removed = {0, 2};
edit.extent_added = {0, 5};
tree = ts_tree_edit(tree, &edit, &pool);
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
AssertThat(tree->has_changes, IsTrue());
@ -329,7 +329,7 @@ describe("Tree", []() {
edit.start_point = {0, 1};
edit.extent_removed = {0, 10};
edit.extent_added = {0, 3};
tree = ts_tree_edit(tree, &edit, &pool);
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
AssertThat(tree->has_changes, IsTrue());
@ -361,7 +361,7 @@ describe("Tree", []() {
edit.start_point = {0, 6};
edit.extent_removed = {0, 1};
edit.extent_added = {0, 1};
tree = ts_tree_edit(tree, &edit, &pool);
tree = ts_subtree_edit(tree, &edit, &pool);
assert_consistent(tree);
AssertThat(tree->children.contents[0]->has_changes, IsTrue());
@ -370,43 +370,43 @@ describe("Tree", []() {
});
describe("eq", [&]() {
Tree *leaf;
Subtree *leaf;
before_each([&]() {
leaf = ts_tree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
leaf = ts_subtree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
});
after_each([&]() {
ts_tree_release(&pool, leaf);
ts_subtree_release(&pool, leaf);
});
it("returns true for identical trees", [&]() {
Tree *leaf_copy = ts_tree_make_leaf(&pool, symbol1, {2, {1, 1}}, {5, {1, 4}}, &language);
AssertThat(ts_tree_eq(leaf, leaf_copy), IsTrue());
Subtree *leaf_copy = ts_subtree_make_leaf(&pool, symbol1, {2, {1, 1}}, {5, {1, 4}}, &language);
AssertThat(ts_subtree_eq(leaf, leaf_copy), IsTrue());
Tree *parent = ts_tree_make_node(&pool, symbol2, tree_array({
Subtree *parent = ts_subtree_make_node(&pool, symbol2, tree_array({
leaf,
leaf_copy,
}), 0, &language);
ts_tree_retain(leaf);
ts_tree_retain(leaf_copy);
ts_subtree_retain(leaf);
ts_subtree_retain(leaf_copy);
Tree *parent_copy = ts_tree_make_node(&pool, symbol2, tree_array({
Subtree *parent_copy = ts_subtree_make_node(&pool, symbol2, tree_array({
leaf,
leaf_copy,
}), 0, &language);
ts_tree_retain(leaf);
ts_tree_retain(leaf_copy);
ts_subtree_retain(leaf);
ts_subtree_retain(leaf_copy);
AssertThat(ts_tree_eq(parent, parent_copy), IsTrue());
AssertThat(ts_subtree_eq(parent, parent_copy), IsTrue());
ts_tree_release(&pool, leaf_copy);
ts_tree_release(&pool, parent);
ts_tree_release(&pool, parent_copy);
ts_subtree_release(&pool, leaf_copy);
ts_subtree_release(&pool, parent);
ts_subtree_release(&pool, parent_copy);
});
it("returns false for trees with different symbols", [&]() {
Tree *different_leaf = ts_tree_make_leaf(
Subtree *different_leaf = ts_subtree_make_leaf(
&pool,
leaf->symbol + 1,
leaf->padding,
@ -414,50 +414,50 @@ describe("Tree", []() {
&language
);
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
ts_tree_release(&pool, different_leaf);
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
ts_subtree_release(&pool, different_leaf);
});
it("returns false for trees with different options", [&]() {
Tree *different_leaf = ts_tree_make_leaf(&pool, leaf->symbol, leaf->padding, leaf->size, &language);
Subtree *different_leaf = ts_subtree_make_leaf(&pool, leaf->symbol, leaf->padding, leaf->size, &language);
different_leaf->visible = !leaf->visible;
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
ts_tree_release(&pool, different_leaf);
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
ts_subtree_release(&pool, different_leaf);
});
it("returns false for trees with different paddings or sizes", [&]() {
Tree *different_leaf = ts_tree_make_leaf(&pool, leaf->symbol, {}, leaf->size, &language);
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
ts_tree_release(&pool, different_leaf);
Subtree *different_leaf = ts_subtree_make_leaf(&pool, leaf->symbol, {}, leaf->size, &language);
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
ts_subtree_release(&pool, different_leaf);
different_leaf = ts_tree_make_leaf(&pool, symbol1, leaf->padding, {}, &language);
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
ts_tree_release(&pool, different_leaf);
different_leaf = ts_subtree_make_leaf(&pool, symbol1, leaf->padding, {}, &language);
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
ts_subtree_release(&pool, different_leaf);
});
it("returns false for trees with different children", [&]() {
Tree *leaf2 = ts_tree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
Subtree *leaf2 = ts_subtree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
Tree *parent = ts_tree_make_node(&pool, symbol2, tree_array({
Subtree *parent = ts_subtree_make_node(&pool, symbol2, tree_array({
leaf,
leaf2,
}), 0, &language);
ts_tree_retain(leaf);
ts_tree_retain(leaf2);
ts_subtree_retain(leaf);
ts_subtree_retain(leaf2);
Tree *different_parent = ts_tree_make_node(&pool, symbol2, tree_array({
Subtree *different_parent = ts_subtree_make_node(&pool, symbol2, tree_array({
leaf2,
leaf,
}), 0, &language);
ts_tree_retain(leaf2);
ts_tree_retain(leaf);
ts_subtree_retain(leaf2);
ts_subtree_retain(leaf);
AssertThat(ts_tree_eq(different_parent, parent), IsFalse());
AssertThat(ts_tree_eq(parent, different_parent), IsFalse());
AssertThat(ts_subtree_eq(different_parent, parent), IsFalse());
AssertThat(ts_subtree_eq(parent, different_parent), IsFalse());
ts_tree_release(&pool, leaf2);
ts_tree_release(&pool, parent);
ts_tree_release(&pool, different_parent);
ts_subtree_release(&pool, leaf2);
ts_subtree_release(&pool, parent);
ts_subtree_release(&pool, different_parent);
});
});
@ -465,32 +465,32 @@ describe("Tree", []() {
Length padding = {1, {0, 1}};
Length size = {2, {0, 2}};
auto make_external = [](Tree *tree) {
auto make_external = [](Subtree *tree) {
tree->has_external_tokens = true;
return tree;
};
it("returns the last serialized external token state in the given tree", [&]() {
Tree *tree1, *tree2, *tree3, *tree4, *tree5, *tree6, *tree7, *tree8, *tree9;
Subtree *tree1, *tree2, *tree3, *tree4, *tree5, *tree6, *tree7, *tree8, *tree9;
tree1 = ts_tree_make_node(&pool, symbol1, tree_array({
(tree2 = ts_tree_make_node(&pool, symbol2, tree_array({
(tree3 = make_external(ts_tree_make_leaf(&pool, symbol3, padding, size, &language))),
(tree4 = ts_tree_make_leaf(&pool, symbol4, padding, size, &language)),
(tree5 = ts_tree_make_leaf(&pool, symbol5, padding, size, &language)),
tree1 = ts_subtree_make_node(&pool, symbol1, tree_array({
(tree2 = ts_subtree_make_node(&pool, symbol2, tree_array({
(tree3 = make_external(ts_subtree_make_leaf(&pool, symbol3, padding, size, &language))),
(tree4 = ts_subtree_make_leaf(&pool, symbol4, padding, size, &language)),
(tree5 = ts_subtree_make_leaf(&pool, symbol5, padding, size, &language)),
}), 0, &language)),
(tree6 = ts_tree_make_node(&pool, symbol6, tree_array({
(tree7 = ts_tree_make_node(&pool, symbol7, tree_array({
(tree8 = ts_tree_make_leaf(&pool, symbol8, padding, size, &language)),
(tree6 = ts_subtree_make_node(&pool, symbol6, tree_array({
(tree7 = ts_subtree_make_node(&pool, symbol7, tree_array({
(tree8 = ts_subtree_make_leaf(&pool, symbol8, padding, size, &language)),
}), 0, &language)),
(tree9 = ts_tree_make_leaf(&pool, symbol9, padding, size, &language)),
(tree9 = ts_subtree_make_leaf(&pool, symbol9, padding, size, &language)),
}), 0, &language)),
}), 0, &language);
auto token = ts_tree_last_external_token(tree1);
auto token = ts_subtree_last_external_token(tree1);
AssertThat(token, Equals(tree3));
ts_tree_release(&pool, tree1);
ts_subtree_release(&pool, tree1);
});
});
});

View file

@ -71,7 +71,7 @@
'test/runtime/node_test.cc',
'test/runtime/parser_test.cc',
'test/runtime/stack_test.cc',
'test/runtime/tree_test.cc',
'test/runtime/subtree_test.cc',
'test/tests.cc',
],
'cflags': [