Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Amaan Qureshi
1a99bfd9ff
wow 2024-09-26 17:51:46 -04:00
6 changed files with 891 additions and 710 deletions

View file

@ -272,6 +272,7 @@ static inline void ts_language_write_symbol_as_dot_string(
TSSymbol symbol TSSymbol symbol
) { ) {
const char *name = ts_language_symbol_name(self, symbol); const char *name = ts_language_symbol_name(self, symbol);
printf("name: %s\n", name);
for (const char *chr = name; *chr; chr++) { for (const char *chr = name; *chr; chr++) {
switch (*chr) { switch (*chr) {
case '"': case '"':

View file

@ -206,12 +206,18 @@ static bool ts_parser__breakdown_top_of_stack(
} }
ts_subtree_retain(child); ts_subtree_retain(child);
ts_stack_push(self->stack, slice.version, child, pending, state); ts_stack_push(self->stack, slice.version, child, pending, state, self->language);
LOG("push 1");
printf("push 1\n");
LOG_STACK();
} }
for (uint32_t j = 1; j < slice.subtrees.size; j++) { for (uint32_t j = 1; j < slice.subtrees.size; j++) {
Subtree tree = slice.subtrees.contents[j]; Subtree tree = slice.subtrees.contents[j];
ts_stack_push(self->stack, slice.version, tree, false, state); ts_stack_push(self->stack, slice.version, tree, false, state, self->language);
LOG("push 2");
printf("push 2\n");
LOG_STACK();
} }
ts_subtree_release(&self->tree_pool, parent); ts_subtree_release(&self->tree_pool, parent);
@ -913,7 +919,10 @@ static void ts_parser__shift(
subtree_to_push = ts_subtree_from_mut(result); subtree_to_push = ts_subtree_from_mut(result);
} }
ts_stack_push(self->stack, version, subtree_to_push, !is_leaf, state); ts_stack_push(self->stack, version, subtree_to_push, !is_leaf, state, self->language);
LOG("push 3");
printf("push 3\n");
LOG_STACK();
if (ts_subtree_has_external_tokens(subtree_to_push)) { if (ts_subtree_has_external_tokens(subtree_to_push)) {
ts_stack_set_last_external_token( ts_stack_set_last_external_token(
self->stack, version, ts_subtree_last_external_token(subtree_to_push) self->stack, version, ts_subtree_last_external_token(subtree_to_push)
@ -1016,9 +1025,15 @@ static StackVersion ts_parser__reduce(
// Push the parent node onto the stack, along with any extra tokens that // Push the parent node onto the stack, along with any extra tokens that
// were previously on top of the stack. // were previously on top of the stack.
ts_stack_push(self->stack, slice_version, ts_subtree_from_mut(parent), false, next_state); ts_stack_push(self->stack, slice_version, ts_subtree_from_mut(parent), false, next_state, self->language);
LOG("push 4");
printf("push 4\n");
LOG_STACK();
for (uint32_t j = 0; j < self->trailing_extras.size; j++) { for (uint32_t j = 0; j < self->trailing_extras.size; j++) {
ts_stack_push(self->stack, slice_version, self->trailing_extras.contents[j], false, next_state); ts_stack_push(self->stack, slice_version, self->trailing_extras.contents[j], false, next_state, self->language);
LOG("push 5");
printf("push 5\n");
LOG_STACK();
} }
for (StackVersion j = 0; j < slice_version; j++) { for (StackVersion j = 0; j < slice_version; j++) {
@ -1042,9 +1057,15 @@ static void ts_parser__accept(
Subtree lookahead Subtree lookahead
) { ) {
assert(ts_subtree_is_eof(lookahead)); assert(ts_subtree_is_eof(lookahead));
ts_stack_push(self->stack, version, lookahead, false, 1); ts_stack_push(self->stack, version, lookahead, false, 1, self->language);
LOG("push 6");
printf("push 6\n");
LOG_STACK();
StackSliceArray pop = ts_stack_pop_all(self->stack, version); LOG("POP ALL")
printf("POP ALL\n");
StackSliceArray pop = ts_stack_pop_all(self->stack, version, self->dot_graph_file);
LOG_STACK();
for (uint32_t i = 0; i < pop.size; i++) { for (uint32_t i = 0; i < pop.size; i++) {
SubtreeArray trees = pop.contents[i].subtrees; SubtreeArray trees = pop.contents[i].subtrees;
@ -1222,14 +1243,20 @@ static bool ts_parser__recover_to_state(
if (slice.subtrees.size > 0) { if (slice.subtrees.size > 0) {
Subtree error = ts_subtree_new_error_node(&slice.subtrees, true, self->language); Subtree error = ts_subtree_new_error_node(&slice.subtrees, true, self->language);
ts_stack_push(self->stack, slice.version, error, false, goal_state); ts_stack_push(self->stack, slice.version, error, false, goal_state, self->language);
LOG("push 7");
printf("push 7\n");
LOG_STACK();
} else { } else {
array_delete(&slice.subtrees); array_delete(&slice.subtrees);
} }
for (unsigned j = 0; j < self->trailing_extras.size; j++) { for (unsigned j = 0; j < self->trailing_extras.size; j++) {
Subtree tree = self->trailing_extras.contents[j]; Subtree tree = self->trailing_extras.contents[j];
ts_stack_push(self->stack, slice.version, tree, false, goal_state); ts_stack_push(self->stack, slice.version, tree, false, goal_state, self->language);
LOG("push 8");
printf("push 8\n");
LOG_STACK();
} }
previous_version = slice.version; previous_version = slice.version;
@ -1339,7 +1366,10 @@ static void ts_parser__recover(
LOG("recover_eof"); LOG("recover_eof");
SubtreeArray children = array_new(); SubtreeArray children = array_new();
Subtree parent = ts_subtree_new_error_node(&children, false, self->language); Subtree parent = ts_subtree_new_error_node(&children, false, self->language);
ts_stack_push(self->stack, version, parent, false, 1); ts_stack_push(self->stack, version, parent, false, 1, self->language);
LOG("push 9");
printf("push 9\n");
LOG_STACK();
ts_parser__accept(self, version, lookahead); ts_parser__accept(self, version, lookahead);
return; return;
} }
@ -1407,7 +1437,10 @@ static void ts_parser__recover(
} }
// Push the new ERROR onto the stack. // Push the new ERROR onto the stack.
ts_stack_push(self->stack, version, ts_subtree_from_mut(error_repeat), false, ERROR_STATE); ts_stack_push(self->stack, version, ts_subtree_from_mut(error_repeat), false, ERROR_STATE, self->language);
LOG("push 10");
printf("push 10\n");
LOG_STACK();
if (ts_subtree_has_external_tokens(lookahead)) { if (ts_subtree_has_external_tokens(lookahead)) {
ts_stack_set_last_external_token( ts_stack_set_last_external_token(
self->stack, version, ts_subtree_last_external_token(lookahead) self->stack, version, ts_subtree_last_external_token(lookahead)
@ -1469,8 +1502,11 @@ static void ts_parser__handle_error(
ts_stack_push( ts_stack_push(
self->stack, version_with_missing_tree, self->stack, version_with_missing_tree,
missing_tree, false, missing_tree, false,
state_after_missing_symbol state_after_missing_symbol, self->language
); );
LOG("push 11");
printf("push 11\n");
LOG_STACK();
if (ts_parser__do_all_potential_reductions( if (ts_parser__do_all_potential_reductions(
self, version_with_missing_tree, self, version_with_missing_tree,
@ -1488,7 +1524,10 @@ static void ts_parser__handle_error(
} }
} }
ts_stack_push(self->stack, v, NULL_SUBTREE, false, ERROR_STATE); ts_stack_push(self->stack, v, NULL_SUBTREE, false, ERROR_STATE, self->language);
LOG("push 12");
printf("push 12\n");
LOG_STACK();
v = (v == version) ? previous_version_count : v + 1; v = (v == version) ? previous_version_count : v + 1;
} }
@ -1847,7 +1886,7 @@ TSParser *ts_parser_new(void) {
array_init(&self->reduce_actions); array_init(&self->reduce_actions);
array_reserve(&self->reduce_actions, 4); array_reserve(&self->reduce_actions, 4);
self->tree_pool = ts_subtree_pool_new(32); self->tree_pool = ts_subtree_pool_new(32);
self->stack = ts_stack_new(&self->tree_pool); self->stack = ts_stack_new(&self->tree_pool, self->language);
self->finished_tree = NULL_SUBTREE; self->finished_tree = NULL_SUBTREE;
self->reusable_node = reusable_node_new(); self->reusable_node = reusable_node_new();
self->dot_graph_file = NULL; self->dot_graph_file = NULL;
@ -1915,6 +1954,8 @@ bool ts_parser_set_language(TSParser *self, const TSLanguage *language) {
} }
self->language = ts_language_copy(language); self->language = ts_language_copy(language);
ts_stack_set_language(self->stack, ts_language_copy(language));
ts_stack_set_lexer(self->stack, &self->lexer);
return true; return true;
} }

View file

@ -1,9 +1,10 @@
#include "./alloc.h"
#include "./language.h"
#include "./subtree.h"
#include "./array.h"
#include "./stack.h" #include "./stack.h"
#include "./alloc.h"
#include "./array.h"
#include "./language.h"
#include "./length.h" #include "./length.h"
#include "./lexer.h"
#include "./subtree.h"
#include <assert.h> #include <assert.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
@ -18,6 +19,32 @@
#define forceinline static inline __attribute__((always_inline)) #define forceinline static inline __attribute__((always_inline))
#endif #endif
#define LOG(...) \
if (self->lexer->logger.log || dot_graph_file) { \
snprintf(self->lexer->debug_buffer, TREE_SITTER_SERIALIZATION_BUFFER_SIZE, __VA_ARGS__); \
ts_stack__log(self, dot_graph_file); \
}
#define LOG_TREE(subtree) \
if (dot_graph_file) { \
printf("self->language:%p\n", (void *)self->language); \
ts_subtree_print_dot_graph(subtree, self->language, dot_graph_file); \
fputs("\n", dot_graph_file); \
}
#define LOG_LINKS() \
for (uint32_t k = 0; k < node->link_count; k++) { \
printf("link %d\n", k); \
printf("node:%p\n", node->links[k].node); \
printf("subtree:%p\n", node->links[k].subtree.ptr); \
if (node->links[k].subtree.ptr) { \
LOG("LINK TREE %d", k); \
LOG_TREE(node->links[k].subtree); \
} else { \
LOG("LINK NO TREE %d", k); \
} \
}
typedef struct StackNode StackNode; typedef struct StackNode StackNode;
typedef struct { typedef struct {
@ -68,9 +95,12 @@ struct Stack {
StackNodeArray node_pool; StackNodeArray node_pool;
StackNode *base_node; StackNode *base_node;
SubtreePool *subtree_pool; SubtreePool *subtree_pool;
const TSLanguage *language;
Lexer *lexer;
}; };
typedef unsigned StackAction; typedef unsigned StackAction;
enum { enum {
StackActionNone, StackActionNone,
StackActionStop = 1, StackActionStop = 1,
@ -87,25 +117,40 @@ static void stack_node_retain(StackNode *self) {
assert(self->ref_count != 0); assert(self->ref_count != 0);
} }
static void stack_node_release( static void ts_stack__log(Stack *self, FILE *dot_graph_file) {
StackNode *self, if (self->lexer->logger.log) {
StackNodeArray *pool, self->lexer->logger.log(self->lexer->logger.payload, TSLogTypeParse, self->lexer->debug_buffer);
SubtreePool *subtree_pool }
) {
if (dot_graph_file) {
fprintf(dot_graph_file, "graph {\nlabel=\"");
for (char *chr = &self->lexer->debug_buffer[0]; *chr != 0; chr++) {
if (*chr == '"' || *chr == '\\')
fputc('\\', dot_graph_file);
fputc(*chr, dot_graph_file);
}
fprintf(dot_graph_file, "\"\n}\n\n");
}
}
static void stack_node_release(StackNode *self, StackNodeArray *pool, SubtreePool *subtree_pool) {
recur: recur:
assert(self->ref_count != 0); assert(self->ref_count != 0);
self->ref_count--; self->ref_count--;
if (self->ref_count > 0) return; if (self->ref_count > 0)
return;
StackNode *first_predecessor = NULL; StackNode *first_predecessor = NULL;
if (self->link_count > 0) { if (self->link_count > 0) {
for (unsigned i = self->link_count - 1; i > 0; i--) { for (unsigned i = self->link_count - 1; i > 0; i--) {
StackLink link = self->links[i]; StackLink link = self->links[i];
if (link.subtree.ptr) ts_subtree_release(subtree_pool, link.subtree); if (link.subtree.ptr)
ts_subtree_release(subtree_pool, link.subtree);
stack_node_release(link.node, pool, subtree_pool); stack_node_release(link.node, pool, subtree_pool);
} }
StackLink link = self->links[0]; StackLink link = self->links[0];
if (link.subtree.ptr) ts_subtree_release(subtree_pool, link.subtree); if (link.subtree.ptr)
ts_subtree_release(subtree_pool, link.subtree);
first_predecessor = self->links[0].node; first_predecessor = self->links[0].node;
} }
@ -125,31 +170,22 @@ recur:
/// how much progress has been made by a given version of the stack. /// how much progress has been made by a given version of the stack.
static uint32_t stack__subtree_node_count(Subtree subtree) { static uint32_t stack__subtree_node_count(Subtree subtree) {
uint32_t count = ts_subtree_visible_descendant_count(subtree); uint32_t count = ts_subtree_visible_descendant_count(subtree);
if (ts_subtree_visible(subtree)) count++; if (ts_subtree_visible(subtree))
count++;
// Count intermediate error nodes even though they are not visible, // Count intermediate error nodes even though they are not visible,
// because a stack version's node count is used to check whether it // because a stack version's node count is used to check whether it
// has made any progress since the last time it encountered an error. // has made any progress since the last time it encountered an error.
if (ts_subtree_symbol(subtree) == ts_builtin_sym_error_repeat) count++; if (ts_subtree_symbol(subtree) == ts_builtin_sym_error_repeat)
count++;
return count; return count;
} }
static StackNode *stack_node_new( static StackNode *stack_node_new(StackNode *previous_node, Subtree subtree, bool is_pending, TSStateId state,
StackNode *previous_node, StackNodeArray *pool) {
Subtree subtree, StackNode *node = pool->size > 0 ? array_pop(pool) : ts_malloc(sizeof(StackNode));
bool is_pending, *node = (StackNode){.ref_count = 1, .link_count = 0, .state = state};
TSStateId state,
StackNodeArray *pool
) {
StackNode *node = pool->size > 0
? array_pop(pool)
: ts_malloc(sizeof(StackNode));
*node = (StackNode) {
.ref_count = 1,
.link_count = 0,
.state = state
};
if (previous_node) { if (previous_node) {
node->link_count = 1; node->link_count = 1;
@ -172,37 +208,35 @@ static StackNode *stack_node_new(
} }
} else { } else {
node->position = length_zero(); node->position = length_zero();
node->error_cost = 0; // node->error_cost = 0;
} }
return node; return node;
} }
static bool stack__subtree_is_equivalent(Subtree left, Subtree right) { static bool stack__subtree_is_equivalent(Subtree left, Subtree right) {
if (left.ptr == right.ptr) return true; if (left.ptr == right.ptr)
if (!left.ptr || !right.ptr) return false; return true;
if (!left.ptr || !right.ptr)
return false;
// Symbols must match // Symbols must match
if (ts_subtree_symbol(left) != ts_subtree_symbol(right)) return false; if (ts_subtree_symbol(left) != ts_subtree_symbol(right))
return false;
// If both have errors, don't bother keeping both. // If both have errors, don't bother keeping both.
if (ts_subtree_error_cost(left) > 0 && ts_subtree_error_cost(right) > 0) return true; if (ts_subtree_error_cost(left) > 0 && ts_subtree_error_cost(right) > 0)
return true;
return ( return (ts_subtree_padding(left).bytes == ts_subtree_padding(right).bytes &&
ts_subtree_padding(left).bytes == ts_subtree_padding(right).bytes &&
ts_subtree_size(left).bytes == ts_subtree_size(right).bytes && ts_subtree_size(left).bytes == ts_subtree_size(right).bytes &&
ts_subtree_child_count(left) == ts_subtree_child_count(right) && ts_subtree_child_count(left) == ts_subtree_child_count(right) &&
ts_subtree_extra(left) == ts_subtree_extra(right) && ts_subtree_extra(left) == ts_subtree_extra(right) && ts_subtree_external_scanner_state_eq(left, right));
ts_subtree_external_scanner_state_eq(left, right)
);
} }
static void stack_node_add_link( static void stack_node_add_link(StackNode *self, StackLink link, SubtreePool *subtree_pool) {
StackNode *self, if (link.node == self)
StackLink link, return;
SubtreePool *subtree_pool
) {
if (link.node == self) return;
for (int i = 0; i < self->link_count; i++) { for (int i = 0; i < self->link_count; i++) {
StackLink *existing_link = &self->links[i]; StackLink *existing_link = &self->links[i];
@ -212,10 +246,8 @@ static void stack_node_add_link(
// the special case where two links directly connect the same pair of nodes, // the special case where two links directly connect the same pair of nodes,
// we can safely remove the ambiguity ahead of time without changing behavior. // we can safely remove the ambiguity ahead of time without changing behavior.
if (existing_link->node == link.node) { if (existing_link->node == link.node) {
if ( if (ts_subtree_dynamic_precedence(link.subtree) >
ts_subtree_dynamic_precedence(link.subtree) > ts_subtree_dynamic_precedence(existing_link->subtree)) {
ts_subtree_dynamic_precedence(existing_link->subtree)
) {
ts_subtree_retain(link.subtree); ts_subtree_retain(link.subtree);
ts_subtree_release(subtree_pool, existing_link->subtree); ts_subtree_release(subtree_pool, existing_link->subtree);
existing_link->subtree = link.subtree; existing_link->subtree = link.subtree;
@ -226,11 +258,9 @@ static void stack_node_add_link(
} }
// If the previous nodes are mergeable, merge them recursively. // If the previous nodes are mergeable, merge them recursively.
if ( if (existing_link->node->state == link.node->state &&
existing_link->node->state == link.node->state &&
existing_link->node->position.bytes == link.node->position.bytes && existing_link->node->position.bytes == link.node->position.bytes &&
existing_link->node->error_cost == link.node->error_cost existing_link->node->error_cost == link.node->error_cost) {
) {
for (int j = 0; j < link.node->link_count; j++) { for (int j = 0; j < link.node->link_count; j++) {
stack_node_add_link(existing_link->node, link.node->links[j], subtree_pool); stack_node_add_link(existing_link->node, link.node->links[j], subtree_pool);
} }
@ -246,7 +276,8 @@ static void stack_node_add_link(
} }
} }
if (self->link_count == MAX_LINK_COUNT) return; if (self->link_count == MAX_LINK_COUNT)
return;
stack_node_retain(link.node); stack_node_retain(link.node);
unsigned node_count = link.node->node_count; unsigned node_count = link.node->node_count;
@ -259,15 +290,13 @@ static void stack_node_add_link(
dynamic_precedence += ts_subtree_dynamic_precedence(link.subtree); dynamic_precedence += ts_subtree_dynamic_precedence(link.subtree);
} }
if (node_count > self->node_count) self->node_count = node_count; if (node_count > self->node_count)
if (dynamic_precedence > self->dynamic_precedence) self->dynamic_precedence = dynamic_precedence; self->node_count = node_count;
if (dynamic_precedence > self->dynamic_precedence)
self->dynamic_precedence = dynamic_precedence;
} }
static void stack_head_delete( static void stack_head_delete(StackHead *self, StackNodeArray *pool, SubtreePool *subtree_pool) {
StackHead *self,
StackNodeArray *pool,
SubtreePool *subtree_pool
) {
if (self->node) { if (self->node) {
if (self->last_external_token.ptr) { if (self->last_external_token.ptr) {
ts_subtree_release(subtree_pool, self->last_external_token); ts_subtree_release(subtree_pool, self->last_external_token);
@ -283,11 +312,7 @@ static void stack_head_delete(
} }
} }
static StackVersion ts_stack__add_version( static StackVersion ts_stack__add_version(Stack *self, StackVersion original_version, StackNode *node) {
Stack *self,
StackVersion original_version,
StackNode *node
) {
StackHead head = { StackHead head = {
.node = node, .node = node,
.node_count_at_last_error = self->heads.contents[original_version].node_count_at_last_error, .node_count_at_last_error = self->heads.contents[original_version].node_count_at_last_error,
@ -297,16 +322,12 @@ static StackVersion ts_stack__add_version(
}; };
array_push(&self->heads, head); array_push(&self->heads, head);
stack_node_retain(node); stack_node_retain(node);
if (head.last_external_token.ptr) ts_subtree_retain(head.last_external_token); if (head.last_external_token.ptr)
ts_subtree_retain(head.last_external_token);
return (StackVersion)(self->heads.size - 1); return (StackVersion)(self->heads.size - 1);
} }
static void ts_stack__add_slice( static void ts_stack__add_slice(Stack *self, StackVersion original_version, StackNode *node, SubtreeArray *subtrees) {
Stack *self,
StackVersion original_version,
StackNode *node,
SubtreeArray *subtrees
) {
for (uint32_t i = self->slices.size - 1; i + 1 > 0; i--) { for (uint32_t i = self->slices.size - 1; i + 1 > 0; i--) {
StackVersion version = self->slices.contents[i].version; StackVersion version = self->slices.contents[i].version;
if (self->heads.contents[version].node == node) { if (self->heads.contents[version].node == node) {
@ -321,13 +342,8 @@ static void ts_stack__add_slice(
array_push(&self->slices, slice); array_push(&self->slices, slice);
} }
static StackSliceArray stack__iter( static StackSliceArray stack__iter(Stack *self, StackVersion version, StackCallback callback, void *payload,
Stack *self, int goal_subtree_count, FILE *dot_graph_file) {
StackVersion version,
StackCallback callback,
void *payload,
int goal_subtree_count
) {
array_clear(&self->slices); array_clear(&self->slices);
array_clear(&self->iterators); array_clear(&self->iterators);
@ -342,10 +358,13 @@ static StackSliceArray stack__iter(
bool include_subtrees = false; bool include_subtrees = false;
if (goal_subtree_count >= 0) { if (goal_subtree_count >= 0) {
include_subtrees = true; include_subtrees = true;
array_reserve(&new_iterator.subtrees, (uint32_t)ts_subtree_alloc_size(goal_subtree_count) / sizeof(Subtree)); array_reserve(&new_iterator.subtrees,
(uint32_t)ts_subtree_alloc_size(goal_subtree_count ? 1 : goal_subtree_count) / sizeof(Subtree));
} }
printf("iterator len: %d\n", self->iterators.size);
array_push(&self->iterators, new_iterator); array_push(&self->iterators, new_iterator);
printf("iterator len: %d\n", self->iterators.size);
while (self->iterators.size > 0) { while (self->iterators.size > 0) {
for (uint32_t i = 0, size = self->iterators.size; i < size; i++) { for (uint32_t i = 0, size = self->iterators.size; i < size; i++) {
@ -355,19 +374,45 @@ static StackSliceArray stack__iter(
StackAction action = callback(payload, iterator); StackAction action = callback(payload, iterator);
bool should_pop = action & StackActionPop; bool should_pop = action & StackActionPop;
bool should_stop = action & StackActionStop || node->link_count == 0; bool should_stop = action & StackActionStop || node->link_count == 0;
printf("should_pop: %d\n", should_pop);
printf("should_stop: %d\n", should_stop);
if (should_pop) { if (should_pop) {
SubtreeArray subtrees = iterator->subtrees; SubtreeArray subtrees = iterator->subtrees;
for (uint32_t j = 0; j < subtrees.size; j++) {
LOG("TREE %d", j);
LOG_TREE(subtrees.contents[j]);
}
if (!should_stop) { if (!should_stop) {
ts_subtree_array_copy(subtrees, &subtrees); ts_subtree_array_copy(subtrees, &subtrees);
LOG("[0] PRE COPY LEN %d", subtrees.size);
for (uint32_t k = 0; k < subtrees.size; k++) {
LOG("[0] PRE COPY TREE %d", k);
LOG_TREE(subtrees.contents[k]);
}
LOG("[0] NEW PTR: %p\n", (void *)subtrees.contents)
LOG("[0] POST COPY LEN %d", subtrees.size);
for (uint32_t k = 0; k < subtrees.size; k++) {
LOG("[0] POST COPY TREE %d", k);
LOG_TREE(subtrees.contents[k]);
}
}
for (uint32_t k = 0; k < subtrees.size; k++) {
LOG("[0] PRE REVERSE TREE %d", k);
LOG_TREE(subtrees.contents[k]);
} }
ts_subtree_array_reverse(&subtrees); ts_subtree_array_reverse(&subtrees);
ts_stack__add_slice( for (uint32_t k = 0; k < subtrees.size; k++) {
self, LOG("[0] POST REVERSE TREE %d", k);
version, LOG_TREE(subtrees.contents[k]);
node, }
&subtrees ts_stack__add_slice(self, version, node, &subtrees);
); printf("ADD SLICE\n");
LOG("ADD SLICE\n");
for (uint32_t j = 0; j < subtrees.size; j++) {
LOG("ADD SLICE TREE %d", j);
LOG_TREE(subtrees.contents[j]);
}
} }
if (should_stop) { if (should_stop) {
@ -383,21 +428,50 @@ static StackSliceArray stack__iter(
StackIterator *next_iterator; StackIterator *next_iterator;
StackLink link; StackLink link;
if (j == node->link_count) { if (j == node->link_count) {
printf("link set 1\n");
link = node->links[0]; link = node->links[0];
LOG("# of links=%d", node->link_count);
for (uint32_t k = 0; k < node->link_count; k++) {
printf("link %d\n", k);
printf("node:%p\n", node->links[k].node);
printf("subtree:%p\n", node->links[k].subtree.ptr);
if (node->links[k].subtree.ptr) {
LOG("LINK TREE %d", k);
LOG_TREE(node->links[k].subtree);
} else {
LOG("LINK NO TREE %d", k);
}
}
next_iterator = &self->iterators.contents[i]; next_iterator = &self->iterators.contents[i];
} else { } else {
if (self->iterators.size >= MAX_ITERATOR_COUNT) continue; if (self->iterators.size >= MAX_ITERATOR_COUNT)
continue;
link = node->links[j]; link = node->links[j];
StackIterator current_iterator = self->iterators.contents[i]; StackIterator current_iterator = self->iterators.contents[i];
array_push(&self->iterators, current_iterator); array_push(&self->iterators, current_iterator);
next_iterator = array_back(&self->iterators); next_iterator = array_back(&self->iterators);
ts_subtree_array_copy(next_iterator->subtrees, &next_iterator->subtrees); ts_subtree_array_copy(next_iterator->subtrees, &next_iterator->subtrees);
LOG("[1] PRE COPY LEN %d", next_iterator->subtrees.size);
for (uint32_t k = 0; k < next_iterator->subtrees.size; k++) {
LOG("[1] PRE COPY TREE %d", k);
LOG_TREE(next_iterator->subtrees.contents[k]);
}
LOG("[1] NEW PTR: %p\n", (void *)next_iterator->subtrees.contents)
LOG("[1] POST COPY LEN %d", next_iterator->subtrees.size);
for (uint32_t k = 0; k < next_iterator->subtrees.size; k++) {
LOG("[1] POST COPY TREE %d", k);
LOG_TREE(next_iterator->subtrees.contents[k]);
}
} }
next_iterator->node = link.node; next_iterator->node = link.node;
if (link.subtree.ptr) { if (link.subtree.ptr) {
if (include_subtrees) { if (include_subtrees) {
printf("PUSH INCLUDE SUBTREE\n");
LOG("PUSH INCLUDING SUBTREE");
LOG_TREE(link.subtree);
array_push(&next_iterator->subtrees, link.subtree); array_push(&next_iterator->subtrees, link.subtree);
ts_subtree_retain(link.subtree); ts_subtree_retain(link.subtree);
} }
@ -418,7 +492,7 @@ static StackSliceArray stack__iter(
return self->slices; return self->slices;
} }
Stack *ts_stack_new(SubtreePool *subtree_pool) { Stack *ts_stack_new(SubtreePool *subtree_pool, const TSLanguage *language) {
Stack *self = ts_calloc(1, sizeof(Stack)); Stack *self = ts_calloc(1, sizeof(Stack));
array_init(&self->heads); array_init(&self->heads);
@ -432,6 +506,8 @@ Stack *ts_stack_new(SubtreePool *subtree_pool) {
self->subtree_pool = subtree_pool; self->subtree_pool = subtree_pool;
self->base_node = stack_node_new(NULL, NULL_SUBTREE, false, 1, &self->node_pool); self->base_node = stack_node_new(NULL, NULL_SUBTREE, false, 1, &self->node_pool);
self->language = language;
printf("language:%p\n", language);
ts_stack_clear(self); ts_stack_clear(self);
return self; return self;
@ -456,9 +532,7 @@ void ts_stack_delete(Stack *self) {
ts_free(self); ts_free(self);
} }
uint32_t ts_stack_version_count(const Stack *self) { uint32_t ts_stack_version_count(const Stack *self) { return self->heads.size; }
return self->heads.size;
}
TSStateId ts_stack_state(const Stack *self, StackVersion version) { TSStateId ts_stack_state(const Stack *self, StackVersion version) {
return array_get(&self->heads, version)->node->state; return array_get(&self->heads, version)->node->state;
@ -474,17 +548,25 @@ Subtree ts_stack_last_external_token(const Stack *self, StackVersion version) {
void ts_stack_set_last_external_token(Stack *self, StackVersion version, Subtree token) { void ts_stack_set_last_external_token(Stack *self, StackVersion version, Subtree token) {
StackHead *head = array_get(&self->heads, version); StackHead *head = array_get(&self->heads, version);
if (token.ptr) ts_subtree_retain(token); if (token.ptr)
if (head->last_external_token.ptr) ts_subtree_release(self->subtree_pool, head->last_external_token); ts_subtree_retain(token);
if (head->last_external_token.ptr)
ts_subtree_release(self->subtree_pool, head->last_external_token);
head->last_external_token = token; head->last_external_token = token;
} }
void ts_stack_set_language(Stack *self, const TSLanguage *language) { self->language = language; }
void ts_stack_set_lexer(Stack *self, Lexer *lexer) { self->lexer = lexer; }
unsigned ts_stack_error_cost(const Stack *self, StackVersion version) { unsigned ts_stack_error_cost(const Stack *self, StackVersion version) {
StackHead *head = array_get(&self->heads, version); StackHead *head = array_get(&self->heads, version);
unsigned result = head->node->error_cost; unsigned result = head->node->error_cost;
if ( if (head->status == StackStatusPaused || (head->node->state == ERROR_STATE && !head->node->links[0].subtree.ptr)) {
head->status == StackStatusPaused || if (head->node->links[0].subtree.data.is_inline) {
(head->node->state == ERROR_STATE && !head->node->links[0].subtree.ptr)) { printf("DID += FOR %s\n",
ts_language_symbol_name(self->language, ts_subtree_symbol(head->node->links[0].subtree)));
}
result += ERROR_COST_PER_RECOVERY; result += ERROR_COST_PER_RECOVERY;
} }
return result; return result;
@ -498,16 +580,19 @@ unsigned ts_stack_node_count_since_error(const Stack *self, StackVersion version
return head->node->node_count - head->node_count_at_last_error; return head->node->node_count - head->node_count_at_last_error;
} }
void ts_stack_push( void ts_stack_push(Stack *self, StackVersion version, Subtree subtree, bool pending, TSStateId state,
Stack *self, const TSLanguage *l) {
StackVersion version,
Subtree subtree,
bool pending,
TSStateId state
) {
StackHead *head = array_get(&self->heads, version); StackHead *head = array_get(&self->heads, version);
StackNode *new_node = stack_node_new(head->node, subtree, pending, state, &self->node_pool); StackNode *new_node = stack_node_new(head->node, subtree, pending, state, &self->node_pool);
if (!subtree.ptr) head->node_count_at_last_error = new_node->node_count; if (!subtree.ptr)
head->node_count_at_last_error = new_node->node_count;
else {
const char *s = ts_language_symbol_name(l, ts_subtree_symbol(subtree));
printf("sym=%s\n", s);
if (strcmp(s, "ERROR") == 0) {
(void)s;
}
}
head->node = new_node; head->node = new_node;
} }
@ -521,7 +606,7 @@ forceinline StackAction pop_count_callback(void *payload, const StackIterator *i
} }
StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t count) { StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t count) {
return stack__iter(self, version, pop_count_callback, &count, (int)count); return stack__iter(self, version, pop_count_callback, &count, (int)count, NULL);
} }
forceinline StackAction pop_pending_callback(void *payload, const StackIterator *iterator) { forceinline StackAction pop_pending_callback(void *payload, const StackIterator *iterator) {
@ -538,7 +623,7 @@ forceinline StackAction pop_pending_callback(void *payload, const StackIterator
} }
StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version) { StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version) {
StackSliceArray pop = stack__iter(self, version, pop_pending_callback, NULL, 0); StackSliceArray pop = stack__iter(self, version, pop_pending_callback, NULL, 0, NULL);
if (pop.size > 0) { if (pop.size > 0) {
ts_stack_renumber_version(self, pop.contents[0].version, version); ts_stack_renumber_version(self, pop.contents[0].version, version);
pop.contents[0].version = version; pop.contents[0].version = version;
@ -565,7 +650,7 @@ SubtreeArray ts_stack_pop_error(Stack *self, StackVersion version) {
for (unsigned i = 0; i < node->link_count; i++) { for (unsigned i = 0; i < node->link_count; i++) {
if (node->links[i].subtree.ptr && ts_subtree_is_error(node->links[i].subtree)) { if (node->links[i].subtree.ptr && ts_subtree_is_error(node->links[i].subtree)) {
bool found_error = false; bool found_error = false;
StackSliceArray pop = stack__iter(self, version, pop_error_callback, &found_error, 1); StackSliceArray pop = stack__iter(self, version, pop_error_callback, &found_error, 1, NULL);
if (pop.size > 0) { if (pop.size > 0) {
assert(pop.size == 1); assert(pop.size == 1);
ts_stack_renumber_version(self, pop.contents[0].version, version); ts_stack_renumber_version(self, pop.contents[0].version, version);
@ -582,8 +667,8 @@ forceinline StackAction pop_all_callback(void *payload, const StackIterator *ite
return iterator->node->link_count == 0 ? StackActionPop : StackActionNone; return iterator->node->link_count == 0 ? StackActionPop : StackActionNone;
} }
StackSliceArray ts_stack_pop_all(Stack *self, StackVersion version) { StackSliceArray ts_stack_pop_all(Stack *self, StackVersion version, FILE *dot_graph_file) {
return stack__iter(self, version, pop_all_callback, NULL, 0); return stack__iter(self, version, pop_all_callback, NULL, 0, dot_graph_file);
} }
typedef struct { typedef struct {
@ -595,11 +680,14 @@ forceinline StackAction summarize_stack_callback(void *payload, const StackItera
SummarizeStackSession *session = payload; SummarizeStackSession *session = payload;
TSStateId state = iterator->node->state; TSStateId state = iterator->node->state;
unsigned depth = iterator->subtree_count; unsigned depth = iterator->subtree_count;
if (depth > session->max_depth) return StackActionStop; if (depth > session->max_depth)
return StackActionStop;
for (unsigned i = session->summary->size - 1; i + 1 > 0; i--) { for (unsigned i = session->summary->size - 1; i + 1 > 0; i--) {
StackSummaryEntry entry = session->summary->contents[i]; StackSummaryEntry entry = session->summary->contents[i];
if (entry.depth < depth) break; if (entry.depth < depth)
if (entry.depth == depth && entry.state == state) return StackActionNone; break;
if (entry.depth == depth && entry.state == state)
return StackActionNone;
} }
array_push(session->summary, ((StackSummaryEntry){ array_push(session->summary, ((StackSummaryEntry){
.position = iterator->node->position, .position = iterator->node->position,
@ -610,12 +698,9 @@ forceinline StackAction summarize_stack_callback(void *payload, const StackItera
} }
void ts_stack_record_summary(Stack *self, StackVersion version, unsigned max_depth) { void ts_stack_record_summary(Stack *self, StackVersion version, unsigned max_depth) {
SummarizeStackSession session = { SummarizeStackSession session = {.summary = ts_malloc(sizeof(StackSummary)), .max_depth = max_depth};
.summary = ts_malloc(sizeof(StackSummary)),
.max_depth = max_depth
};
array_init(session.summary); array_init(session.summary);
stack__iter(self, version, summarize_stack_callback, &session, -1); stack__iter(self, version, summarize_stack_callback, &session, -1, NULL);
StackHead *head = &self->heads.contents[version]; StackHead *head = &self->heads.contents[version];
if (head->summary) { if (head->summary) {
array_delete(head->summary); array_delete(head->summary);
@ -635,17 +720,15 @@ int ts_stack_dynamic_precedence(Stack *self, StackVersion version) {
bool ts_stack_has_advanced_since_error(const Stack *self, StackVersion version) { bool ts_stack_has_advanced_since_error(const Stack *self, StackVersion version) {
const StackHead *head = array_get(&self->heads, version); const StackHead *head = array_get(&self->heads, version);
const StackNode *node = head->node; const StackNode *node = head->node;
if (node->error_cost == 0) return true; if (node->error_cost == 0)
return true;
while (node) { while (node) {
if (node->link_count > 0) { if (node->link_count > 0) {
Subtree subtree = node->links[0].subtree; Subtree subtree = node->links[0].subtree;
if (subtree.ptr) { if (subtree.ptr) {
if (ts_subtree_total_bytes(subtree) > 0) { if (ts_subtree_total_bytes(subtree) > 0) {
return true; return true;
} else if ( } else if (node->node_count > head->node_count_at_last_error && ts_subtree_error_cost(subtree) == 0) {
node->node_count > head->node_count_at_last_error &&
ts_subtree_error_cost(subtree) == 0
) {
node = node->links[0].node; node = node->links[0].node;
continue; continue;
} }
@ -662,7 +745,8 @@ void ts_stack_remove_version(Stack *self, StackVersion version) {
} }
void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2) { void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2) {
if (v1 == v2) return; if (v1 == v2)
return;
assert(v2 < v1); assert(v2 < v1);
assert((uint32_t)v1 < self->heads.size); assert((uint32_t)v1 < self->heads.size);
StackHead *source_head = &self->heads.contents[v1]; StackHead *source_head = &self->heads.contents[v1];
@ -687,13 +771,15 @@ StackVersion ts_stack_copy_version(Stack *self, StackVersion version) {
array_push(&self->heads, self->heads.contents[version]); array_push(&self->heads, self->heads.contents[version]);
StackHead *head = array_back(&self->heads); StackHead *head = array_back(&self->heads);
stack_node_retain(head->node); stack_node_retain(head->node);
if (head->last_external_token.ptr) ts_subtree_retain(head->last_external_token); if (head->last_external_token.ptr)
ts_subtree_retain(head->last_external_token);
head->summary = NULL; head->summary = NULL;
return self->heads.size - 1; return self->heads.size - 1;
} }
bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2) { bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2) {
if (!ts_stack_can_merge(self, version1, version2)) return false; if (!ts_stack_can_merge(self, version1, version2))
return false;
StackHead *head1 = &self->heads.contents[version1]; StackHead *head1 = &self->heads.contents[version1];
StackHead *head2 = &self->heads.contents[version2]; StackHead *head2 = &self->heads.contents[version2];
for (uint32_t i = 0; i < head2->node->link_count; i++) { for (uint32_t i = 0; i < head2->node->link_count; i++) {
@ -709,18 +795,13 @@ bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2) {
bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version2) { bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version2) {
StackHead *head1 = &self->heads.contents[version1]; StackHead *head1 = &self->heads.contents[version1];
StackHead *head2 = &self->heads.contents[version2]; StackHead *head2 = &self->heads.contents[version2];
return return head1->status == StackStatusActive && head2->status == StackStatusActive &&
head1->status == StackStatusActive && head1->node->state == head2->node->state && head1->node->position.bytes == head2->node->position.bytes &&
head2->status == StackStatusActive &&
head1->node->state == head2->node->state &&
head1->node->position.bytes == head2->node->position.bytes &&
head1->node->error_cost == head2->node->error_cost && head1->node->error_cost == head2->node->error_cost &&
ts_subtree_external_scanner_state_eq(head1->last_external_token, head2->last_external_token); ts_subtree_external_scanner_state_eq(head1->last_external_token, head2->last_external_token);
} }
void ts_stack_halt(Stack *self, StackVersion version) { void ts_stack_halt(Stack *self, StackVersion version) { array_get(&self->heads, version)->status = StackStatusHalted; }
array_get(&self->heads, version)->status = StackStatusHalted;
}
void ts_stack_pause(Stack *self, StackVersion version, Subtree lookahead) { void ts_stack_pause(Stack *self, StackVersion version, Subtree lookahead) {
StackHead *head = array_get(&self->heads, version); StackHead *head = array_get(&self->heads, version);
@ -766,7 +847,8 @@ void ts_stack_clear(Stack *self) {
bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f) { bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f) {
array_reserve(&self->iterators, 32); array_reserve(&self->iterators, 32);
if (!f) f = stderr; if (!f)
f = stderr;
fprintf(f, "digraph stack {\n"); fprintf(f, "digraph stack {\n");
fprintf(f, "rankdir=\"RL\";\n"); fprintf(f, "rankdir=\"RL\";\n");
@ -777,7 +859,8 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
array_clear(&self->iterators); array_clear(&self->iterators);
for (uint32_t i = 0; i < self->heads.size; i++) { for (uint32_t i = 0; i < self->heads.size; i++) {
StackHead *head = &self->heads.contents[i]; StackHead *head = &self->heads.contents[i];
if (head->status == StackStatusHalted) continue; if (head->status == StackStatusHalted)
continue;
fprintf(f, "node_head_%u [shape=none, label=\"\"]\n", i); fprintf(f, "node_head_%u [shape=none, label=\"\"]\n", i);
fprintf(f, "node_head_%u -> node_%p [", i, (void *)head->node); fprintf(f, "node_head_%u -> node_%p [", i, (void *)head->node);
@ -785,29 +868,25 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
if (head->status == StackStatusPaused) { if (head->status == StackStatusPaused) {
fprintf(f, "color=red "); fprintf(f, "color=red ");
} }
fprintf(f, fprintf(f, "label=%u, fontcolor=blue, weight=10000, labeltooltip=\"node_count: %u\nerror_cost: %u", i,
"label=%u, fontcolor=blue, weight=10000, labeltooltip=\"node_count: %u\nerror_cost: %u", ts_stack_node_count_since_error(self, i), ts_stack_error_cost(self, i));
i,
ts_stack_node_count_since_error(self, i),
ts_stack_error_cost(self, i)
);
if (head->summary) { if (head->summary) {
fprintf(f, "\nsummary:"); fprintf(f, "\nsummary:");
for (uint32_t j = 0; j < head->summary->size; j++) fprintf(f, " %u", head->summary->contents[j].state); for (uint32_t j = 0; j < head->summary->size; j++)
fprintf(f, " %u", head->summary->contents[j].state);
} }
if (head->last_external_token.ptr) { if (head->last_external_token.ptr) {
const ExternalScannerState *state = &head->last_external_token.ptr->external_scanner_state; const ExternalScannerState *state = &head->last_external_token.ptr->external_scanner_state;
const char *data = ts_external_scanner_state_data(state); const char *data = ts_external_scanner_state_data(state);
fprintf(f, "\nexternal_scanner_state:"); fprintf(f, "\nexternal_scanner_state:");
for (uint32_t j = 0; j < state->length; j++) fprintf(f, " %2X", data[j]); for (uint32_t j = 0; j < state->length; j++)
fprintf(f, " %2X", data[j]);
} }
fprintf(f, "\"]\n"); fprintf(f, "\"]\n");
array_push(&self->iterators, ((StackIterator) { array_push(&self->iterators, ((StackIterator){.node = head->node}));
.node = head->node
}));
} }
bool all_iterators_done = false; bool all_iterators_done = false;
@ -825,53 +904,66 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
} }
} }
if (!node) continue; if (!node)
continue;
all_iterators_done = false; all_iterators_done = false;
fprintf(f, "node_%p [", (void *)node); fprintf(f, "node_%p [", (void *)node);
if (node->state == ERROR_STATE) { if (node->state == ERROR_STATE) {
fprintf(f, "label=\"?\""); fprintf(f, "label=\"?\"");
} else if ( } else if (node->link_count == 1 && node->links[0].subtree.ptr &&
node->link_count == 1 && ts_subtree_extra(node->links[0].subtree)) {
node->links[0].subtree.ptr &&
ts_subtree_extra(node->links[0].subtree)
) {
fprintf(f, "shape=point margin=0 label=\"\""); fprintf(f, "shape=point margin=0 label=\"\"");
} else { } else {
fprintf(f, "label=\"%d\"", node->state); fprintf(f, "label=\"%d\"", node->state);
} }
fprintf( fprintf(f, " tooltip=\"position: %u,%u\nnode_count:%u\nerror_cost: %u\ndynamic_precedence: %d\"];\n",
f, node->position.extent.row + 1, node->position.extent.column, node->node_count, node->error_cost,
" tooltip=\"position: %u,%u\nnode_count:%u\nerror_cost: %u\ndynamic_precedence: %d\"];\n", node->dynamic_precedence);
node->position.extent.row + 1,
node->position.extent.column,
node->node_count,
node->error_cost,
node->dynamic_precedence
);
for (int j = 0; j < node->link_count; j++) { for (int j = 0; j < node->link_count; j++) {
StackLink link = node->links[j]; StackLink link = node->links[j];
fprintf(f, "node_%p -> node_%p [", (void *)node, (void *)link.node); fprintf(f, "node_%p -> node_%p [", (void *)node, (void *)link.node);
if (link.is_pending) fprintf(f, "style=dashed "); if (link.is_pending)
if (link.subtree.ptr && ts_subtree_extra(link.subtree)) fprintf(f, "fontcolor=gray "); fprintf(f, "style=dashed ");
if (link.subtree.ptr && ts_subtree_extra(link.subtree))
fprintf(f, "fontcolor=gray ");
if (!link.subtree.ptr) { if (!link.subtree.ptr) {
fprintf(f, "color=red"); fprintf(f, "color=red");
} else { } else {
fprintf(f, "label=\""); fprintf(f, "label=\"");
bool quoted = ts_subtree_visible(link.subtree) && !ts_subtree_named(link.subtree); bool quoted = ts_subtree_visible(link.subtree) && !ts_subtree_named(link.subtree);
if (quoted) fprintf(f, "'"); if (quoted)
fprintf(f, "'");
ts_language_write_symbol_as_dot_string(language, f, ts_subtree_symbol(link.subtree)); ts_language_write_symbol_as_dot_string(language, f, ts_subtree_symbol(link.subtree));
if (quoted) fprintf(f, "'"); printf("[1]ts_subtree_error_cost(link.subtree)=%u\n", ts_subtree_error_cost(link.subtree));
if (quoted)
fprintf(f, "'");
fprintf(f, "\""); fprintf(f, "\"");
fprintf( fprintf(f, "labeltooltip=\"ptr: %p\nerror_cost: %u\ndynamic_precedence: %" PRId32,
f, (void *)link.subtree.ptr, ts_subtree_error_cost(link.subtree),
"labeltooltip=\"error_cost: %u\ndynamic_precedence: %" PRId32 "\"", ts_subtree_dynamic_precedence(link.subtree));
ts_subtree_error_cost(link.subtree), if (ts_subtree_is_error(link.subtree) && ts_subtree_child_count(link.subtree) == 0 &&
ts_subtree_dynamic_precedence(link.subtree) link.subtree.ptr->lookahead_char != 0) {
); fprintf(f, "\ncharacter: '%c'", link.subtree.ptr->lookahead_char);
} else {
fprintf(f, "\nno character");
}
if (link.subtree.data.is_inline) {
fprintf(f, "\nis_inline:%d", link.subtree.data.is_inline);
} else {
fprintf(f, "\nog_ptr:%p", (void *)link.subtree.ptr->og_ptr);
}
fprintf(f, "\"");
if (ts_subtree_error_cost(link.subtree) == 500 &&
ts_language_symbol_name(language, ts_subtree_symbol(link.subtree)) != NULL) {
printf("ptr to target stack tree node: %p\n", (void *)link.subtree.ptr);
} else if (ts_subtree_error_cost(link.subtree) == 0 &&
ts_language_symbol_name(language, ts_subtree_symbol(link.subtree)) != NULL) {
printf("ptr to bad target stack tree node: %p\n", (void *)link.subtree.ptr);
}
} }
fprintf(f, "];\n"); fprintf(f, "];\n");

View file

@ -7,6 +7,7 @@ extern "C" {
#include "./array.h" #include "./array.h"
#include "./subtree.h" #include "./subtree.h"
#include "./lexer.h"
#include "./error_costs.h" #include "./error_costs.h"
#include <stdio.h> #include <stdio.h>
@ -29,7 +30,7 @@ typedef struct {
typedef Array(StackSummaryEntry) StackSummary; typedef Array(StackSummaryEntry) StackSummary;
// Create a stack. // Create a stack.
Stack *ts_stack_new(SubtreePool *); Stack *ts_stack_new(SubtreePool *, const TSLanguage*);
// Release the memory reserved for a given stack. // Release the memory reserved for a given stack.
void ts_stack_delete(Stack *); void ts_stack_delete(Stack *);
@ -47,6 +48,10 @@ Subtree ts_stack_last_external_token(const Stack *, StackVersion);
// Set the last external token associated with a given version of the stack. // Set the last external token associated with a given version of the stack.
void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree ); void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree );
void ts_stack_set_language(Stack *self, const TSLanguage *language);
void ts_stack_set_lexer(Stack *self, Lexer *lexer);
// Get the position of the given version of the stack within the document. // Get the position of the given version of the stack within the document.
Length ts_stack_position(const Stack *, StackVersion); Length ts_stack_position(const Stack *, StackVersion);
@ -55,7 +60,7 @@ Length ts_stack_position(const Stack *, StackVersion);
// This transfers ownership of the tree to the Stack. Callers that // This transfers ownership of the tree to the Stack. Callers that
// need to retain ownership of the tree for their own purposes should // need to retain ownership of the tree for their own purposes should
// first retain the tree. // first retain the tree.
void ts_stack_push(Stack *, StackVersion, Subtree , bool, TSStateId); void ts_stack_push(Stack *, StackVersion, Subtree , bool, TSStateId, const TSLanguage*);
// Pop the given number of entries from the given version of the stack. This // 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 // operation can increase the number of stack versions by revealing multiple
@ -71,7 +76,7 @@ SubtreeArray ts_stack_pop_error(Stack *, StackVersion);
StackSliceArray ts_stack_pop_pending(Stack *, StackVersion); StackSliceArray ts_stack_pop_pending(Stack *, StackVersion);
// Remove any all trees from the given version of the stack. // Remove any all trees from the given version of the stack.
StackSliceArray ts_stack_pop_all(Stack *, StackVersion); StackSliceArray ts_stack_pop_all(Stack *, StackVersion, FILE*);
// Get the maximum number of tree nodes reachable from this version of the stack // Get the maximum number of tree nodes reachable from this version of the stack
// since the last error was detected. // since the last error was detected.

View file

@ -22,6 +22,7 @@ typedef struct {
#define TS_MAX_INLINE_TREE_LENGTH UINT8_MAX #define TS_MAX_INLINE_TREE_LENGTH UINT8_MAX
#define TS_MAX_TREE_POOL_SIZE 32 #define TS_MAX_TREE_POOL_SIZE 32
// ExternalScannerState // ExternalScannerState
void ts_external_scanner_state_init(ExternalScannerState *self, const char *data, unsigned length) { void ts_external_scanner_state_init(ExternalScannerState *self, const char *data, unsigned length) {
@ -196,8 +197,10 @@ Subtree ts_subtree_new_leaf(
}}; }};
} else { } else {
SubtreeHeapData *data = ts_subtree_pool_allocate(pool); SubtreeHeapData *data = ts_subtree_pool_allocate(pool);
printf("[1] ALLOCATED %p\n", (void *)data);
*data = (SubtreeHeapData) { *data = (SubtreeHeapData) {
.ref_count = 1, .ref_count = 1,
.og_ptr = (size_t)data,
.padding = padding, .padding = padding,
.size = size, .size = size,
.lookahead_bytes = lookahead_bytes, .lookahead_bytes = lookahead_bytes,
@ -272,6 +275,7 @@ MutableSubtree ts_subtree_clone(Subtree self) {
); );
} }
result->ref_count = 1; result->ref_count = 1;
printf("NEW SUBTREE: %p\n", result);
return (MutableSubtree) {.ptr = result}; return (MutableSubtree) {.ptr = result};
} }
@ -375,7 +379,10 @@ void ts_subtree_summarize_children(
self.ptr->named_child_count = 0; self.ptr->named_child_count = 0;
self.ptr->visible_child_count = 0; self.ptr->visible_child_count = 0;
if (!ts_subtree_is_error(ts_subtree_from_mut(self))) {
printf("SET 0: %s\n", ts_language_symbol_name(language, self.ptr->symbol));
self.ptr->error_cost = 0; self.ptr->error_cost = 0;
}
self.ptr->repeat_depth = 0; self.ptr->repeat_depth = 0;
self.ptr->visible_descendant_count = 0; self.ptr->visible_descendant_count = 0;
self.ptr->has_external_tokens = false; self.ptr->has_external_tokens = false;
@ -422,16 +429,27 @@ void ts_subtree_summarize_children(
} }
uint32_t grandchild_count = ts_subtree_child_count(child); uint32_t grandchild_count = ts_subtree_child_count(child);
printf("HI: %s\n", ts_language_symbol_name(language, self.ptr->symbol));
if ( if (
self.ptr->symbol == ts_builtin_sym_error || self.ptr->symbol == ts_builtin_sym_error ||
self.ptr->symbol == ts_builtin_sym_error_repeat self.ptr->symbol == ts_builtin_sym_error_repeat
) { ) {
printf("THE FIRST BLOCK\n");
if (!ts_subtree_extra(child) && !(ts_subtree_is_error(child) && grandchild_count == 0)) { if (!ts_subtree_extra(child) && !(ts_subtree_is_error(child) && grandchild_count == 0)) {
if (ts_subtree_visible(child)) { if (ts_subtree_visible(child)) {
self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE; self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE;
} else if (grandchild_count > 0) { } else if (grandchild_count > 0) {
self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE * child.ptr->visible_child_count; self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE * child.ptr->visible_child_count;
} }
} else {
printf("FALSE BLOCK\n");
}
if (ts_subtree_is_error(child) && grandchild_count == 0) {
MutableSubtree child_mut = ts_subtree_to_mut_unsafe(child);
child_mut.ptr->error_cost = ERROR_COST_PER_RECOVERY +
ERROR_COST_PER_SKIPPED_CHAR * child.ptr->size.bytes +
ERROR_COST_PER_SKIPPED_LINE * child.ptr->size.extent.row;
} }
} }
@ -465,10 +483,13 @@ void ts_subtree_summarize_children(
self.ptr->lookahead_bytes = lookahead_end_byte - self.ptr->size.bytes - self.ptr->padding.bytes; self.ptr->lookahead_bytes = lookahead_end_byte - self.ptr->size.bytes - self.ptr->padding.bytes;
printf("HI 2: %d\n", self.ptr->symbol);
printf("HI 2: %s\n", ts_language_symbol_name(language, self.ptr->symbol));
if ( if (
self.ptr->symbol == ts_builtin_sym_error || self.ptr->symbol == ts_builtin_sym_error ||
self.ptr->symbol == ts_builtin_sym_error_repeat self.ptr->symbol == ts_builtin_sym_error_repeat
) { ) {
printf("HI 3\n");
self.ptr->error_cost += self.ptr->error_cost +=
ERROR_COST_PER_RECOVERY + ERROR_COST_PER_RECOVERY +
ERROR_COST_PER_SKIPPED_CHAR * self.ptr->size.bytes + ERROR_COST_PER_SKIPPED_CHAR * self.ptr->size.bytes +
@ -519,9 +540,10 @@ MutableSubtree ts_subtree_new_node(
children->capacity = (uint32_t)(new_byte_size / sizeof(Subtree)); children->capacity = (uint32_t)(new_byte_size / sizeof(Subtree));
} }
SubtreeHeapData *data = (SubtreeHeapData *)&children->contents[children->size]; SubtreeHeapData *data = (SubtreeHeapData *)&children->contents[children->size];
printf("[0]ALLOCATED %p\n", (void *)data);
*data = (SubtreeHeapData) { *data = (SubtreeHeapData) {
.ref_count = 1, .ref_count = 1,
.og_ptr = (size_t)data,
.symbol = symbol, .symbol = symbol,
.child_count = children->size, .child_count = children->size,
.visible = metadata.visible, .visible = metadata.visible,
@ -538,6 +560,11 @@ MutableSubtree ts_subtree_new_node(
}} }}
}; };
MutableSubtree result = {.ptr = data}; MutableSubtree result = {.ptr = data};
if (symbol == ts_builtin_sym_error_repeat) {
printf("ptr: %p\n", (void *)result.ptr);
} else if (symbol == ts_builtin_sym_error) {
printf("ptr: %p\n", (void *)result.ptr);
}
ts_subtree_summarize_children(result, language); ts_subtree_summarize_children(result, language);
return result; return result;
} }
@ -981,6 +1008,7 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset,
uint32_t end_offset = start_offset + ts_subtree_total_bytes(*self); uint32_t end_offset = start_offset + ts_subtree_total_bytes(*self);
fprintf(f, "tree_%p [label=\"", (void *)self); fprintf(f, "tree_%p [label=\"", (void *)self);
ts_language_write_symbol_as_dot_string(language, f, symbol); ts_language_write_symbol_as_dot_string(language, f, symbol);
printf("[0]ts_subtree_error_cost(link.subtree)=%u\n", ts_subtree_error_cost(*self));
fprintf(f, "\""); fprintf(f, "\"");
if (ts_subtree_child_count(*self) == 0) fprintf(f, ", shape=plaintext"); if (ts_subtree_child_count(*self) == 0) fprintf(f, ", shape=plaintext");
@ -994,7 +1022,8 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset,
"depends-on-column: %u\n" "depends-on-column: %u\n"
"descendant-count: %u\n" "descendant-count: %u\n"
"repeat-depth: %u\n" "repeat-depth: %u\n"
"lookahead-bytes: %u", "lookahead-bytes: %u\n"
"ptr: %p",
start_offset, end_offset, start_offset, end_offset,
ts_subtree_parse_state(*self), ts_subtree_parse_state(*self),
ts_subtree_error_cost(*self), ts_subtree_error_cost(*self),
@ -1002,11 +1031,23 @@ void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset,
ts_subtree_depends_on_column(*self), ts_subtree_depends_on_column(*self),
ts_subtree_visible_descendant_count(*self), ts_subtree_visible_descendant_count(*self),
ts_subtree_repeat_depth(*self), ts_subtree_repeat_depth(*self),
ts_subtree_lookahead_bytes(*self) ts_subtree_lookahead_bytes(*self),
(void*)self->ptr
); );
if (self->data.is_inline) {
fprintf(f, "\nis_inline: %d", self->data.is_inline);
} else {
fprintf(f, "\nog_ptr: %p", (void*)self->ptr->og_ptr);
}
if (ts_subtree_is_error(*self) && ts_subtree_child_count(*self) == 0 && self->ptr->lookahead_char != 0) { if (ts_subtree_is_error(*self) && ts_subtree_child_count(*self) == 0 && self->ptr->lookahead_char != 0) {
fprintf(f, "\ncharacter: '%c'", self->ptr->lookahead_char); fprintf(f, "\ncharacter: '%c'", self->ptr->lookahead_char);
printf("ptr %p is error with an error cost of %d\n", (void*)self->ptr, ts_subtree_error_cost(*self));
printf("branch [1] %d %p\n", ts_subtree_missing(*self), self->ptr);
printf("branch [2] %d\n", self->data.is_inline);
} else {
printf("no call!\n");
} }
fprintf(f, "\"]\n"); fprintf(f, "\"]\n");

View file

@ -110,6 +110,7 @@ struct SubtreeInlineData {
// the inline representation. // the inline representation.
typedef struct { typedef struct {
volatile uint32_t ref_count; volatile uint32_t ref_count;
size_t og_ptr;
Length padding; Length padding;
Length size; Length size;
uint32_t lookahead_bytes; uint32_t lookahead_bytes;