diff --git a/cli/src/main.rs b/cli/src/main.rs index 9e8f885b..4b387050 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,9 +1,8 @@ use clap::{App, AppSettings, Arg, SubCommand}; use error::Error; -use std::io::Read; use std::path::Path; use std::process::exit; -use std::{env, fs, io, u64}; +use std::{env, fs, u64}; use tree_sitter::Language; use tree_sitter_cli::{ config, error, generate, highlight, loader, logger, parse, query, test, wasm, web_ui, diff --git a/cli/src/query.rs b/cli/src/query.rs index 74f3e327..2f50325a 100644 --- a/cli/src/query.rs +++ b/cli/src/query.rs @@ -2,7 +2,7 @@ use super::error::{Error, Result}; use std::fs; use std::io::{self, Write}; use std::path::Path; -use tree_sitter::{Language, Parser, Query}; +use tree_sitter::{Language, Parser, Query, QueryCursor}; pub fn query_files_at_paths( language: Language, @@ -18,7 +18,7 @@ pub fn query_files_at_paths( let query = Query::new(language, &query_source) .map_err(|e| Error::new(format!("Query compilation failed: {:?}", e)))?; - let query_context = query.context(); + let mut query_cursor = QueryCursor::new(); let mut parser = Parser::new(); parser.set_language(language).map_err(|e| e.to_string())?; @@ -32,7 +32,7 @@ pub fn query_files_at_paths( let tree = parser.parse(&source_code, None).unwrap(); - for mat in query_context.exec(tree.root_node()) { + for mat in query_cursor.exec(&query, tree.root_node()) { writeln!(&mut stdout, " pattern: {}", mat.pattern_index())?; for (capture_id, node) in mat.captures() { writeln!( diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 6131d1ea..c95bdfa2 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -1,6 +1,6 @@ use super::helpers::allocations; use super::helpers::fixtures::get_language; -use tree_sitter::{Parser, Query, QueryError, QueryMatch}; +use tree_sitter::{Parser, Query, QueryCursor, QueryError, QueryMatch}; #[test] fn test_query_errors_on_invalid_syntax() { @@ -77,8 +77,8 @@ fn test_query_exec_with_simple_pattern() { parser.set_language(language).unwrap(); let tree = parser.parse(source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -117,8 +117,8 @@ fn test_query_exec_with_multiple_matches_same_root() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -164,8 +164,8 @@ fn test_query_exec_multiple_patterns_different_roots() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -206,8 +206,8 @@ fn test_query_exec_multiple_patterns_same_root() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -243,8 +243,8 @@ fn test_query_exec_nested_matches_without_fields() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -269,8 +269,8 @@ fn test_query_exec_many_matches() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(&source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source.as_str()), @@ -298,8 +298,8 @@ fn test_query_exec_too_many_match_permutations_to_track() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(&source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); // For this pathological query, some match permutations will be dropped. // Just check that a subset of the results are returned, and crash or @@ -329,8 +329,8 @@ fn test_query_exec_with_anonymous_tokens() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(&source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -354,8 +354,8 @@ fn test_query_exec_within_byte_range() { parser.set_language(language).unwrap(); let tree = parser.parse(&source, None).unwrap(); - let mut context = query.context(); - let matches = context.set_byte_range(5, 15).exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.set_byte_range(5, 15).exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), @@ -420,8 +420,8 @@ fn test_query_comments() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); let tree = parser.parse(source, None).unwrap(); - let context = query.context(); - let matches = context.exec(tree.root_node()); + let mut cursor = QueryCursor::new(); + let matches = cursor.exec(&query, tree.root_node()); assert_eq!( collect_matches(matches, &query, source), &[(0, vec![("fn-name", "one")]),], diff --git a/lib/binding_rust/bindings.rs b/lib/binding_rust/bindings.rs index b44b5622..effd0c81 100644 --- a/lib/binding_rust/bindings.rs +++ b/lib/binding_rust/bindings.rs @@ -26,7 +26,7 @@ pub struct TSQuery { } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct TSQueryContext { +pub struct TSQueryCursor { _unused: [u8; 0], } pub const TSInputEncoding_TSInputEncodingUTF8: TSInputEncoding = 0; @@ -604,56 +604,52 @@ extern "C" { ) -> ::std::os::raw::c_int; } extern "C" { - #[doc = " Create a new context for executing a given query."] + #[doc = " Create a new cursor for executing a given query."] #[doc = ""] - #[doc = " The context stores the state that is needed to iteratively search"] - #[doc = " for matches. To use the query context:"] - #[doc = " 1. First call `ts_query_context_exec` to start running the query"] - #[doc = " on a particular syntax node."] - #[doc = " 2. Then repeatedly call `ts_query_context_next` to iterate over"] - #[doc = " the matches."] - #[doc = " 3. After each successful call to `ts_query_context_next`, you can call"] - #[doc = " `ts_query_context_matched_pattern_index` to determine which pattern"] - #[doc = " matched. You can also call `ts_query_context_matched_captures` to"] - #[doc = " determine which nodes were captured by which capture names."] + #[doc = " The cursor stores the state that is needed to iteratively search"] + #[doc = " for matches. To use the query cursor:"] + #[doc = " 1. First call `ts_query_cursor_exec` to start running a given query on"] + #[doc = "a given syntax node."] + #[doc = " 2. Then repeatedly call `ts_query_cursor_next` to iterate over the matches."] + #[doc = " This will return `false` when there are no more matches left."] + #[doc = " 3. After each successful call to `ts_query_cursor_next`, you can call"] + #[doc = " `ts_query_cursor_matched_pattern_index` to determine which pattern"] + #[doc = " matched. You can also call `ts_query_cursor_matched_captures` to"] + #[doc = " determine which nodes were captured, and by which capture names."] #[doc = ""] #[doc = " If you don\'t care about finding all of the matches, you can stop calling"] - #[doc = " `ts_query_context_next` at any point. And you can start executing the"] - #[doc = " query against a different node by calling `ts_query_context_exec` again."] - pub fn ts_query_context_new(arg1: *const TSQuery) -> *mut TSQueryContext; + #[doc = " `ts_query_cursor_next` at any point. And you can start executing another"] + #[doc = " query on another node by calling `ts_query_cursor_exec` again."] + pub fn ts_query_cursor_new() -> *mut TSQueryCursor; } extern "C" { - #[doc = " Delete a query context, freeing all of the memory that it used."] - pub fn ts_query_context_delete(arg1: *mut TSQueryContext); + #[doc = " Delete a query cursor, freeing all of the memory that it used."] + pub fn ts_query_cursor_delete(arg1: *mut TSQueryCursor); } extern "C" { - #[doc = " Start running a query on a given node."] - pub fn ts_query_context_exec(arg1: *mut TSQueryContext, arg2: TSNode); + #[doc = " Start running a given query on a given node."] + pub fn ts_query_cursor_exec(arg1: *mut TSQueryCursor, arg2: *const TSQuery, arg3: TSNode); } extern "C" { #[doc = " Set the range of bytes or (row, column) positions in which the query"] #[doc = " will be executed."] - pub fn ts_query_context_set_byte_range(arg1: *mut TSQueryContext, arg2: u32, arg3: u32); + pub fn ts_query_cursor_set_byte_range(arg1: *mut TSQueryCursor, arg2: u32, arg3: u32); } extern "C" { - pub fn ts_query_context_set_point_range( - arg1: *mut TSQueryContext, - arg2: TSPoint, - arg3: TSPoint, - ); + pub fn ts_query_cursor_set_point_range(arg1: *mut TSQueryCursor, arg2: TSPoint, arg3: TSPoint); } extern "C" { #[doc = " Advance to the next match of the currently running query."] - pub fn ts_query_context_next(arg1: *mut TSQueryContext) -> bool; + pub fn ts_query_cursor_next(arg1: *mut TSQueryCursor) -> bool; } extern "C" { #[doc = " Check which pattern matched."] - pub fn ts_query_context_matched_pattern_index(arg1: *const TSQueryContext) -> u32; + pub fn ts_query_cursor_matched_pattern_index(arg1: *const TSQueryCursor) -> u32; } extern "C" { #[doc = " Check which pattern matched."] - pub fn ts_query_context_matched_captures( - arg1: *const TSQueryContext, + pub fn ts_query_cursor_matched_captures( + arg1: *const TSQueryCursor, arg2: *mut u32, ) -> *const TSQueryCapture; } diff --git a/lib/binding_rust/lib.rs b/lib/binding_rust/lib.rs index 8d29a3c3..2c20fd12 100644 --- a/lib/binding_rust/lib.rs +++ b/lib/binding_rust/lib.rs @@ -142,9 +142,9 @@ pub struct Query { capture_names: Vec, } -pub struct QueryContext<'a>(*mut ffi::TSQueryContext, PhantomData<&'a ()>); +pub struct QueryCursor(*mut ffi::TSQueryCursor); -pub struct QueryMatch<'a>(&'a QueryContext<'a>); +pub struct QueryMatch<'a>(*mut ffi::TSQueryCursor, PhantomData<&'a ()>); #[derive(Debug, PartialEq, Eq)] pub enum QueryError<'a> { @@ -989,22 +989,21 @@ impl Query { pub fn capture_names(&self) -> &[String] { &self.capture_names } - - pub fn context(&self) -> QueryContext { - let context = unsafe { ffi::ts_query_context_new(self.ptr) }; - QueryContext(context, PhantomData) - } } -impl<'a> QueryContext<'a> { - pub fn exec(&'a self, node: Node<'a>) -> impl Iterator> + 'a { +impl QueryCursor { + pub fn new() -> Self { + QueryCursor(unsafe { ffi::ts_query_cursor_new() }) + } + + pub fn exec<'a>(&'a mut self, query: &'a Query, node: Node<'a>) -> impl Iterator> + 'a { unsafe { - ffi::ts_query_context_exec(self.0, node.0); + ffi::ts_query_cursor_exec(self.0, query.ptr, node.0); } std::iter::from_fn(move || -> Option> { unsafe { - if ffi::ts_query_context_next(self.0) { - Some(QueryMatch(self)) + if ffi::ts_query_cursor_next(self.0) { + Some(QueryMatch(self.0, PhantomData)) } else { None } @@ -1014,14 +1013,14 @@ impl<'a> QueryContext<'a> { pub fn set_byte_range(&mut self, start: usize, end: usize) -> &mut Self { unsafe { - ffi::ts_query_context_set_byte_range(self.0, start as u32, end as u32); + ffi::ts_query_cursor_set_byte_range(self.0, start as u32, end as u32); } self } pub fn set_point_range(&mut self, start: Point, end: Point) -> &mut Self { unsafe { - ffi::ts_query_context_set_point_range(self.0, start.into(), end.into()); + ffi::ts_query_cursor_set_point_range(self.0, start.into(), end.into()); } self } @@ -1029,14 +1028,14 @@ impl<'a> QueryContext<'a> { impl<'a> QueryMatch<'a> { pub fn pattern_index(&self) -> usize { - unsafe { ffi::ts_query_context_matched_pattern_index((self.0).0) as usize } + unsafe { ffi::ts_query_cursor_matched_pattern_index(self.0) as usize } } pub fn captures(&self) -> impl ExactSizeIterator { unsafe { let mut capture_count = 0u32; let captures = - ffi::ts_query_context_matched_captures((self.0).0, &mut capture_count as *mut u32); + ffi::ts_query_cursor_matched_captures(self.0, &mut capture_count as *mut u32); let captures = slice::from_raw_parts(captures, capture_count as usize); captures .iter() @@ -1057,9 +1056,9 @@ impl Drop for Query { } } -impl<'a> Drop for QueryContext<'a> { +impl Drop for QueryCursor { fn drop(&mut self) { - unsafe { ffi::ts_query_context_delete(self.0) } + unsafe { ffi::ts_query_cursor_delete(self.0) } } } diff --git a/lib/binding_web/binding.c b/lib/binding_web/binding.c index f46d1def..501cf1cd 100644 --- a/lib/binding_web/binding.c +++ b/lib/binding_web/binding.c @@ -306,6 +306,7 @@ void ts_tree_cursor_current_node_wasm(const TSTree *tree) { /******************/ static TSTreeCursor scratch_cursor = {0}; +static TSQueryCursor *scratch_query_cursor = NULL; uint16_t ts_node_symbol_wasm(const TSTree *tree) { TSNode node = unmarshal_node(tree); @@ -566,24 +567,22 @@ int ts_node_is_missing_wasm(const TSTree *tree) { /* Section - Query */ /******************/ -void ts_query_exec_wasm( - const TSQuery *self, - TSQueryContext *context, - const TSTree *tree -) { +void ts_query_exec_wasm(const TSQuery *self, const TSTree *tree) { + if (!scratch_query_cursor) scratch_query_cursor = ts_query_cursor_new(); + TSNode node = unmarshal_node(tree); Array(const void *) result = array_new(); unsigned index = 0; unsigned match_count = 0; - ts_query_context_exec(context, node); - while (ts_query_context_next(context)) { + ts_query_cursor_exec(scratch_query_cursor, self, node); + while (ts_query_cursor_next(scratch_query_cursor)) { match_count++; - uint32_t pattern_index = ts_query_context_matched_pattern_index(context); + uint32_t pattern_index = ts_query_cursor_matched_pattern_index(scratch_query_cursor); uint32_t capture_count; - const TSQueryCapture *captures = ts_query_context_matched_captures( - context, + const TSQueryCapture *captures = ts_query_cursor_matched_captures( + scratch_query_cursor, &capture_count ); diff --git a/lib/binding_web/binding.js b/lib/binding_web/binding.js index ac48cb70..85bd4053 100644 --- a/lib/binding_web/binding.js +++ b/lib/binding_web/binding.js @@ -677,7 +677,6 @@ class Language { TRANSFER_BUFFER + SIZE_OF_INT ); if (address) { - const contextAddress = C._ts_query_context_new(address); const captureCount = C._ts_query_capture_count(address); const captureNames = new Array(captureCount); for (let i = 0; i < captureCount; i++) { @@ -689,7 +688,7 @@ class Language { const nameLength = getValue(TRANSFER_BUFFER, 'i32'); captureNames[i] = UTF8ToString(nameAddress, nameLength); } - return new Query(INTERNAL, address, contextAddress, captureNames); + return new Query(INTERNAL, address, captureNames); } else { const errorId = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32'); const utf8ErrorOffset = getValue(TRANSFER_BUFFER, 'i32'); @@ -743,22 +742,20 @@ class Language { } class Query { - constructor(internal, address, contextAddress, captureNames) { + constructor(internal, address, captureNames) { assertInternal(internal); this[0] = address; - this[1] = contextAddress; this.captureNames = captureNames; } delete() { C._ts_query_delete(this[0]); - C._ts_query_context_delete(this[0]); } exec(queryNode) { marshalNode(queryNode); - C._ts_query_exec_wasm(this[0], this[1], queryNode.tree[0]); + C._ts_query_exec_wasm(this[0], queryNode.tree[0]); const matchCount = getValue(TRANSFER_BUFFER, 'i32'); const nodesAddress = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32'); diff --git a/lib/include/tree_sitter/api.h b/lib/include/tree_sitter/api.h index d951a35a..624658b4 100644 --- a/lib/include/tree_sitter/api.h +++ b/lib/include/tree_sitter/api.h @@ -27,7 +27,7 @@ typedef struct TSLanguage TSLanguage; typedef struct TSParser TSParser; typedef struct TSTree TSTree; typedef struct TSQuery TSQuery; -typedef struct TSQueryContext TSQueryContext; +typedef struct TSQueryCursor TSQueryCursor; typedef enum { TSInputEncodingUTF8, @@ -670,57 +670,57 @@ int ts_query_capture_id_for_name( ); /** - * Create a new context for executing a given query. + * Create a new cursor for executing a given query. * - * The context stores the state that is needed to iteratively search - * for matches. To use the query context: - * 1. First call `ts_query_context_exec` to start running the query - * on a particular syntax node. - * 2. Then repeatedly call `ts_query_context_next` to iterate over - * the matches. - * 3. After each successful call to `ts_query_context_next`, you can call - * `ts_query_context_matched_pattern_index` to determine which pattern - * matched. You can also call `ts_query_context_matched_captures` to - * determine which nodes were captured by which capture names. + * The cursor stores the state that is needed to iteratively search + * for matches. To use the query cursor: + * 1. First call `ts_query_cursor_exec` to start running a given query on + a given syntax node. + * 2. Then repeatedly call `ts_query_cursor_next` to iterate over the matches. + * This will return `false` when there are no more matches left. + * 3. After each successful call to `ts_query_cursor_next`, you can call + * `ts_query_cursor_matched_pattern_index` to determine which pattern + * matched. You can also call `ts_query_cursor_matched_captures` to + * determine which nodes were captured, and by which capture names. * * If you don't care about finding all of the matches, you can stop calling - * `ts_query_context_next` at any point. And you can start executing the - * query against a different node by calling `ts_query_context_exec` again. + * `ts_query_cursor_next` at any point. And you can start executing another + * query on another node by calling `ts_query_cursor_exec` again. */ -TSQueryContext *ts_query_context_new(const TSQuery *); +TSQueryCursor *ts_query_cursor_new(); /** - * Delete a query context, freeing all of the memory that it used. + * Delete a query cursor, freeing all of the memory that it used. */ -void ts_query_context_delete(TSQueryContext *); +void ts_query_cursor_delete(TSQueryCursor *); /** - * Start running a query on a given node. + * Start running a given query on a given node. */ -void ts_query_context_exec(TSQueryContext *, TSNode); +void ts_query_cursor_exec(TSQueryCursor *, const TSQuery *, TSNode); /** * Set the range of bytes or (row, column) positions in which the query * will be executed. */ -void ts_query_context_set_byte_range(TSQueryContext *, uint32_t, uint32_t); -void ts_query_context_set_point_range(TSQueryContext *, TSPoint, TSPoint); +void ts_query_cursor_set_byte_range(TSQueryCursor *, uint32_t, uint32_t); +void ts_query_cursor_set_point_range(TSQueryCursor *, TSPoint, TSPoint); /** * Advance to the next match of the currently running query. */ -bool ts_query_context_next(TSQueryContext *); +bool ts_query_cursor_next(TSQueryCursor *); /** * Check which pattern matched. */ -uint32_t ts_query_context_matched_pattern_index(const TSQueryContext *); +uint32_t ts_query_cursor_matched_pattern_index(const TSQueryCursor *); /** * Check which pattern matched. */ -const TSQueryCapture *ts_query_context_matched_captures( - const TSQueryContext *, +const TSQueryCapture *ts_query_cursor_matched_captures( + const TSQueryCursor *, uint32_t * ); diff --git a/lib/src/query.c b/lib/src/query.c index 8b4deb81..a082e131 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -50,7 +50,7 @@ typedef struct { /* * QueryState - The state of an in-progress match of a particular pattern - * in a query. While executing, a QueryContext must keep track of a number + * in a query. While executing, a `TSQueryCursor` must keep track of a number * of possible in-progress matches. Each of those possible matches is * represented as one of these states. */ @@ -69,15 +69,14 @@ typedef struct { * parts of the shared array are currently in use by a QueryState. */ typedef struct { - TSQueryCapture *contents; - uint32_t list_size; + Array(TSQueryCapture) list; uint32_t usage_map; } CaptureListPool; /* * TSQuery - A tree query, compiled from a string of S-expressions. The query * itself is immutable. The mutable state used in the process of executing the - * query is stored in a `TSQueryContext`. + * query is stored in a `TSQueryCursor`. */ struct TSQuery { Array(QueryStep) steps; @@ -90,9 +89,9 @@ struct TSQuery { }; /* - * TSQueryContext - A stateful struct used to execute a query on a tree. + * TSQueryCursor - A stateful struct used to execute a query on a tree. */ -struct TSQueryContext { +struct TSQueryCursor { const TSQuery *query; TSTreeCursor cursor; Array(QueryState) states; @@ -185,24 +184,26 @@ static void stream_scan_identifier(Stream *stream) { * CaptureListPool ******************/ -static CaptureListPool capture_list_pool_new(uint16_t list_size) { +static CaptureListPool capture_list_pool_new() { return (CaptureListPool) { - .contents = ts_calloc(MAX_STATE_COUNT * list_size, sizeof(TSQueryCapture)), - .list_size = list_size, + .list = array_new(), .usage_map = UINT32_MAX, }; } -static void capture_list_pool_clear(CaptureListPool *self) { +static void capture_list_pool_reset(CaptureListPool *self, uint16_t list_size) { self->usage_map = UINT32_MAX; + uint32_t total_size = MAX_STATE_COUNT * list_size; + array_reserve(&self->list, total_size); + self->list.size = total_size; } static void capture_list_pool_delete(CaptureListPool *self) { - ts_free(self->contents); + array_delete(&self->list); } static TSQueryCapture *capture_list_pool_get(CaptureListPool *self, uint16_t id) { - return &self->contents[id * self->list_size]; + return &self->list.contents[id * (self->list.size / MAX_STATE_COUNT)]; } static inline uint32_t capture_list_bitmask_for_id(uint16_t id) { @@ -599,17 +600,16 @@ int ts_query_capture_id_for_name( } /*************** - * QueryContext + * QueryCursor ***************/ -TSQueryContext *ts_query_context_new(const TSQuery *query) { - TSQueryContext *self = ts_malloc(sizeof(TSQueryContext)); - *self = (TSQueryContext) { - .query = query, +TSQueryCursor *ts_query_cursor_new() { + TSQueryCursor *self = ts_malloc(sizeof(TSQueryCursor)); + *self = (TSQueryCursor) { .ascending = false, .states = array_new(), .finished_states = array_new(), - .capture_list_pool = capture_list_pool_new(query->max_capture_count), + .capture_list_pool = capture_list_pool_new(), .start_byte = 0, .end_byte = UINT32_MAX, .start_point = {0, 0}, @@ -618,7 +618,7 @@ TSQueryContext *ts_query_context_new(const TSQuery *query) { return self; } -void ts_query_context_delete(TSQueryContext *self) { +void ts_query_cursor_delete(TSQueryCursor *self) { array_delete(&self->states); array_delete(&self->finished_states); ts_tree_cursor_delete(&self->cursor); @@ -626,17 +626,22 @@ void ts_query_context_delete(TSQueryContext *self) { ts_free(self); } -void ts_query_context_exec(TSQueryContext *self, TSNode node) { +void ts_query_cursor_exec( + TSQueryCursor *self, + const TSQuery *query, + TSNode node +) { array_clear(&self->states); array_clear(&self->finished_states); ts_tree_cursor_reset(&self->cursor, node); - capture_list_pool_clear(&self->capture_list_pool); + capture_list_pool_reset(&self->capture_list_pool, query->max_capture_count); self->depth = 0; self->ascending = false; + self->query = query; } -void ts_query_context_set_byte_range( - TSQueryContext *self, +void ts_query_cursor_set_byte_range( + TSQueryCursor *self, uint32_t start_byte, uint32_t end_byte ) { @@ -648,8 +653,8 @@ void ts_query_context_set_byte_range( self->end_byte = end_byte; } -void ts_query_context_set_point_range( - TSQueryContext *self, +void ts_query_cursor_set_point_range( + TSQueryCursor *self, TSPoint start_point, TSPoint end_point ) { @@ -661,8 +666,8 @@ void ts_query_context_set_point_range( self->end_point = end_point; } -static QueryState *ts_query_context_copy_state( - TSQueryContext *self, +static QueryState *ts_query_cursor_copy_state( + TSQueryCursor *self, QueryState *state ) { uint32_t new_list_id = capture_list_pool_acquire(&self->capture_list_pool); @@ -682,7 +687,7 @@ static QueryState *ts_query_context_copy_state( return new_state; } -bool ts_query_context_next(TSQueryContext *self) { +bool ts_query_cursor_next(TSQueryCursor *self) { if (self->finished_states.size > 0) { QueryState state = array_pop(&self->finished_states); capture_list_pool_release(&self->capture_list_pool, state.capture_list_id); @@ -853,7 +858,7 @@ bool ts_query_context_next(TSQueryContext *self) { // siblings. QueryState *next_state = state; if (step->depth > 0 && (!step->field || field_occurs_in_later_sibling)) { - QueryState *copy = ts_query_context_copy_state(self, state); + QueryState *copy = ts_query_cursor_copy_state(self, state); if (copy) next_state = copy; } @@ -873,7 +878,7 @@ bool ts_query_context_next(TSQueryContext *self) { }; } - // If the pattern is now done, then populate the query context's + // If the pattern is now done, then populate the query cursor's // finished state. next_state->step_index++; QueryStep *next_step = step + 1; @@ -902,7 +907,7 @@ bool ts_query_context_next(TSQueryContext *self) { return true; } -uint32_t ts_query_context_matched_pattern_index(const TSQueryContext *self) { +uint32_t ts_query_cursor_matched_pattern_index(const TSQueryCursor *self) { if (self->finished_states.size > 0) { QueryState *state = array_back(&self->finished_states); return state->pattern_index; @@ -910,8 +915,8 @@ uint32_t ts_query_context_matched_pattern_index(const TSQueryContext *self) { return 0; } -const TSQueryCapture *ts_query_context_matched_captures( - const TSQueryContext *self, +const TSQueryCapture *ts_query_cursor_matched_captures( + const TSQueryCursor *self, uint32_t *count ) { if (self->finished_states.size > 0) {