From 2a7b884ffc214d3b1041e00627afe935ca3430db Mon Sep 17 00:00:00 2001 From: Eric Minish Date: Fri, 6 Nov 2026 16:34:46 -0500 Subject: [PATCH 1/3] fix(extraction): vendor tree-sitter runtime 0.25.10 + #5997 (error-recovery livelock) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A .tsx file holding `c:d(e f)` timed out its parse worker 3 x 30s and was dropped (fork issue inth3shadows/tree-sitter-typescript#16, upstream #323). The loop is in tree-sitter's error recovery (tree-sitter/tree-sitter#5997), fixed only in 0.27.1 — which rejects legacy-dylink grammars (all tree-sitter-wasms 0.1.x + dart): 193 test failures. So: 0.25.10 built with the 3-line patch, loaded via locateFile. - src/extraction/runtime/tree-sitter.wasm (sha256 d48b82be); unpatched rebuild == npm 0.25.10 tree-sitter.wasm byte-for-byte (f38dcc4b) - initGrammars() throws if the runtime is missing; copy-assets + check-ui-build ship it - web-tree-sitter pinned 0.25.10 exact; test fails if the glue version moves - PoC project: 92s, 1 file dropped -> 1.43s, 2 files indexed --- CHANGELOG.md | 1 + __tests__/tsx-error-recovery-hang.test.ts | 52 +++++++++++++++++++ docs/grammars/web-tree-sitter-runtime.md | 53 ++++++++++++++++++++ docs/grammars/web-tree-sitter-runtime.patch | 14 ++++++ package-lock.json | 2 +- package.json | 4 +- scripts/check-ui-build.mjs | 14 +++++- src/extraction/grammars.ts | 19 ++++++- src/extraction/runtime/tree-sitter.wasm | Bin 0 -> 205492 bytes 9 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 __tests__/tsx-error-recovery-hang.test.ts create mode 100644 docs/grammars/web-tree-sitter-runtime.md create mode 100644 docs/grammars/web-tree-sitter-runtime.patch create mode 100755 src/extraction/runtime/tree-sitter.wasm diff --git a/CHANGELOG.md b/CHANGELOG.md index 848465cb67..ccd1530b2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixes +- A TSX file holding a broken JSX attribute such as `c:d(e f)` no longer costs each index run three 30-second worker kills and then gets dropped. It now parses in milliseconds and is indexed like any other file with a syntax error. The hang was in tree-sitter's error recovery. CodeGraph now ships web-tree-sitter 0.25.10's runtime with the upstream fix (tree-sitter/tree-sitter#5997) applied, because 0.27.1, the first release that has it, cannot load most of the grammars CodeGraph uses. - TypeScript variance annotations like `interface Stream` or `` now parse. Before, each one was a parse error, and in a large file enough of them could make the whole file fail to parse and show up with almost no symbols. Re-index TypeScript projects after upgrading. - In TypeScript, an awaited call with type arguments like `await fetchApi("/me")` or `await api.get(url)` now links to the function it calls. Before, the call was dropped, so typed fetch wrappers looked like they had no callers. (#2586) - In JavaScript and TypeScript, a call or `new` in a parameter's default value, like `function renderWithNote(note = buildNote())`, a destructured `{ size = defaultSize() }` or `constructor(private svc = new Service())`, now counts as the function's own call. Before, it was dropped, so `buildNote` was missing that caller and impact on it came back incomplete. Re-index JavaScript and TypeScript projects after upgrading. Thanks @inth3shadows for the report and the pull request. (#2588) diff --git a/__tests__/tsx-error-recovery-hang.test.ts b/__tests__/tsx-error-recovery-hang.test.ts new file mode 100644 index 0000000000..acd8632089 --- /dev/null +++ b/__tests__/tsx-error-recovery-hang.test.ts @@ -0,0 +1,52 @@ +/** + * tree-sitter's error recovery before 0.27.1 never finishes on some broken + * input (tree-sitter/tree-sitter#5997; tree-sitter-typescript upstream #323): + * a TSX file holding `c:d(e f)` timed out the parse worker three + * times (3 x 30s) and was then dropped from the index. The grammar is not at + * fault, so this pins the runtime: each input must give a tree, errors and + * all, well inside the budget. web-tree-sitter 0.25.10's own tree-sitter.wasm + * fails it; the vendored src/extraction/runtime/tree-sitter.wasm (0.25.10 + + * tree-sitter/tree-sitter#5997) passes. See docs/grammars/web-tree-sitter-runtime.md. + */ +import { describe, it, expect, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as path from 'path'; +import { initGrammars, loadGrammarsForLanguages, getParser, RUNTIME_WASM_PATH } from '../src/extraction/grammars'; +import { parseWithinBudget } from '../src/extraction/parse-budget'; + +// The vendored runtime wasm is paired with web-tree-sitter's JS glue: both must be 0.25.10. +const VENDORED_RUNTIME_VERSION = '0.25.10'; + +beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['typescript', 'tsx']); +}); + +const HANG_INPUTS = [ + 'c:d(e f)\n', + '
Note: This is important. (And this)
\n', +]; + +describe('vendored tree-sitter runtime', () => { + it('is in place and matches the installed web-tree-sitter glue', () => { + expect(fs.existsSync(RUNTIME_WASM_PATH)).toBe(true); + const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'web-tree-sitter', 'package.json'), 'utf8')); + expect( + pkg.version, + 'web-tree-sitter changed: rebuild src/extraction/runtime/tree-sitter.wasm for it (docs/grammars/web-tree-sitter-runtime.md)', + ).toBe(VENDORED_RUNTIME_VERSION); + }); +}); + +describe('error recovery finishes on input that once looped forever', () => { + it.each(['tsx', 'typescript'] as const)('%s', (language) => { + for (const src of HANG_INPUTS) { + const started = Date.now(); + const tree = parseWithinBudget(getParser(language)!, src, 2000); + expect(tree, `${language}: ${JSON.stringify(src)} did not finish within 2000ms`).not.toBeNull(); + expect(tree!.rootNode.hasError).toBe(true); + expect(Date.now() - started).toBeLessThan(2000); + tree!.delete(); + } + }); +}); diff --git a/docs/grammars/web-tree-sitter-runtime.md b/docs/grammars/web-tree-sitter-runtime.md new file mode 100644 index 0000000000..79608cd622 --- /dev/null +++ b/docs/grammars/web-tree-sitter-runtime.md @@ -0,0 +1,53 @@ +# Vendored tree-sitter runtime (web-tree-sitter 0.25.10 + #5997) + +`src/extraction/runtime/tree-sitter.wasm` replaces the `tree-sitter.wasm` that ships in the +web-tree-sitter npm package. `initGrammars()` loads it through `Parser.init({ locateFile })` +and throws if it is missing. `copy-assets` copies it into `dist/extraction/runtime/`, and +`scripts/check-ui-build.mjs` fails a build without it. + +## Why + +tree-sitter's error recovery before 0.27.1 can loop forever: after removing a stack version +it skips the version that shifted into its slot, so recovery keeps restarting without +consuming input (tree-sitter/tree-sitter#5997). In codegraph a `.tsx` file containing +`
c:d(e f)` timed out its parse worker three times (3 x 30s) and was then dropped +from the index. Upstream report: tree-sitter/tree-sitter-typescript#323. + +0.27.1 has the fix, but it only loads grammars with a `dylink.0` section. Every +tree-sitter-wasms 0.1.x grammar and the vendored Dart wasm use the legacy `dylink` +section, so 0.27.1 drops about 20 languages (193 failing tests). This build is +0.25.10 plus the 3-line fix, and it still loads every grammar. + +## Provenance + +| | | +|---|---| +| source | tree-sitter/tree-sitter `v0.25.10` (da6fe9beb4f7f67beb75914ca8e0d48ae48d6406) | +| patch | `docs/grammars/web-tree-sitter-runtime.patch` (`lib/src/parser.c`, from #5997) | +| build | `cargo xtask build-wasm` (emscripten 4.0.4 via docker, `cli/loader/emscripten-version`) | +| output | `lib/binding_web/lib/tree-sitter.wasm` | +| sha256 | `d48b82be2c17998ef4b2b9ab0cadbbd5ae838ef6ff0eca37b9c12ab887988d78` | + +Reproducibility check: the same build without the patch produced +`f38dcc4b43b818f9a0785bc1c6d5611a75ac4cdd428ff3f02757c34ca4e46d7f`, which is byte-identical to +`node_modules/web-tree-sitter/tree-sitter.wasm` from npm 0.25.10. The vendored file therefore +differs from npm's only by the patch, and it pairs with npm's 0.25.10 JS glue. + +## Rebuild + +```sh +git clone --depth 1 --branch v0.25.10 https://github.com/tree-sitter/tree-sitter.git ts +cd ts && git apply /docs/grammars/web-tree-sitter-runtime.patch +cargo xtask build-wasm +cp lib/binding_web/lib/tree-sitter.wasm /src/extraction/runtime/tree-sitter.wasm +``` + +## Rules + +- web-tree-sitter is pinned exactly (`0.25.10`). `__tests__/tsx-error-recovery-hang.test.ts` + fails if the installed version moves, because new glue with this wasm is untested. +- The same test fails under the unpatched npm runtime (`did not finish within 2000ms`). +- Exit: once the legacy-`dylink` grammars are rebuilt (or tree-sitter-wasms is replaced), move to + web-tree-sitter 0.27.1+ and delete this runtime, the patch and this file. +- The native kernel (`codegraph-kernel`, Rust `tree-sitter` 0.25) carries the same bug and is + not patched here. diff --git a/docs/grammars/web-tree-sitter-runtime.patch b/docs/grammars/web-tree-sitter-runtime.patch new file mode 100644 index 0000000000..62ab7e9ea8 --- /dev/null +++ b/docs/grammars/web-tree-sitter-runtime.patch @@ -0,0 +1,14 @@ +diff --git a/lib/src/parser.c b/lib/src/parser.c +index 39e6b89..29b33b7 100644 +--- a/lib/src/parser.c ++++ b/lib/src/parser.c +@@ -1182,6 +1182,9 @@ static bool ts_parser__do_all_potential_reductions( + continue; + } else if (lookahead_symbol != 0) { + ts_stack_remove_version(self->stack, version); ++ // Removing this version shifts the next reduction version into its slot. ++ // Check that version before advancing. ++ continue; + } + + if (version == starting_version) { diff --git a/package-lock.json b/package-lock.json index 7d4162e041..524310036b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "picomatch": "^4.0.3", "sisteransi": "^1.0.5", "tree-sitter-wasms": "^0.1.11", - "web-tree-sitter": "^0.25.3" + "web-tree-sitter": "0.25.10" }, "bin": { "codegraph": "dist/bin/codegraph.js" diff --git a/package.json b/package.json index a2c224122f..9930f901a4 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "build:ui": "cd ui && npm run build && cd .. && node scripts/check-ui-build.mjs", "build:lib": "cd ui && npm run build:lib", "preuninstall": "node dist/bin/uninstall.js", - "copy-assets": "node -e \"const fs=require('fs');fs.mkdirSync('dist/db',{recursive:true});fs.copyFileSync('src/db/schema.sql','dist/db/schema.sql');fs.mkdirSync('dist/extraction/wasm',{recursive:true});fs.readdirSync('src/extraction/wasm').filter(f=>f.endsWith('.wasm')).forEach(f=>fs.copyFileSync('src/extraction/wasm/'+f,'dist/extraction/wasm/'+f))\"", + "copy-assets": "node -e \"const fs=require('fs');fs.mkdirSync('dist/db',{recursive:true});fs.copyFileSync('src/db/schema.sql','dist/db/schema.sql');fs.mkdirSync('dist/extraction/wasm',{recursive:true});fs.readdirSync('src/extraction/wasm').filter(f=>f.endsWith('.wasm')).forEach(f=>fs.copyFileSync('src/extraction/wasm/'+f,'dist/extraction/wasm/'+f));fs.mkdirSync('dist/extraction/runtime',{recursive:true});fs.copyFileSync('src/extraction/runtime/tree-sitter.wasm','dist/extraction/runtime/tree-sitter.wasm')\"", "dev": "tsc --watch", "build:kernel": "bash scripts/build-kernel.sh", "cli": "npm run build && node dist/bin/codegraph.js", @@ -58,7 +58,7 @@ "picomatch": "^4.0.3", "sisteransi": "^1.0.5", "tree-sitter-wasms": "^0.1.11", - "web-tree-sitter": "^0.25.3" + "web-tree-sitter": "0.25.10" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^6.2.4", diff --git a/scripts/check-ui-build.mjs b/scripts/check-ui-build.mjs index 9bdd22a849..62b0912d50 100644 --- a/scripts/check-ui-build.mjs +++ b/scripts/check-ui-build.mjs @@ -149,9 +149,21 @@ if (missingGrammars.length > 0) { ); } +// The vendored tree-sitter runtime (see src/extraction/grammars.ts RUNTIME_WASM_PATH): without it +// initGrammars() throws, so every parse fails. Copied by copy-assets like the grammars. +const runtimeWasm = join(root, 'dist', 'extraction', 'runtime', 'tree-sitter.wasm'); +if (!existsSync(runtimeWasm)) { + fail( + `missing ${runtimeWasm}`, + staged + ? 'dist/extraction/runtime was not copied into the bundle — re-run scripts/build-bundle.sh' + : 'run `npm run copy-assets` (it copies src/extraction/runtime/tree-sitter.wasm into dist/)' + ); +} + const grammarCount = readdirSync(wasmDir).filter((n) => n.endsWith('.wasm')).length; console.log( `[check-ui-build] dist/viewer ok (index.html + ${assets} referenced asset(s)); ` + - `dist/extraction/wasm ok (${grammarCount} grammars); dist/ engine intact` + `dist/extraction/wasm ok (${grammarCount} grammars); runtime ok; dist/ engine intact` ); diff --git a/src/extraction/grammars.ts b/src/extraction/grammars.ts index 6d7556dd1a..a03f297fbd 100644 --- a/src/extraction/grammars.ts +++ b/src/extraction/grammars.ts @@ -342,6 +342,15 @@ const unavailableGrammarErrors = new Map(); let parserInitialized = false; +/** + * The tree-sitter runtime wasm, vendored in place of web-tree-sitter's own: the + * same v0.25.10 build plus tree-sitter/tree-sitter#5997, without which error + * recovery loops forever on some broken input (`c:d(e f)` in a .tsx + * file). 0.27.1 has the fix but cannot load the legacy-`dylink` grammars from + * tree-sitter-wasms. See docs/grammars/web-tree-sitter-runtime.md. + */ +export const RUNTIME_WASM_PATH = path.join(__dirname, 'runtime', 'tree-sitter.wasm'); + /** * Initialize the tree-sitter WASM runtime. Must be called before loading grammars. * Does NOT load any grammar WASM files — use loadGrammarsForLanguages() for that. @@ -350,7 +359,15 @@ let parserInitialized = false; export async function initGrammars(): Promise { if (parserInitialized) return; - await Parser.init(); + // Fail loudly rather than fall back to the npm runtime, which would bring the hang back. + if (!fs.existsSync(RUNTIME_WASM_PATH)) { + throw new Error(`tree-sitter runtime missing: ${RUNTIME_WASM_PATH} (npm run copy-assets copies it into dist/)`); + } + await Parser.init({ + // Emscripten's default is scriptDirectory + file; only the runtime itself is swapped. + locateFile: (file: string, scriptDirectory: string) => + file === 'tree-sitter.wasm' ? RUNTIME_WASM_PATH : scriptDirectory + file, + }); parserInitialized = true; } diff --git a/src/extraction/runtime/tree-sitter.wasm b/src/extraction/runtime/tree-sitter.wasm new file mode 100755 index 0000000000000000000000000000000000000000..340a3d720747ef06e421c0c3871fe9b006cc541f GIT binary patch literal 205492 zcmb@v3z%Kkb>DX$_x+f;0}Oxx1_bv#9N7a25aEagSb>dkQIa4{%3@-+<=5)#00c$^ zWc)6i(!jO(d6Tl$K7}nsyYINt8xuXos# z`l*dvOICmXwf4D>nE^=W3nk3i_ndw9UVH8J-fQoZoVxO4n($w*apvRa&s|u3|Dm+{ z{C`r}m!vACf_<>jR-=hoMk*Oty-d}8VJsq^O_KXrOFsp|2b@yC}=tzB6jRj8}NZ4(vN zEB`xQ>(p3&`rPuzzNhig zGfSt>U%axM+^WXM*3PXjCpGofTsrmm#kKXNl`Bc(CT&j9;OW(+^>a@yFFmomp7d@~ zuTI}rmX}wP88y6f`N=D%*Unv9U%s%!D9`<8%S&gMPhCn9J)B-zy0Q-1mM&d9cL7}H zS8eFsrKKmApS;M3A3t?vIlpRkJ4;LJryf7QT;8jn`0%6er&@c-8jQE?{hGg>rPnIg zu4U?I_tMh23un%)EuUUr`sh;^POqQ4c)^=XFD3i(AJ0CWH5!d1P3vhU+D(#5T1(SP znxz#$<#$%CW=S>a@T-~UdD^UZt67$%`L^wqdS1;d>1;Ev@w=1PTS?Yx^02CxlM4T( z`Y*4xshFnKW{c+SUbR}UCdrPZLeoj6nw7lLZdCJDEy>a}Qy1}%fJ#(N|78wk2E

ch!{UVcjfgQ-SA6 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%0APcSiu$c$w;hB=8RZbJM!)J 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 literal 0 HcmV?d00001 From 8d405ac0a1b1bb0671095f894b43fce4d05c70b2 Mon Sep 17 00:00:00 2001 From: Eric Minish Date: Fri, 6 Nov 2026 17:11:51 -0500 Subject: [PATCH 2/3] fix(kernel,scripts): patched tree-sitter runtime on every path (PR #18 review round 1) F1 kernel: codegraph-kernel/vendor/tree-sitter = crates.io tree-sitter 0.25.10 (its parser.c == git v0.25.10) + the #5997 patch, via [patch.crates-io]. Kernel hang test (child process, 10s): unpatched crate -> tsx ETIMEDOUT; patched -> 5/5 pass. F2 dev scripts (ts-differential, add-lang/dump-ast, add-lang/check-grammar, gen-go-stdlib-methods) and grammar-wasm-bytes test init through the vendored runtime (scripts/tree-sitter-runtime.mjs); dump-ast on the PoC: exit 124 -> 0. F5 check-ui-build verifies the dist runtime's sha256 (npm wasm swapped in -> exit 1). F7 drop the hang test's redundant wall-clock assertion. F8 CHANGELOG/doc: both paths covered. Suite with the kernel built: 11099 passed, 0 failed. Kernel tests: 312 passed. ts-differential: exit 0, 0 new / 0 worse. --- .github/workflows/ts-differential.yml | 4 + CHANGELOG.md | 2 +- __tests__/grammar-wasm-bytes.test.ts | 4 +- __tests__/tsx-error-recovery-hang.test.ts | 29 +- codegraph-kernel/Cargo.lock | 2 - codegraph-kernel/Cargo.toml | 6 + .../vendor/tree-sitter/Cargo.toml | 170 + .../vendor/tree-sitter/Cargo.toml.orig | 66 + .../vendor/tree-sitter/binding_rust/README.md | 116 + .../tree-sitter/binding_rust/bindings.rs | 963 ++++ .../vendor/tree-sitter/binding_rust/build.rs | 122 + .../vendor/tree-sitter/binding_rust/ffi.rs | 216 + .../vendor/tree-sitter/binding_rust/lib.rs | 3937 +++++++++++++++ .../vendor/tree-sitter/binding_rust/util.rs | 45 + .../tree-sitter/binding_rust/wasm_language.rs | 147 + .../tree-sitter/include/tree_sitter/api.h | 1478 ++++++ .../vendor/tree-sitter/src/alloc.c | 48 + .../vendor/tree-sitter/src/alloc.h | 41 + .../vendor/tree-sitter/src/array.h | 291 ++ .../vendor/tree-sitter/src/atomic.h | 68 + .../vendor/tree-sitter/src/clock.h | 146 + .../vendor/tree-sitter/src/error_costs.h | 11 + .../tree-sitter/src/get_changed_ranges.c | 523 ++ .../tree-sitter/src/get_changed_ranges.h | 36 + .../vendor/tree-sitter/src/host.h | 21 + .../vendor/tree-sitter/src/language.c | 293 ++ .../vendor/tree-sitter/src/language.h | 293 ++ .../vendor/tree-sitter/src/length.h | 52 + .../vendor/tree-sitter/src/lexer.c | 483 ++ .../vendor/tree-sitter/src/lexer.h | 54 + codegraph-kernel/vendor/tree-sitter/src/lib.c | 12 + .../vendor/tree-sitter/src/node.c | 875 ++++ .../vendor/tree-sitter/src/parser.c | 2300 +++++++++ .../vendor/tree-sitter/src/parser.h | 286 ++ .../vendor/tree-sitter/src/point.h | 48 + .../vendor/tree-sitter/src/portable/endian.h | 241 + .../vendor/tree-sitter/src/query.c | 4347 +++++++++++++++++ .../vendor/tree-sitter/src/reduce_action.h | 34 + .../vendor/tree-sitter/src/reusable_node.h | 95 + .../vendor/tree-sitter/src/stack.c | 912 ++++ .../vendor/tree-sitter/src/stack.h | 133 + .../vendor/tree-sitter/src/subtree.c | 1034 ++++ .../vendor/tree-sitter/src/subtree.h | 399 ++ .../vendor/tree-sitter/src/tree.c | 170 + .../vendor/tree-sitter/src/tree.h | 31 + .../vendor/tree-sitter/src/tree_cursor.c | 716 +++ .../vendor/tree-sitter/src/tree_cursor.h | 48 + .../vendor/tree-sitter/src/ts_assert.h | 11 + .../vendor/tree-sitter/src/unicode.h | 75 + .../vendor/tree-sitter/src/unicode/ICU_SHA | 1 + .../vendor/tree-sitter/src/unicode/LICENSE | 414 ++ .../vendor/tree-sitter/src/unicode/README.md | 29 + .../vendor/tree-sitter/src/unicode/ptypes.h | 1 + .../vendor/tree-sitter/src/unicode/umachine.h | 448 ++ .../vendor/tree-sitter/src/unicode/urename.h | 1 + .../vendor/tree-sitter/src/unicode/utf.h | 1 + .../vendor/tree-sitter/src/unicode/utf16.h | 733 +++ .../vendor/tree-sitter/src/unicode/utf8.h | 881 ++++ .../tree-sitter/src/wasm/stdlib-symbols.txt | 24 + .../vendor/tree-sitter/src/wasm/stdlib.c | 137 + .../vendor/tree-sitter/src/wasm/wasm-stdlib.h | 1314 +++++ .../vendor/tree-sitter/src/wasm_store.c | 1937 ++++++++ .../vendor/tree-sitter/src/wasm_store.h | 31 + docs/grammars/web-tree-sitter-runtime.md | 17 +- scripts/add-lang/check-grammar.mjs | 4 +- scripts/add-lang/dump-ast.mjs | 7 +- scripts/check-ui-build.mjs | 11 + scripts/gen-go-stdlib-methods.mjs | 3 +- scripts/tree-sitter-runtime.mjs | 25 + scripts/ts-differential.mjs | 3 +- 70 files changed, 27437 insertions(+), 19 deletions(-) create mode 100644 codegraph-kernel/vendor/tree-sitter/Cargo.toml create mode 100644 codegraph-kernel/vendor/tree-sitter/Cargo.toml.orig create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/README.md create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/bindings.rs create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/build.rs create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/ffi.rs create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/lib.rs create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/util.rs create mode 100644 codegraph-kernel/vendor/tree-sitter/binding_rust/wasm_language.rs create mode 100644 codegraph-kernel/vendor/tree-sitter/include/tree_sitter/api.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/alloc.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/alloc.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/array.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/atomic.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/clock.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/error_costs.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/host.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/language.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/language.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/length.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/lexer.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/lexer.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/lib.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/node.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/parser.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/parser.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/point.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/portable/endian.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/query.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/reduce_action.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/reusable_node.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/stack.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/stack.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/subtree.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/subtree.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/tree.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/tree.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/tree_cursor.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/tree_cursor.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/ts_assert.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/ICU_SHA create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/LICENSE create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/README.md create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/ptypes.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/umachine.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/urename.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/utf.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/utf16.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/unicode/utf8.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib-symbols.txt create mode 100644 codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/wasm/wasm-stdlib.h create mode 100644 codegraph-kernel/vendor/tree-sitter/src/wasm_store.c create mode 100644 codegraph-kernel/vendor/tree-sitter/src/wasm_store.h create mode 100644 scripts/tree-sitter-runtime.mjs diff --git a/.github/workflows/ts-differential.yml b/.github/workflows/ts-differential.yml index 902b72c336..1e4446ddea 100644 --- a/.github/workflows/ts-differential.yml +++ b/.github/workflows/ts-differential.yml @@ -13,6 +13,8 @@ on: - 'codegraph-kernel/grammars/typescript/**' - 'docs/grammars/tree-sitter-typescript.*' - 'scripts/ts-differential.mjs' + - 'scripts/tree-sitter-runtime.mjs' + - 'src/extraction/runtime/**' - 'scripts/ts-differential.corpora.json' - 'scripts/ts-differential.baseline.json' - '__tests__/fixtures/ts-syntax/**' @@ -27,6 +29,8 @@ on: - 'codegraph-kernel/grammars/typescript/**' - 'docs/grammars/tree-sitter-typescript.*' - 'scripts/ts-differential.mjs' + - 'scripts/tree-sitter-runtime.mjs' + - 'src/extraction/runtime/**' - 'scripts/ts-differential.corpora.json' - 'scripts/ts-differential.baseline.json' - '__tests__/fixtures/ts-syntax/**' diff --git a/CHANGELOG.md b/CHANGELOG.md index ccd1530b2e..36616009f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixes -- A TSX file holding a broken JSX attribute such as `c:d(e f)` no longer costs each index run three 30-second worker kills and then gets dropped. It now parses in milliseconds and is indexed like any other file with a syntax error. The hang was in tree-sitter's error recovery. CodeGraph now ships web-tree-sitter 0.25.10's runtime with the upstream fix (tree-sitter/tree-sitter#5997) applied, because 0.27.1, the first release that has it, cannot load most of the grammars CodeGraph uses. +- A TSX file holding a broken JSX attribute such as `c:d(e f)` no longer costs each index run three 30-second worker kills and then gets dropped. It now parses in milliseconds and is indexed like any other file with a syntax error. The hang was in tree-sitter's error recovery. CodeGraph now ships web-tree-sitter 0.25.10's runtime with the upstream fix (tree-sitter/tree-sitter#5997) applied, because 0.27.1, the first release that has it, cannot load most of the grammars CodeGraph uses. The native kernel builds against the same patched runtime. - TypeScript variance annotations like `interface Stream` or `` now parse. Before, each one was a parse error, and in a large file enough of them could make the whole file fail to parse and show up with almost no symbols. Re-index TypeScript projects after upgrading. - In TypeScript, an awaited call with type arguments like `await fetchApi("/me")` or `await api.get(url)` now links to the function it calls. Before, the call was dropped, so typed fetch wrappers looked like they had no callers. (#2586) - In JavaScript and TypeScript, a call or `new` in a parameter's default value, like `function renderWithNote(note = buildNote())`, a destructured `{ size = defaultSize() }` or `constructor(private svc = new Service())`, now counts as the function's own call. Before, it was dropped, so `buildNote` was missing that caller and impact on it came back incomplete. Re-index JavaScript and TypeScript projects after upgrading. Thanks @inth3shadows for the report and the pull request. (#2588) diff --git a/__tests__/grammar-wasm-bytes.test.ts b/__tests__/grammar-wasm-bytes.test.ts index e2daa2746d..46781734b4 100644 --- a/__tests__/grammar-wasm-bytes.test.ts +++ b/__tests__/grammar-wasm-bytes.test.ts @@ -9,7 +9,7 @@ */ import { describe, it, expect } from 'vitest'; import { Parser, Language as WasmLanguage } from 'web-tree-sitter'; -import { readGrammarWasmBytes } from '../src/extraction/grammars'; +import { initGrammars, readGrammarWasmBytes } from '../src/extraction/grammars'; describe('readGrammarWasmBytes', () => { it('reads bytes for a tree-sitter-wasms grammar and a vendored grammar', async () => { @@ -31,7 +31,7 @@ describe('readGrammarWasmBytes', () => { }); it('produces bytes web-tree-sitter can load into a working parser', async () => { - await Parser.init(); + await initGrammars(); const bytes = await readGrammarWasmBytes(['javascript']); const language = await WasmLanguage.load(bytes.javascript); const parser = new Parser(); diff --git a/__tests__/tsx-error-recovery-hang.test.ts b/__tests__/tsx-error-recovery-hang.test.ts index acd8632089..95cb68b856 100644 --- a/__tests__/tsx-error-recovery-hang.test.ts +++ b/__tests__/tsx-error-recovery-hang.test.ts @@ -11,6 +11,7 @@ import { describe, it, expect, beforeAll } from 'vitest'; import * as fs from 'fs'; import * as path from 'path'; +import { spawnSync } from 'child_process'; import { initGrammars, loadGrammarsForLanguages, getParser, RUNTIME_WASM_PATH } from '../src/extraction/grammars'; import { parseWithinBudget } from '../src/extraction/parse-budget'; @@ -38,14 +39,38 @@ describe('vendored tree-sitter runtime', () => { }); }); +// The native kernel links the same runtime C (codegraph-kernel/vendor/tree-sitter, patched). +// A native parse cannot be cancelled from JS, so it runs in a child with a hard timeout. +// The kernel throws `defer: parse tree contains errors` for an erroring tree (the file then +// goes to wasm): that is a finished parse, so it counts as done. +const KERNEL_PATH = path.join(__dirname, '..', 'codegraph-kernel', 'prebuilds', `${process.platform}-${process.arch}`, 'codegraph-kernel.node'); +const KERNEL_CHILD = ` +const k = require(process.argv[1]); +const [src, lang] = [process.argv[2], process.argv[3]]; +try { k.extractFile(lang === 'tsx' ? 'poc.tsx' : 'poc.ts', src, lang); } +catch (e) { if (!String(e && e.message).startsWith('defer:')) throw e; } +console.log('done'); +`; + +describe.skipIf(!fs.existsSync(KERNEL_PATH))('kernel: error recovery finishes on the same input', () => { + it.each(['tsx', 'typescript'] as const)('%s', (language) => { + for (const src of HANG_INPUTS) { + const child = spawnSync(process.execPath, ['-e', KERNEL_CHILD, KERNEL_PATH, src, language], { + encoding: 'utf8', + timeout: 10_000, + }); + expect(child.error?.message, `${language}: ${JSON.stringify(src)} — kernel parse did not finish within 10s`).toBeUndefined(); + expect(child.stdout.trim(), child.stderr).toBe('done'); + } + }); +}); + describe('error recovery finishes on input that once looped forever', () => { it.each(['tsx', 'typescript'] as const)('%s', (language) => { for (const src of HANG_INPUTS) { - const started = Date.now(); const tree = parseWithinBudget(getParser(language)!, src, 2000); expect(tree, `${language}: ${JSON.stringify(src)} did not finish within 2000ms`).not.toBeNull(); expect(tree!.rootNode.hasError).toBe(true); - expect(Date.now() - started).toBeLessThan(2000); tree!.delete(); } }); diff --git a/codegraph-kernel/Cargo.lock b/codegraph-kernel/Cargo.lock index c6725f332d..9c6ea49839 100644 --- a/codegraph-kernel/Cargo.lock +++ b/codegraph-kernel/Cargo.lock @@ -481,8 +481,6 @@ dependencies = [ [[package]] name = "tree-sitter" version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" dependencies = [ "cc", "regex", diff --git a/codegraph-kernel/Cargo.toml b/codegraph-kernel/Cargo.toml index ae15a1b5de..65fbc4659a 100644 --- a/codegraph-kernel/Cargo.toml +++ b/codegraph-kernel/Cargo.toml @@ -76,3 +76,9 @@ cc = "1" lto = true codegen-units = 1 strip = "symbols" + +# tree-sitter 0.25.10 + tree-sitter/tree-sitter#5997 (error-recovery livelock), the same +# runtime C as the wasm path's src/extraction/runtime/tree-sitter.wasm. Patch: +# docs/grammars/web-tree-sitter-runtime.patch. See docs/grammars/web-tree-sitter-runtime.md. +[patch.crates-io] +tree-sitter = { path = "vendor/tree-sitter" } diff --git a/codegraph-kernel/vendor/tree-sitter/Cargo.toml b/codegraph-kernel/vendor/tree-sitter/Cargo.toml new file mode 100644 index 0000000000..ff4b7bc099 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/Cargo.toml @@ -0,0 +1,170 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.76" +name = "tree-sitter" +version = "0.25.10" +authors = [ + "Max Brunsfeld ", + "Amaan Qureshi ", +] +build = "binding_rust/build.rs" +links = "tree-sitter" +include = [ + "/binding_rust/*", + "/Cargo.toml", + "/src/*.h", + "/src/*.c", + "/src/portable/*", + "/src/unicode/*", + "/src/wasm/*", + "/include/tree_sitter/api.h", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Rust bindings to the Tree-sitter parsing library" +homepage = "https://tree-sitter.github.io/tree-sitter" +readme = "binding_rust/README.md" +keywords = [ + "incremental", + "parsing", +] +categories = [ + "api-bindings", + "external-ffi-bindings", + "parsing", + "text-editors", +] +license = "MIT" +repository = "https://github.com/tree-sitter/tree-sitter" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] +targets = [ + "x86_64-unknown-linux-gnu", + "x86_64-pc-windows-gnu", +] + +[features] +default = ["std"] +std = [ + "regex/std", + "regex/perf", + "regex-syntax/unicode", +] +wasm = [ + "std", + "wasmtime-c-api", +] + +[lib] +name = "tree_sitter" +path = "binding_rust/lib.rs" + +[dependencies.regex] +version = "1.11.1" +features = ["unicode"] +default-features = false + +[dependencies.regex-syntax] +version = "0.8.5" +default-features = false + +[dependencies.streaming-iterator] +version = "0.1.9" + +[dependencies.tree-sitter-language] +version = "0.1" + +[dependencies.wasmtime-c-api] +version = "29.0.1" +features = [ + "cranelift", + "gc-drc", +] +optional = true +default-features = false +package = "wasmtime-c-api-impl" + +[build-dependencies.bindgen] +version = "0.71.1" +optional = true + +[build-dependencies.cc] +version = "1.2.10" + +[build-dependencies.serde_json] +version = "1.0.137" +features = ["preserve_order"] + +[lints.clippy] +branches_sharing_code = "allow" +cast_lossless = "allow" +cast_possible_truncation = "allow" +cast_possible_wrap = "allow" +cast_precision_loss = "allow" +cast_sign_loss = "allow" +checked_conversions = "allow" +cognitive_complexity = "allow" +collection_is_never_read = "allow" +dbg_macro = "deny" +fallible_impl_from = "allow" +fn_params_excessive_bools = "allow" +if_not_else = "allow" +inline_always = "allow" +items_after_statements = "allow" +match_wildcard_for_single_variants = "allow" +missing_errors_doc = "allow" +missing_panics_doc = "allow" +module_name_repetitions = "allow" +multiple_crate_versions = "allow" +needless_for_each = "allow" +obfuscated_if_else = "allow" +option_if_let_else = "allow" +or_fun_call = "allow" +range_plus_one = "allow" +redundant_clone = "allow" +redundant_closure_for_method_calls = "allow" +ref_option = "allow" +similar_names = "allow" +string_lit_as_bytes = "allow" +struct_excessive_bools = "allow" +struct_field_names = "allow" +todo = "deny" +too_many_lines = "allow" +transmute_undefined_repr = "allow" +unnecessary_wraps = "allow" +unused_self = "allow" +used_underscore_items = "allow" + +[lints.clippy.cargo] +level = "warn" +priority = -1 + +[lints.clippy.nursery] +level = "warn" +priority = -1 + +[lints.clippy.pedantic] +level = "warn" +priority = -1 + +[lints.rust] +mismatched_lifetime_syntaxes = "allow" diff --git a/codegraph-kernel/vendor/tree-sitter/Cargo.toml.orig b/codegraph-kernel/vendor/tree-sitter/Cargo.toml.orig new file mode 100644 index 0000000000..9b4a3352c4 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/Cargo.toml.orig @@ -0,0 +1,66 @@ +[package] +name = "tree-sitter" +version.workspace = true +description = "Rust bindings to the Tree-sitter parsing library" +authors.workspace = true +edition.workspace = true +rust-version = "1.76" +readme = "binding_rust/README.md" +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories = [ + "api-bindings", + "external-ffi-bindings", + "parsing", + "text-editors", +] + +build = "binding_rust/build.rs" +links = "tree-sitter" + +include = [ + "/binding_rust/*", + "/Cargo.toml", + "/src/*.h", + "/src/*.c", + "/src/portable/*", + "/src/unicode/*", + "/src/wasm/*", + "/include/tree_sitter/api.h", +] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] +targets = ["x86_64-unknown-linux-gnu", "x86_64-pc-windows-gnu"] + +[lints] +workspace = true + +[features] +default = ["std"] +std = ["regex/std", "regex/perf", "regex-syntax/unicode"] +wasm = ["std", "wasmtime-c-api"] + +[dependencies] +regex = { version = "1.11.1", default-features = false, features = ["unicode"] } +regex-syntax = { version = "0.8.5", default-features = false } +tree-sitter-language = { version = "0.1", path = "language" } +streaming-iterator = "0.1.9" + +[dependencies.wasmtime-c-api] +version = "29.0.1" +optional = true +package = "wasmtime-c-api-impl" +default-features = false +features = ["cranelift", "gc-drc"] + +[build-dependencies] +bindgen = { version = "0.71.1", optional = true } +cc.workspace = true +serde_json.workspace = true + +[lib] +path = "binding_rust/lib.rs" diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/README.md b/codegraph-kernel/vendor/tree-sitter/binding_rust/README.md new file mode 100644 index 0000000000..602f647b02 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/README.md @@ -0,0 +1,116 @@ +# Rust Tree-sitter + +[![crates.io badge]][crates.io] + +[crates.io]: https://crates.io/crates/tree-sitter +[crates.io badge]: https://img.shields.io/crates/v/tree-sitter.svg?color=%23B48723 + +Rust bindings to the [Tree-sitter][] parsing library. + +## Basic Usage + +First, create a parser: + +```rust +use tree_sitter::{InputEdit, Language, Parser, Point}; + +let mut parser = Parser::new(); +``` + +Add the `cc` crate to your `Cargo.toml` under `[build-dependencies]`: + +```toml +[build-dependencies] +cc="*" +``` + +Then, add a language as a dependency: + +```toml +[dependencies] +tree-sitter = "0.24" +tree-sitter-rust = "0.23" +``` + +To then use a language, you assign them to the parser. + +```rust +parser.set_language(&tree_sitter_rust::LANGUAGE.into()).expect("Error loading Rust grammar"); +``` + +Now you can parse source code: + +```rust +let source_code = "fn test() {}"; +let mut tree = parser.parse(source_code, None).unwrap(); +let root_node = tree.root_node(); + +assert_eq!(root_node.kind(), "source_file"); +assert_eq!(root_node.start_position().column, 0); +assert_eq!(root_node.end_position().column, 12); +``` + +### Editing + +Once you have a syntax tree, you can update it when your source code changes. +Passing in the previous edited tree makes `parse` run much more quickly: + +```rust +let new_source_code = "fn test(a: u32) {}"; + +tree.edit(&InputEdit { + start_byte: 8, + old_end_byte: 8, + new_end_byte: 14, + start_position: Point::new(0, 8), + old_end_position: Point::new(0, 8), + new_end_position: Point::new(0, 14), +}); + +let new_tree = parser.parse(new_source_code, Some(&tree)); +``` + +### Text Input + +The source code to parse can be provided either as a string, a slice, a vector, +or as a function that returns a slice. The text can be encoded as either UTF8 or UTF16: + +```rust +// Store some source code in an array of lines. +let lines = &[ + "pub fn foo() {", + " 1", + "}", +]; + +// Parse the source code using a custom callback. The callback is called +// with both a byte offset and a row/column offset. +let tree = parser.parse_with(&mut |_byte: usize, position: Point| -> &[u8] { + let row = position.row as usize; + let column = position.column as usize; + if row < lines.len() { + if column < lines[row].as_bytes().len() { + &lines[row].as_bytes()[column..] + } else { + b"\n" + } + } else { + &[] + } +}, None).unwrap(); + +assert_eq!( + tree.root_node().to_sexp(), + "(source_file (function_item (visibility_modifier) (identifier) (parameters) (block (number_literal))))" +); +``` + +[tree-sitter]: https://github.com/tree-sitter/tree-sitter + +## Features + +- **std** - This feature is enabled by default and allows `tree-sitter` to use the standard library. + - Error types implement the `std::error:Error` trait. + - `regex` performance optimizations are enabled. + - The DOT graph methods are enabled. +- **wasm** - This feature allows `tree-sitter` to be built for Wasm targets using the `wasmtime-c-api` crate. diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/bindings.rs b/codegraph-kernel/vendor/tree-sitter/binding_rust/bindings.rs new file mode 100644 index 0000000000..8323bd0661 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/bindings.rs @@ -0,0 +1,963 @@ +/* automatically generated by rust-bindgen 0.71.1 */ + +pub const TREE_SITTER_LANGUAGE_VERSION: u32 = 15; +pub const TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION: u32 = 13; +pub type TSStateId = u16; +pub type TSSymbol = u16; +pub type TSFieldId = u16; +#[repr(C)] +#[derive(Debug)] +pub struct TSLanguage { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug)] +pub struct TSParser { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug)] +pub struct TSTree { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug)] +pub struct TSQuery { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug)] +pub struct TSQueryCursor { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug)] +pub struct TSLookaheadIterator { + _unused: [u8; 0], +} +pub type DecodeFunction = ::core::option::Option< + unsafe extern "C" fn(string: *const u8, length: u32, code_point: *mut i32) -> u32, +>; +pub const TSInputEncodingUTF8: TSInputEncoding = 0; +pub const TSInputEncodingUTF16LE: TSInputEncoding = 1; +pub const TSInputEncodingUTF16BE: TSInputEncoding = 2; +pub const TSInputEncodingCustom: TSInputEncoding = 3; +pub type TSInputEncoding = ::core::ffi::c_uint; +pub const TSSymbolTypeRegular: TSSymbolType = 0; +pub const TSSymbolTypeAnonymous: TSSymbolType = 1; +pub const TSSymbolTypeSupertype: TSSymbolType = 2; +pub const TSSymbolTypeAuxiliary: TSSymbolType = 3; +pub type TSSymbolType = ::core::ffi::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSPoint { + pub row: u32, + pub column: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSRange { + pub start_point: TSPoint, + pub end_point: TSPoint, + pub start_byte: u32, + pub end_byte: u32, +} +#[repr(C)] +#[derive(Debug)] +pub struct TSInput { + pub payload: *mut ::core::ffi::c_void, + pub read: ::core::option::Option< + unsafe extern "C" fn( + payload: *mut ::core::ffi::c_void, + byte_index: u32, + position: TSPoint, + bytes_read: *mut u32, + ) -> *const ::core::ffi::c_char, + >, + pub encoding: TSInputEncoding, + pub decode: DecodeFunction, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSParseState { + pub payload: *mut ::core::ffi::c_void, + pub current_byte_offset: u32, + pub has_error: bool, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSParseOptions { + pub payload: *mut ::core::ffi::c_void, + pub progress_callback: + ::core::option::Option bool>, +} +pub const TSLogTypeParse: TSLogType = 0; +pub const TSLogTypeLex: TSLogType = 1; +pub type TSLogType = ::core::ffi::c_uint; +#[repr(C)] +#[derive(Debug)] +pub struct TSLogger { + pub payload: *mut ::core::ffi::c_void, + pub log: ::core::option::Option< + unsafe extern "C" fn( + payload: *mut ::core::ffi::c_void, + log_type: TSLogType, + buffer: *const ::core::ffi::c_char, + ), + >, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSInputEdit { + pub start_byte: u32, + pub old_end_byte: u32, + pub new_end_byte: u32, + pub start_point: TSPoint, + pub old_end_point: TSPoint, + pub new_end_point: TSPoint, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSNode { + pub context: [u32; 4usize], + pub id: *const ::core::ffi::c_void, + pub tree: *const TSTree, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSTreeCursor { + pub tree: *const ::core::ffi::c_void, + pub id: *const ::core::ffi::c_void, + pub context: [u32; 3usize], +} +#[repr(C)] +#[derive(Debug)] +pub struct TSQueryCapture { + pub node: TSNode, + pub index: u32, +} +pub const TSQuantifierZero: TSQuantifier = 0; +pub const TSQuantifierZeroOrOne: TSQuantifier = 1; +pub const TSQuantifierZeroOrMore: TSQuantifier = 2; +pub const TSQuantifierOne: TSQuantifier = 3; +pub const TSQuantifierOneOrMore: TSQuantifier = 4; +pub type TSQuantifier = ::core::ffi::c_uint; +#[repr(C)] +#[derive(Debug)] +pub struct TSQueryMatch { + pub id: u32, + pub pattern_index: u16, + pub capture_count: u16, + pub captures: *const TSQueryCapture, +} +pub const TSQueryPredicateStepTypeDone: TSQueryPredicateStepType = 0; +pub const TSQueryPredicateStepTypeCapture: TSQueryPredicateStepType = 1; +pub const TSQueryPredicateStepTypeString: TSQueryPredicateStepType = 2; +pub type TSQueryPredicateStepType = ::core::ffi::c_uint; +#[repr(C)] +#[derive(Debug)] +pub struct TSQueryPredicateStep { + pub type_: TSQueryPredicateStepType, + pub value_id: u32, +} +pub const TSQueryErrorNone: TSQueryError = 0; +pub const TSQueryErrorSyntax: TSQueryError = 1; +pub const TSQueryErrorNodeType: TSQueryError = 2; +pub const TSQueryErrorField: TSQueryError = 3; +pub const TSQueryErrorCapture: TSQueryError = 4; +pub const TSQueryErrorStructure: TSQueryError = 5; +pub const TSQueryErrorLanguage: TSQueryError = 6; +pub type TSQueryError = ::core::ffi::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSQueryCursorState { + pub payload: *mut ::core::ffi::c_void, + pub current_byte_offset: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSQueryCursorOptions { + pub payload: *mut ::core::ffi::c_void, + pub progress_callback: + ::core::option::Option bool>, +} +#[doc = " The metadata associated with a language.\n\n Currently, this metadata can be used to check the [Semantic Version](https://semver.org/)\n of the language. This version information should be used to signal if a given parser might\n be incompatible with existing queries when upgrading between major versions, or minor versions\n if it's in zerover."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSLanguageMetadata { + pub major_version: u8, + pub minor_version: u8, + pub patch_version: u8, +} +extern "C" { + #[doc = " Create a new parser."] + pub fn ts_parser_new() -> *mut TSParser; +} +extern "C" { + #[doc = " Delete the parser, freeing all of the memory that it used."] + pub fn ts_parser_delete(self_: *mut TSParser); +} +extern "C" { + #[doc = " Get the parser's current language."] + pub fn ts_parser_language(self_: *const TSParser) -> *const TSLanguage; +} +extern "C" { + #[doc = " Set the language that the parser should use for parsing.\n\n Returns a boolean indicating whether or not the language was successfully\n assigned. True means assignment succeeded. False means there was a version\n mismatch: the language was generated with an incompatible version of the\n Tree-sitter CLI. Check the language's ABI version using [`ts_language_abi_version`]\n and compare it to this library's [`TREE_SITTER_LANGUAGE_VERSION`] and\n [`TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION`] constants."] + pub fn ts_parser_set_language(self_: *mut TSParser, language: *const TSLanguage) -> bool; +} +extern "C" { + #[doc = " Set the ranges of text that the parser should include when parsing.\n\n By default, the parser will always include entire documents. This function\n allows you to parse only a *portion* of a document but still return a syntax\n tree whose ranges match up with the document as a whole. You can also pass\n multiple disjoint ranges.\n\n The second and third parameters specify the location and length of an array\n of ranges. The parser does *not* take ownership of these ranges; it copies\n the data, so it doesn't matter how these ranges are allocated.\n\n If `count` is zero, then the entire document will be parsed. Otherwise,\n the given ranges must be ordered from earliest to latest in the document,\n and they must not overlap. That is, the following must hold for all:\n\n `i < count - 1`: `ranges[i].end_byte <= ranges[i + 1].start_byte`\n\n If this requirement is not satisfied, the operation will fail, the ranges\n will not be assigned, and this function will return `false`. On success,\n this function returns `true`"] + pub fn ts_parser_set_included_ranges( + self_: *mut TSParser, + ranges: *const TSRange, + count: u32, + ) -> bool; +} +extern "C" { + #[doc = " Get the ranges of text that the parser will include when parsing.\n\n The returned pointer is owned by the parser. The caller should not free it\n or write to it. The length of the array will be written to the given\n `count` pointer."] + pub fn ts_parser_included_ranges(self_: *const TSParser, count: *mut u32) -> *const TSRange; +} +extern "C" { + #[doc = " Use the parser to parse some source code and create a syntax tree.\n\n If you are parsing this document for the first time, pass `NULL` for the\n `old_tree` parameter. Otherwise, if you have already parsed an earlier\n version of this document and the document has since been edited, pass the\n previous syntax tree so that the unchanged parts of it can be reused.\n This will save time and memory. For this to work correctly, you must have\n already edited the old syntax tree using the [`ts_tree_edit`] function in a\n way that exactly matches the source code changes.\n\n The [`TSInput`] parameter lets you specify how to read the text. It has the\n following three fields:\n 1. [`read`]: A function to retrieve a chunk of text at a given byte offset\n and (row, column) position. The function should return a pointer to the\n text and write its length to the [`bytes_read`] pointer. The parser does\n not take ownership of this buffer; it just borrows it until it has\n finished reading it. The function should write a zero value to the\n [`bytes_read`] pointer to indicate the end of the document.\n 2. [`payload`]: An arbitrary pointer that will be passed to each invocation\n of the [`read`] function.\n 3. [`encoding`]: An indication of how the text is encoded. Either\n `TSInputEncodingUTF8` or `TSInputEncodingUTF16`.\n\n This function returns a syntax tree on success, and `NULL` on failure. There\n are four possible reasons for failure:\n 1. The parser does not have a language assigned. Check for this using the\n[`ts_parser_language`] function.\n 2. Parsing was cancelled due to a timeout that was set by an earlier call to\n the [`ts_parser_set_timeout_micros`] function. You can resume parsing from\n where the parser left out by calling [`ts_parser_parse`] again with the\n same arguments. Or you can start parsing from scratch by first calling\n [`ts_parser_reset`].\n 3. Parsing was cancelled using a cancellation flag that was set by an\n earlier call to [`ts_parser_set_cancellation_flag`]. You can resume parsing\n from where the parser left out by calling [`ts_parser_parse`] again with\n the same arguments.\n 4. Parsing was cancelled due to the progress callback returning true. This callback\n is passed in [`ts_parser_parse_with_options`] inside the [`TSParseOptions`] struct.\n\n [`read`]: TSInput::read\n [`payload`]: TSInput::payload\n [`encoding`]: TSInput::encoding\n [`bytes_read`]: TSInput::read"] + pub fn ts_parser_parse( + self_: *mut TSParser, + old_tree: *const TSTree, + input: TSInput, + ) -> *mut TSTree; +} +extern "C" { + #[doc = " Use the parser to parse some source code and create a syntax tree, with some options.\n\n See [`ts_parser_parse`] for more details.\n\n See [`TSParseOptions`] for more details on the options."] + pub fn ts_parser_parse_with_options( + self_: *mut TSParser, + old_tree: *const TSTree, + input: TSInput, + parse_options: TSParseOptions, + ) -> *mut TSTree; +} +extern "C" { + #[doc = " Use the parser to parse some source code stored in one contiguous buffer.\n The first two parameters are the same as in the [`ts_parser_parse`] function\n above. The second two parameters indicate the location of the buffer and its\n length in bytes."] + pub fn ts_parser_parse_string( + self_: *mut TSParser, + old_tree: *const TSTree, + string: *const ::core::ffi::c_char, + length: u32, + ) -> *mut TSTree; +} +extern "C" { + #[doc = " Use the parser to parse some source code stored in one contiguous buffer with\n a given encoding. The first four parameters work the same as in the\n [`ts_parser_parse_string`] method above. The final parameter indicates whether\n the text is encoded as UTF8 or UTF16."] + pub fn ts_parser_parse_string_encoding( + self_: *mut TSParser, + old_tree: *const TSTree, + string: *const ::core::ffi::c_char, + length: u32, + encoding: TSInputEncoding, + ) -> *mut TSTree; +} +extern "C" { + #[doc = " Instruct the parser to start the next parse from the beginning.\n\n If the parser previously failed because of a timeout or a cancellation, then\n by default, it will resume where it left off on the next call to\n [`ts_parser_parse`] or other parsing functions. If you don't want to resume,\n and instead intend to use this parser to parse some other document, you must\n call [`ts_parser_reset`] first."] + pub fn ts_parser_reset(self_: *mut TSParser); +} +extern "C" { + #[doc = " @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26.\n\n Set the maximum duration in microseconds that parsing should be allowed to\n take before halting.\n\n If parsing takes longer than this, it will halt early, returning NULL.\n See [`ts_parser_parse`] for more information."] + pub fn ts_parser_set_timeout_micros(self_: *mut TSParser, timeout_micros: u64); +} +extern "C" { + #[doc = " @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26.\n\n Get the duration in microseconds that parsing is allowed to take."] + pub fn ts_parser_timeout_micros(self_: *const TSParser) -> u64; +} +extern "C" { + #[doc = " @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26.\n\n Set the parser's current cancellation flag pointer.\n\n If a non-null pointer is assigned, then the parser will periodically read\n from this pointer during parsing. If it reads a non-zero value, it will\n halt early, returning NULL. See [`ts_parser_parse`] for more information."] + pub fn ts_parser_set_cancellation_flag(self_: *mut TSParser, flag: *const usize); +} +extern "C" { + #[doc = " @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26.\n\n Get the parser's current cancellation flag pointer."] + pub fn ts_parser_cancellation_flag(self_: *const TSParser) -> *const usize; +} +extern "C" { + #[doc = " Set the logger that a parser should use during parsing.\n\n The parser does not take ownership over the logger payload. If a logger was\n previously assigned, the caller is responsible for releasing any memory\n owned by the previous logger."] + pub fn ts_parser_set_logger(self_: *mut TSParser, logger: TSLogger); +} +extern "C" { + #[doc = " Get the parser's current logger."] + pub fn ts_parser_logger(self_: *const TSParser) -> TSLogger; +} +extern "C" { + #[doc = " Set the file descriptor to which the parser should write debugging graphs\n during parsing. The graphs are formatted in the DOT language. You may want\n to pipe these graphs directly to a `dot(1)` process in order to generate\n SVG output. You can turn off this logging by passing a negative number."] + pub fn ts_parser_print_dot_graphs(self_: *mut TSParser, fd: ::core::ffi::c_int); +} +extern "C" { + #[doc = " Create a shallow copy of the syntax tree. This is very fast.\n\n You need to copy a syntax tree in order to use it on more than one thread at\n a time, as syntax trees are not thread safe."] + pub fn ts_tree_copy(self_: *const TSTree) -> *mut TSTree; +} +extern "C" { + #[doc = " Delete the syntax tree, freeing all of the memory that it used."] + pub fn ts_tree_delete(self_: *mut TSTree); +} +extern "C" { + #[doc = " Get the root node of the syntax tree."] + pub fn ts_tree_root_node(self_: *const TSTree) -> TSNode; +} +extern "C" { + #[doc = " Get the root node of the syntax tree, but with its position\n shifted forward by the given offset."] + pub fn ts_tree_root_node_with_offset( + self_: *const TSTree, + offset_bytes: u32, + offset_extent: TSPoint, + ) -> TSNode; +} +extern "C" { + #[doc = " Get the language that was used to parse the syntax tree."] + pub fn ts_tree_language(self_: *const TSTree) -> *const TSLanguage; +} +extern "C" { + #[doc = " Get the array of included ranges that was used to parse the syntax tree.\n\n The returned pointer must be freed by the caller."] + pub fn ts_tree_included_ranges(self_: *const TSTree, length: *mut u32) -> *mut TSRange; +} +extern "C" { + #[doc = " Edit the syntax tree to keep it in sync with source code that has been\n edited.\n\n You must describe the edit both in terms of byte offsets and in terms of\n (row, column) coordinates."] + pub fn ts_tree_edit(self_: *mut TSTree, edit: *const TSInputEdit); +} +extern "C" { + #[doc = " Compare an old edited syntax tree to a new syntax tree representing the same\n document, returning an array of ranges whose syntactic structure has changed.\n\n For this to work correctly, the old syntax tree must have been edited such\n that its ranges match up to the new tree. Generally, you'll want to call\n this function right after calling one of the [`ts_parser_parse`] functions.\n You need to pass the old tree that was passed to parse, as well as the new\n tree that was returned from that function.\n\n The returned ranges indicate areas where the hierarchical structure of syntax\n nodes (from root to leaf) has changed between the old and new trees. Characters\n outside these ranges have identical ancestor nodes in both trees.\n\n Note that the returned ranges may be slightly larger than the exact changed areas,\n but Tree-sitter attempts to make them as small as possible.\n\n The returned array is allocated using `malloc` and the caller is responsible\n for freeing it using `free`. The length of the array will be written to the\n given `length` pointer."] + pub fn ts_tree_get_changed_ranges( + old_tree: *const TSTree, + new_tree: *const TSTree, + length: *mut u32, + ) -> *mut TSRange; +} +extern "C" { + #[doc = " Write a DOT graph describing the syntax tree to the given file."] + pub fn ts_tree_print_dot_graph(self_: *const TSTree, file_descriptor: ::core::ffi::c_int); +} +extern "C" { + #[doc = " Get the node's type as a null-terminated string."] + pub fn ts_node_type(self_: TSNode) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the node's type as a numerical id."] + pub fn ts_node_symbol(self_: TSNode) -> TSSymbol; +} +extern "C" { + #[doc = " Get the node's language."] + pub fn ts_node_language(self_: TSNode) -> *const TSLanguage; +} +extern "C" { + #[doc = " Get the node's type as it appears in the grammar ignoring aliases as a\n null-terminated string."] + pub fn ts_node_grammar_type(self_: TSNode) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the node's type as a numerical id as it appears in the grammar ignoring\n aliases. This should be used in [`ts_language_next_state`] instead of\n [`ts_node_symbol`]."] + pub fn ts_node_grammar_symbol(self_: TSNode) -> TSSymbol; +} +extern "C" { + #[doc = " Get the node's start byte."] + pub fn ts_node_start_byte(self_: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the node's start position in terms of rows and columns."] + pub fn ts_node_start_point(self_: TSNode) -> TSPoint; +} +extern "C" { + #[doc = " Get the node's end byte."] + pub fn ts_node_end_byte(self_: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the node's end position in terms of rows and columns."] + pub fn ts_node_end_point(self_: TSNode) -> TSPoint; +} +extern "C" { + #[doc = " Get an S-expression representing the node as a string.\n\n This string is allocated with `malloc` and the caller is responsible for\n freeing it using `free`."] + pub fn ts_node_string(self_: TSNode) -> *mut ::core::ffi::c_char; +} +extern "C" { + #[doc = " Check if the node is null. Functions like [`ts_node_child`] and\n [`ts_node_next_sibling`] will return a null node to indicate that no such node\n was found."] + pub fn ts_node_is_null(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if the node is *named*. Named nodes correspond to named rules in the\n grammar, whereas *anonymous* nodes correspond to string literals in the\n grammar."] + pub fn ts_node_is_named(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if the node is *missing*. Missing nodes are inserted by the parser in\n order to recover from certain kinds of syntax errors."] + pub fn ts_node_is_missing(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if the node is *extra*. Extra nodes represent things like comments,\n which are not required the grammar, but can appear anywhere."] + pub fn ts_node_is_extra(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if a syntax node has been edited."] + pub fn ts_node_has_changes(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if the node is a syntax error or contains any syntax errors."] + pub fn ts_node_has_error(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Check if the node is a syntax error."] + pub fn ts_node_is_error(self_: TSNode) -> bool; +} +extern "C" { + #[doc = " Get this node's parse state."] + pub fn ts_node_parse_state(self_: TSNode) -> TSStateId; +} +extern "C" { + #[doc = " Get the parse state after this node."] + pub fn ts_node_next_parse_state(self_: TSNode) -> TSStateId; +} +extern "C" { + #[doc = " Get the node's immediate parent.\n Prefer [`ts_node_child_with_descendant`] for\n iterating over the node's ancestors."] + pub fn ts_node_parent(self_: TSNode) -> TSNode; +} +extern "C" { + #[doc = " Get the node that contains `descendant`.\n\n Note that this can return `descendant` itself."] + pub fn ts_node_child_with_descendant(self_: TSNode, descendant: TSNode) -> TSNode; +} +extern "C" { + #[doc = " Get the node's child at the given index, where zero represents the first\n child."] + pub fn ts_node_child(self_: TSNode, child_index: u32) -> TSNode; +} +extern "C" { + #[doc = " Get the field name for node's child at the given index, where zero represents\n the first child. Returns NULL, if no field is found."] + pub fn ts_node_field_name_for_child( + self_: TSNode, + child_index: u32, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the field name for node's named child at the given index, where zero\n represents the first named child. Returns NULL, if no field is found."] + pub fn ts_node_field_name_for_named_child( + self_: TSNode, + named_child_index: u32, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the node's number of children."] + pub fn ts_node_child_count(self_: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the node's *named* child at the given index.\n\n See also [`ts_node_is_named`]."] + pub fn ts_node_named_child(self_: TSNode, child_index: u32) -> TSNode; +} +extern "C" { + #[doc = " Get the node's number of *named* children.\n\n See also [`ts_node_is_named`]."] + pub fn ts_node_named_child_count(self_: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the node's child with the given field name."] + pub fn ts_node_child_by_field_name( + self_: TSNode, + name: *const ::core::ffi::c_char, + name_length: u32, + ) -> TSNode; +} +extern "C" { + #[doc = " Get the node's child with the given numerical field id.\n\n You can convert a field name to an id using the\n [`ts_language_field_id_for_name`] function."] + pub fn ts_node_child_by_field_id(self_: TSNode, field_id: TSFieldId) -> TSNode; +} +extern "C" { + #[doc = " Get the node's next / previous sibling."] + pub fn ts_node_next_sibling(self_: TSNode) -> TSNode; +} +extern "C" { + pub fn ts_node_prev_sibling(self_: TSNode) -> TSNode; +} +extern "C" { + #[doc = " Get the node's next / previous *named* sibling."] + pub fn ts_node_next_named_sibling(self_: TSNode) -> TSNode; +} +extern "C" { + pub fn ts_node_prev_named_sibling(self_: TSNode) -> TSNode; +} +extern "C" { + #[doc = " Get the node's first child that contains or starts after the given byte offset."] + pub fn ts_node_first_child_for_byte(self_: TSNode, byte: u32) -> TSNode; +} +extern "C" { + #[doc = " Get the node's first named child that contains or starts after the given byte offset."] + pub fn ts_node_first_named_child_for_byte(self_: TSNode, byte: u32) -> TSNode; +} +extern "C" { + #[doc = " Get the node's number of descendants, including one for the node itself."] + pub fn ts_node_descendant_count(self_: TSNode) -> u32; +} +extern "C" { + #[doc = " Get the smallest node within this node that spans the given range of bytes\n or (row, column) positions."] + pub fn ts_node_descendant_for_byte_range(self_: TSNode, start: u32, end: u32) -> TSNode; +} +extern "C" { + pub fn ts_node_descendant_for_point_range( + self_: TSNode, + start: TSPoint, + end: TSPoint, + ) -> TSNode; +} +extern "C" { + #[doc = " Get the smallest named node within this node that spans the given range of\n bytes or (row, column) positions."] + pub fn ts_node_named_descendant_for_byte_range(self_: TSNode, start: u32, end: u32) -> TSNode; +} +extern "C" { + pub fn ts_node_named_descendant_for_point_range( + self_: TSNode, + start: TSPoint, + end: TSPoint, + ) -> TSNode; +} +extern "C" { + #[doc = " Edit the node to keep it in-sync with source code that has been edited.\n\n This function is only rarely needed. When you edit a syntax tree with the\n [`ts_tree_edit`] function, all of the nodes that you retrieve from the tree\n afterward will already reflect the edit. You only need to use [`ts_node_edit`]\n when you have a [`TSNode`] instance that you want to keep and continue to use\n after an edit."] + pub fn ts_node_edit(self_: *mut TSNode, edit: *const TSInputEdit); +} +extern "C" { + #[doc = " Check if two nodes are identical."] + pub fn ts_node_eq(self_: TSNode, other: TSNode) -> bool; +} +extern "C" { + #[doc = " Create a new tree cursor starting from the given node.\n\n A tree cursor allows you to walk a syntax tree more efficiently than is\n possible using the [`TSNode`] functions. It is a mutable object that is always\n on a certain syntax node, and can be moved imperatively to different nodes.\n\n Note that the given node is considered the root of the cursor,\n and the cursor cannot walk outside this node."] + pub fn ts_tree_cursor_new(node: TSNode) -> TSTreeCursor; +} +extern "C" { + #[doc = " Delete a tree cursor, freeing all of the memory that it used."] + pub fn ts_tree_cursor_delete(self_: *mut TSTreeCursor); +} +extern "C" { + #[doc = " Re-initialize a tree cursor to start at the original node that the cursor was\n constructed with."] + pub fn ts_tree_cursor_reset(self_: *mut TSTreeCursor, node: TSNode); +} +extern "C" { + #[doc = " Re-initialize a tree cursor to the same position as another cursor.\n\n Unlike [`ts_tree_cursor_reset`], this will not lose parent information and\n allows reusing already created cursors."] + pub fn ts_tree_cursor_reset_to(dst: *mut TSTreeCursor, src: *const TSTreeCursor); +} +extern "C" { + #[doc = " Get the tree cursor's current node."] + pub fn ts_tree_cursor_current_node(self_: *const TSTreeCursor) -> TSNode; +} +extern "C" { + #[doc = " Get the field name of the tree cursor's current node.\n\n This returns `NULL` if the current node doesn't have a field.\n See also [`ts_node_child_by_field_name`]."] + pub fn ts_tree_cursor_current_field_name( + self_: *const TSTreeCursor, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the field id of the tree cursor's current node.\n\n This returns zero if the current node doesn't have a field.\n See also [`ts_node_child_by_field_id`], [`ts_language_field_id_for_name`]."] + pub fn ts_tree_cursor_current_field_id(self_: *const TSTreeCursor) -> TSFieldId; +} +extern "C" { + #[doc = " Move the cursor to the parent of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false`\n if there was no parent node (the cursor was already on the root node).\n\n Note that the node the cursor was constructed with is considered the root\n of the cursor, and the cursor cannot walk outside this node."] + pub fn ts_tree_cursor_goto_parent(self_: *mut TSTreeCursor) -> bool; +} +extern "C" { + #[doc = " Move the cursor to the next sibling of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false`\n if there was no next sibling node.\n\n Note that the node the cursor was constructed with is considered the root\n of the cursor, and the cursor cannot walk outside this node."] + pub fn ts_tree_cursor_goto_next_sibling(self_: *mut TSTreeCursor) -> bool; +} +extern "C" { + #[doc = " Move the cursor to the previous sibling of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false` if\n there was no previous sibling node.\n\n Note, that this function may be slower than\n [`ts_tree_cursor_goto_next_sibling`] due to how node positions are stored. In\n the worst case, this will need to iterate through all the children up to the\n previous sibling node to recalculate its position. Also note that the node the cursor\n was constructed with is considered the root of the cursor, and the cursor cannot\n walk outside this node."] + pub fn ts_tree_cursor_goto_previous_sibling(self_: *mut TSTreeCursor) -> bool; +} +extern "C" { + #[doc = " Move the cursor to the first child of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false`\n if there were no children."] + pub fn ts_tree_cursor_goto_first_child(self_: *mut TSTreeCursor) -> bool; +} +extern "C" { + #[doc = " Move the cursor to the last child of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false` if\n there were no children.\n\n Note that this function may be slower than [`ts_tree_cursor_goto_first_child`]\n because it needs to iterate through all the children to compute the child's\n position."] + pub fn ts_tree_cursor_goto_last_child(self_: *mut TSTreeCursor) -> bool; +} +extern "C" { + #[doc = " Move the cursor to the node that is the nth descendant of\n the original node that the cursor was constructed with, where\n zero represents the original node itself."] + pub fn ts_tree_cursor_goto_descendant(self_: *mut TSTreeCursor, goal_descendant_index: u32); +} +extern "C" { + #[doc = " Get the index of the cursor's current node out of all of the\n descendants of the original node that the cursor was constructed with."] + pub fn ts_tree_cursor_current_descendant_index(self_: *const TSTreeCursor) -> u32; +} +extern "C" { + #[doc = " Get the depth of the cursor's current node relative to the original\n node that the cursor was constructed with."] + pub fn ts_tree_cursor_current_depth(self_: *const TSTreeCursor) -> u32; +} +extern "C" { + #[doc = " Move the cursor to the first child of its current node that contains or starts after\n the given byte offset or point.\n\n This returns the index of the child node if one was found, and returns -1\n if no such child was found."] + pub fn ts_tree_cursor_goto_first_child_for_byte( + self_: *mut TSTreeCursor, + goal_byte: u32, + ) -> i64; +} +extern "C" { + pub fn ts_tree_cursor_goto_first_child_for_point( + self_: *mut TSTreeCursor, + goal_point: TSPoint, + ) -> i64; +} +extern "C" { + pub fn ts_tree_cursor_copy(cursor: *const TSTreeCursor) -> TSTreeCursor; +} +extern "C" { + #[doc = " Create a new query from a string containing one or more S-expression\n patterns. The query is associated with a particular language, and can\n only be run on syntax nodes parsed with that language.\n\n If all of the given patterns are valid, this returns a [`TSQuery`].\n If a pattern is invalid, this returns `NULL`, and provides two pieces\n of information about the problem:\n 1. The byte offset of the error is written to the `error_offset` parameter.\n 2. The type of error is written to the `error_type` parameter."] + pub fn ts_query_new( + language: *const TSLanguage, + source: *const ::core::ffi::c_char, + source_len: u32, + error_offset: *mut u32, + error_type: *mut TSQueryError, + ) -> *mut TSQuery; +} +extern "C" { + #[doc = " Delete a query, freeing all of the memory that it used."] + pub fn ts_query_delete(self_: *mut TSQuery); +} +extern "C" { + #[doc = " Get the number of patterns, captures, or string literals in the query."] + pub fn ts_query_pattern_count(self_: *const TSQuery) -> u32; +} +extern "C" { + pub fn ts_query_capture_count(self_: *const TSQuery) -> u32; +} +extern "C" { + pub fn ts_query_string_count(self_: *const TSQuery) -> u32; +} +extern "C" { + #[doc = " Get the byte offset where the given pattern starts in the query's source.\n\n This can be useful when combining queries by concatenating their source\n code strings."] + pub fn ts_query_start_byte_for_pattern(self_: *const TSQuery, pattern_index: u32) -> u32; +} +extern "C" { + #[doc = " Get the byte offset where the given pattern ends in the query's source.\n\n This can be useful when combining queries by concatenating their source\n code strings."] + pub fn ts_query_end_byte_for_pattern(self_: *const TSQuery, pattern_index: u32) -> u32; +} +extern "C" { + #[doc = " Get all of the predicates for the given pattern in the query.\n\n The predicates are represented as a single array of steps. There are three\n types of steps in this array, which correspond to the three legal values for\n the `type` field:\n - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names\n of captures. Their `value_id` can be used with the\n [`ts_query_capture_name_for_id`] function to obtain the name of the capture.\n - `TSQueryPredicateStepTypeString` - Steps with this type represent literal\n strings. Their `value_id` can be used with the\n [`ts_query_string_value_for_id`] function to obtain their string value.\n - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels*\n that represent the end of an individual predicate. If a pattern has two\n predicates, then there will be two steps with this `type` in the array."] + pub fn ts_query_predicates_for_pattern( + self_: *const TSQuery, + pattern_index: u32, + step_count: *mut u32, + ) -> *const TSQueryPredicateStep; +} +extern "C" { + pub fn ts_query_is_pattern_rooted(self_: *const TSQuery, pattern_index: u32) -> bool; +} +extern "C" { + pub fn ts_query_is_pattern_non_local(self_: *const TSQuery, pattern_index: u32) -> bool; +} +extern "C" { + pub fn ts_query_is_pattern_guaranteed_at_step(self_: *const TSQuery, byte_offset: u32) -> bool; +} +extern "C" { + #[doc = " Get the name and length of one of the query's captures, or one of the\n query's string literals. Each capture and string is associated with a\n numeric id based on the order that it appeared in the query's source."] + pub fn ts_query_capture_name_for_id( + self_: *const TSQuery, + index: u32, + length: *mut u32, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the quantifier of the query's captures. Each capture is * associated\n with a numeric id based on the order that it appeared in the query's source."] + pub fn ts_query_capture_quantifier_for_id( + self_: *const TSQuery, + pattern_index: u32, + capture_index: u32, + ) -> TSQuantifier; +} +extern "C" { + pub fn ts_query_string_value_for_id( + self_: *const TSQuery, + index: u32, + length: *mut u32, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Disable a certain capture within a query.\n\n This prevents the capture from being returned in matches, and also avoids\n any resource usage associated with recording the capture. Currently, there\n is no way to undo this."] + pub fn ts_query_disable_capture( + self_: *mut TSQuery, + name: *const ::core::ffi::c_char, + length: u32, + ); +} +extern "C" { + #[doc = " Disable a certain pattern within a query.\n\n This prevents the pattern from matching and removes most of the overhead\n associated with the pattern. Currently, there is no way to undo this."] + pub fn ts_query_disable_pattern(self_: *mut TSQuery, pattern_index: u32); +} +extern "C" { + #[doc = " Create a new cursor for executing a given query.\n\n The cursor stores the state that is needed to iteratively search\n for matches. To use the query cursor, first call [`ts_query_cursor_exec`]\n to start running a given query on a given syntax node. Then, there are\n two options for consuming the results of the query:\n 1. Repeatedly call [`ts_query_cursor_next_match`] to iterate over all of the\n *matches* in the order that they were found. Each match contains the\n index of the pattern that matched, and an array of captures. Because\n multiple patterns can match the same set of nodes, one match may contain\n captures that appear *before* some of the captures from a previous match.\n 2. Repeatedly call [`ts_query_cursor_next_capture`] to iterate over all of the\n individual *captures* in the order that they appear. This is useful if\n don't care about which pattern matched, and just want a single ordered\n sequence of captures.\n\n If you don't care about consuming all of the results, you can stop calling\n [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] at any point.\n You can then start executing another query on another node by calling\n [`ts_query_cursor_exec`] again."] + pub fn ts_query_cursor_new() -> *mut TSQueryCursor; +} +extern "C" { + #[doc = " Delete a query cursor, freeing all of the memory that it used."] + pub fn ts_query_cursor_delete(self_: *mut TSQueryCursor); +} +extern "C" { + #[doc = " Start running a given query on a given node."] + pub fn ts_query_cursor_exec(self_: *mut TSQueryCursor, query: *const TSQuery, node: TSNode); +} +extern "C" { + #[doc = " Start running a given query on a given node, with some options."] + pub fn ts_query_cursor_exec_with_options( + self_: *mut TSQueryCursor, + query: *const TSQuery, + node: TSNode, + query_options: *const TSQueryCursorOptions, + ); +} +extern "C" { + #[doc = " Manage the maximum number of in-progress matches allowed by this query\n cursor.\n\n Query cursors have an optional maximum capacity for storing lists of\n in-progress captures. If this capacity is exceeded, then the\n earliest-starting match will silently be dropped to make room for further\n matches. This maximum capacity is optional — by default, query cursors allow\n any number of pending matches, dynamically allocating new space for them as\n needed as the query is executed."] + pub fn ts_query_cursor_did_exceed_match_limit(self_: *const TSQueryCursor) -> bool; +} +extern "C" { + pub fn ts_query_cursor_match_limit(self_: *const TSQueryCursor) -> u32; +} +extern "C" { + pub fn ts_query_cursor_set_match_limit(self_: *mut TSQueryCursor, limit: u32); +} +extern "C" { + #[doc = " @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26.\n\n Set the maximum duration in microseconds that query execution should be allowed to\n take before halting.\n\n If query execution takes longer than this, it will halt early, returning NULL.\n See [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] for more information."] + pub fn ts_query_cursor_set_timeout_micros(self_: *mut TSQueryCursor, timeout_micros: u64); +} +extern "C" { + #[doc = " @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26.\n\n Get the duration in microseconds that query execution is allowed to take.\n\n This is set via [`ts_query_cursor_set_timeout_micros`]."] + pub fn ts_query_cursor_timeout_micros(self_: *const TSQueryCursor) -> u64; +} +extern "C" { + #[doc = " Set the range of bytes in which the query will be executed.\n\n The query cursor will return matches that intersect with the given point range.\n This means that a match may be returned even if some of its captures fall\n outside the specified range, as long as at least part of the match\n overlaps with the range.\n\n For example, if a query pattern matches a node that spans a larger area\n than the specified range, but part of that node intersects with the range,\n the entire match will be returned.\n\n This will return `false` if the start byte is greater than the end byte, otherwise\n it will return `true`."] + pub fn ts_query_cursor_set_byte_range( + self_: *mut TSQueryCursor, + start_byte: u32, + end_byte: u32, + ) -> bool; +} +extern "C" { + #[doc = " Set the range of (row, column) positions in which the query will be executed.\n\n The query cursor will return matches that intersect with the given point range.\n This means that a match may be returned even if some of its captures fall\n outside the specified range, as long as at least part of the match\n overlaps with the range.\n\n For example, if a query pattern matches a node that spans a larger area\n than the specified range, but part of that node intersects with the range,\n the entire match will be returned.\n\n This will return `false` if the start point is greater than the end point, otherwise\n it will return `true`."] + pub fn ts_query_cursor_set_point_range( + self_: *mut TSQueryCursor, + start_point: TSPoint, + end_point: TSPoint, + ) -> bool; +} +extern "C" { + #[doc = " Advance to the next match of the currently running query.\n\n If there is a match, write it to `*match` and return `true`.\n Otherwise, return `false`."] + pub fn ts_query_cursor_next_match(self_: *mut TSQueryCursor, match_: *mut TSQueryMatch) + -> bool; +} +extern "C" { + pub fn ts_query_cursor_remove_match(self_: *mut TSQueryCursor, match_id: u32); +} +extern "C" { + #[doc = " Advance to the next capture of the currently running query.\n\n If there is a capture, write its match to `*match` and its index within\n the match's capture list to `*capture_index`. Otherwise, return `false`."] + pub fn ts_query_cursor_next_capture( + self_: *mut TSQueryCursor, + match_: *mut TSQueryMatch, + capture_index: *mut u32, + ) -> bool; +} +extern "C" { + #[doc = " Set the maximum start depth for a query cursor.\n\n This prevents cursors from exploring children nodes at a certain depth.\n Note if a pattern includes many children, then they will still be checked.\n\n The zero max start depth value can be used as a special behavior and\n it helps to destructure a subtree by staying on a node and using captures\n for interested parts. Note that the zero max start depth only limit a search\n depth for a pattern's root node but other nodes that are parts of the pattern\n may be searched at any depth what defined by the pattern structure.\n\n Set to `UINT32_MAX` to remove the maximum start depth."] + pub fn ts_query_cursor_set_max_start_depth(self_: *mut TSQueryCursor, max_start_depth: u32); +} +extern "C" { + #[doc = " Get another reference to the given language."] + pub fn ts_language_copy(self_: *const TSLanguage) -> *const TSLanguage; +} +extern "C" { + #[doc = " Free any dynamically-allocated resources for this language, if\n this is the last reference."] + pub fn ts_language_delete(self_: *const TSLanguage); +} +extern "C" { + #[doc = " Get the number of distinct node types in the language."] + pub fn ts_language_symbol_count(self_: *const TSLanguage) -> u32; +} +extern "C" { + #[doc = " Get the number of valid states in this language."] + pub fn ts_language_state_count(self_: *const TSLanguage) -> u32; +} +extern "C" { + #[doc = " Get the numerical id for the given node type string."] + pub fn ts_language_symbol_for_name( + self_: *const TSLanguage, + string: *const ::core::ffi::c_char, + length: u32, + is_named: bool, + ) -> TSSymbol; +} +extern "C" { + #[doc = " Get the number of distinct field names in the language."] + pub fn ts_language_field_count(self_: *const TSLanguage) -> u32; +} +extern "C" { + #[doc = " Get the field name string for the given numerical id."] + pub fn ts_language_field_name_for_id( + self_: *const TSLanguage, + id: TSFieldId, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Get the numerical id for the given field name string."] + pub fn ts_language_field_id_for_name( + self_: *const TSLanguage, + name: *const ::core::ffi::c_char, + name_length: u32, + ) -> TSFieldId; +} +extern "C" { + #[doc = " Get a list of all supertype symbols for the language."] + pub fn ts_language_supertypes(self_: *const TSLanguage, length: *mut u32) -> *const TSSymbol; +} +extern "C" { + #[doc = " Get a list of all subtype symbol ids for a given supertype symbol.\n\n See [`ts_language_supertypes`] for fetching all supertype symbols."] + pub fn ts_language_subtypes( + self_: *const TSLanguage, + supertype: TSSymbol, + length: *mut u32, + ) -> *const TSSymbol; +} +extern "C" { + #[doc = " Get a node type string for the given numerical id."] + pub fn ts_language_symbol_name( + self_: *const TSLanguage, + symbol: TSSymbol, + ) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Check whether the given node type id belongs to named nodes, anonymous nodes,\n or a hidden nodes.\n\n See also [`ts_node_is_named`]. Hidden nodes are never returned from the API."] + pub fn ts_language_symbol_type(self_: *const TSLanguage, symbol: TSSymbol) -> TSSymbolType; +} +extern "C" { + #[doc = " @deprecated use [`ts_language_abi_version`] instead, this will be removed in 0.26.\n\n Get the ABI version number for this language. This version number is used\n to ensure that languages were generated by a compatible version of\n Tree-sitter.\n\n See also [`ts_parser_set_language`]."] + pub fn ts_language_version(self_: *const TSLanguage) -> u32; +} +extern "C" { + #[doc = " Get the ABI version number for this language. This version number is used\n to ensure that languages were generated by a compatible version of\n Tree-sitter.\n\n See also [`ts_parser_set_language`]."] + pub fn ts_language_abi_version(self_: *const TSLanguage) -> u32; +} +extern "C" { + #[doc = " Get the metadata for this language. This information is generated by the\n CLI, and relies on the language author providing the correct metadata in\n the language's `tree-sitter.json` file.\n\n See also [`TSMetadata`]."] + pub fn ts_language_metadata(self_: *const TSLanguage) -> *const TSLanguageMetadata; +} +extern "C" { + #[doc = " Get the next parse state. Combine this with lookahead iterators to generate\n completion suggestions or valid symbols in error nodes. Use\n [`ts_node_grammar_symbol`] for valid symbols."] + pub fn ts_language_next_state( + self_: *const TSLanguage, + state: TSStateId, + symbol: TSSymbol, + ) -> TSStateId; +} +extern "C" { + #[doc = " Get the name of this language. This returns `NULL` in older parsers."] + pub fn ts_language_name(self_: *const TSLanguage) -> *const ::core::ffi::c_char; +} +extern "C" { + #[doc = " Create a new lookahead iterator for the given language and parse state.\n\n This returns `NULL` if state is invalid for the language.\n\n Repeatedly using [`ts_lookahead_iterator_next`] and\n [`ts_lookahead_iterator_current_symbol`] will generate valid symbols in the\n given parse state. Newly created lookahead iterators will contain the `ERROR`\n symbol.\n\n Lookahead iterators can be useful to generate suggestions and improve syntax\n error diagnostics. To get symbols valid in an ERROR node, use the lookahead\n iterator on its first leaf node state. For `MISSING` nodes, a lookahead\n iterator created on the previous non-extra leaf node may be appropriate."] + pub fn ts_lookahead_iterator_new( + self_: *const TSLanguage, + state: TSStateId, + ) -> *mut TSLookaheadIterator; +} +extern "C" { + #[doc = " Delete a lookahead iterator freeing all the memory used."] + pub fn ts_lookahead_iterator_delete(self_: *mut TSLookaheadIterator); +} +extern "C" { + #[doc = " Reset the lookahead iterator to another state.\n\n This returns `true` if the iterator was reset to the given state and `false`\n otherwise."] + pub fn ts_lookahead_iterator_reset_state( + self_: *mut TSLookaheadIterator, + state: TSStateId, + ) -> bool; +} +extern "C" { + #[doc = " Reset the lookahead iterator.\n\n This returns `true` if the language was set successfully and `false`\n otherwise."] + pub fn ts_lookahead_iterator_reset( + self_: *mut TSLookaheadIterator, + language: *const TSLanguage, + state: TSStateId, + ) -> bool; +} +extern "C" { + #[doc = " Get the current language of the lookahead iterator."] + pub fn ts_lookahead_iterator_language(self_: *const TSLookaheadIterator) -> *const TSLanguage; +} +extern "C" { + #[doc = " Advance the lookahead iterator to the next symbol.\n\n This returns `true` if there is a new symbol and `false` otherwise."] + pub fn ts_lookahead_iterator_next(self_: *mut TSLookaheadIterator) -> bool; +} +extern "C" { + #[doc = " Get the current symbol of the lookahead iterator;"] + pub fn ts_lookahead_iterator_current_symbol(self_: *const TSLookaheadIterator) -> TSSymbol; +} +extern "C" { + #[doc = " Get the current symbol type of the lookahead iterator as a null terminated\n string."] + pub fn ts_lookahead_iterator_current_symbol_name( + self_: *const TSLookaheadIterator, + ) -> *const ::core::ffi::c_char; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct wasm_engine_t { + _unused: [u8; 0], +} +pub type TSWasmEngine = wasm_engine_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSWasmStore { + _unused: [u8; 0], +} +pub const TSWasmErrorKindNone: TSWasmErrorKind = 0; +pub const TSWasmErrorKindParse: TSWasmErrorKind = 1; +pub const TSWasmErrorKindCompile: TSWasmErrorKind = 2; +pub const TSWasmErrorKindInstantiate: TSWasmErrorKind = 3; +pub const TSWasmErrorKindAllocate: TSWasmErrorKind = 4; +pub type TSWasmErrorKind = ::core::ffi::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TSWasmError { + pub kind: TSWasmErrorKind, + pub message: *mut ::core::ffi::c_char, +} +extern "C" { + #[doc = " Create a Wasm store."] + pub fn ts_wasm_store_new( + engine: *mut TSWasmEngine, + error: *mut TSWasmError, + ) -> *mut TSWasmStore; +} +extern "C" { + #[doc = " Free the memory associated with the given Wasm store."] + pub fn ts_wasm_store_delete(arg1: *mut TSWasmStore); +} +extern "C" { + #[doc = " Create a language from a buffer of Wasm. The resulting language behaves\n like any other Tree-sitter language, except that in order to use it with\n a parser, that parser must have a Wasm store. Note that the language\n can be used with any Wasm store, it doesn't need to be the same store that\n was used to originally load it."] + pub fn ts_wasm_store_load_language( + arg1: *mut TSWasmStore, + name: *const ::core::ffi::c_char, + wasm: *const ::core::ffi::c_char, + wasm_len: u32, + error: *mut TSWasmError, + ) -> *const TSLanguage; +} +extern "C" { + #[doc = " Get the number of languages instantiated in the given wasm store."] + pub fn ts_wasm_store_language_count(arg1: *const TSWasmStore) -> usize; +} +extern "C" { + #[doc = " Check if the language came from a Wasm module. If so, then in order to use\n this language with a Parser, that parser must have a Wasm store assigned."] + pub fn ts_language_is_wasm(arg1: *const TSLanguage) -> bool; +} +extern "C" { + #[doc = " Assign the given Wasm store to the parser. A parser must have a Wasm store\n in order to use Wasm languages."] + pub fn ts_parser_set_wasm_store(arg1: *mut TSParser, arg2: *mut TSWasmStore); +} +extern "C" { + #[doc = " Remove the parser's current Wasm store and return it. This returns NULL if\n the parser doesn't have a Wasm store."] + pub fn ts_parser_take_wasm_store(arg1: *mut TSParser) -> *mut TSWasmStore; +} +extern "C" { + #[doc = " Set the allocation functions used by the library.\n\n By default, Tree-sitter uses the standard libc allocation functions,\n but aborts the process when an allocation fails. This function lets\n you supply alternative allocation functions at runtime.\n\n If you pass `NULL` for any parameter, Tree-sitter will switch back to\n its default implementation of that function.\n\n If you call this function after the library has already been used, then\n you must ensure that either:\n 1. All the existing objects have been freed.\n 2. The new allocator shares its state with the old one, so it is capable\n of freeing memory that was allocated by the old allocator."] + pub fn ts_set_allocator( + new_malloc: ::core::option::Option< + unsafe extern "C" fn(arg1: usize) -> *mut ::core::ffi::c_void, + >, + new_calloc: ::core::option::Option< + unsafe extern "C" fn(arg1: usize, arg2: usize) -> *mut ::core::ffi::c_void, + >, + new_realloc: ::core::option::Option< + unsafe extern "C" fn( + arg1: *mut ::core::ffi::c_void, + arg2: usize, + ) -> *mut ::core::ffi::c_void, + >, + new_free: ::core::option::Option, + ); +} diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/build.rs b/codegraph-kernel/vendor/tree-sitter/binding_rust/build.rs new file mode 100644 index 0000000000..a566419271 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/build.rs @@ -0,0 +1,122 @@ +use std::{env, fs, path::PathBuf}; + +fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + #[cfg(feature = "bindgen")] + generate_bindings(&out_dir); + + fs::copy( + "src/wasm/stdlib-symbols.txt", + out_dir.join("stdlib-symbols.txt"), + ) + .unwrap(); + + let mut config = cc::Build::new(); + + println!("cargo:rerun-if-env-changed=CARGO_FEATURE_WASM"); + if env::var("CARGO_FEATURE_WASM").is_ok() { + config + .define("TREE_SITTER_FEATURE_WASM", "") + .define("static_assert(...)", "") + .include(env::var("DEP_WASMTIME_C_API_INCLUDE").unwrap()); + } + + let manifest_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let include_path = manifest_path.join("include"); + let src_path = manifest_path.join("src"); + let wasm_path = src_path.join("wasm"); + for entry in fs::read_dir(&src_path).unwrap() { + let entry = entry.unwrap(); + let path = src_path.join(entry.file_name()); + println!("cargo:rerun-if-changed={}", path.to_str().unwrap()); + } + + config + .flag_if_supported("-std=c11") + .flag_if_supported("-fvisibility=hidden") + .flag_if_supported("-Wshadow") + .flag_if_supported("-Wno-unused-parameter") + .flag_if_supported("-Wno-incompatible-pointer-types") + .include(&src_path) + .include(&wasm_path) + .include(&include_path) + .define("_POSIX_C_SOURCE", "200112L") + .define("_DEFAULT_SOURCE", None) + .define("_DARWIN_C_SOURCE", None) + .warnings(false) + .file(src_path.join("lib.c")) + .compile("tree-sitter"); + + println!("cargo:include={}", include_path.display()); +} + +#[cfg(feature = "bindgen")] +fn generate_bindings(out_dir: &std::path::Path) { + use std::{process::Command, str::FromStr}; + + use bindgen::RustTarget; + + let output = Command::new("cargo") + .args(["metadata", "--format-version", "1"]) + .output() + .unwrap(); + + let metadata = serde_json::from_slice::(&output.stdout).unwrap(); + + let Some(rust_version) = metadata + .get("packages") + .and_then(|packages| packages.as_array()) + .and_then(|packages| { + packages.iter().find_map(|package| { + if package["name"] == "tree-sitter" { + package.get("rust_version").and_then(|v| v.as_str()) + } else { + None + } + }) + }) + else { + panic!("Failed to find tree-sitter package in cargo metadata"); + }; + + const HEADER_PATH: &str = "include/tree_sitter/api.h"; + + println!("cargo:rerun-if-changed={HEADER_PATH}"); + + let no_copy = [ + "TSInput", + "TSLanguage", + "TSLogger", + "TSLookaheadIterator", + "TSParser", + "TSTree", + "TSQuery", + "TSQueryCursor", + "TSQueryCapture", + "TSQueryMatch", + "TSQueryPredicateStep", + ]; + + let bindings = bindgen::Builder::default() + .header(HEADER_PATH) + .layout_tests(false) + .allowlist_type("^TS.*") + .allowlist_function("^ts_.*") + .allowlist_var("^TREE_SITTER.*") + .no_copy(no_copy.join("|")) + .prepend_enum_name(false) + .use_core() + .clang_arg("-D TREE_SITTER_FEATURE_WASM") + .rust_target(RustTarget::from_str(rust_version).unwrap()) + .generate() + .expect("Failed to generate bindings"); + + let bindings_rs = out_dir.join("bindings.rs"); + bindings.write_to_file(&bindings_rs).unwrap_or_else(|_| { + panic!( + "Failed to write bindings into path: {}", + bindings_rs.display() + ) + }); +} diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/ffi.rs b/codegraph-kernel/vendor/tree-sitter/binding_rust/ffi.rs new file mode 100644 index 0000000000..4c68a633ca --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/ffi.rs @@ -0,0 +1,216 @@ +#![allow(dead_code)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(clippy::missing_const_for_fn)] + +#[cfg(feature = "bindgen")] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +#[cfg(not(feature = "bindgen"))] +include!("./bindings.rs"); + +#[cfg(unix)] +#[cfg(feature = "std")] +extern "C" { + pub(crate) fn _ts_dup(fd: std::os::raw::c_int) -> std::os::raw::c_int; +} + +#[cfg(windows)] +#[cfg(feature = "std")] +extern "C" { + pub(crate) fn _ts_dup(handle: *mut std::os::raw::c_void) -> std::os::raw::c_int; +} + +use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull, str}; + +use crate::{ + Language, LookaheadIterator, Node, ParseState, Parser, Query, QueryCursor, QueryCursorState, + QueryError, Tree, TreeCursor, +}; + +impl Language { + /// Reconstructs a [`Language`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *const TSLanguage) -> Self { + Self(ptr) + } + + /// Consumes the [`Language`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *const TSLanguage { + ManuallyDrop::new(self).0 + } +} + +impl Parser { + /// Reconstructs a [`Parser`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *mut TSParser) -> Self { + Self(NonNull::new_unchecked(ptr)) + } + + /// Consumes the [`Parser`], returning a raw pointer to the underlying C structure. + /// + /// # Safety + /// + /// It's a caller responsibility to adjust parser's state + /// like disable logging or dot graphs printing if this + /// may cause issues like use after free. + #[must_use] + pub fn into_raw(self) -> *mut TSParser { + ManuallyDrop::new(self).0.as_ptr() + } +} + +impl ParseState { + /// Reconstructs a [`ParseState`] from a raw pointer + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *mut TSParseState) -> Self { + Self(NonNull::new_unchecked(ptr)) + } + + /// Consumes the [`ParseState`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *mut TSParseState { + ManuallyDrop::new(self).0.as_ptr() + } +} + +impl Tree { + /// Reconstructs a [`Tree`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *mut TSTree) -> Self { + Self(NonNull::new_unchecked(ptr)) + } + + /// Consumes the [`Tree`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *mut TSTree { + ManuallyDrop::new(self).0.as_ptr() + } +} + +impl Node<'_> { + /// Reconstructs a [`Node`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(raw: TSNode) -> Self { + Self(raw, PhantomData) + } + + /// Consumes the [`Node`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> TSNode { + ManuallyDrop::new(self).0 + } +} + +impl TreeCursor<'_> { + /// Reconstructs a [`TreeCursor`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(raw: TSTreeCursor) -> Self { + Self(raw, PhantomData) + } + + /// Consumes the [`TreeCursor`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> TSTreeCursor { + ManuallyDrop::new(self).0 + } +} + +impl Query { + /// Reconstructs a [`Query`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + pub unsafe fn from_raw(ptr: *mut TSQuery, source: &str) -> Result { + Self::from_raw_parts(ptr, source) + } + + /// Consumes the [`Query`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *mut TSQuery { + ManuallyDrop::new(self).ptr.as_ptr() + } +} + +impl QueryCursor { + /// Reconstructs a [`QueryCursor`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *mut TSQueryCursor) -> Self { + Self { + ptr: NonNull::new_unchecked(ptr), + } + } + + /// Consumes the [`QueryCursor`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *mut TSQueryCursor { + ManuallyDrop::new(self).ptr.as_ptr() + } +} + +impl QueryCursorState { + /// Reconstructs a [`QueryCursorState`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *mut TSQueryCursorState) -> Self { + Self(NonNull::new_unchecked(ptr)) + } + + /// Consumes the [`QueryCursorState`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *mut TSQueryCursorState { + ManuallyDrop::new(self).0.as_ptr() + } +} + +impl LookaheadIterator { + /// Reconstructs a [`LookaheadIterator`] from a raw pointer. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[must_use] + pub const unsafe fn from_raw(ptr: *mut TSLookaheadIterator) -> Self { + Self(NonNull::new_unchecked(ptr)) + } + + /// Consumes the [`LookaheadIterator`], returning a raw pointer to the underlying C structure. + #[must_use] + pub fn into_raw(self) -> *mut TSLookaheadIterator { + ManuallyDrop::new(self).0.as_ptr() + } +} diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/lib.rs b/codegraph-kernel/vendor/tree-sitter/binding_rust/lib.rs new file mode 100644 index 0000000000..72c2d5c9df --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/lib.rs @@ -0,0 +1,3937 @@ +#![doc = include_str!("./README.md")] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(docsrs, feature(doc_cfg))] + +pub mod ffi; +mod util; + +#[cfg(not(feature = "std"))] +extern crate alloc; +#[cfg(not(feature = "std"))] +use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec}; +use core::{ + ffi::{c_char, c_void, CStr}, + fmt::{self, Write}, + hash, iter, + marker::PhantomData, + mem::MaybeUninit, + num::NonZeroU16, + ops::{self, Deref}, + ptr::{self, NonNull}, + slice, str, + sync::atomic::AtomicUsize, +}; +#[cfg(feature = "std")] +use std::error; +#[cfg(all(unix, feature = "std"))] +use std::os::fd::AsRawFd; +#[cfg(all(windows, feature = "std"))] +use std::os::windows::io::AsRawHandle; + +pub use streaming_iterator::{StreamingIterator, StreamingIteratorMut}; +use tree_sitter_language::LanguageFn; + +#[cfg(feature = "wasm")] +mod wasm_language; +#[cfg(feature = "wasm")] +#[cfg_attr(docsrs, doc(cfg(feature = "wasm")))] +pub use wasm_language::*; + +/// The latest ABI version that is supported by the current version of the +/// library. +/// +/// When Languages are generated by the Tree-sitter CLI, they are +/// assigned an ABI version number that corresponds to the current CLI version. +/// The Tree-sitter library is generally backwards-compatible with languages +/// generated using older CLI versions, but is not forwards-compatible. +#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")] +pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize; + +/// The earliest ABI version that is supported by the current version of the +/// library. +#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")] +pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize = + ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize; + +pub const PARSER_HEADER: &str = include_str!("../src/parser.h"); + +/// An opaque object that defines how to parse a particular language. The code +/// for each `Language` is generated by the Tree-sitter CLI. +#[doc(alias = "TSLanguage")] +#[derive(Debug, PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct Language(*const ffi::TSLanguage); + +pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>); + +/// The metadata associated with a language. +/// +/// Currently, this metadata can be used to check the [Semantic Version](https://semver.org/) +/// of the language. This version information should be used to signal if a given parser might +/// be incompatible with existing queries when upgrading between major versions, or minor versions +/// if it's in zerover. +#[doc(alias = "TSLanguageMetadata")] +pub struct LanguageMetadata { + pub major_version: u8, + pub minor_version: u8, + pub patch_version: u8, +} + +impl From for LanguageMetadata { + fn from(val: ffi::TSLanguageMetadata) -> Self { + Self { + major_version: val.major_version, + minor_version: val.minor_version, + patch_version: val.patch_version, + } + } +} + +/// A tree that represents the syntactic structure of a source code file. +#[doc(alias = "TSTree")] +pub struct Tree(NonNull); + +/// A position in a multi-line text document, in terms of rows and columns. +/// +/// Rows and columns are zero-based. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Point { + pub row: usize, + pub column: usize, +} + +/// A range of positions in a multi-line text document, both in terms of bytes +/// and of rows and columns. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Range { + pub start_byte: usize, + pub end_byte: usize, + pub start_point: Point, + pub end_point: Point, +} + +/// A summary of a change to a text document. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct InputEdit { + pub start_byte: usize, + pub old_end_byte: usize, + pub new_end_byte: usize, + pub start_position: Point, + pub old_end_position: Point, + pub new_end_position: Point, +} + +/// A single node within a syntax [`Tree`]. +#[doc(alias = "TSNode")] +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>); + +/// A stateful object that this is used to produce a [`Tree`] based on some +/// source code. +#[doc(alias = "TSParser")] +pub struct Parser(NonNull); + +/// A stateful object that is used to look up symbols valid in a specific parse +/// state +#[doc(alias = "TSLookaheadIterator")] +pub struct LookaheadIterator(NonNull); +struct LookaheadNamesIterator<'a>(&'a mut LookaheadIterator); + +/// A stateful object that is passed into a [`ParseProgressCallback`] +/// to pass in the current state of the parser. +pub struct ParseState(NonNull); + +impl ParseState { + #[must_use] + pub const fn current_byte_offset(&self) -> usize { + unsafe { self.0.as_ref() }.current_byte_offset as usize + } + + #[must_use] + pub const fn has_error(&self) -> bool { + unsafe { self.0.as_ref() }.has_error + } +} + +/// A stateful object that is passed into a [`QueryProgressCallback`] +/// to pass in the current state of the query execution. +pub struct QueryCursorState(NonNull); + +impl QueryCursorState { + #[must_use] + pub const fn current_byte_offset(&self) -> usize { + unsafe { self.0.as_ref() }.current_byte_offset as usize + } +} + +#[derive(Default)] +pub struct ParseOptions<'a> { + pub progress_callback: Option>, +} + +impl<'a> ParseOptions<'a> { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + #[must_use] + pub fn progress_callback bool>(mut self, callback: &'a mut F) -> Self { + self.progress_callback = Some(callback); + self + } +} + +#[derive(Default)] +pub struct QueryCursorOptions<'a> { + pub progress_callback: Option>, +} + +impl<'a> QueryCursorOptions<'a> { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + #[must_use] + pub fn progress_callback bool>( + mut self, + callback: &'a mut F, + ) -> Self { + self.progress_callback = Some(callback); + self + } +} + +struct QueryCursorOptionsDrop(*mut ffi::TSQueryCursorOptions); + +impl Drop for QueryCursorOptionsDrop { + fn drop(&mut self) { + unsafe { + if !(*self.0).payload.is_null() { + drop(Box::from_raw( + (*self.0).payload.cast::(), + )); + } + drop(Box::from_raw(self.0)); + } + } +} + +/// A type of log message. +#[derive(Debug, PartialEq, Eq)] +pub enum LogType { + Parse, + Lex, +} + +type FieldId = NonZeroU16; + +/// A callback that receives log messages during parsing. +type Logger<'a> = Box; + +/// A callback that receives the parse state during parsing. +type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> bool; + +/// A callback that receives the query state during query execution. +type QueryProgressCallback<'a> = &'a mut dyn FnMut(&QueryCursorState) -> bool; + +pub trait Decode { + /// A callback that decodes the next code point from the input slice. It should return the code + /// point, and how many bytes were decoded. + fn decode(bytes: &[u8]) -> (i32, u32); +} + +/// A stateful object for walking a syntax [`Tree`] efficiently. +#[doc(alias = "TSTreeCursor")] +pub struct TreeCursor<'cursor>(ffi::TSTreeCursor, PhantomData<&'cursor ()>); + +/// A set of patterns that match nodes in a syntax tree. +#[doc(alias = "TSQuery")] +#[derive(Debug)] +#[allow(clippy::type_complexity)] +pub struct Query { + ptr: NonNull, + capture_names: Box<[&'static str]>, + capture_quantifiers: Box<[Box<[CaptureQuantifier]>]>, + text_predicates: Box<[Box<[TextPredicateCapture]>]>, + property_settings: Box<[Box<[QueryProperty]>]>, + property_predicates: Box<[Box<[(QueryProperty, bool)]>]>, + general_predicates: Box<[Box<[QueryPredicate]>]>, +} + +/// A quantifier for captures +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum CaptureQuantifier { + Zero, + ZeroOrOne, + ZeroOrMore, + One, + OneOrMore, +} + +impl From for CaptureQuantifier { + fn from(value: ffi::TSQuantifier) -> Self { + match value { + ffi::TSQuantifierZero => Self::Zero, + ffi::TSQuantifierZeroOrOne => Self::ZeroOrOne, + ffi::TSQuantifierZeroOrMore => Self::ZeroOrMore, + ffi::TSQuantifierOne => Self::One, + ffi::TSQuantifierOneOrMore => Self::OneOrMore, + _ => panic!("Unrecognized quantifier: {value}"), + } + } +} + +/// A stateful object for executing a [`Query`] on a syntax [`Tree`]. +#[doc(alias = "TSQueryCursor")] +pub struct QueryCursor { + ptr: NonNull, +} + +/// A key-value pair associated with a particular pattern in a [`Query`]. +#[derive(Debug, PartialEq, Eq)] +pub struct QueryProperty { + pub key: Box, + pub value: Option>, + pub capture_id: Option, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum QueryPredicateArg { + Capture(u32), + String(Box), +} + +/// A key-value pair associated with a particular pattern in a [`Query`]. +#[derive(Debug, PartialEq, Eq)] +pub struct QueryPredicate { + pub operator: Box, + pub args: Box<[QueryPredicateArg]>, +} + +/// A match of a [`Query`] to a particular set of [`Node`]s. +pub struct QueryMatch<'cursor, 'tree> { + pub pattern_index: usize, + pub captures: &'cursor [QueryCapture<'tree>], + id: u32, + cursor: *mut ffi::TSQueryCursor, +} + +/// A sequence of [`QueryMatch`]es associated with a given [`QueryCursor`]. +pub struct QueryMatches<'query, 'tree: 'query, T: TextProvider, I: AsRef<[u8]>> { + ptr: *mut ffi::TSQueryCursor, + query: &'query Query, + text_provider: T, + buffer1: Vec, + buffer2: Vec, + current_match: Option>, + _options: Option, + _phantom: PhantomData<(&'tree (), I)>, +} + +/// A sequence of [`QueryCapture`]s associated with a given [`QueryCursor`]. +/// +/// During iteration, each element contains a [`QueryMatch`] and index. The index can +/// be used to access the new capture inside of the [`QueryMatch::captures`]'s [`captures`]. +pub struct QueryCaptures<'query, 'tree: 'query, T: TextProvider, I: AsRef<[u8]>> { + ptr: *mut ffi::TSQueryCursor, + query: &'query Query, + text_provider: T, + buffer1: Vec, + buffer2: Vec, + current_match: Option<(QueryMatch<'query, 'tree>, usize)>, + _options: Option, + _phantom: PhantomData<(&'tree (), I)>, +} + +pub trait TextProvider +where + I: AsRef<[u8]>, +{ + type I: Iterator; + fn text(&mut self, node: Node) -> Self::I; +} + +/// A particular [`Node`] that has been captured with a particular name within a +/// [`Query`]. +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct QueryCapture<'tree> { + pub node: Node<'tree>, + pub index: u32, +} + +/// An error that occurred when trying to assign an incompatible [`Language`] to +/// a [`Parser`]. +#[derive(Debug, PartialEq, Eq)] +pub struct LanguageError { + version: usize, +} + +/// An error that occurred in [`Parser::set_included_ranges`]. +#[derive(Debug, PartialEq, Eq)] +pub struct IncludedRangesError(pub usize); + +/// An error that occurred when trying to create a [`Query`]. +#[derive(Debug, PartialEq, Eq)] +pub struct QueryError { + pub row: usize, + pub column: usize, + pub offset: usize, + pub message: String, + pub kind: QueryErrorKind, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum QueryErrorKind { + Syntax, + NodeType, + Field, + Capture, + Predicate, + Structure, + Language, +} + +#[derive(Debug)] +/// The first item is the capture index +/// The next is capture specific, depending on what item is expected +/// The first bool is if the capture is positive +/// The last item is a bool signifying whether or not it's meant to match +/// any or all captures +enum TextPredicateCapture { + EqString(u32, Box, bool, bool), + EqCapture(u32, u32, bool, bool), + MatchString(u32, regex::bytes::Regex, bool, bool), + AnyString(u32, Box<[Box]>, bool), +} + +// TODO: Remove this struct at some point. If `core::str::lossy::Utf8Lossy` +// is ever stabilized. +pub struct LossyUtf8<'a> { + bytes: &'a [u8], + in_replacement: bool, +} + +impl Language { + #[must_use] + pub fn new(builder: LanguageFn) -> Self { + Self(unsafe { builder.into_raw()().cast() }) + } + + /// Get the name of this language. This returns `None` in older parsers. + #[doc(alias = "ts_language_name")] + #[must_use] + pub fn name(&self) -> Option<&'static str> { + let ptr = unsafe { ffi::ts_language_name(self.0) }; + (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()) + } + + /// Get the ABI version number that indicates which version of the + /// Tree-sitter CLI that was used to generate this [`Language`]. + #[doc(alias = "ts_language_version")] + #[deprecated(since = "0.25.0", note = "Use abi_version instead")] + #[must_use] + pub fn version(&self) -> usize { + unsafe { ffi::ts_language_version(self.0) as usize } + } + + /// Get the ABI version number that indicates which version of the + /// Tree-sitter CLI that was used to generate this [`Language`]. + #[doc(alias = "ts_language_abi_version")] + #[must_use] + pub fn abi_version(&self) -> usize { + unsafe { ffi::ts_language_abi_version(self.0) as usize } + } + + /// Get the metadata for this language. This information is generated by the + /// CLI, and relies on the language author providing the correct metadata in + /// the language's `tree-sitter.json` file. + /// + /// See also [`LanguageMetadata`]. + #[doc(alias = "ts_language_metadata")] + #[must_use] + pub fn metadata(&self) -> Option { + unsafe { + let ptr = ffi::ts_language_metadata(self.0); + (!ptr.is_null()).then(|| (*ptr).into()) + } + } + + /// Get the number of distinct node types in this language. + #[doc(alias = "ts_language_symbol_count")] + #[must_use] + pub fn node_kind_count(&self) -> usize { + unsafe { ffi::ts_language_symbol_count(self.0) as usize } + } + + /// Get the number of valid states in this language. + #[doc(alias = "ts_language_state_count")] + #[must_use] + pub fn parse_state_count(&self) -> usize { + unsafe { ffi::ts_language_state_count(self.0) as usize } + } + + /// Get a list of all supertype symbols for the language. + #[doc(alias = "ts_language_supertypes")] + #[must_use] + pub fn supertypes(&self) -> &[u16] { + let mut length = 0u32; + unsafe { + let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length)); + if length == 0 { + &[] + } else { + slice::from_raw_parts(ptr.cast_mut(), length as usize) + } + } + } + + /// Get a list of all subtype symbols for a given supertype symbol. + #[doc(alias = "ts_language_supertype_map")] + #[must_use] + pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] { + unsafe { + let mut length = 0u32; + let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length)); + if length == 0 { + &[] + } else { + slice::from_raw_parts(ptr.cast_mut(), length as usize) + } + } + } + + /// Get the name of the node kind for the given numerical id. + #[doc(alias = "ts_language_symbol_name")] + #[must_use] + pub fn node_kind_for_id(&self, id: u16) -> Option<&'static str> { + let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) }; + (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()) + } + + /// Get the numeric id for the given node kind. + #[doc(alias = "ts_language_symbol_for_name")] + #[must_use] + pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 { + unsafe { + ffi::ts_language_symbol_for_name( + self.0, + kind.as_bytes().as_ptr().cast::(), + kind.len() as u32, + named, + ) + } + } + + /// Check if the node type for the given numerical id is named (as opposed + /// to an anonymous node type). + #[must_use] + pub fn node_kind_is_named(&self, id: u16) -> bool { + unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular } + } + + /// Check if the node type for the given numerical id is visible (as opposed + /// to a hidden node type). + #[must_use] + pub fn node_kind_is_visible(&self, id: u16) -> bool { + unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous } + } + + /// Check if the node type for the given numerical id is a supertype. + #[must_use] + pub fn node_kind_is_supertype(&self, id: u16) -> bool { + unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype } + } + + /// Get the number of distinct field names in this language. + #[doc(alias = "ts_language_field_count")] + #[must_use] + pub fn field_count(&self) -> usize { + unsafe { ffi::ts_language_field_count(self.0) as usize } + } + + /// Get the field name for the given numerical id. + #[doc(alias = "ts_language_field_name_for_id")] + #[must_use] + pub fn field_name_for_id(&self, field_id: u16) -> Option<&'static str> { + let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) }; + (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()) + } + + /// Get the numerical id for the given field name. + #[doc(alias = "ts_language_field_id_for_name")] + #[must_use] + pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option { + let field_name = field_name.as_ref(); + let id = unsafe { + ffi::ts_language_field_id_for_name( + self.0, + field_name.as_ptr().cast::(), + field_name.len() as u32, + ) + }; + FieldId::new(id) + } + + /// Get the next parse state. Combine this with + /// [`lookahead_iterator`](Language::lookahead_iterator) to + /// generate completion suggestions or valid symbols in error nodes. + /// + /// Example: + /// ``` + /// let state = language.next_state(node.parse_state(), node.grammar_id()); + /// ``` + #[doc(alias = "ts_language_next_state")] + #[must_use] + pub fn next_state(&self, state: u16, id: u16) -> u16 { + unsafe { ffi::ts_language_next_state(self.0, state, id) } + } + + /// Create a new lookahead iterator for this language and parse state. + /// + /// This returns `None` if state is invalid for this language. + /// + /// Iterating [`LookaheadIterator`] will yield valid symbols in the given + /// parse state. Newly created lookahead iterators will return the `ERROR` + /// symbol from [`LookaheadIterator::current_symbol`]. + /// + /// Lookahead iterators can be useful to generate suggestions and improve + /// syntax error diagnostics. To get symbols valid in an `ERROR` node, use the + /// lookahead iterator on its first leaf node state. For `MISSING` nodes, a + /// lookahead iterator created on the previous non-extra leaf node may be + /// appropriate. + #[doc(alias = "ts_lookahead_iterator_new")] + #[must_use] + pub fn lookahead_iterator(&self, state: u16) -> Option { + let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) }; + (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) }) + } +} + +impl From for Language { + fn from(value: LanguageFn) -> Self { + Self::new(value) + } +} + +impl Clone for Language { + fn clone(&self) -> Self { + unsafe { Self(ffi::ts_language_copy(self.0)) } + } +} + +impl Drop for Language { + fn drop(&mut self) { + unsafe { ffi::ts_language_delete(self.0) } + } +} + +impl Deref for LanguageRef<'_> { + type Target = Language; + + fn deref(&self) -> &Self::Target { + unsafe { &*(core::ptr::addr_of!(self.0).cast::()) } + } +} + +impl Default for Parser { + fn default() -> Self { + Self::new() + } +} + +impl Parser { + /// Create a new parser. + #[doc(alias = "ts_parser_new")] + #[must_use] + pub fn new() -> Self { + unsafe { + let parser = ffi::ts_parser_new(); + Self(NonNull::new_unchecked(parser)) + } + } + + /// Set the language that the parser should use for parsing. + /// + /// Returns a Result indicating whether or not the language was successfully + /// assigned. True means assignment succeeded. False means there was a + /// version mismatch: the language was generated with an incompatible + /// version of the Tree-sitter CLI. Check the language's version using + /// [`Language::version`] and compare it to this library's + /// [`LANGUAGE_VERSION`] and [`MIN_COMPATIBLE_LANGUAGE_VERSION`] constants. + #[doc(alias = "ts_parser_set_language")] + pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> { + let version = language.abi_version(); + if (MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION).contains(&version) { + unsafe { + ffi::ts_parser_set_language(self.0.as_ptr(), language.0); + } + Ok(()) + } else { + Err(LanguageError { version }) + } + } + + /// Get the parser's current language. + #[doc(alias = "ts_parser_language")] + #[must_use] + pub fn language(&self) -> Option> { + let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) }; + (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData)) + } + + /// Get the parser's current logger. + #[doc(alias = "ts_parser_logger")] + #[must_use] + pub fn logger(&self) -> Option<&Logger> { + let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) }; + unsafe { logger.payload.cast::().as_ref() } + } + + /// Set the logging callback that the parser should use during parsing. + #[doc(alias = "ts_parser_set_logger")] + pub fn set_logger(&mut self, logger: Option) { + let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) }; + if !prev_logger.payload.is_null() { + drop(unsafe { Box::from_raw(prev_logger.payload.cast::()) }); + } + + let c_logger = if let Some(logger) = logger { + let container = Box::new(logger); + + unsafe extern "C" fn log( + payload: *mut c_void, + c_log_type: ffi::TSLogType, + c_message: *const c_char, + ) { + let callback = payload.cast::().as_mut().unwrap(); + if let Ok(message) = CStr::from_ptr(c_message).to_str() { + let log_type = if c_log_type == ffi::TSLogTypeParse { + LogType::Parse + } else { + LogType::Lex + }; + callback(log_type, message); + } + } + + let raw_container = Box::into_raw(container); + + ffi::TSLogger { + payload: raw_container.cast::(), + log: Some(log), + } + } else { + ffi::TSLogger { + payload: ptr::null_mut(), + log: None, + } + }; + + unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) }; + } + + /// Set the destination to which the parser should write debugging graphs + /// during parsing. The graphs are formatted in the DOT language. You may + /// want to pipe these graphs directly to a `dot(1)` process in order to + /// generate SVG output. + #[doc(alias = "ts_parser_print_dot_graphs")] + #[cfg(not(target_os = "wasi"))] + #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + pub fn print_dot_graphs( + &mut self, + #[cfg(unix)] file: &impl AsRawFd, + #[cfg(windows)] file: &impl AsRawHandle, + ) { + #[cfg(unix)] + { + let fd = file.as_raw_fd(); + unsafe { + ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd)); + } + } + + #[cfg(windows)] + { + let handle = file.as_raw_handle(); + unsafe { + ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle)); + } + } + } + + /// Stop the parser from printing debugging graphs while parsing. + #[doc(alias = "ts_parser_print_dot_graphs")] + #[cfg(not(target_os = "wasi"))] + #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + pub fn stop_printing_dot_graphs(&mut self) { + unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) } + } + + /// Parse a slice of UTF8 text. + /// + /// # Arguments: + /// * `text` The UTF8-encoded text to parse. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + /// + /// Returns a [`Tree`] if parsing succeeded, or `None` if: + /// * The parser has not yet had a language assigned with [`Parser::set_language`] + /// * The timeout set with [`Parser::set_timeout_micros`] expired (deprecated) + /// * The cancellation flag set with [`Parser::set_cancellation_flag`] was flipped (deprecated) + #[doc(alias = "ts_parser_parse")] + pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option { + let bytes = text.as_ref(); + let len = bytes.len(); + self.parse_with_options( + &mut |i, _| (i < len).then(|| &bytes[i..]).unwrap_or_default(), + old_tree, + None, + ) + } + + /// Parse a slice of UTF16 text. + /// + /// # Arguments: + /// * `text` The UTF16-encoded text to parse. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + #[deprecated(since = "0.25.0", note = "Prefer parse_utf16_le instead")] + pub fn parse_utf16( + &mut self, + input: impl AsRef<[u16]>, + old_tree: Option<&Tree>, + ) -> Option { + let code_points = input.as_ref(); + let len = code_points.len(); + self.parse_utf16_le_with_options( + &mut |i, _| (i < len).then(|| &code_points[i..]).unwrap_or_default(), + old_tree, + None, + ) + } + + /// Parse UTF8 text provided in chunks by a callback. + /// + /// # Arguments: + /// * `callback` A function that takes a byte offset and position and returns a slice of + /// UTF8-encoded text starting at that byte offset and position. The slices can be of any + /// length. If the given position is at the end of the text, the callback should return an + /// empty slice. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + #[deprecated(since = "0.25.0", note = "Prefer `parse_with_options` instead")] + pub fn parse_with, F: FnMut(usize, Point) -> T>( + &mut self, + callback: &mut F, + old_tree: Option<&Tree>, + ) -> Option { + self.parse_with_options(callback, old_tree, None) + } + + /// Parse text provided in chunks by a callback. + /// + /// # Arguments: + /// * `callback` A function that takes a byte offset and position and returns a slice of + /// UTF8-encoded text starting at that byte offset and position. The slices can be of any + /// length. If the given position is at the end of the text, the callback should return an + /// empty slice. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + /// * `options` Options for parsing the text. This can be used to set a progress callback. + pub fn parse_with_options, F: FnMut(usize, Point) -> T>( + &mut self, + callback: &mut F, + old_tree: Option<&Tree>, + options: Option, + ) -> Option { + type Payload<'a, F, T> = (&'a mut F, Option); + + // This C function is passed to Tree-sitter as the progress callback. + unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool { + let callback = (*state) + .payload + .cast::() + .as_mut() + .unwrap(); + callback(&ParseState::from_raw(state)) + } + + // This C function is passed to Tree-sitter as the input callback. + unsafe extern "C" fn read, F: FnMut(usize, Point) -> T>( + payload: *mut c_void, + byte_offset: u32, + position: ffi::TSPoint, + bytes_read: *mut u32, + ) -> *const c_char { + let (callback, text) = payload.cast::>().as_mut().unwrap(); + *text = Some(callback(byte_offset as usize, position.into())); + let slice = text.as_ref().unwrap().as_ref(); + *bytes_read = slice.len() as u32; + slice.as_ptr().cast::() + } + + let empty_options = ffi::TSParseOptions { + payload: ptr::null_mut(), + progress_callback: None, + }; + + let mut callback_ptr; + let parse_options = if let Some(options) = options { + if let Some(cb) = options.progress_callback { + callback_ptr = cb; + ffi::TSParseOptions { + payload: core::ptr::addr_of_mut!(callback_ptr).cast::(), + progress_callback: Some(progress), + } + } else { + empty_options + } + } else { + empty_options + }; + + // A pointer to this payload is passed on every call to the `read` C function. + // The payload contains two things: + // 1. A reference to the rust `callback`. + // 2. The text that was returned from the previous call to `callback`. This allows the + // callback to return owned values like vectors. + let mut payload: Payload = (callback, None); + + let c_input = ffi::TSInput { + payload: ptr::addr_of_mut!(payload).cast::(), + read: Some(read::), + encoding: ffi::TSInputEncodingUTF8, + decode: None, + }; + + let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr()); + unsafe { + let c_new_tree = ffi::ts_parser_parse_with_options( + self.0.as_ptr(), + c_old_tree, + c_input, + parse_options, + ); + + NonNull::new(c_new_tree).map(Tree) + } + } + + /// Parse UTF16 text provided in chunks by a callback. + /// + /// # Arguments: + /// * `callback` A function that takes a code point offset and position and returns a slice of + /// UTF16-encoded text starting at that byte offset and position. The slices can be of any + /// length. If the given position is at the end of the text, the callback should return an + /// empty slice. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + #[deprecated( + since = "0.25.0", + note = "Prefer `parse_utf16_le_with_options` instead" + )] + pub fn parse_utf16_with, F: FnMut(usize, Point) -> T>( + &mut self, + callback: &mut F, + old_tree: Option<&Tree>, + ) -> Option { + self.parse_utf16_le_with_options(callback, old_tree, None) + } + + /// Parse a slice of UTF16 little-endian text. + /// + /// # Arguments: + /// * `text` The UTF16-encoded text to parse. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + pub fn parse_utf16_le( + &mut self, + input: impl AsRef<[u16]>, + old_tree: Option<&Tree>, + ) -> Option { + let code_points = input.as_ref(); + let len = code_points.len(); + self.parse_utf16_le_with_options( + &mut |i, _| (i < len).then(|| &code_points[i..]).unwrap_or_default(), + old_tree, + None, + ) + } + + /// Parse UTF16 little-endian text provided in chunks by a callback. + /// + /// # Arguments: + /// * `callback` A function that takes a code point offset and position and returns a slice of + /// UTF16-encoded text starting at that byte offset and position. The slices can be of any + /// length. If the given position is at the end of the text, the callback should return an + /// empty slice. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + /// * `options` Options for parsing the text. This can be used to set a progress callback. + pub fn parse_utf16_le_with_options, F: FnMut(usize, Point) -> T>( + &mut self, + callback: &mut F, + old_tree: Option<&Tree>, + options: Option, + ) -> Option { + type Payload<'a, F, T> = (&'a mut F, Option); + + unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool { + let callback = (*state) + .payload + .cast::() + .as_mut() + .unwrap(); + callback(&ParseState::from_raw(state)) + } + + // This C function is passed to Tree-sitter as the input callback. + unsafe extern "C" fn read, F: FnMut(usize, Point) -> T>( + payload: *mut c_void, + byte_offset: u32, + position: ffi::TSPoint, + bytes_read: *mut u32, + ) -> *const c_char { + let (callback, text) = payload.cast::>().as_mut().unwrap(); + *text = Some(callback( + (byte_offset / 2) as usize, + Point { + row: position.row as usize, + column: position.column as usize / 2, + }, + )); + let slice = text.as_ref().unwrap().as_ref(); + *bytes_read = slice.len() as u32 * 2; + slice.as_ptr().cast::() + } + + let empty_options = ffi::TSParseOptions { + payload: ptr::null_mut(), + progress_callback: None, + }; + + let mut callback_ptr; + let parse_options = if let Some(options) = options { + if let Some(cb) = options.progress_callback { + callback_ptr = cb; + ffi::TSParseOptions { + payload: core::ptr::addr_of_mut!(callback_ptr).cast::(), + progress_callback: Some(progress), + } + } else { + empty_options + } + } else { + empty_options + }; + + // A pointer to this payload is passed on every call to the `read` C function. + // The payload contains two things: + // 1. A reference to the rust `callback`. + // 2. The text that was returned from the previous call to `callback`. This allows the + // callback to return owned values like vectors. + let mut payload: Payload = (callback, None); + + let c_input = ffi::TSInput { + payload: core::ptr::addr_of_mut!(payload).cast::(), + read: Some(read::), + encoding: ffi::TSInputEncodingUTF16LE, + decode: None, + }; + + let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr()); + unsafe { + let c_new_tree = ffi::ts_parser_parse_with_options( + self.0.as_ptr(), + c_old_tree, + c_input, + parse_options, + ); + + NonNull::new(c_new_tree).map(Tree) + } + } + + /// Parse a slice of UTF16 big-endian text. + /// + /// # Arguments: + /// * `text` The UTF16-encoded text to parse. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + pub fn parse_utf16_be( + &mut self, + input: impl AsRef<[u16]>, + old_tree: Option<&Tree>, + ) -> Option { + let code_points = input.as_ref(); + let len = code_points.len(); + self.parse_utf16_be_with_options( + &mut |i, _| if i < len { &code_points[i..] } else { &[] }, + old_tree, + None, + ) + } + + /// Parse UTF16 big-endian text provided in chunks by a callback. + /// + /// # Arguments: + /// * `callback` A function that takes a code point offset and position and returns a slice of + /// UTF16-encoded text starting at that byte offset and position. The slices can be of any + /// length. If the given position is at the end of the text, the callback should return an + /// empty slice. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + /// * `options` Options for parsing the text. This can be used to set a progress callback. + pub fn parse_utf16_be_with_options, F: FnMut(usize, Point) -> T>( + &mut self, + callback: &mut F, + old_tree: Option<&Tree>, + options: Option, + ) -> Option { + type Payload<'a, F, T> = (&'a mut F, Option); + + // This C function is passed to Tree-sitter as the progress callback. + unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool { + let callback = (*state) + .payload + .cast::() + .as_mut() + .unwrap(); + callback(&ParseState::from_raw(state)) + } + + // This C function is passed to Tree-sitter as the input callback. + unsafe extern "C" fn read, F: FnMut(usize, Point) -> T>( + payload: *mut c_void, + byte_offset: u32, + position: ffi::TSPoint, + bytes_read: *mut u32, + ) -> *const c_char { + let (callback, text) = payload.cast::>().as_mut().unwrap(); + *text = Some(callback( + (byte_offset / 2) as usize, + Point { + row: position.row as usize, + column: position.column as usize / 2, + }, + )); + let slice = text.as_ref().unwrap().as_ref(); + *bytes_read = slice.len() as u32 * 2; + slice.as_ptr().cast::() + } + + let empty_options = ffi::TSParseOptions { + payload: ptr::null_mut(), + progress_callback: None, + }; + + let mut callback_ptr; + let parse_options = if let Some(options) = options { + if let Some(cb) = options.progress_callback { + callback_ptr = cb; + ffi::TSParseOptions { + payload: core::ptr::addr_of_mut!(callback_ptr).cast::(), + progress_callback: Some(progress), + } + } else { + empty_options + } + } else { + empty_options + }; + + // A pointer to this payload is passed on every call to the `read` C function. + // The payload contains two things: + // 1. A reference to the rust `callback`. + // 2. The text that was returned from the previous call to `callback`. This allows the + // callback to return owned values like vectors. + let mut payload: Payload = (callback, None); + + let c_input = ffi::TSInput { + payload: core::ptr::addr_of_mut!(payload).cast::(), + read: Some(read::), + encoding: ffi::TSInputEncodingUTF16BE, + decode: None, + }; + + let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr()); + unsafe { + let c_new_tree = ffi::ts_parser_parse_with_options( + self.0.as_ptr(), + c_old_tree, + c_input, + parse_options, + ); + + NonNull::new(c_new_tree).map(Tree) + } + } + + /// Parse text provided in chunks by a callback using a custom encoding. + /// This is useful for parsing text in encodings that are not UTF-8 or UTF-16. + /// + /// # Arguments: + /// * `callback` A function that takes a byte offset and position and returns a slice of text + /// starting at that byte offset and position. The slices can be of any length. If the given + /// position is at the end of the text, the callback should return an empty slice. + /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the + /// document has changed since `old_tree` was created, then you must edit `old_tree` to match + /// the new text using [`Tree::edit`]. + /// * `options` Options for parsing the text. This can be used to set a progress callback. + /// + /// Additionally, you must set the generic parameter [`D`] to a type that implements the + /// [`Decode`] trait. This trait has a single method, [`decode`](Decode::decode), which takes a + /// slice of bytes and returns a tuple of the code point and the number of bytes consumed. + /// The `decode` method should return `-1` for the code point if decoding fails. + pub fn parse_custom_encoding, F: FnMut(usize, Point) -> T>( + &mut self, + callback: &mut F, + old_tree: Option<&Tree>, + options: Option, + ) -> Option { + type Payload<'a, F, T> = (&'a mut F, Option); + + unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool { + let callback = (*state) + .payload + .cast::() + .as_mut() + .unwrap(); + callback(&ParseState::from_raw(state)) + } + + // At compile time, create a C-compatible callback that calls the custom `decode` method. + unsafe extern "C" fn decode_fn( + data: *const u8, + len: u32, + code_point: *mut i32, + ) -> u32 { + let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize)); + if let Some(code_point) = code_point.as_mut() { + *code_point = c; + } + len + } + + // This C function is passed to Tree-sitter as the input callback. + unsafe extern "C" fn read, F: FnMut(usize, Point) -> T>( + payload: *mut c_void, + byte_offset: u32, + position: ffi::TSPoint, + bytes_read: *mut u32, + ) -> *const c_char { + let (callback, text) = payload.cast::>().as_mut().unwrap(); + *text = Some(callback(byte_offset as usize, position.into())); + let slice = text.as_ref().unwrap().as_ref(); + *bytes_read = slice.len() as u32; + slice.as_ptr().cast::() + } + + let empty_options = ffi::TSParseOptions { + payload: ptr::null_mut(), + progress_callback: None, + }; + + let mut callback_ptr; + let parse_options = if let Some(options) = options { + if let Some(cb) = options.progress_callback { + callback_ptr = cb; + ffi::TSParseOptions { + payload: core::ptr::addr_of_mut!(callback_ptr).cast::(), + progress_callback: Some(progress), + } + } else { + empty_options + } + } else { + empty_options + }; + + // A pointer to this payload is passed on every call to the `read` C function. + // The payload contains two things: + // 1. A reference to the rust `callback`. + // 2. The text that was returned from the previous call to `callback`. This allows the + // callback to return owned values like vectors. + let mut payload: Payload = (callback, None); + + let c_input = ffi::TSInput { + payload: core::ptr::addr_of_mut!(payload).cast::(), + read: Some(read::), + encoding: ffi::TSInputEncodingCustom, + // Use this custom decode callback + decode: Some(decode_fn::), + }; + + let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr()); + unsafe { + let c_new_tree = ffi::ts_parser_parse_with_options( + self.0.as_ptr(), + c_old_tree, + c_input, + parse_options, + ); + + NonNull::new(c_new_tree).map(Tree) + } + } + + /// Instruct the parser to start the next parse from the beginning. + /// + /// If the parser previously failed because of a timeout, cancellation, + /// or callback, then by default, it will resume where it left off on the + /// next call to [`parse`](Parser::parse) or other parsing functions. + /// If you don't want to resume, and instead intend to use this parser to + /// parse some other document, you must call `reset` first. + #[doc(alias = "ts_parser_reset")] + pub fn reset(&mut self) { + unsafe { ffi::ts_parser_reset(self.0.as_ptr()) } + } + + /// Get the duration in microseconds that parsing is allowed to take. + /// + /// This is set via [`set_timeout_micros`](Parser::set_timeout_micros). + #[doc(alias = "ts_parser_timeout_micros")] + #[deprecated( + since = "0.25.0", + note = "Prefer using `parse_with_options` and using a callback" + )] + #[must_use] + pub fn timeout_micros(&self) -> u64 { + unsafe { ffi::ts_parser_timeout_micros(self.0.as_ptr()) } + } + + /// Set the maximum duration in microseconds that parsing should be allowed + /// to take before halting. + /// + /// If parsing takes longer than this, it will halt early, returning `None`. + /// See [`parse`](Parser::parse) for more information. + #[doc(alias = "ts_parser_set_timeout_micros")] + #[deprecated( + since = "0.25.0", + note = "Prefer using `parse_with_options` and using a callback" + )] + pub fn set_timeout_micros(&mut self, timeout_micros: u64) { + unsafe { ffi::ts_parser_set_timeout_micros(self.0.as_ptr(), timeout_micros) } + } + + /// Set the ranges of text that the parser should include when parsing. + /// + /// By default, the parser will always include entire documents. This + /// function allows you to parse only a *portion* of a document but + /// still return a syntax tree whose ranges match up with the document + /// as a whole. You can also pass multiple disjoint ranges. + /// + /// If `ranges` is empty, then the entire document will be parsed. + /// Otherwise, the given ranges must be ordered from earliest to latest + /// in the document, and they must not overlap. That is, the following + /// must hold for all `i` < `length - 1`: + /// ```text + /// ranges[i].end_byte <= ranges[i + 1].start_byte + /// ``` + /// If this requirement is not satisfied, method will return + /// [`IncludedRangesError`] error with an offset in the passed ranges + /// slice pointing to a first incorrect range. + #[doc(alias = "ts_parser_set_included_ranges")] + pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> { + let ts_ranges = ranges.iter().copied().map(Into::into).collect::>(); + let result = unsafe { + ffi::ts_parser_set_included_ranges( + self.0.as_ptr(), + ts_ranges.as_ptr(), + ts_ranges.len() as u32, + ) + }; + + if result { + Ok(()) + } else { + let mut prev_end_byte = 0; + for (i, range) in ranges.iter().enumerate() { + if range.start_byte < prev_end_byte || range.end_byte < range.start_byte { + return Err(IncludedRangesError(i)); + } + prev_end_byte = range.end_byte; + } + Err(IncludedRangesError(0)) + } + } + + /// Get the ranges of text that the parser will include when parsing. + #[doc(alias = "ts_parser_included_ranges")] + #[must_use] + pub fn included_ranges(&self) -> Vec { + let mut count = 0u32; + unsafe { + let ptr = + ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count)); + let ranges = slice::from_raw_parts(ptr, count as usize); + let result = ranges.iter().copied().map(Into::into).collect(); + result + } + } + + /// Get the parser's current cancellation flag pointer. + /// + /// # Safety + /// + /// It uses FFI + #[doc(alias = "ts_parser_cancellation_flag")] + #[deprecated( + since = "0.25.0", + note = "Prefer using `parse_with_options` and using a callback" + )] + #[must_use] + pub unsafe fn cancellation_flag(&self) -> Option<&AtomicUsize> { + ffi::ts_parser_cancellation_flag(self.0.as_ptr()) + .cast::() + .as_ref() + } + + /// Set the parser's current cancellation flag pointer. + /// + /// If a pointer is assigned, then the parser will periodically read from + /// this pointer during parsing. If it reads a non-zero value, it will halt + /// early, returning `None`. See [`parse`](Parser::parse) for more + /// information. + /// + /// # Safety + /// + /// It uses FFI + #[doc(alias = "ts_parser_set_cancellation_flag")] + #[deprecated( + since = "0.25.0", + note = "Prefer using `parse_with_options` and using a callback" + )] + pub unsafe fn set_cancellation_flag(&mut self, flag: Option<&AtomicUsize>) { + if let Some(flag) = flag { + ffi::ts_parser_set_cancellation_flag( + self.0.as_ptr(), + core::ptr::from_ref::(flag).cast::(), + ); + } else { + ffi::ts_parser_set_cancellation_flag(self.0.as_ptr(), ptr::null()); + } + } +} + +impl Drop for Parser { + fn drop(&mut self) { + #[cfg(feature = "std")] + #[cfg(not(target_os = "wasi"))] + { + self.stop_printing_dot_graphs(); + } + self.set_logger(None); + unsafe { ffi::ts_parser_delete(self.0.as_ptr()) } + } +} + +#[cfg(windows)] +extern "C" { + fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int; +} + +impl Tree { + /// Get the root node of the syntax tree. + #[doc(alias = "ts_tree_root_node")] + #[must_use] + pub fn root_node(&self) -> Node { + Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap() + } + + /// Get the root node of the syntax tree, but with its position shifted + /// forward by the given offset. + #[doc(alias = "ts_tree_root_node_with_offset")] + #[must_use] + pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node { + Node::new(unsafe { + ffi::ts_tree_root_node_with_offset( + self.0.as_ptr(), + offset_bytes as u32, + offset_extent.into(), + ) + }) + .unwrap() + } + + /// Get the language that was used to parse the syntax tree. + #[doc(alias = "ts_tree_language")] + #[must_use] + pub fn language(&self) -> LanguageRef { + LanguageRef( + unsafe { ffi::ts_tree_language(self.0.as_ptr()) }, + PhantomData, + ) + } + + /// Edit the syntax tree to keep it in sync with source code that has been + /// edited. + /// + /// You must describe the edit both in terms of byte offsets and in terms of + /// row/column coordinates. + #[doc(alias = "ts_tree_edit")] + pub fn edit(&mut self, edit: &InputEdit) { + let edit = edit.into(); + unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &edit) }; + } + + /// Create a new [`TreeCursor`] starting from the root of the tree. + #[must_use] + pub fn walk(&self) -> TreeCursor { + self.root_node().walk() + } + + /// Compare this old edited syntax tree to a new syntax tree representing + /// the same document, returning a sequence of ranges whose syntactic + /// structure has changed. + /// + /// For this to work correctly, this syntax tree must have been edited such + /// that its ranges match up to the new tree. Generally, you'll want to + /// call this method right after calling one of the [`Parser::parse`] + /// functions. Call it on the old tree that was passed to parse, and + /// pass the new tree that was returned from `parse`. + #[doc(alias = "ts_tree_get_changed_ranges")] + #[must_use] + pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator { + let mut count = 0u32; + unsafe { + let ptr = ffi::ts_tree_get_changed_ranges( + self.0.as_ptr(), + other.0.as_ptr(), + core::ptr::addr_of_mut!(count), + ); + util::CBufferIter::new(ptr, count as usize).map(Into::into) + } + } + + /// Get the included ranges that were used to parse the syntax tree. + #[doc(alias = "ts_tree_included_ranges")] + #[must_use] + pub fn included_ranges(&self) -> Vec { + let mut count = 0u32; + unsafe { + let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count)); + let ranges = slice::from_raw_parts(ptr, count as usize); + let result = ranges.iter().copied().map(Into::into).collect(); + (FREE_FN)(ptr.cast::()); + result + } + } + + /// Print a graph of the tree to the given file descriptor. + /// The graph is formatted in the DOT language. You may want to pipe this + /// graph directly to a `dot(1)` process in order to generate SVG + /// output. + #[doc(alias = "ts_tree_print_dot_graph")] + #[cfg(not(target_os = "wasi"))] + #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + pub fn print_dot_graph( + &self, + #[cfg(unix)] file: &impl AsRawFd, + #[cfg(windows)] file: &impl AsRawHandle, + ) { + #[cfg(unix)] + { + let fd = file.as_raw_fd(); + unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) } + } + + #[cfg(windows)] + { + let handle = file.as_raw_handle(); + let fd = unsafe { _open_osfhandle(handle as isize, 0) }; + unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) } + } + } +} + +impl fmt::Debug for Tree { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{{Tree {:?}}}", self.root_node()) + } +} + +impl Drop for Tree { + fn drop(&mut self) { + unsafe { ffi::ts_tree_delete(self.0.as_ptr()) } + } +} + +impl Clone for Tree { + fn clone(&self) -> Self { + unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) } + } +} + +impl<'tree> Node<'tree> { + fn new(node: ffi::TSNode) -> Option { + (!node.id.is_null()).then_some(Node(node, PhantomData)) + } + + /// Get a numeric id for this node that is unique. + /// + /// Within a given syntax tree, no two nodes have the same id. However: + /// + /// - If a new tree is created based on an older tree, and a node from the old tree is reused in + /// the process, then that node will have the same id in both trees. + /// + /// - A node not marked as having changes does not guarantee it was reused. + /// + /// - If a node is marked as having changed in the old tree, it will not be reused. + #[must_use] + pub fn id(&self) -> usize { + self.0.id as usize + } + + /// Get this node's type as a numerical id. + #[doc(alias = "ts_node_symbol")] + #[must_use] + pub fn kind_id(&self) -> u16 { + unsafe { ffi::ts_node_symbol(self.0) } + } + + /// Get the node's type as a numerical id as it appears in the grammar + /// ignoring aliases. + #[doc(alias = "ts_node_grammar_symbol")] + #[must_use] + pub fn grammar_id(&self) -> u16 { + unsafe { ffi::ts_node_grammar_symbol(self.0) } + } + + /// Get this node's type as a string. + #[doc(alias = "ts_node_type")] + #[must_use] + pub fn kind(&self) -> &'static str { + unsafe { CStr::from_ptr(ffi::ts_node_type(self.0)) } + .to_str() + .unwrap() + } + + /// Get this node's symbol name as it appears in the grammar ignoring + /// aliases as a string. + #[doc(alias = "ts_node_grammar_type")] + #[must_use] + pub fn grammar_name(&self) -> &'static str { + unsafe { CStr::from_ptr(ffi::ts_node_grammar_type(self.0)) } + .to_str() + .unwrap() + } + + /// Get the [`Language`] that was used to parse this node's syntax tree. + #[doc(alias = "ts_node_language")] + #[must_use] + pub fn language(&self) -> LanguageRef { + LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData) + } + + /// Check if this node is *named*. + /// + /// Named nodes correspond to named rules in the grammar, whereas + /// *anonymous* nodes correspond to string literals in the grammar. + #[doc(alias = "ts_node_is_named")] + #[must_use] + pub fn is_named(&self) -> bool { + unsafe { ffi::ts_node_is_named(self.0) } + } + + /// Check if this node is *extra*. + /// + /// Extra nodes represent things like comments, which are not required by the + /// grammar, but can appear anywhere. + #[doc(alias = "ts_node_is_extra")] + #[must_use] + pub fn is_extra(&self) -> bool { + unsafe { ffi::ts_node_is_extra(self.0) } + } + + /// Check if this node has been edited. + #[doc(alias = "ts_node_has_changes")] + #[must_use] + pub fn has_changes(&self) -> bool { + unsafe { ffi::ts_node_has_changes(self.0) } + } + + /// Check if this node represents a syntax error or contains any syntax + /// errors anywhere within it. + #[doc(alias = "ts_node_has_error")] + #[must_use] + pub fn has_error(&self) -> bool { + unsafe { ffi::ts_node_has_error(self.0) } + } + + /// Check if this node represents a syntax error. + /// + /// Syntax errors represent parts of the code that could not be incorporated + /// into a valid syntax tree. + #[doc(alias = "ts_node_is_error")] + #[must_use] + pub fn is_error(&self) -> bool { + unsafe { ffi::ts_node_is_error(self.0) } + } + + /// Get this node's parse state. + #[doc(alias = "ts_node_parse_state")] + #[must_use] + pub fn parse_state(&self) -> u16 { + unsafe { ffi::ts_node_parse_state(self.0) } + } + + /// Get the parse state after this node. + #[doc(alias = "ts_node_next_parse_state")] + #[must_use] + pub fn next_parse_state(&self) -> u16 { + unsafe { ffi::ts_node_next_parse_state(self.0) } + } + + /// Check if this node is *missing*. + /// + /// Missing nodes are inserted by the parser in order to recover from + /// certain kinds of syntax errors. + #[doc(alias = "ts_node_is_missing")] + #[must_use] + pub fn is_missing(&self) -> bool { + unsafe { ffi::ts_node_is_missing(self.0) } + } + + /// Get the byte offset where this node starts. + #[doc(alias = "ts_node_start_byte")] + #[must_use] + pub fn start_byte(&self) -> usize { + unsafe { ffi::ts_node_start_byte(self.0) as usize } + } + + /// Get the byte offset where this node ends. + #[doc(alias = "ts_node_end_byte")] + #[must_use] + pub fn end_byte(&self) -> usize { + unsafe { ffi::ts_node_end_byte(self.0) as usize } + } + + /// Get the byte range of source code that this node represents. + #[must_use] + pub fn byte_range(&self) -> core::ops::Range { + self.start_byte()..self.end_byte() + } + + /// Get the range of source code that this node represents, both in terms of + /// raw bytes and of row/column coordinates. + #[must_use] + pub fn range(&self) -> Range { + Range { + start_byte: self.start_byte(), + end_byte: self.end_byte(), + start_point: self.start_position(), + end_point: self.end_position(), + } + } + + /// Get this node's start position in terms of rows and columns. + #[doc(alias = "ts_node_start_point")] + #[must_use] + pub fn start_position(&self) -> Point { + let result = unsafe { ffi::ts_node_start_point(self.0) }; + result.into() + } + + /// Get this node's end position in terms of rows and columns. + #[doc(alias = "ts_node_end_point")] + #[must_use] + pub fn end_position(&self) -> Point { + let result = unsafe { ffi::ts_node_end_point(self.0) }; + result.into() + } + + /// Get the node's child at the given index, where zero represents the first + /// child. + /// + /// This method is fairly fast, but its cost is technically log(i), so if + /// you might be iterating over a long list of children, you should use + /// [`Node::children`] instead. + #[doc(alias = "ts_node_child")] + #[must_use] + pub fn child(&self, i: usize) -> Option { + Self::new(unsafe { ffi::ts_node_child(self.0, i as u32) }) + } + + /// Get this node's number of children. + #[doc(alias = "ts_node_child_count")] + #[must_use] + pub fn child_count(&self) -> usize { + unsafe { ffi::ts_node_child_count(self.0) as usize } + } + + /// Get this node's *named* child at the given index. + /// + /// See also [`Node::is_named`]. + /// This method is fairly fast, but its cost is technically log(i), so if + /// you might be iterating over a long list of children, you should use + /// [`Node::named_children`] instead. + #[doc(alias = "ts_node_named_child")] + #[must_use] + pub fn named_child(&self, i: usize) -> Option { + Self::new(unsafe { ffi::ts_node_named_child(self.0, i as u32) }) + } + + /// Get this node's number of *named* children. + /// + /// See also [`Node::is_named`]. + #[doc(alias = "ts_node_named_child_count")] + #[must_use] + pub fn named_child_count(&self) -> usize { + unsafe { ffi::ts_node_named_child_count(self.0) as usize } + } + + /// Get the first child with the given field name. + /// + /// If multiple children may have the same field name, access them using + /// [`children_by_field_name`](Node::children_by_field_name) + #[doc(alias = "ts_node_child_by_field_name")] + #[must_use] + pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option { + let field_name = field_name.as_ref(); + Self::new(unsafe { + ffi::ts_node_child_by_field_name( + self.0, + field_name.as_ptr().cast::(), + field_name.len() as u32, + ) + }) + } + + /// Get this node's child with the given numerical field id. + /// + /// See also [`child_by_field_name`](Node::child_by_field_name). You can + /// convert a field name to an id using [`Language::field_id_for_name`]. + #[doc(alias = "ts_node_child_by_field_id")] + #[must_use] + pub fn child_by_field_id(&self, field_id: u16) -> Option { + Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) }) + } + + /// Get the field name of this node's child at the given index. + #[doc(alias = "ts_node_field_name_for_child")] + #[must_use] + pub fn field_name_for_child(&self, child_index: u32) -> Option<&'static str> { + unsafe { + let ptr = ffi::ts_node_field_name_for_child(self.0, child_index); + (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap()) + } + } + + /// Get the field name of this node's named child at the given index. + #[must_use] + pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'static str> { + unsafe { + let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index); + (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap()) + } + } + + /// Iterate over this node's children. + /// + /// A [`TreeCursor`] is used to retrieve the children efficiently. Obtain + /// a [`TreeCursor`] by calling [`Tree::walk`] or [`Node::walk`]. To avoid + /// unnecessary allocations, you should reuse the same cursor for + /// subsequent calls to this method. + /// + /// If you're walking the tree recursively, you may want to use the + /// [`TreeCursor`] APIs directly instead. + pub fn children<'cursor>( + &self, + cursor: &'cursor mut TreeCursor<'tree>, + ) -> impl ExactSizeIterator> + 'cursor { + cursor.reset(*self); + cursor.goto_first_child(); + (0..self.child_count()).map(move |_| { + let result = cursor.node(); + cursor.goto_next_sibling(); + result + }) + } + + /// Iterate over this node's named children. + /// + /// See also [`Node::children`]. + pub fn named_children<'cursor>( + &self, + cursor: &'cursor mut TreeCursor<'tree>, + ) -> impl ExactSizeIterator> + 'cursor { + cursor.reset(*self); + cursor.goto_first_child(); + (0..self.named_child_count()).map(move |_| { + while !cursor.node().is_named() { + if !cursor.goto_next_sibling() { + break; + } + } + let result = cursor.node(); + cursor.goto_next_sibling(); + result + }) + } + + /// Iterate over this node's children with a given field name. + /// + /// See also [`Node::children`]. + pub fn children_by_field_name<'cursor>( + &self, + field_name: &str, + cursor: &'cursor mut TreeCursor<'tree>, + ) -> impl Iterator> + 'cursor { + let field_id = self.language().field_id_for_name(field_name); + let mut done = field_id.is_none(); + if !done { + cursor.reset(*self); + cursor.goto_first_child(); + } + iter::from_fn(move || { + if !done { + while cursor.field_id() != field_id { + if !cursor.goto_next_sibling() { + return None; + } + } + let result = cursor.node(); + if !cursor.goto_next_sibling() { + done = true; + } + return Some(result); + } + None + }) + } + + /// Iterate over this node's children with a given field id. + /// + /// See also [`Node::children_by_field_name`]. + pub fn children_by_field_id<'cursor>( + &self, + field_id: FieldId, + cursor: &'cursor mut TreeCursor<'tree>, + ) -> impl Iterator> + 'cursor { + cursor.reset(*self); + cursor.goto_first_child(); + let mut done = false; + iter::from_fn(move || { + if !done { + while cursor.field_id() != Some(field_id) { + if !cursor.goto_next_sibling() { + return None; + } + } + let result = cursor.node(); + if !cursor.goto_next_sibling() { + done = true; + } + return Some(result); + } + None + }) + } + + /// Get this node's immediate parent. + /// Prefer [`child_with_descendant`](Node::child_with_descendant) + /// for iterating over this node's ancestors. + #[doc(alias = "ts_node_parent")] + #[must_use] + pub fn parent(&self) -> Option { + Self::new(unsafe { ffi::ts_node_parent(self.0) }) + } + + /// Get the node that contains `descendant`. + /// + /// Note that this can return `descendant` itself. + #[doc(alias = "ts_node_child_with_descendant")] + #[must_use] + pub fn child_with_descendant(&self, descendant: Self) -> Option { + Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) }) + } + + /// Get this node's next sibling. + #[doc(alias = "ts_node_next_sibling")] + #[must_use] + pub fn next_sibling(&self) -> Option { + Self::new(unsafe { ffi::ts_node_next_sibling(self.0) }) + } + + /// Get this node's previous sibling. + #[doc(alias = "ts_node_prev_sibling")] + #[must_use] + pub fn prev_sibling(&self) -> Option { + Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) }) + } + + /// Get this node's next named sibling. + #[doc(alias = "ts_node_next_named_sibling")] + #[must_use] + pub fn next_named_sibling(&self) -> Option { + Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) }) + } + + /// Get this node's previous named sibling. + #[doc(alias = "ts_node_prev_named_sibling")] + #[must_use] + pub fn prev_named_sibling(&self) -> Option { + Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) }) + } + + /// Get this node's first child that contains or starts after the given byte offset. + #[doc(alias = "ts_node_first_child_for_byte")] + #[must_use] + pub fn first_child_for_byte(&self, byte: usize) -> Option { + Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) }) + } + + /// Get this node's first named child that contains or starts after the given byte offset. + #[doc(alias = "ts_node_first_named_child_for_point")] + #[must_use] + pub fn first_named_child_for_byte(&self, byte: usize) -> Option { + Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) }) + } + + /// Get the node's number of descendants, including one for the node itself. + #[doc(alias = "ts_node_descendant_count")] + #[must_use] + pub fn descendant_count(&self) -> usize { + unsafe { ffi::ts_node_descendant_count(self.0) as usize } + } + + /// Get the smallest node within this node that spans the given byte range. + #[doc(alias = "ts_node_descendant_for_byte_range")] + #[must_use] + pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option { + Self::new(unsafe { + ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32) + }) + } + + /// Get the smallest named node within this node that spans the given byte range. + #[doc(alias = "ts_node_named_descendant_for_byte_range")] + #[must_use] + pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option { + Self::new(unsafe { + ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32) + }) + } + + /// Get the smallest node within this node that spans the given point range. + #[doc(alias = "ts_node_descendant_for_point_range")] + #[must_use] + pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option { + Self::new(unsafe { + ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into()) + }) + } + + /// Get the smallest named node within this node that spans the given point range. + #[doc(alias = "ts_node_named_descendant_for_point_range")] + #[must_use] + pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option { + Self::new(unsafe { + ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into()) + }) + } + + /// Get an S-expression representing the node. + #[doc(alias = "ts_node_string")] + #[must_use] + pub fn to_sexp(&self) -> String { + let c_string = unsafe { ffi::ts_node_string(self.0) }; + let result = unsafe { CStr::from_ptr(c_string) } + .to_str() + .unwrap() + .to_string(); + unsafe { (FREE_FN)(c_string.cast::()) }; + result + } + + pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> { + str::from_utf8(&source[self.start_byte()..self.end_byte()]) + } + + #[must_use] + pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] { + &source[self.start_byte() / 2..self.end_byte() / 2] + } + + /// Create a new [`TreeCursor`] starting from this node. + /// + /// Note that the given node is considered the root of the cursor, + /// and the cursor cannot walk outside this node. + #[doc(alias = "ts_tree_cursor_new")] + #[must_use] + pub fn walk(&self) -> TreeCursor<'tree> { + TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData) + } + + /// Edit this node to keep it in-sync with source code that has been edited. + /// + /// This function is only rarely needed. When you edit a syntax tree with + /// the [`Tree::edit`] method, all of the nodes that you retrieve from + /// the tree afterward will already reflect the edit. You only need to + /// use [`Node::edit`] when you have a specific [`Node`] instance that + /// you want to keep and continue to use after an edit. + #[doc(alias = "ts_node_edit")] + pub fn edit(&mut self, edit: &InputEdit) { + let edit = edit.into(); + unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &edit) } + } +} + +impl PartialEq for Node<'_> { + fn eq(&self, other: &Self) -> bool { + core::ptr::eq(self.0.id, other.0.id) + } +} + +impl Eq for Node<'_> {} + +impl hash::Hash for Node<'_> { + fn hash(&self, state: &mut H) { + self.0.id.hash(state); + self.0.context[0].hash(state); + self.0.context[1].hash(state); + self.0.context[2].hash(state); + self.0.context[3].hash(state); + } +} + +impl fmt::Debug for Node<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{{Node {} {} - {}}}", + self.kind(), + self.start_position(), + self.end_position() + ) + } +} + +impl fmt::Display for Node<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let sexp = self.to_sexp(); + if sexp.is_empty() { + write!(f, "") + } else if !f.alternate() { + write!(f, "{sexp}") + } else { + write!(f, "{}", format_sexp(&sexp, f.width().unwrap_or(0))) + } + } +} + +impl<'cursor> TreeCursor<'cursor> { + /// Get the tree cursor's current [`Node`]. + #[doc(alias = "ts_tree_cursor_current_node")] + #[must_use] + pub fn node(&self) -> Node<'cursor> { + Node( + unsafe { ffi::ts_tree_cursor_current_node(&self.0) }, + PhantomData, + ) + } + + /// Get the numerical field id of this tree cursor's current node. + /// + /// See also [`field_name`](TreeCursor::field_name). + #[doc(alias = "ts_tree_cursor_current_field_id")] + #[must_use] + pub fn field_id(&self) -> Option { + let id = unsafe { ffi::ts_tree_cursor_current_field_id(&self.0) }; + FieldId::new(id) + } + + /// Get the field name of this tree cursor's current node. + #[doc(alias = "ts_tree_cursor_current_field_name")] + #[must_use] + pub fn field_name(&self) -> Option<&'static str> { + unsafe { + let ptr = ffi::ts_tree_cursor_current_field_name(&self.0); + (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap()) + } + } + + /// Get the depth of the cursor's current node relative to the original + /// node that the cursor was constructed with. + #[doc(alias = "ts_tree_cursor_current_depth")] + #[must_use] + pub fn depth(&self) -> u32 { + unsafe { ffi::ts_tree_cursor_current_depth(&self.0) } + } + + /// Get the index of the cursor's current node out of all of the + /// descendants of the original node that the cursor was constructed with + #[doc(alias = "ts_tree_cursor_current_descendant_index")] + #[must_use] + pub fn descendant_index(&self) -> usize { + unsafe { ffi::ts_tree_cursor_current_descendant_index(&self.0) as usize } + } + + /// Move this cursor to the first child of its current node. + /// + /// This returns `true` if the cursor successfully moved, and returns + /// `false` if there were no children. + #[doc(alias = "ts_tree_cursor_goto_first_child")] + pub fn goto_first_child(&mut self) -> bool { + unsafe { ffi::ts_tree_cursor_goto_first_child(&mut self.0) } + } + + /// Move this cursor to the last child of its current node. + /// + /// This returns `true` if the cursor successfully moved, and returns + /// `false` if there were no children. + /// + /// Note that this function may be slower than + /// [`goto_first_child`](TreeCursor::goto_first_child) because it needs to + /// iterate through all the children to compute the child's position. + #[doc(alias = "ts_tree_cursor_goto_last_child")] + pub fn goto_last_child(&mut self) -> bool { + unsafe { ffi::ts_tree_cursor_goto_last_child(&mut self.0) } + } + + /// Move this cursor to the parent of its current node. + /// + /// This returns `true` if the cursor successfully moved, and returns + /// `false` if there was no parent node (the cursor was already on the + /// root node). + /// + /// Note that the node the cursor was constructed with is considered the root + /// of the cursor, and the cursor cannot walk outside this node. + #[doc(alias = "ts_tree_cursor_goto_parent")] + pub fn goto_parent(&mut self) -> bool { + unsafe { ffi::ts_tree_cursor_goto_parent(&mut self.0) } + } + + /// Move this cursor to the next sibling of its current node. + /// + /// This returns `true` if the cursor successfully moved, and returns + /// `false` if there was no next sibling node. + /// + /// Note that the node the cursor was constructed with is considered the root + /// of the cursor, and the cursor cannot walk outside this node. + #[doc(alias = "ts_tree_cursor_goto_next_sibling")] + pub fn goto_next_sibling(&mut self) -> bool { + unsafe { ffi::ts_tree_cursor_goto_next_sibling(&mut self.0) } + } + + /// Move the cursor to the node that is the nth descendant of + /// the original node that the cursor was constructed with, where + /// zero represents the original node itself. + #[doc(alias = "ts_tree_cursor_goto_descendant")] + pub fn goto_descendant(&mut self, descendant_index: usize) { + unsafe { ffi::ts_tree_cursor_goto_descendant(&mut self.0, descendant_index as u32) } + } + + /// Move this cursor to the previous sibling of its current node. + /// + /// This returns `true` if the cursor successfully moved, and returns + /// `false` if there was no previous sibling node. + /// + /// Note, that this function may be slower than + /// [`goto_next_sibling`](TreeCursor::goto_next_sibling) due to how node + /// positions are stored. In the worst case, this will need to iterate + /// through all the children up to the previous sibling node to recalculate + /// its position. Also note that the node the cursor was constructed with is + /// considered the root of the cursor, and the cursor cannot walk outside this node. + #[doc(alias = "ts_tree_cursor_goto_previous_sibling")] + pub fn goto_previous_sibling(&mut self) -> bool { + unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&mut self.0) } + } + + /// Move this cursor to the first child of its current node that contains or + /// starts after the given byte offset. + /// + /// This returns the index of the child node if one was found, and returns + /// `None` if no such child was found. + #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")] + pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option { + let result = + unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&mut self.0, index as u32) }; + result.try_into().ok() + } + + /// Move this cursor to the first child of its current node that contains or + /// starts after the given byte offset. + /// + /// This returns the index of the child node if one was found, and returns + /// `None` if no such child was found. + #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")] + pub fn goto_first_child_for_point(&mut self, point: Point) -> Option { + let result = + unsafe { ffi::ts_tree_cursor_goto_first_child_for_point(&mut self.0, point.into()) }; + result.try_into().ok() + } + + /// Re-initialize this tree cursor to start at the original node that the + /// cursor was constructed with. + #[doc(alias = "ts_tree_cursor_reset")] + pub fn reset(&mut self, node: Node<'cursor>) { + unsafe { ffi::ts_tree_cursor_reset(&mut self.0, node.0) }; + } + + /// Re-initialize a tree cursor to the same position as another cursor. + /// + /// Unlike [`reset`](TreeCursor::reset), this will not lose parent + /// information and allows reusing already created cursors. + #[doc(alias = "ts_tree_cursor_reset_to")] + pub fn reset_to(&mut self, cursor: &Self) { + unsafe { ffi::ts_tree_cursor_reset_to(&mut self.0, &cursor.0) }; + } +} + +impl Clone for TreeCursor<'_> { + fn clone(&self) -> Self { + TreeCursor(unsafe { ffi::ts_tree_cursor_copy(&self.0) }, PhantomData) + } +} + +impl Drop for TreeCursor<'_> { + fn drop(&mut self) { + unsafe { ffi::ts_tree_cursor_delete(&mut self.0) } + } +} + +impl LookaheadIterator { + /// Get the current language of the lookahead iterator. + #[doc(alias = "ts_lookahead_iterator_language")] + #[must_use] + pub fn language(&self) -> LanguageRef<'_> { + LanguageRef( + unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) }, + PhantomData, + ) + } + + /// Get the current symbol of the lookahead iterator. + #[doc(alias = "ts_lookahead_iterator_current_symbol")] + #[must_use] + pub fn current_symbol(&self) -> u16 { + unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) } + } + + /// Get the current symbol name of the lookahead iterator. + #[doc(alias = "ts_lookahead_iterator_current_symbol_name")] + #[must_use] + pub fn current_symbol_name(&self) -> &'static str { + unsafe { + CStr::from_ptr(ffi::ts_lookahead_iterator_current_symbol_name( + self.0.as_ptr(), + )) + .to_str() + .unwrap() + } + } + + /// Reset the lookahead iterator. + /// + /// This returns `true` if the language was set successfully and `false` + /// otherwise. + #[doc(alias = "ts_lookahead_iterator_reset")] + pub fn reset(&mut self, language: &Language, state: u16) -> bool { + unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) } + } + + /// Reset the lookahead iterator to another state. + /// + /// This returns `true` if the iterator was reset to the given state and + /// `false` otherwise. + #[doc(alias = "ts_lookahead_iterator_reset_state")] + pub fn reset_state(&mut self, state: u16) -> bool { + unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) } + } + + /// Iterate symbol names. + pub fn iter_names(&mut self) -> impl Iterator + '_ { + LookaheadNamesIterator(self) + } +} + +impl Iterator for LookaheadNamesIterator<'_> { + type Item = &'static str; + + #[doc(alias = "ts_lookahead_iterator_next")] + fn next(&mut self) -> Option { + unsafe { ffi::ts_lookahead_iterator_next(self.0 .0.as_ptr()) } + .then(|| self.0.current_symbol_name()) + } +} + +impl Iterator for LookaheadIterator { + type Item = u16; + + #[doc(alias = "ts_lookahead_iterator_next")] + fn next(&mut self) -> Option { + // the first symbol is always `0` so we can safely skip it + unsafe { ffi::ts_lookahead_iterator_next(self.0.as_ptr()) }.then(|| self.current_symbol()) + } +} + +impl Drop for LookaheadIterator { + #[doc(alias = "ts_lookahead_iterator_delete")] + fn drop(&mut self) { + unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) } + } +} + +impl Query { + /// Create a new query from a string containing one or more S-expression + /// patterns. + /// + /// The query is associated with a particular language, and can only be run + /// on syntax nodes parsed with that language. References to Queries can be + /// shared between multiple threads. + pub fn new(language: &Language, source: &str) -> Result { + let mut error_offset = 0u32; + let mut error_type: ffi::TSQueryError = 0; + let bytes = source.as_bytes(); + + // Compile the query. + let ptr = unsafe { + ffi::ts_query_new( + language.0, + bytes.as_ptr().cast::(), + bytes.len() as u32, + core::ptr::addr_of_mut!(error_offset), + core::ptr::addr_of_mut!(error_type), + ) + }; + + // On failure, build an error based on the error code and offset. + if ptr.is_null() { + if error_type == ffi::TSQueryErrorLanguage { + return Err(QueryError { + row: 0, + column: 0, + offset: 0, + message: LanguageError { + version: language.abi_version(), + } + .to_string(), + kind: QueryErrorKind::Language, + }); + } + + let offset = error_offset as usize; + let mut line_start = 0; + let mut row = 0; + let mut line_containing_error = None; + for line in source.lines() { + let line_end = line_start + line.len() + 1; + if line_end > offset { + line_containing_error = Some(line); + break; + } + line_start = line_end; + row += 1; + } + let column = offset - line_start; + + let kind; + let message; + match error_type { + // Error types that report names + ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => { + let suffix = source.split_at(offset).1; + let in_quotes = offset > 0 && source.as_bytes()[offset - 1] == b'"'; + let mut backslashes = 0; + let end_offset = suffix + .find(|c| { + if in_quotes { + if c == '"' && backslashes % 2 == 0 { + true + } else if c == '\\' { + backslashes += 1; + false + } else { + backslashes = 0; + false + } + } else { + !char::is_alphanumeric(c) && c != '_' && c != '-' + } + }) + .unwrap_or(suffix.len()); + message = suffix.split_at(end_offset).0.to_string(); + kind = match error_type { + ffi::TSQueryErrorNodeType => QueryErrorKind::NodeType, + ffi::TSQueryErrorField => QueryErrorKind::Field, + ffi::TSQueryErrorCapture => QueryErrorKind::Capture, + _ => unreachable!(), + }; + } + + // Error types that report positions + _ => { + message = line_containing_error.map_or_else( + || "Unexpected EOF".to_string(), + |line| line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^", + ); + kind = match error_type { + ffi::TSQueryErrorStructure => QueryErrorKind::Structure, + _ => QueryErrorKind::Syntax, + }; + } + } + + return Err(QueryError { + row, + column, + offset, + message, + kind, + }); + } + + unsafe { Self::from_raw_parts(ptr, source) } + } + + #[doc(hidden)] + unsafe fn from_raw_parts(ptr: *mut ffi::TSQuery, source: &str) -> Result { + let ptr = { + struct TSQueryDrop(*mut ffi::TSQuery); + impl Drop for TSQueryDrop { + fn drop(&mut self) { + unsafe { ffi::ts_query_delete(self.0) } + } + } + TSQueryDrop(ptr) + }; + + let string_count = unsafe { ffi::ts_query_string_count(ptr.0) }; + let capture_count = unsafe { ffi::ts_query_capture_count(ptr.0) }; + let pattern_count = unsafe { ffi::ts_query_pattern_count(ptr.0) as usize }; + + let mut capture_names = Vec::with_capacity(capture_count as usize); + let mut capture_quantifiers_vec = Vec::with_capacity(pattern_count as usize); + let mut text_predicates_vec = Vec::with_capacity(pattern_count); + let mut property_predicates_vec = Vec::with_capacity(pattern_count); + let mut property_settings_vec = Vec::with_capacity(pattern_count); + let mut general_predicates_vec = Vec::with_capacity(pattern_count); + + // Build a vector of strings to store the capture names. + for i in 0..capture_count { + unsafe { + let mut length = 0u32; + let name = + ffi::ts_query_capture_name_for_id(ptr.0, i, core::ptr::addr_of_mut!(length)) + .cast::(); + let name = slice::from_raw_parts(name, length as usize); + let name = str::from_utf8_unchecked(name); + capture_names.push(name); + } + } + + // Build a vector to store capture quantifiers. + for i in 0..pattern_count { + let mut capture_quantifiers = Vec::with_capacity(capture_count as usize); + for j in 0..capture_count { + unsafe { + let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr.0, i as u32, j); + capture_quantifiers.push(quantifier.into()); + } + } + capture_quantifiers_vec.push(capture_quantifiers.into()); + } + + // Build a vector of strings to represent literal values used in predicates. + let string_values = (0..string_count) + .map(|i| unsafe { + let mut length = 0u32; + let value = + ffi::ts_query_string_value_for_id(ptr.0, i, core::ptr::addr_of_mut!(length)) + .cast::(); + let value = slice::from_raw_parts(value, length as usize); + let value = str::from_utf8_unchecked(value); + value + }) + .collect::>(); + + // Build a vector of predicates for each pattern. + for i in 0..pattern_count { + let predicate_steps = unsafe { + let mut length = 0u32; + let raw_predicates = ffi::ts_query_predicates_for_pattern( + ptr.0, + i as u32, + core::ptr::addr_of_mut!(length), + ); + (length > 0) + .then(|| slice::from_raw_parts(raw_predicates, length as usize)) + .unwrap_or_default() + }; + + let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) }; + let row = source + .char_indices() + .take_while(|(i, _)| *i < byte_offset as usize) + .filter(|(_, c)| *c == '\n') + .count(); + + use ffi::TSQueryPredicateStepType as T; + const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone; + const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture; + const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString; + + let mut text_predicates = Vec::new(); + let mut property_predicates = Vec::new(); + let mut property_settings = Vec::new(); + let mut general_predicates = Vec::new(); + for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) { + if p.is_empty() { + continue; + } + + if p[0].type_ != TYPE_STRING { + return Err(predicate_error( + row, + format!( + "Expected predicate to start with a function name. Got @{}.", + capture_names[p[0].value_id as usize], + ), + )); + } + + // Build a predicate for each of the known predicate function names. + let operator_name = string_values[p[0].value_id as usize]; + match operator_name { + "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => { + if p.len() != 3 { + return Err(predicate_error( + row, + format!( + "Wrong number of arguments to #eq? predicate. Expected 2, got {}.", + p.len() - 1 + ), + )); + } + if p[1].type_ != TYPE_CAPTURE { + return Err(predicate_error(row, format!( + "First argument to #eq? predicate must be a capture name. Got literal \"{}\".", + string_values[p[1].value_id as usize], + ))); + } + + let is_positive = operator_name == "eq?" || operator_name == "any-eq?"; + let match_all = match operator_name { + "eq?" | "not-eq?" => true, + "any-eq?" | "any-not-eq?" => false, + _ => unreachable!(), + }; + text_predicates.push(if p[2].type_ == TYPE_CAPTURE { + TextPredicateCapture::EqCapture( + p[1].value_id, + p[2].value_id, + is_positive, + match_all, + ) + } else { + TextPredicateCapture::EqString( + p[1].value_id, + string_values[p[2].value_id as usize].to_string().into(), + is_positive, + match_all, + ) + }); + } + + "match?" | "not-match?" | "any-match?" | "any-not-match?" => { + if p.len() != 3 { + return Err(predicate_error(row, format!( + "Wrong number of arguments to #match? predicate. Expected 2, got {}.", + p.len() - 1 + ))); + } + if p[1].type_ != TYPE_CAPTURE { + return Err(predicate_error(row, format!( + "First argument to #match? predicate must be a capture name. Got literal \"{}\".", + string_values[p[1].value_id as usize], + ))); + } + if p[2].type_ == TYPE_CAPTURE { + return Err(predicate_error(row, format!( + "Second argument to #match? predicate must be a literal. Got capture @{}.", + capture_names[p[2].value_id as usize], + ))); + } + + let is_positive = + operator_name == "match?" || operator_name == "any-match?"; + let match_all = match operator_name { + "match?" | "not-match?" => true, + "any-match?" | "any-not-match?" => false, + _ => unreachable!(), + }; + let regex = &string_values[p[2].value_id as usize]; + text_predicates.push(TextPredicateCapture::MatchString( + p[1].value_id, + regex::bytes::Regex::new(regex).map_err(|_| { + predicate_error(row, format!("Invalid regex '{regex}'")) + })?, + is_positive, + match_all, + )); + } + + "set!" => property_settings.push(Self::parse_property( + row, + operator_name, + &capture_names, + &string_values, + &p[1..], + )?), + + "is?" | "is-not?" => property_predicates.push(( + Self::parse_property( + row, + operator_name, + &capture_names, + &string_values, + &p[1..], + )?, + operator_name == "is?", + )), + + "any-of?" | "not-any-of?" => { + if p.len() < 2 { + return Err(predicate_error(row, format!( + "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.", + p.len() - 1 + ))); + } + if p[1].type_ != TYPE_CAPTURE { + return Err(predicate_error(row, format!( + "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".", + string_values[p[1].value_id as usize], + ))); + } + + let is_positive = operator_name == "any-of?"; + let mut values = Vec::new(); + for arg in &p[2..] { + if arg.type_ == TYPE_CAPTURE { + return Err(predicate_error(row, format!( + "Arguments to #any-of? predicate must be literals. Got capture @{}.", + capture_names[arg.value_id as usize], + ))); + } + values.push(string_values[arg.value_id as usize]); + } + text_predicates.push(TextPredicateCapture::AnyString( + p[1].value_id, + values + .iter() + .map(|x| (*x).to_string().into()) + .collect::>() + .into(), + is_positive, + )); + } + + _ => general_predicates.push(QueryPredicate { + operator: operator_name.to_string().into(), + args: p[1..] + .iter() + .map(|a| { + if a.type_ == TYPE_CAPTURE { + QueryPredicateArg::Capture(a.value_id) + } else { + QueryPredicateArg::String( + string_values[a.value_id as usize].to_string().into(), + ) + } + }) + .collect(), + }), + } + } + + text_predicates_vec.push(text_predicates.into()); + property_predicates_vec.push(property_predicates.into()); + property_settings_vec.push(property_settings.into()); + general_predicates_vec.push(general_predicates.into()); + } + + let result = Self { + ptr: unsafe { NonNull::new_unchecked(ptr.0) }, + capture_names: capture_names.into(), + capture_quantifiers: capture_quantifiers_vec.into(), + text_predicates: text_predicates_vec.into(), + property_predicates: property_predicates_vec.into(), + property_settings: property_settings_vec.into(), + general_predicates: general_predicates_vec.into(), + }; + + core::mem::forget(ptr); + + Ok(result) + } + + /// Get the byte offset where the given pattern starts in the query's + /// source. + #[doc(alias = "ts_query_start_byte_for_pattern")] + #[must_use] + pub fn start_byte_for_pattern(&self, pattern_index: usize) -> usize { + assert!( + pattern_index < self.text_predicates.len(), + "Pattern index is {pattern_index} but the pattern count is {}", + self.text_predicates.len(), + ); + unsafe { + ffi::ts_query_start_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize + } + } + + /// Get the byte offset where the given pattern ends in the query's + /// source. + #[doc(alias = "ts_query_end_byte_for_pattern")] + #[must_use] + pub fn end_byte_for_pattern(&self, pattern_index: usize) -> usize { + assert!( + pattern_index < self.text_predicates.len(), + "Pattern index is {pattern_index} but the pattern count is {}", + self.text_predicates.len(), + ); + unsafe { + ffi::ts_query_end_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize + } + } + + /// Get the number of patterns in the query. + #[doc(alias = "ts_query_pattern_count")] + #[must_use] + pub fn pattern_count(&self) -> usize { + unsafe { ffi::ts_query_pattern_count(self.ptr.as_ptr()) as usize } + } + + /// Get the names of the captures used in the query. + #[must_use] + pub const fn capture_names(&self) -> &[&str] { + &self.capture_names + } + + /// Get the quantifiers of the captures used in the query. + #[must_use] + pub const fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] { + &self.capture_quantifiers[index] + } + + /// Get the index for a given capture name. + #[must_use] + pub fn capture_index_for_name(&self, name: &str) -> Option { + self.capture_names + .iter() + .position(|n| *n == name) + .map(|ix| ix as u32) + } + + /// Get the properties that are checked for the given pattern index. + /// + /// This includes predicates with the operators `is?` and `is-not?`. + #[must_use] + pub const fn property_predicates(&self, index: usize) -> &[(QueryProperty, bool)] { + &self.property_predicates[index] + } + + /// Get the properties that are set for the given pattern index. + /// + /// This includes predicates with the operator `set!`. + #[must_use] + pub const fn property_settings(&self, index: usize) -> &[QueryProperty] { + &self.property_settings[index] + } + + /// Get the other user-defined predicates associated with the given index. + /// + /// This includes predicate with operators other than: + /// * `match?` + /// * `eq?` and `not-eq?` + /// * `is?` and `is-not?` + /// * `set!` + #[must_use] + pub const fn general_predicates(&self, index: usize) -> &[QueryPredicate] { + &self.general_predicates[index] + } + + /// Disable a certain capture within a query. + /// + /// This prevents the capture from being returned in matches, and also + /// avoids any resource usage associated with recording the capture. + #[doc(alias = "ts_query_disable_capture")] + pub fn disable_capture(&mut self, name: &str) { + unsafe { + ffi::ts_query_disable_capture( + self.ptr.as_ptr(), + name.as_bytes().as_ptr().cast::(), + name.len() as u32, + ); + } + } + + /// Disable a certain pattern within a query. + /// + /// This prevents the pattern from matching, and also avoids any resource + /// usage associated with the pattern. + #[doc(alias = "ts_query_disable_pattern")] + pub fn disable_pattern(&mut self, index: usize) { + unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) } + } + + /// Check if a given pattern within a query has a single root node. + #[doc(alias = "ts_query_is_pattern_rooted")] + #[must_use] + pub fn is_pattern_rooted(&self, index: usize) -> bool { + unsafe { ffi::ts_query_is_pattern_rooted(self.ptr.as_ptr(), index as u32) } + } + + /// Check if a given pattern within a query has a single root node. + #[doc(alias = "ts_query_is_pattern_non_local")] + #[must_use] + pub fn is_pattern_non_local(&self, index: usize) -> bool { + unsafe { ffi::ts_query_is_pattern_non_local(self.ptr.as_ptr(), index as u32) } + } + + /// Check if a given step in a query is 'definite'. + /// + /// A query step is 'definite' if its parent pattern will be guaranteed to + /// match successfully once it reaches the step. + #[doc(alias = "ts_query_is_pattern_guaranteed_at_step")] + #[must_use] + pub fn is_pattern_guaranteed_at_step(&self, byte_offset: usize) -> bool { + unsafe { + ffi::ts_query_is_pattern_guaranteed_at_step(self.ptr.as_ptr(), byte_offset as u32) + } + } + + fn parse_property( + row: usize, + function_name: &str, + capture_names: &[&str], + string_values: &[&str], + args: &[ffi::TSQueryPredicateStep], + ) -> Result { + if args.is_empty() || args.len() > 3 { + return Err(predicate_error( + row, + format!( + "Wrong number of arguments to {function_name} predicate. Expected 1 to 3, got {}.", + args.len(), + ), + )); + } + + let mut capture_id = None; + let mut key = None; + let mut value = None; + + for arg in args { + if arg.type_ == ffi::TSQueryPredicateStepTypeCapture { + if capture_id.is_some() { + return Err(predicate_error( + row, + format!( + "Invalid arguments to {function_name} predicate. Unexpected second capture name @{}", + capture_names[arg.value_id as usize] + ), + )); + } + capture_id = Some(arg.value_id as usize); + } else if key.is_none() { + key = Some(&string_values[arg.value_id as usize]); + } else if value.is_none() { + value = Some(string_values[arg.value_id as usize]); + } else { + return Err(predicate_error( + row, + format!( + "Invalid arguments to {function_name} predicate. Unexpected third argument @{}", + string_values[arg.value_id as usize] + ), + )); + } + } + + if let Some(key) = key { + Ok(QueryProperty::new(key, value, capture_id)) + } else { + Err(predicate_error( + row, + format!("Invalid arguments to {function_name} predicate. Missing key argument",), + )) + } + } +} + +impl Default for QueryCursor { + fn default() -> Self { + Self::new() + } +} + +impl QueryCursor { + /// Create a new cursor for executing a given query. + /// + /// The cursor stores the state that is needed to iteratively search for + /// matches. + #[doc(alias = "ts_query_cursor_new")] + #[must_use] + pub fn new() -> Self { + Self { + ptr: unsafe { NonNull::new_unchecked(ffi::ts_query_cursor_new()) }, + } + } + + /// Return the maximum number of in-progress matches for this cursor. + #[doc(alias = "ts_query_cursor_match_limit")] + #[must_use] + pub fn match_limit(&self) -> u32 { + unsafe { ffi::ts_query_cursor_match_limit(self.ptr.as_ptr()) } + } + + /// Set the maximum number of in-progress matches for this cursor. The + /// limit must be > 0 and <= 65536. + #[doc(alias = "ts_query_cursor_set_match_limit")] + pub fn set_match_limit(&mut self, limit: u32) { + unsafe { + ffi::ts_query_cursor_set_match_limit(self.ptr.as_ptr(), limit); + } + } + + /// Set the maximum duration in microseconds that query execution should be allowed to + /// take before halting. + /// + /// If query execution takes longer than this, it will halt early, returning None. + #[doc(alias = "ts_query_cursor_set_timeout_micros")] + #[deprecated( + since = "0.25.0", + note = "Prefer using `matches_with_options` or `captures_with_options` and using a callback" + )] + pub fn set_timeout_micros(&mut self, timeout: u64) { + unsafe { + ffi::ts_query_cursor_set_timeout_micros(self.ptr.as_ptr(), timeout); + } + } + + /// Get the duration in microseconds that query execution is allowed to take. + /// + /// This is set via [`set_timeout_micros`](QueryCursor::set_timeout_micros). + #[doc(alias = "ts_query_cursor_timeout_micros")] + #[deprecated( + since = "0.25.0", + note = "Prefer using `matches_with_options` or `captures_with_options` and using a callback" + )] + #[must_use] + pub fn timeout_micros(&self) -> u64 { + unsafe { ffi::ts_query_cursor_timeout_micros(self.ptr.as_ptr()) } + } + + /// Check if, on its last execution, this cursor exceeded its maximum number + /// of in-progress matches. + #[doc(alias = "ts_query_cursor_did_exceed_match_limit")] + #[must_use] + pub fn did_exceed_match_limit(&self) -> bool { + unsafe { ffi::ts_query_cursor_did_exceed_match_limit(self.ptr.as_ptr()) } + } + + /// Iterate over all of the matches in the order that they were found. + /// + /// Each match contains the index of the pattern that matched, and a list of + /// captures. Because multiple patterns can match the same set of nodes, + /// one match may contain captures that appear *before* some of the + /// captures from a previous match. + /// + /// Iterating over a `QueryMatches` object requires the `StreamingIterator` + /// or `StreamingIteratorMut` trait to be in scope. This can be done via + /// `use tree_sitter::StreamingIterator` or `use tree_sitter::StreamingIteratorMut` + #[doc(alias = "ts_query_cursor_exec")] + pub fn matches<'query, 'cursor: 'query, 'tree, T: TextProvider, I: AsRef<[u8]>>( + &'cursor mut self, + query: &'query Query, + node: Node<'tree>, + text_provider: T, + ) -> QueryMatches<'query, 'tree, T, I> { + let ptr = self.ptr.as_ptr(); + unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) }; + QueryMatches { + ptr, + query, + text_provider, + buffer1: Vec::default(), + buffer2: Vec::default(), + current_match: None, + _options: None, + _phantom: PhantomData, + } + } + + /// Iterate over all of the matches in the order that they were found, with options. + /// + /// Each match contains the index of the pattern that matched, and a list of + /// captures. Because multiple patterns can match the same set of nodes, + /// one match may contain captures that appear *before* some of the + /// captures from a previous match. + #[doc(alias = "ts_query_cursor_exec_with_options")] + pub fn matches_with_options< + 'query, + 'cursor: 'query, + 'tree, + T: TextProvider, + I: AsRef<[u8]>, + >( + &'cursor mut self, + query: &'query Query, + node: Node<'tree>, + text_provider: T, + options: QueryCursorOptions, + ) -> QueryMatches<'query, 'tree, T, I> { + unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool { + let callback = (*state) + .payload + .cast::() + .as_mut() + .unwrap(); + (callback)(&QueryCursorState::from_raw(state)) + } + + let query_options = options.progress_callback.map(|cb| { + QueryCursorOptionsDrop(Box::into_raw(Box::new(ffi::TSQueryCursorOptions { + payload: Box::into_raw(Box::new(cb)).cast::(), + progress_callback: Some(progress), + }))) + }); + + let ptr = self.ptr.as_ptr(); + unsafe { + ffi::ts_query_cursor_exec_with_options( + ptr, + query.ptr.as_ptr(), + node.0, + query_options.as_ref().map_or(ptr::null_mut(), |q| q.0), + ); + } + QueryMatches { + ptr, + query, + text_provider, + buffer1: Vec::default(), + buffer2: Vec::default(), + current_match: None, + _options: query_options, + _phantom: PhantomData, + } + } + + /// Iterate over all of the individual captures in the order that they + /// appear. + /// + /// This is useful if you don't care about which pattern matched, and just + /// want a single, ordered sequence of captures. + /// + /// Iterating over a `QueryCaptures` object requires the `StreamingIterator` + /// or `StreamingIteratorMut` trait to be in scope. This can be done via + /// `use tree_sitter::StreamingIterator` or `use tree_sitter::StreamingIteratorMut` + #[doc(alias = "ts_query_cursor_exec")] + pub fn captures<'query, 'cursor: 'query, 'tree, T: TextProvider, I: AsRef<[u8]>>( + &'cursor mut self, + query: &'query Query, + node: Node<'tree>, + text_provider: T, + ) -> QueryCaptures<'query, 'tree, T, I> { + let ptr = self.ptr.as_ptr(); + unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) }; + QueryCaptures { + ptr, + query, + text_provider, + buffer1: Vec::default(), + buffer2: Vec::default(), + current_match: None, + _options: None, + _phantom: PhantomData, + } + } + + /// Iterate over all of the individual captures in the order that they + /// appear, with options. + /// + /// This is useful if you don't care about which pattern matched, and just + /// want a single, ordered sequence of captures. + #[doc(alias = "ts_query_cursor_exec")] + pub fn captures_with_options< + 'query, + 'cursor: 'query, + 'tree, + T: TextProvider, + I: AsRef<[u8]>, + >( + &'cursor mut self, + query: &'query Query, + node: Node<'tree>, + text_provider: T, + options: QueryCursorOptions, + ) -> QueryCaptures<'query, 'tree, T, I> { + unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool { + let callback = (*state) + .payload + .cast::() + .as_mut() + .unwrap(); + (callback)(&QueryCursorState::from_raw(state)) + } + + let query_options = options.progress_callback.map(|cb| { + QueryCursorOptionsDrop(Box::into_raw(Box::new(ffi::TSQueryCursorOptions { + payload: Box::into_raw(Box::new(cb)).cast::(), + progress_callback: Some(progress), + }))) + }); + + let ptr = self.ptr.as_ptr(); + unsafe { + ffi::ts_query_cursor_exec_with_options( + ptr, + query.ptr.as_ptr(), + node.0, + query_options.as_ref().map_or(ptr::null_mut(), |q| q.0), + ); + } + QueryCaptures { + ptr, + query, + text_provider, + buffer1: Vec::default(), + buffer2: Vec::default(), + current_match: None, + _options: query_options, + _phantom: PhantomData, + } + } + + /// Set the range in which the query will be executed, in terms of byte + /// offsets. + #[doc(alias = "ts_query_cursor_set_byte_range")] + pub fn set_byte_range(&mut self, range: ops::Range) -> &mut Self { + unsafe { + ffi::ts_query_cursor_set_byte_range( + self.ptr.as_ptr(), + range.start as u32, + range.end as u32, + ); + } + self + } + + /// Set the range in which the query will be executed, in terms of rows and + /// columns. + #[doc(alias = "ts_query_cursor_set_point_range")] + pub fn set_point_range(&mut self, range: ops::Range) -> &mut Self { + unsafe { + ffi::ts_query_cursor_set_point_range( + self.ptr.as_ptr(), + range.start.into(), + range.end.into(), + ); + } + self + } + + /// Set the maximum start depth for a query cursor. + /// + /// This prevents cursors from exploring children nodes at a certain depth. + /// Note if a pattern includes many children, then they will still be + /// checked. + /// + /// The zero max start depth value can be used as a special behavior and + /// it helps to destructure a subtree by staying on a node and using + /// captures for interested parts. Note that the zero max start depth + /// only limit a search depth for a pattern's root node but other nodes + /// that are parts of the pattern may be searched at any depth what + /// defined by the pattern structure. + /// + /// Set to `None` to remove the maximum start depth. + #[doc(alias = "ts_query_cursor_set_max_start_depth")] + pub fn set_max_start_depth(&mut self, max_start_depth: Option) -> &mut Self { + unsafe { + ffi::ts_query_cursor_set_max_start_depth( + self.ptr.as_ptr(), + max_start_depth.unwrap_or(u32::MAX), + ); + } + self + } +} + +impl<'tree> QueryMatch<'_, 'tree> { + #[must_use] + pub const fn id(&self) -> u32 { + self.id + } + + #[doc(alias = "ts_query_cursor_remove_match")] + pub fn remove(&self) { + unsafe { ffi::ts_query_cursor_remove_match(self.cursor, self.id) } + } + + pub fn nodes_for_capture_index( + &self, + capture_ix: u32, + ) -> impl Iterator> + '_ { + self.captures + .iter() + .filter_map(move |capture| (capture.index == capture_ix).then_some(capture.node)) + } + + fn new(m: &ffi::TSQueryMatch, cursor: *mut ffi::TSQueryCursor) -> Self { + QueryMatch { + cursor, + id: m.id, + pattern_index: m.pattern_index as usize, + captures: (m.capture_count > 0) + .then(|| unsafe { + slice::from_raw_parts( + m.captures.cast::>(), + m.capture_count as usize, + ) + }) + .unwrap_or_default(), + } + } + + pub fn satisfies_text_predicates>( + &self, + query: &Query, + buffer1: &mut Vec, + buffer2: &mut Vec, + text_provider: &mut impl TextProvider, + ) -> bool { + struct NodeText<'a, T> { + buffer: &'a mut Vec, + first_chunk: Option, + } + impl<'a, T: AsRef<[u8]>> NodeText<'a, T> { + fn new(buffer: &'a mut Vec) -> Self { + Self { + buffer, + first_chunk: None, + } + } + + fn get_text(&mut self, chunks: &mut impl Iterator) -> &[u8] { + self.first_chunk = chunks.next(); + if let Some(next_chunk) = chunks.next() { + self.buffer.clear(); + self.buffer + .extend_from_slice(self.first_chunk.as_ref().unwrap().as_ref()); + self.buffer.extend_from_slice(next_chunk.as_ref()); + for chunk in chunks { + self.buffer.extend_from_slice(chunk.as_ref()); + } + self.buffer.as_slice() + } else if let Some(ref first_chunk) = self.first_chunk { + first_chunk.as_ref() + } else { + &[] + } + } + } + + let mut node_text1 = NodeText::new(buffer1); + let mut node_text2 = NodeText::new(buffer2); + + query.text_predicates[self.pattern_index] + .iter() + .all(|predicate| match predicate { + TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => { + let mut nodes_1 = self.nodes_for_capture_index(*i).peekable(); + let mut nodes_2 = self.nodes_for_capture_index(*j).peekable(); + while nodes_1.peek().is_some() && nodes_2.peek().is_some() { + let node1 = nodes_1.next().unwrap(); + let node2 = nodes_2.next().unwrap(); + let mut text1 = text_provider.text(node1); + let mut text2 = text_provider.text(node2); + let text1 = node_text1.get_text(&mut text1); + let text2 = node_text2.get_text(&mut text2); + let is_positive_match = text1 == text2; + if is_positive_match != *is_positive && *match_all_nodes { + return false; + } + if is_positive_match == *is_positive && !*match_all_nodes { + return true; + } + } + nodes_1.next().is_none() && nodes_2.next().is_none() + } + TextPredicateCapture::EqString(i, s, is_positive, match_all_nodes) => { + let nodes = self.nodes_for_capture_index(*i); + for node in nodes { + let mut text = text_provider.text(node); + let text = node_text1.get_text(&mut text); + let is_positive_match = text == s.as_bytes(); + if is_positive_match != *is_positive && *match_all_nodes { + return false; + } + if is_positive_match == *is_positive && !*match_all_nodes { + return true; + } + } + true + } + TextPredicateCapture::MatchString(i, r, is_positive, match_all_nodes) => { + let nodes = self.nodes_for_capture_index(*i); + for node in nodes { + let mut text = text_provider.text(node); + let text = node_text1.get_text(&mut text); + let is_positive_match = r.is_match(text); + if is_positive_match != *is_positive && *match_all_nodes { + return false; + } + if is_positive_match == *is_positive && !*match_all_nodes { + return true; + } + } + true + } + TextPredicateCapture::AnyString(i, v, is_positive) => { + let nodes = self.nodes_for_capture_index(*i); + for node in nodes { + let mut text = text_provider.text(node); + let text = node_text1.get_text(&mut text); + if (v.iter().any(|s| text == s.as_bytes())) != *is_positive { + return false; + } + } + true + } + }) + } +} + +impl QueryProperty { + #[must_use] + pub fn new(key: &str, value: Option<&str>, capture_id: Option) -> Self { + Self { + capture_id, + key: key.to_string().into(), + value: value.map(|s| s.to_string().into()), + } + } +} + +/// Provide a `StreamingIterator` instead of the traditional `Iterator`, as the +/// underlying object in the C library gets updated on each iteration. Copies would +/// have their internal state overwritten, leading to Undefined Behavior +impl<'query, 'tree: 'query, T: TextProvider, I: AsRef<[u8]>> StreamingIterator + for QueryMatches<'query, 'tree, T, I> +{ + type Item = QueryMatch<'query, 'tree>; + + fn advance(&mut self) { + self.current_match = unsafe { + loop { + let mut m = MaybeUninit::::uninit(); + if ffi::ts_query_cursor_next_match(self.ptr, m.as_mut_ptr()) { + let result = QueryMatch::new(&m.assume_init(), self.ptr); + if result.satisfies_text_predicates( + self.query, + &mut self.buffer1, + &mut self.buffer2, + &mut self.text_provider, + ) { + break Some(result); + } + } else { + break None; + } + } + }; + } + + fn get(&self) -> Option<&Self::Item> { + self.current_match.as_ref() + } +} + +impl<'query, 'tree: 'query, T: TextProvider, I: AsRef<[u8]>> StreamingIteratorMut + for QueryMatches<'query, 'tree, T, I> +{ + fn get_mut(&mut self) -> Option<&mut Self::Item> { + self.current_match.as_mut() + } +} + +impl<'query, 'tree: 'query, T: TextProvider, I: AsRef<[u8]>> StreamingIterator + for QueryCaptures<'query, 'tree, T, I> +{ + type Item = (QueryMatch<'query, 'tree>, usize); + + fn advance(&mut self) { + self.current_match = unsafe { + loop { + let mut capture_index = 0u32; + let mut m = MaybeUninit::::uninit(); + if ffi::ts_query_cursor_next_capture( + self.ptr, + m.as_mut_ptr(), + core::ptr::addr_of_mut!(capture_index), + ) { + let result = QueryMatch::new(&m.assume_init(), self.ptr); + if result.satisfies_text_predicates( + self.query, + &mut self.buffer1, + &mut self.buffer2, + &mut self.text_provider, + ) { + break Some((result, capture_index as usize)); + } + result.remove(); + } else { + break None; + } + } + } + } + + fn get(&self) -> Option<&Self::Item> { + self.current_match.as_ref() + } +} + +impl<'query, 'tree: 'query, T: TextProvider, I: AsRef<[u8]>> StreamingIteratorMut + for QueryCaptures<'query, 'tree, T, I> +{ + fn get_mut(&mut self) -> Option<&mut Self::Item> { + self.current_match.as_mut() + } +} + +impl, I: AsRef<[u8]>> QueryMatches<'_, '_, T, I> { + #[doc(alias = "ts_query_cursor_set_byte_range")] + pub fn set_byte_range(&mut self, range: ops::Range) { + unsafe { + ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32); + } + } + + #[doc(alias = "ts_query_cursor_set_point_range")] + pub fn set_point_range(&mut self, range: ops::Range) { + unsafe { + ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into()); + } + } +} + +impl, I: AsRef<[u8]>> QueryCaptures<'_, '_, T, I> { + #[doc(alias = "ts_query_cursor_set_byte_range")] + pub fn set_byte_range(&mut self, range: ops::Range) { + unsafe { + ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32); + } + } + + #[doc(alias = "ts_query_cursor_set_point_range")] + pub fn set_point_range(&mut self, range: ops::Range) { + unsafe { + ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into()); + } + } +} + +impl fmt::Debug for QueryMatch<'_, '_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}", + self.id, self.pattern_index, self.captures + ) + } +} + +impl TextProvider for F +where + F: FnMut(Node) -> R, + R: Iterator, + I: AsRef<[u8]>, +{ + type I = R; + + fn text(&mut self, node: Node) -> Self::I { + (self)(node) + } +} + +impl<'a> TextProvider<&'a [u8]> for &'a [u8] { + type I = iter::Once<&'a [u8]>; + + fn text(&mut self, node: Node) -> Self::I { + iter::once(&self[node.byte_range()]) + } +} + +impl PartialEq for Query { + fn eq(&self, other: &Self) -> bool { + self.ptr == other.ptr + } +} + +impl Drop for Query { + fn drop(&mut self) { + unsafe { ffi::ts_query_delete(self.ptr.as_ptr()) } + } +} + +impl Drop for QueryCursor { + fn drop(&mut self) { + unsafe { ffi::ts_query_cursor_delete(self.ptr.as_ptr()) } + } +} + +impl Point { + #[must_use] + pub const fn new(row: usize, column: usize) -> Self { + Self { row, column } + } +} + +impl fmt::Display for Point { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.row, self.column) + } +} + +impl From for ffi::TSPoint { + fn from(val: Point) -> Self { + Self { + row: val.row as u32, + column: val.column as u32, + } + } +} + +impl From for Point { + fn from(point: ffi::TSPoint) -> Self { + Self { + row: point.row as usize, + column: point.column as usize, + } + } +} + +impl From for ffi::TSRange { + fn from(val: Range) -> Self { + Self { + start_byte: val.start_byte as u32, + end_byte: val.end_byte as u32, + start_point: val.start_point.into(), + end_point: val.end_point.into(), + } + } +} + +impl From for Range { + fn from(range: ffi::TSRange) -> Self { + Self { + start_byte: range.start_byte as usize, + end_byte: range.end_byte as usize, + start_point: range.start_point.into(), + end_point: range.end_point.into(), + } + } +} + +impl From<&'_ InputEdit> for ffi::TSInputEdit { + fn from(val: &'_ InputEdit) -> Self { + Self { + start_byte: val.start_byte as u32, + old_end_byte: val.old_end_byte as u32, + new_end_byte: val.new_end_byte as u32, + start_point: val.start_position.into(), + old_end_point: val.old_end_position.into(), + new_end_point: val.new_end_position.into(), + } + } +} + +impl<'a> LossyUtf8<'a> { + #[must_use] + pub const fn new(bytes: &'a [u8]) -> Self { + LossyUtf8 { + bytes, + in_replacement: false, + } + } +} + +impl<'a> Iterator for LossyUtf8<'a> { + type Item = &'a str; + + fn next(&mut self) -> Option<&'a str> { + if self.bytes.is_empty() { + return None; + } + if self.in_replacement { + self.in_replacement = false; + return Some("\u{fffd}"); + } + match core::str::from_utf8(self.bytes) { + Ok(valid) => { + self.bytes = &[]; + Some(valid) + } + Err(error) => { + if let Some(error_len) = error.error_len() { + let error_start = error.valid_up_to(); + if error_start > 0 { + let result = + unsafe { core::str::from_utf8_unchecked(&self.bytes[..error_start]) }; + self.bytes = &self.bytes[(error_start + error_len)..]; + self.in_replacement = true; + Some(result) + } else { + self.bytes = &self.bytes[error_len..]; + Some("\u{fffd}") + } + } else { + None + } + } + } + } +} + +#[must_use] +const fn predicate_error(row: usize, message: String) -> QueryError { + QueryError { + kind: QueryErrorKind::Predicate, + row, + column: 0, + offset: 0, + message, + } +} + +impl fmt::Display for IncludedRangesError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Incorrect range by index: {}", self.0) + } +} + +impl fmt::Display for LanguageError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "Incompatible language version {}. Expected minimum {}, maximum {}", + self.version, MIN_COMPATIBLE_LANGUAGE_VERSION, LANGUAGE_VERSION, + ) + } +} + +impl fmt::Display for QueryError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let msg = match self.kind { + QueryErrorKind::Field => "Invalid field name ", + QueryErrorKind::NodeType => "Invalid node type ", + QueryErrorKind::Capture => "Invalid capture name ", + QueryErrorKind::Predicate => "Invalid predicate: ", + QueryErrorKind::Structure => "Impossible pattern:\n", + QueryErrorKind::Syntax => "Invalid syntax:\n", + QueryErrorKind::Language => "", + }; + if msg.is_empty() { + write!(f, "{}", self.message) + } else { + write!( + f, + "Query error at {}:{}. {}{}", + self.row + 1, + self.column + 1, + msg, + self.message + ) + } + } +} + +#[doc(hidden)] +#[must_use] +pub fn format_sexp(sexp: &str, initial_indent_level: usize) -> String { + let mut indent_level = initial_indent_level; + let mut formatted = String::new(); + let mut has_field = false; + + let mut c_iter = sexp.chars().peekable(); + let mut s = String::with_capacity(sexp.len()); + let mut quote = '\0'; + let mut saw_paren = false; + let mut did_last = false; + + let mut fetch_next_str = |next: &mut String| { + next.clear(); + while let Some(c) = c_iter.next() { + if c == '\'' || c == '"' { + quote = c; + } else if c == ' ' || (c == ')' && quote != '\0') { + if let Some(next_c) = c_iter.peek() { + if *next_c == quote { + next.push(c); + next.push(*next_c); + c_iter.next(); + quote = '\0'; + continue; + } + } + break; + } + if c == ')' { + saw_paren = true; + break; + } + next.push(c); + } + + // at the end + if c_iter.peek().is_none() && next.is_empty() { + if saw_paren { + // but did we see a ) before ending? + saw_paren = false; + return Some(()); + } + if !did_last { + // but did we account for the end empty string as if we're splitting? + did_last = true; + return Some(()); + } + return None; + } + Some(()) + }; + + while fetch_next_str(&mut s).is_some() { + if s.is_empty() && indent_level > 0 { + // ")" + indent_level -= 1; + write!(formatted, ")").unwrap(); + } else if s.starts_with('(') { + if has_field { + has_field = false; + } else { + if indent_level > 0 { + writeln!(formatted).unwrap(); + for _ in 0..indent_level { + write!(formatted, " ").unwrap(); + } + } + indent_level += 1; + } + + // "(node_name" + write!(formatted, "{s}").unwrap(); + + // "(MISSING node_name" or "(UNEXPECTED 'x'" + if s.starts_with("(MISSING") || s.starts_with("(UNEXPECTED") { + fetch_next_str(&mut s).unwrap(); + if s.is_empty() { + while indent_level > 0 { + indent_level -= 1; + write!(formatted, ")").unwrap(); + } + } else { + write!(formatted, " {s}").unwrap(); + } + } + } else if s.ends_with(':') { + // "field:" + writeln!(formatted).unwrap(); + for _ in 0..indent_level { + write!(formatted, " ").unwrap(); + } + write!(formatted, "{s} ").unwrap(); + has_field = true; + indent_level += 1; + } + } + + formatted +} + +pub fn wasm_stdlib_symbols() -> impl Iterator { + const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt")); + + WASM_STDLIB_SYMBOLS + .lines() + .map(|s| s.trim_matches(|c| c == '"' || c == ',')) +} + +extern "C" { + fn free(ptr: *mut c_void); +} + +static mut FREE_FN: unsafe extern "C" fn(ptr: *mut c_void) = free; + +/// Sets the memory allocation functions that the core library should use. +/// +/// # Safety +/// +/// This function uses FFI and mutates a static global. +#[doc(alias = "ts_set_allocator")] +pub unsafe fn set_allocator( + new_malloc: Option *mut c_void>, + new_calloc: Option *mut c_void>, + new_realloc: Option *mut c_void>, + new_free: Option, +) { + FREE_FN = new_free.unwrap_or(free); + ffi::ts_set_allocator(new_malloc, new_calloc, new_realloc, new_free); +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl error::Error for IncludedRangesError {} +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl error::Error for LanguageError {} +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl error::Error for QueryError {} + +unsafe impl Send for Language {} +unsafe impl Sync for Language {} + +unsafe impl Send for Node<'_> {} +unsafe impl Sync for Node<'_> {} + +unsafe impl Send for LookaheadIterator {} +unsafe impl Sync for LookaheadIterator {} + +unsafe impl Send for LookaheadNamesIterator<'_> {} +unsafe impl Sync for LookaheadNamesIterator<'_> {} + +unsafe impl Send for Parser {} +unsafe impl Sync for Parser {} + +unsafe impl Send for Query {} +unsafe impl Sync for Query {} + +unsafe impl Send for QueryCursor {} +unsafe impl Sync for QueryCursor {} + +unsafe impl Send for Tree {} +unsafe impl Sync for Tree {} + +unsafe impl Send for TreeCursor<'_> {} +unsafe impl Sync for TreeCursor<'_> {} diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/util.rs b/codegraph-kernel/vendor/tree-sitter/binding_rust/util.rs new file mode 100644 index 0000000000..dc67f1f754 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/util.rs @@ -0,0 +1,45 @@ +use core::ffi::c_void; + +use super::FREE_FN; + +/// A raw pointer and a length, exposed as an iterator. +pub struct CBufferIter { + ptr: *mut T, + count: usize, + i: usize, +} + +impl CBufferIter { + pub const unsafe fn new(ptr: *mut T, count: usize) -> Self { + Self { ptr, count, i: 0 } + } +} + +impl Iterator for CBufferIter { + type Item = T; + + fn next(&mut self) -> Option { + let i = self.i; + if i >= self.count { + None + } else { + self.i += 1; + Some(unsafe { *self.ptr.add(i) }) + } + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.count - self.i; + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for CBufferIter {} + +impl Drop for CBufferIter { + fn drop(&mut self) { + if !self.ptr.is_null() { + unsafe { (FREE_FN)(self.ptr.cast::()) }; + } + } +} diff --git a/codegraph-kernel/vendor/tree-sitter/binding_rust/wasm_language.rs b/codegraph-kernel/vendor/tree-sitter/binding_rust/wasm_language.rs new file mode 100644 index 0000000000..76aff50a74 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/binding_rust/wasm_language.rs @@ -0,0 +1,147 @@ +use std::{ + error, + ffi::{CStr, CString}, + fmt, + mem::{self, MaybeUninit}, + os::raw::c_char, +}; + +pub use wasmtime_c_api::wasmtime; + +use crate::{ffi, Language, LanguageError, Parser, FREE_FN}; + +// Force Cargo to include wasmtime-c-api as a dependency of this crate, +// even though it is only used by the C code. +#[allow(unused)] +fn _use_wasmtime() { + wasmtime_c_api::wasm_engine_new(); +} + +#[repr(C)] +#[derive(Clone)] +#[allow(non_camel_case_types)] +pub struct wasm_engine_t { + pub(crate) engine: wasmtime::Engine, +} + +pub struct WasmStore(*mut ffi::TSWasmStore); + +unsafe impl Send for WasmStore {} +unsafe impl Sync for WasmStore {} + +#[derive(Debug, PartialEq, Eq)] +pub struct WasmError { + pub kind: WasmErrorKind, + pub message: String, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum WasmErrorKind { + Parse, + Compile, + Instantiate, + Other, +} + +impl WasmStore { + pub fn new(engine: &wasmtime::Engine) -> Result { + unsafe { + let mut error = MaybeUninit::::uninit(); + let store = ffi::ts_wasm_store_new( + std::ptr::from_ref::(engine) + .cast_mut() + .cast(), + error.as_mut_ptr(), + ); + if store.is_null() { + Err(WasmError::new(error.assume_init())) + } else { + Ok(Self(store)) + } + } + } + + pub fn load_language(&mut self, name: &str, bytes: &[u8]) -> Result { + let name = CString::new(name).unwrap(); + unsafe { + let mut error = MaybeUninit::::uninit(); + let language = ffi::ts_wasm_store_load_language( + self.0, + name.as_ptr(), + bytes.as_ptr().cast::(), + bytes.len() as u32, + error.as_mut_ptr(), + ); + if language.is_null() { + Err(WasmError::new(error.assume_init())) + } else { + Ok(Language(language)) + } + } + } + + #[must_use] + pub fn language_count(&self) -> usize { + unsafe { ffi::ts_wasm_store_language_count(self.0) } + } +} + +impl WasmError { + unsafe fn new(error: ffi::TSWasmError) -> Self { + let message = CStr::from_ptr(error.message).to_str().unwrap().to_string(); + (FREE_FN)(error.message.cast()); + Self { + kind: match error.kind { + ffi::TSWasmErrorKindParse => WasmErrorKind::Parse, + ffi::TSWasmErrorKindCompile => WasmErrorKind::Compile, + ffi::TSWasmErrorKindInstantiate => WasmErrorKind::Instantiate, + _ => WasmErrorKind::Other, + }, + message, + } + } +} + +impl Language { + #[must_use] + pub fn is_wasm(&self) -> bool { + unsafe { ffi::ts_language_is_wasm(self.0) } + } +} + +impl Parser { + pub fn set_wasm_store(&mut self, store: WasmStore) -> Result<(), LanguageError> { + unsafe { ffi::ts_parser_set_wasm_store(self.0.as_ptr(), store.0) }; + mem::forget(store); + Ok(()) + } + + pub fn take_wasm_store(&mut self) -> Option { + let ptr = unsafe { ffi::ts_parser_take_wasm_store(self.0.as_ptr()) }; + if ptr.is_null() { + None + } else { + Some(WasmStore(ptr)) + } + } +} + +impl Drop for WasmStore { + fn drop(&mut self) { + unsafe { ffi::ts_wasm_store_delete(self.0) }; + } +} + +impl fmt::Display for WasmError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let kind = match self.kind { + WasmErrorKind::Parse => "Failed to parse wasm", + WasmErrorKind::Compile => "Failed to compile wasm", + WasmErrorKind::Instantiate => "Failed to instantiate wasm module", + WasmErrorKind::Other => "Unknown error", + }; + write!(f, "{kind}: {}", self.message) + } +} + +impl error::Error for WasmError {} diff --git a/codegraph-kernel/vendor/tree-sitter/include/tree_sitter/api.h b/codegraph-kernel/vendor/tree-sitter/include/tree_sitter/api.h new file mode 100644 index 0000000000..2bbfe66ffe --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/include/tree_sitter/api.h @@ -0,0 +1,1478 @@ +#ifndef TREE_SITTER_API_H_ +#define TREE_SITTER_API_H_ + +#ifndef TREE_SITTER_HIDE_SYMBOLS +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC visibility push(default) +#endif +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************/ +/* Section - ABI Versioning */ +/****************************/ + +/** + * The latest ABI version that is supported by the current version of the + * library. When Languages are generated by the Tree-sitter CLI, they are + * assigned an ABI version number that corresponds to the current CLI version. + * The Tree-sitter library is generally backwards-compatible with languages + * generated using older CLI versions, but is not forwards-compatible. + */ +#define TREE_SITTER_LANGUAGE_VERSION 15 + +/** + * The earliest ABI version that is supported by the current version of the + * library. + */ +#define TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION 13 + +/*******************/ +/* Section - Types */ +/*******************/ + +typedef uint16_t TSStateId; +typedef uint16_t TSSymbol; +typedef uint16_t TSFieldId; +typedef struct TSLanguage TSLanguage; +typedef struct TSParser TSParser; +typedef struct TSTree TSTree; +typedef struct TSQuery TSQuery; +typedef struct TSQueryCursor TSQueryCursor; +typedef struct TSLookaheadIterator TSLookaheadIterator; + +// This function signature reads one code point from the given string, +// returning the number of bytes consumed. It should write the code point +// to the `code_point` pointer, or write -1 if the input is invalid. +typedef uint32_t (*DecodeFunction)( + const uint8_t *string, + uint32_t length, + int32_t *code_point +); + +typedef enum TSInputEncoding { + TSInputEncodingUTF8, + TSInputEncodingUTF16LE, + TSInputEncodingUTF16BE, + TSInputEncodingCustom +} TSInputEncoding; + +typedef enum TSSymbolType { + TSSymbolTypeRegular, + TSSymbolTypeAnonymous, + TSSymbolTypeSupertype, + TSSymbolTypeAuxiliary, +} TSSymbolType; + +typedef struct TSPoint { + uint32_t row; + uint32_t column; +} TSPoint; + +typedef struct TSRange { + TSPoint start_point; + TSPoint end_point; + uint32_t start_byte; + uint32_t end_byte; +} TSRange; + +typedef struct TSInput { + void *payload; + const char *(*read)(void *payload, uint32_t byte_index, TSPoint position, uint32_t *bytes_read); + TSInputEncoding encoding; + DecodeFunction decode; +} TSInput; + +typedef struct TSParseState { + void *payload; + uint32_t current_byte_offset; + bool has_error; +} TSParseState; + +typedef struct TSParseOptions { + void *payload; + bool (*progress_callback)(TSParseState *state); +} TSParseOptions; + +typedef enum TSLogType { + TSLogTypeParse, + TSLogTypeLex, +} TSLogType; + +typedef struct TSLogger { + void *payload; + void (*log)(void *payload, TSLogType log_type, const char *buffer); +} TSLogger; + +typedef struct TSInputEdit { + uint32_t start_byte; + uint32_t old_end_byte; + uint32_t new_end_byte; + TSPoint start_point; + TSPoint old_end_point; + TSPoint new_end_point; +} TSInputEdit; + +typedef struct TSNode { + uint32_t context[4]; + const void *id; + const TSTree *tree; +} TSNode; + +typedef struct TSTreeCursor { + const void *tree; + const void *id; + uint32_t context[3]; +} TSTreeCursor; + +typedef struct TSQueryCapture { + TSNode node; + uint32_t index; +} TSQueryCapture; + +typedef enum TSQuantifier { + TSQuantifierZero = 0, // must match the array initialization value + TSQuantifierZeroOrOne, + TSQuantifierZeroOrMore, + TSQuantifierOne, + TSQuantifierOneOrMore, +} TSQuantifier; + +typedef struct TSQueryMatch { + uint32_t id; + uint16_t pattern_index; + uint16_t capture_count; + const TSQueryCapture *captures; +} TSQueryMatch; + +typedef enum TSQueryPredicateStepType { + TSQueryPredicateStepTypeDone, + TSQueryPredicateStepTypeCapture, + TSQueryPredicateStepTypeString, +} TSQueryPredicateStepType; + +typedef struct TSQueryPredicateStep { + TSQueryPredicateStepType type; + uint32_t value_id; +} TSQueryPredicateStep; + +typedef enum TSQueryError { + TSQueryErrorNone = 0, + TSQueryErrorSyntax, + TSQueryErrorNodeType, + TSQueryErrorField, + TSQueryErrorCapture, + TSQueryErrorStructure, + TSQueryErrorLanguage, +} TSQueryError; + +typedef struct TSQueryCursorState { + void *payload; + uint32_t current_byte_offset; +} TSQueryCursorState; + +typedef struct TSQueryCursorOptions { + void *payload; + bool (*progress_callback)(TSQueryCursorState *state); +} TSQueryCursorOptions; + +/** + * The metadata associated with a language. + * + * Currently, this metadata can be used to check the [Semantic Version](https://semver.org/) + * of the language. This version information should be used to signal if a given parser might + * be incompatible with existing queries when upgrading between major versions, or minor versions + * if it's in zerover. + */ +typedef struct TSLanguageMetadata { + uint8_t major_version; + uint8_t minor_version; + uint8_t patch_version; +} TSLanguageMetadata; + +/********************/ +/* Section - Parser */ +/********************/ + +/** + * Create a new parser. + */ +TSParser *ts_parser_new(void); + +/** + * Delete the parser, freeing all of the memory that it used. + */ +void ts_parser_delete(TSParser *self); + +/** + * Get the parser's current language. + */ +const TSLanguage *ts_parser_language(const TSParser *self); + +/** + * Set the language that the parser should use for parsing. + * + * Returns a boolean indicating whether or not the language was successfully + * assigned. True means assignment succeeded. False means there was a version + * mismatch: the language was generated with an incompatible version of the + * Tree-sitter CLI. Check the language's ABI version using [`ts_language_abi_version`] + * and compare it to this library's [`TREE_SITTER_LANGUAGE_VERSION`] and + * [`TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION`] constants. + */ +bool ts_parser_set_language(TSParser *self, const TSLanguage *language); + +/** + * Set the ranges of text that the parser should include when parsing. + * + * By default, the parser will always include entire documents. This function + * allows you to parse only a *portion* of a document but still return a syntax + * tree whose ranges match up with the document as a whole. You can also pass + * multiple disjoint ranges. + * + * The second and third parameters specify the location and length of an array + * of ranges. The parser does *not* take ownership of these ranges; it copies + * the data, so it doesn't matter how these ranges are allocated. + * + * If `count` is zero, then the entire document will be parsed. Otherwise, + * the given ranges must be ordered from earliest to latest in the document, + * and they must not overlap. That is, the following must hold for all: + * + * `i < count - 1`: `ranges[i].end_byte <= ranges[i + 1].start_byte` + * + * If this requirement is not satisfied, the operation will fail, the ranges + * will not be assigned, and this function will return `false`. On success, + * this function returns `true` + */ +bool ts_parser_set_included_ranges( + TSParser *self, + const TSRange *ranges, + uint32_t count +); + +/** + * Get the ranges of text that the parser will include when parsing. + * + * The returned pointer is owned by the parser. The caller should not free it + * or write to it. The length of the array will be written to the given + * `count` pointer. + */ +const TSRange *ts_parser_included_ranges( + const TSParser *self, + uint32_t *count +); + +/** + * Use the parser to parse some source code and create a syntax tree. + * + * If you are parsing this document for the first time, pass `NULL` for the + * `old_tree` parameter. Otherwise, if you have already parsed an earlier + * version of this document and the document has since been edited, pass the + * previous syntax tree so that the unchanged parts of it can be reused. + * This will save time and memory. For this to work correctly, you must have + * already edited the old syntax tree using the [`ts_tree_edit`] function in a + * way that exactly matches the source code changes. + * + * The [`TSInput`] parameter lets you specify how to read the text. It has the + * following three fields: + * 1. [`read`]: A function to retrieve a chunk of text at a given byte offset + * and (row, column) position. The function should return a pointer to the + * text and write its length to the [`bytes_read`] pointer. The parser does + * not take ownership of this buffer; it just borrows it until it has + * finished reading it. The function should write a zero value to the + * [`bytes_read`] pointer to indicate the end of the document. + * 2. [`payload`]: An arbitrary pointer that will be passed to each invocation + * of the [`read`] function. + * 3. [`encoding`]: An indication of how the text is encoded. Either + * `TSInputEncodingUTF8` or `TSInputEncodingUTF16`. + * + * This function returns a syntax tree on success, and `NULL` on failure. There + * are four possible reasons for failure: + * 1. The parser does not have a language assigned. Check for this using the + [`ts_parser_language`] function. + * 2. Parsing was cancelled due to a timeout that was set by an earlier call to + * the [`ts_parser_set_timeout_micros`] function. You can resume parsing from + * where the parser left out by calling [`ts_parser_parse`] again with the + * same arguments. Or you can start parsing from scratch by first calling + * [`ts_parser_reset`]. + * 3. Parsing was cancelled using a cancellation flag that was set by an + * earlier call to [`ts_parser_set_cancellation_flag`]. You can resume parsing + * from where the parser left out by calling [`ts_parser_parse`] again with + * the same arguments. + * 4. Parsing was cancelled due to the progress callback returning true. This callback + * is passed in [`ts_parser_parse_with_options`] inside the [`TSParseOptions`] struct. + * + * [`read`]: TSInput::read + * [`payload`]: TSInput::payload + * [`encoding`]: TSInput::encoding + * [`bytes_read`]: TSInput::read + */ +TSTree *ts_parser_parse( + TSParser *self, + const TSTree *old_tree, + TSInput input +); + +/** + * Use the parser to parse some source code and create a syntax tree, with some options. + * + * See [`ts_parser_parse`] for more details. + * + * See [`TSParseOptions`] for more details on the options. + */ +TSTree* ts_parser_parse_with_options( + TSParser *self, + const TSTree *old_tree, + TSInput input, + TSParseOptions parse_options +); + +/** + * Use the parser to parse some source code stored in one contiguous buffer. + * The first two parameters are the same as in the [`ts_parser_parse`] function + * above. The second two parameters indicate the location of the buffer and its + * length in bytes. + */ +TSTree *ts_parser_parse_string( + TSParser *self, + const TSTree *old_tree, + const char *string, + uint32_t length +); + +/** + * Use the parser to parse some source code stored in one contiguous buffer with + * a given encoding. The first four parameters work the same as in the + * [`ts_parser_parse_string`] method above. The final parameter indicates whether + * the text is encoded as UTF8 or UTF16. + */ +TSTree *ts_parser_parse_string_encoding( + TSParser *self, + const TSTree *old_tree, + const char *string, + uint32_t length, + TSInputEncoding encoding +); + +/** + * Instruct the parser to start the next parse from the beginning. + * + * If the parser previously failed because of a timeout or a cancellation, then + * by default, it will resume where it left off on the next call to + * [`ts_parser_parse`] or other parsing functions. If you don't want to resume, + * and instead intend to use this parser to parse some other document, you must + * call [`ts_parser_reset`] first. + */ +void ts_parser_reset(TSParser *self); + +/** + * @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. + * + * Set the maximum duration in microseconds that parsing should be allowed to + * take before halting. + * + * If parsing takes longer than this, it will halt early, returning NULL. + * See [`ts_parser_parse`] for more information. + */ +void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout_micros); + +/** + * @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. + * + * Get the duration in microseconds that parsing is allowed to take. + */ +uint64_t ts_parser_timeout_micros(const TSParser *self); + +/** + * @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. + * + * Set the parser's current cancellation flag pointer. + * + * If a non-null pointer is assigned, then the parser will periodically read + * from this pointer during parsing. If it reads a non-zero value, it will + * halt early, returning NULL. See [`ts_parser_parse`] for more information. + */ +void ts_parser_set_cancellation_flag(TSParser *self, const size_t *flag); + +/** + * @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. + * + * Get the parser's current cancellation flag pointer. + */ +const size_t *ts_parser_cancellation_flag(const TSParser *self); + +/** + * Set the logger that a parser should use during parsing. + * + * The parser does not take ownership over the logger payload. If a logger was + * previously assigned, the caller is responsible for releasing any memory + * owned by the previous logger. + */ +void ts_parser_set_logger(TSParser *self, TSLogger logger); + +/** + * Get the parser's current logger. + */ +TSLogger ts_parser_logger(const TSParser *self); + +/** + * Set the file descriptor to which the parser should write debugging graphs + * during parsing. The graphs are formatted in the DOT language. You may want + * to pipe these graphs directly to a `dot(1)` process in order to generate + * SVG output. You can turn off this logging by passing a negative number. + */ +void ts_parser_print_dot_graphs(TSParser *self, int fd); + +/******************/ +/* Section - Tree */ +/******************/ + +/** + * Create a shallow copy of the syntax tree. This is very fast. + * + * You need to copy a syntax tree in order to use it on more than one thread at + * a time, as syntax trees are not thread safe. + */ +TSTree *ts_tree_copy(const TSTree *self); + +/** + * Delete the syntax tree, freeing all of the memory that it used. + */ +void ts_tree_delete(TSTree *self); + +/** + * Get the root node of the syntax tree. + */ +TSNode ts_tree_root_node(const TSTree *self); + +/** + * Get the root node of the syntax tree, but with its position + * shifted forward by the given offset. + */ +TSNode ts_tree_root_node_with_offset( + const TSTree *self, + uint32_t offset_bytes, + TSPoint offset_extent +); + +/** + * Get the language that was used to parse the syntax tree. + */ +const TSLanguage *ts_tree_language(const TSTree *self); + +/** + * Get the array of included ranges that was used to parse the syntax tree. + * + * The returned pointer must be freed by the caller. + */ +TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length); + +/** + * Edit the syntax tree to keep it in sync with source code that has been + * edited. + * + * You must describe the edit both in terms of byte offsets and in terms of + * (row, column) coordinates. + */ +void ts_tree_edit(TSTree *self, const TSInputEdit *edit); + +/** + * Compare an old edited syntax tree to a new syntax tree representing the same + * document, returning an array of ranges whose syntactic structure has changed. + * + * For this to work correctly, the old syntax tree must have been edited such + * that its ranges match up to the new tree. Generally, you'll want to call + * this function right after calling one of the [`ts_parser_parse`] functions. + * You need to pass the old tree that was passed to parse, as well as the new + * tree that was returned from that function. + * + * The returned ranges indicate areas where the hierarchical structure of syntax + * nodes (from root to leaf) has changed between the old and new trees. Characters + * outside these ranges have identical ancestor nodes in both trees. + * + * Note that the returned ranges may be slightly larger than the exact changed areas, + * but Tree-sitter attempts to make them as small as possible. + * + * The returned array is allocated using `malloc` and the caller is responsible + * for freeing it using `free`. The length of the array will be written to the + * given `length` pointer. + */ +TSRange *ts_tree_get_changed_ranges( + const TSTree *old_tree, + const TSTree *new_tree, + uint32_t *length +); + +/** + * Write a DOT graph describing the syntax tree to the given file. + */ +void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor); + +/******************/ +/* Section - Node */ +/******************/ + +/** + * Get the node's type as a null-terminated string. + */ +const char *ts_node_type(TSNode self); + +/** + * Get the node's type as a numerical id. + */ +TSSymbol ts_node_symbol(TSNode self); + +/** + * Get the node's language. + */ +const TSLanguage *ts_node_language(TSNode self); + +/** + * Get the node's type as it appears in the grammar ignoring aliases as a + * null-terminated string. + */ +const char *ts_node_grammar_type(TSNode self); + +/** + * Get the node's type as a numerical id as it appears in the grammar ignoring + * aliases. This should be used in [`ts_language_next_state`] instead of + * [`ts_node_symbol`]. + */ +TSSymbol ts_node_grammar_symbol(TSNode self); + +/** + * Get the node's start byte. + */ +uint32_t ts_node_start_byte(TSNode self); + +/** + * Get the node's start position in terms of rows and columns. + */ +TSPoint ts_node_start_point(TSNode self); + +/** + * Get the node's end byte. + */ +uint32_t ts_node_end_byte(TSNode self); + +/** + * Get the node's end position in terms of rows and columns. + */ +TSPoint ts_node_end_point(TSNode self); + +/** + * Get an S-expression representing the node as a string. + * + * This string is allocated with `malloc` and the caller is responsible for + * freeing it using `free`. + */ +char *ts_node_string(TSNode self); + +/** + * Check if the node is null. Functions like [`ts_node_child`] and + * [`ts_node_next_sibling`] will return a null node to indicate that no such node + * was found. + */ +bool ts_node_is_null(TSNode self); + +/** + * Check if the node is *named*. Named nodes correspond to named rules in the + * grammar, whereas *anonymous* nodes correspond to string literals in the + * grammar. + */ +bool ts_node_is_named(TSNode self); + +/** + * Check if the node is *missing*. Missing nodes are inserted by the parser in + * order to recover from certain kinds of syntax errors. + */ +bool ts_node_is_missing(TSNode self); + +/** + * Check if the node is *extra*. Extra nodes represent things like comments, + * which are not required the grammar, but can appear anywhere. + */ +bool ts_node_is_extra(TSNode self); + +/** + * Check if a syntax node has been edited. + */ +bool ts_node_has_changes(TSNode self); + +/** + * Check if the node is a syntax error or contains any syntax errors. + */ +bool ts_node_has_error(TSNode self); + +/** + * Check if the node is a syntax error. +*/ +bool ts_node_is_error(TSNode self); + +/** + * Get this node's parse state. +*/ +TSStateId ts_node_parse_state(TSNode self); + +/** + * Get the parse state after this node. +*/ +TSStateId ts_node_next_parse_state(TSNode self); + +/** + * Get the node's immediate parent. + * Prefer [`ts_node_child_with_descendant`] for + * iterating over the node's ancestors. + */ +TSNode ts_node_parent(TSNode self); + +/** + * Get the node that contains `descendant`. + * + * Note that this can return `descendant` itself. + */ +TSNode ts_node_child_with_descendant(TSNode self, TSNode descendant); + +/** + * Get the node's child at the given index, where zero represents the first + * child. + */ +TSNode ts_node_child(TSNode self, uint32_t child_index); + +/** + * Get the field name for node's child at the given index, where zero represents + * the first child. Returns NULL, if no field is found. + */ +const char *ts_node_field_name_for_child(TSNode self, uint32_t child_index); + +/** + * Get the field name for node's named child at the given index, where zero + * represents the first named child. Returns NULL, if no field is found. + */ +const char *ts_node_field_name_for_named_child(TSNode self, uint32_t named_child_index); + +/** + * Get the node's number of children. + */ +uint32_t ts_node_child_count(TSNode self); + +/** + * Get the node's *named* child at the given index. + * + * See also [`ts_node_is_named`]. + */ +TSNode ts_node_named_child(TSNode self, uint32_t child_index); + +/** + * Get the node's number of *named* children. + * + * See also [`ts_node_is_named`]. + */ +uint32_t ts_node_named_child_count(TSNode self); + +/** + * Get the node's child with the given field name. + */ +TSNode ts_node_child_by_field_name( + TSNode self, + const char *name, + uint32_t name_length +); + +/** + * Get the node's child with the given numerical field id. + * + * You can convert a field name to an id using the + * [`ts_language_field_id_for_name`] function. + */ +TSNode ts_node_child_by_field_id(TSNode self, TSFieldId field_id); + +/** + * Get the node's next / previous sibling. + */ +TSNode ts_node_next_sibling(TSNode self); +TSNode ts_node_prev_sibling(TSNode self); + +/** + * Get the node's next / previous *named* sibling. + */ +TSNode ts_node_next_named_sibling(TSNode self); +TSNode ts_node_prev_named_sibling(TSNode self); + +/** + * Get the node's first child that contains or starts after the given byte offset. + */ +TSNode ts_node_first_child_for_byte(TSNode self, uint32_t byte); + +/** + * Get the node's first named child that contains or starts after the given byte offset. + */ +TSNode ts_node_first_named_child_for_byte(TSNode self, uint32_t byte); + +/** + * Get the node's number of descendants, including one for the node itself. + */ +uint32_t ts_node_descendant_count(TSNode self); + +/** + * Get the smallest node within this node that spans the given range of bytes + * or (row, column) positions. + */ +TSNode ts_node_descendant_for_byte_range(TSNode self, uint32_t start, uint32_t end); +TSNode ts_node_descendant_for_point_range(TSNode self, TSPoint start, TSPoint end); + +/** + * Get the smallest named node within this node that spans the given range of + * bytes or (row, column) positions. + */ +TSNode ts_node_named_descendant_for_byte_range(TSNode self, uint32_t start, uint32_t end); +TSNode ts_node_named_descendant_for_point_range(TSNode self, TSPoint start, TSPoint end); + +/** + * Edit the node to keep it in-sync with source code that has been edited. + * + * This function is only rarely needed. When you edit a syntax tree with the + * [`ts_tree_edit`] function, all of the nodes that you retrieve from the tree + * afterward will already reflect the edit. You only need to use [`ts_node_edit`] + * when you have a [`TSNode`] instance that you want to keep and continue to use + * after an edit. + */ +void ts_node_edit(TSNode *self, const TSInputEdit *edit); + +/** + * Check if two nodes are identical. + */ +bool ts_node_eq(TSNode self, TSNode other); + +/************************/ +/* Section - TreeCursor */ +/************************/ + +/** + * Create a new tree cursor starting from the given node. + * + * A tree cursor allows you to walk a syntax tree more efficiently than is + * possible using the [`TSNode`] functions. It is a mutable object that is always + * on a certain syntax node, and can be moved imperatively to different nodes. + * + * Note that the given node is considered the root of the cursor, + * and the cursor cannot walk outside this node. + */ +TSTreeCursor ts_tree_cursor_new(TSNode node); + +/** + * Delete a tree cursor, freeing all of the memory that it used. + */ +void ts_tree_cursor_delete(TSTreeCursor *self); + +/** + * Re-initialize a tree cursor to start at the original node that the cursor was + * constructed with. + */ +void ts_tree_cursor_reset(TSTreeCursor *self, TSNode node); + +/** + * Re-initialize a tree cursor to the same position as another cursor. + * + * Unlike [`ts_tree_cursor_reset`], this will not lose parent information and + * allows reusing already created cursors. +*/ +void ts_tree_cursor_reset_to(TSTreeCursor *dst, const TSTreeCursor *src); + +/** + * Get the tree cursor's current node. + */ +TSNode ts_tree_cursor_current_node(const TSTreeCursor *self); + +/** + * Get the field name of the tree cursor's current node. + * + * This returns `NULL` if the current node doesn't have a field. + * See also [`ts_node_child_by_field_name`]. + */ +const char *ts_tree_cursor_current_field_name(const TSTreeCursor *self); + +/** + * Get the field id of the tree cursor's current node. + * + * This returns zero if the current node doesn't have a field. + * See also [`ts_node_child_by_field_id`], [`ts_language_field_id_for_name`]. + */ +TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *self); + +/** + * Move the cursor to the parent of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` + * if there was no parent node (the cursor was already on the root node). + * + * Note that the node the cursor was constructed with is considered the root + * of the cursor, and the cursor cannot walk outside this node. + */ +bool ts_tree_cursor_goto_parent(TSTreeCursor *self); + +/** + * Move the cursor to the next sibling of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` + * if there was no next sibling node. + * + * Note that the node the cursor was constructed with is considered the root + * of the cursor, and the cursor cannot walk outside this node. + */ +bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self); + +/** + * Move the cursor to the previous sibling of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` if + * there was no previous sibling node. + * + * Note, that this function may be slower than + * [`ts_tree_cursor_goto_next_sibling`] due to how node positions are stored. In + * the worst case, this will need to iterate through all the children up to the + * previous sibling node to recalculate its position. Also note that the node the cursor + * was constructed with is considered the root of the cursor, and the cursor cannot + * walk outside this node. + */ +bool ts_tree_cursor_goto_previous_sibling(TSTreeCursor *self); + +/** + * Move the cursor to the first child of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` + * if there were no children. + */ +bool ts_tree_cursor_goto_first_child(TSTreeCursor *self); + +/** + * Move the cursor to the last child of its current node. + * + * This returns `true` if the cursor successfully moved, and returns `false` if + * there were no children. + * + * Note that this function may be slower than [`ts_tree_cursor_goto_first_child`] + * because it needs to iterate through all the children to compute the child's + * position. + */ +bool ts_tree_cursor_goto_last_child(TSTreeCursor *self); + +/** + * Move the cursor to the node that is the nth descendant of + * the original node that the cursor was constructed with, where + * zero represents the original node itself. + */ +void ts_tree_cursor_goto_descendant(TSTreeCursor *self, uint32_t goal_descendant_index); + +/** + * Get the index of the cursor's current node out of all of the + * descendants of the original node that the cursor was constructed with. + */ +uint32_t ts_tree_cursor_current_descendant_index(const TSTreeCursor *self); + +/** + * Get the depth of the cursor's current node relative to the original + * node that the cursor was constructed with. + */ +uint32_t ts_tree_cursor_current_depth(const TSTreeCursor *self); + +/** + * Move the cursor to the first child of its current node that contains or starts after + * the given byte offset or point. + * + * This returns the index of the child node if one was found, and returns -1 + * if no such child was found. + */ +int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *self, uint32_t goal_byte); +int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *self, TSPoint goal_point); + +TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *cursor); + +/*******************/ +/* Section - Query */ +/*******************/ + +/** + * Create a new query from a string containing one or more S-expression + * patterns. The query is associated with a particular language, and can + * only be run on syntax nodes parsed with that language. + * + * If all of the given patterns are valid, this returns a [`TSQuery`]. + * If a pattern is invalid, this returns `NULL`, and provides two pieces + * of information about the problem: + * 1. The byte offset of the error is written to the `error_offset` parameter. + * 2. The type of error is written to the `error_type` parameter. + */ +TSQuery *ts_query_new( + const TSLanguage *language, + const char *source, + uint32_t source_len, + uint32_t *error_offset, + TSQueryError *error_type +); + +/** + * Delete a query, freeing all of the memory that it used. + */ +void ts_query_delete(TSQuery *self); + +/** + * Get the number of patterns, captures, or string literals in the query. + */ +uint32_t ts_query_pattern_count(const TSQuery *self); +uint32_t ts_query_capture_count(const TSQuery *self); +uint32_t ts_query_string_count(const TSQuery *self); + +/** + * Get the byte offset where the given pattern starts in the query's source. + * + * This can be useful when combining queries by concatenating their source + * code strings. + */ +uint32_t ts_query_start_byte_for_pattern(const TSQuery *self, uint32_t pattern_index); + +/** + * Get the byte offset where the given pattern ends in the query's source. + * + * This can be useful when combining queries by concatenating their source + * code strings. + */ +uint32_t ts_query_end_byte_for_pattern(const TSQuery *self, uint32_t pattern_index); + +/** + * Get all of the predicates for the given pattern in the query. + * + * The predicates are represented as a single array of steps. There are three + * types of steps in this array, which correspond to the three legal values for + * the `type` field: + * - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names + * of captures. Their `value_id` can be used with the + * [`ts_query_capture_name_for_id`] function to obtain the name of the capture. + * - `TSQueryPredicateStepTypeString` - Steps with this type represent literal + * strings. Their `value_id` can be used with the + * [`ts_query_string_value_for_id`] function to obtain their string value. + * - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels* + * that represent the end of an individual predicate. If a pattern has two + * predicates, then there will be two steps with this `type` in the array. + */ +const TSQueryPredicateStep *ts_query_predicates_for_pattern( + const TSQuery *self, + uint32_t pattern_index, + uint32_t *step_count +); + +/* + * Check if the given pattern in the query has a single root node. + */ +bool ts_query_is_pattern_rooted(const TSQuery *self, uint32_t pattern_index); + +/* + * Check if the given pattern in the query is 'non local'. + * + * A non-local pattern has multiple root nodes and can match within a + * repeating sequence of nodes, as specified by the grammar. Non-local + * patterns disable certain optimizations that would otherwise be possible + * when executing a query on a specific range of a syntax tree. + */ +bool ts_query_is_pattern_non_local(const TSQuery *self, uint32_t pattern_index); + +/* + * Check if a given pattern is guaranteed to match once a given step is reached. + * The step is specified by its byte offset in the query's source code. + */ +bool ts_query_is_pattern_guaranteed_at_step(const TSQuery *self, uint32_t byte_offset); + +/** + * Get the name and length of one of the query's captures, or one of the + * query's string literals. Each capture and string is associated with a + * numeric id based on the order that it appeared in the query's source. + */ +const char *ts_query_capture_name_for_id( + const TSQuery *self, + uint32_t index, + uint32_t *length +); + +/** + * Get the quantifier of the query's captures. Each capture is * associated + * with a numeric id based on the order that it appeared in the query's source. + */ +TSQuantifier ts_query_capture_quantifier_for_id( + const TSQuery *self, + uint32_t pattern_index, + uint32_t capture_index +); + +const char *ts_query_string_value_for_id( + const TSQuery *self, + uint32_t index, + uint32_t *length +); + +/** + * Disable a certain capture within a query. + * + * This prevents the capture from being returned in matches, and also avoids + * any resource usage associated with recording the capture. Currently, there + * is no way to undo this. + */ +void ts_query_disable_capture(TSQuery *self, const char *name, uint32_t length); + +/** + * Disable a certain pattern within a query. + * + * This prevents the pattern from matching and removes most of the overhead + * associated with the pattern. Currently, there is no way to undo this. + */ +void ts_query_disable_pattern(TSQuery *self, uint32_t pattern_index); + +/** + * Create a new cursor for executing a given query. + * + * The cursor stores the state that is needed to iteratively search + * for matches. To use the query cursor, first call [`ts_query_cursor_exec`] + * to start running a given query on a given syntax node. Then, there are + * two options for consuming the results of the query: + * 1. Repeatedly call [`ts_query_cursor_next_match`] to iterate over all of the + * *matches* in the order that they were found. Each match contains the + * index of the pattern that matched, and an array of captures. Because + * multiple patterns can match the same set of nodes, one match may contain + * captures that appear *before* some of the captures from a previous match. + * 2. Repeatedly call [`ts_query_cursor_next_capture`] to iterate over all of the + * individual *captures* in the order that they appear. This is useful if + * don't care about which pattern matched, and just want a single ordered + * sequence of captures. + * + * If you don't care about consuming all of the results, you can stop calling + * [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] at any point. + * You can then start executing another query on another node by calling + * [`ts_query_cursor_exec`] again. + */ +TSQueryCursor *ts_query_cursor_new(void); + +/** + * Delete a query cursor, freeing all of the memory that it used. + */ +void ts_query_cursor_delete(TSQueryCursor *self); + +/** + * Start running a given query on a given node. + */ +void ts_query_cursor_exec(TSQueryCursor *self, const TSQuery *query, TSNode node); + +/** + * Start running a given query on a given node, with some options. + */ +void ts_query_cursor_exec_with_options( + TSQueryCursor *self, + const TSQuery *query, + TSNode node, + const TSQueryCursorOptions *query_options +); + +/** + * Manage the maximum number of in-progress matches allowed by this query + * cursor. + * + * Query cursors have an optional maximum capacity for storing lists of + * in-progress captures. If this capacity is exceeded, then the + * earliest-starting match will silently be dropped to make room for further + * matches. This maximum capacity is optional — by default, query cursors allow + * any number of pending matches, dynamically allocating new space for them as + * needed as the query is executed. + */ +bool ts_query_cursor_did_exceed_match_limit(const TSQueryCursor *self); +uint32_t ts_query_cursor_match_limit(const TSQueryCursor *self); +void ts_query_cursor_set_match_limit(TSQueryCursor *self, uint32_t limit); + +/** + * @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26. + * + * Set the maximum duration in microseconds that query execution should be allowed to + * take before halting. + * + * If query execution takes longer than this, it will halt early, returning NULL. + * See [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] for more information. + */ +void ts_query_cursor_set_timeout_micros(TSQueryCursor *self, uint64_t timeout_micros); + +/** + * @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26. + * + * Get the duration in microseconds that query execution is allowed to take. + * + * This is set via [`ts_query_cursor_set_timeout_micros`]. + */ +uint64_t ts_query_cursor_timeout_micros(const TSQueryCursor *self); + +/** + * Set the range of bytes in which the query will be executed. + * + * The query cursor will return matches that intersect with the given point range. + * This means that a match may be returned even if some of its captures fall + * outside the specified range, as long as at least part of the match + * overlaps with the range. + * + * For example, if a query pattern matches a node that spans a larger area + * than the specified range, but part of that node intersects with the range, + * the entire match will be returned. + * + * This will return `false` if the start byte is greater than the end byte, otherwise + * it will return `true`. + */ +bool ts_query_cursor_set_byte_range(TSQueryCursor *self, uint32_t start_byte, uint32_t end_byte); + +/** + * Set the range of (row, column) positions in which the query will be executed. + * + * The query cursor will return matches that intersect with the given point range. + * This means that a match may be returned even if some of its captures fall + * outside the specified range, as long as at least part of the match + * overlaps with the range. + * + * For example, if a query pattern matches a node that spans a larger area + * than the specified range, but part of that node intersects with the range, + * the entire match will be returned. + * + * This will return `false` if the start point is greater than the end point, otherwise + * it will return `true`. + */ +bool ts_query_cursor_set_point_range(TSQueryCursor *self, TSPoint start_point, TSPoint end_point); + +/** + * Advance to the next match of the currently running query. + * + * If there is a match, write it to `*match` and return `true`. + * Otherwise, return `false`. + */ +bool ts_query_cursor_next_match(TSQueryCursor *self, TSQueryMatch *match); +void ts_query_cursor_remove_match(TSQueryCursor *self, uint32_t match_id); + +/** + * Advance to the next capture of the currently running query. + * + * If there is a capture, write its match to `*match` and its index within + * the match's capture list to `*capture_index`. Otherwise, return `false`. + */ +bool ts_query_cursor_next_capture( + TSQueryCursor *self, + TSQueryMatch *match, + uint32_t *capture_index +); + +/** + * Set the maximum start depth for a query cursor. + * + * This prevents cursors from exploring children nodes at a certain depth. + * Note if a pattern includes many children, then they will still be checked. + * + * The zero max start depth value can be used as a special behavior and + * it helps to destructure a subtree by staying on a node and using captures + * for interested parts. Note that the zero max start depth only limit a search + * depth for a pattern's root node but other nodes that are parts of the pattern + * may be searched at any depth what defined by the pattern structure. + * + * Set to `UINT32_MAX` to remove the maximum start depth. + */ +void ts_query_cursor_set_max_start_depth(TSQueryCursor *self, uint32_t max_start_depth); + +/**********************/ +/* Section - Language */ +/**********************/ + +/** + * Get another reference to the given language. + */ +const TSLanguage *ts_language_copy(const TSLanguage *self); + +/** + * Free any dynamically-allocated resources for this language, if + * this is the last reference. + */ +void ts_language_delete(const TSLanguage *self); + +/** + * Get the number of distinct node types in the language. + */ +uint32_t ts_language_symbol_count(const TSLanguage *self); + +/** + * Get the number of valid states in this language. +*/ +uint32_t ts_language_state_count(const TSLanguage *self); + +/** + * Get the numerical id for the given node type string. + */ +TSSymbol ts_language_symbol_for_name( + const TSLanguage *self, + const char *string, + uint32_t length, + bool is_named +); + +/** + * Get the number of distinct field names in the language. + */ +uint32_t ts_language_field_count(const TSLanguage *self); + +/** + * Get the field name string for the given numerical id. + */ +const char *ts_language_field_name_for_id(const TSLanguage *self, TSFieldId id); + +/** + * Get the numerical id for the given field name string. + */ +TSFieldId ts_language_field_id_for_name(const TSLanguage *self, const char *name, uint32_t name_length); + +/** + * Get a list of all supertype symbols for the language. +*/ +const TSSymbol *ts_language_supertypes(const TSLanguage *self, uint32_t *length); + +/** + * Get a list of all subtype symbol ids for a given supertype symbol. + * + * See [`ts_language_supertypes`] for fetching all supertype symbols. + */ +const TSSymbol *ts_language_subtypes( + const TSLanguage *self, + TSSymbol supertype, + uint32_t *length +); + +/** + * Get a node type string for the given numerical id. + */ +const char *ts_language_symbol_name(const TSLanguage *self, TSSymbol symbol); + +/** + * Check whether the given node type id belongs to named nodes, anonymous nodes, + * or a hidden nodes. + * + * See also [`ts_node_is_named`]. Hidden nodes are never returned from the API. + */ +TSSymbolType ts_language_symbol_type(const TSLanguage *self, TSSymbol symbol); + +/** + * @deprecated use [`ts_language_abi_version`] instead, this will be removed in 0.26. + * + * Get the ABI version number for this language. This version number is used + * to ensure that languages were generated by a compatible version of + * Tree-sitter. + * + * See also [`ts_parser_set_language`]. + */ +uint32_t ts_language_version(const TSLanguage *self); + +/** + * Get the ABI version number for this language. This version number is used + * to ensure that languages were generated by a compatible version of + * Tree-sitter. + * + * See also [`ts_parser_set_language`]. + */ +uint32_t ts_language_abi_version(const TSLanguage *self); + +/** + * Get the metadata for this language. This information is generated by the + * CLI, and relies on the language author providing the correct metadata in + * the language's `tree-sitter.json` file. + * + * See also [`TSMetadata`]. + */ +const TSLanguageMetadata *ts_language_metadata(const TSLanguage *self); + +/** + * Get the next parse state. Combine this with lookahead iterators to generate + * completion suggestions or valid symbols in error nodes. Use + * [`ts_node_grammar_symbol`] for valid symbols. +*/ +TSStateId ts_language_next_state(const TSLanguage *self, TSStateId state, TSSymbol symbol); + +/** + * Get the name of this language. This returns `NULL` in older parsers. + */ +const char *ts_language_name(const TSLanguage *self); + +/********************************/ +/* Section - Lookahead Iterator */ +/********************************/ + +/** + * Create a new lookahead iterator for the given language and parse state. + * + * This returns `NULL` if state is invalid for the language. + * + * Repeatedly using [`ts_lookahead_iterator_next`] and + * [`ts_lookahead_iterator_current_symbol`] will generate valid symbols in the + * given parse state. Newly created lookahead iterators will contain the `ERROR` + * symbol. + * + * Lookahead iterators can be useful to generate suggestions and improve syntax + * error diagnostics. To get symbols valid in an ERROR node, use the lookahead + * iterator on its first leaf node state. For `MISSING` nodes, a lookahead + * iterator created on the previous non-extra leaf node may be appropriate. +*/ +TSLookaheadIterator *ts_lookahead_iterator_new(const TSLanguage *self, TSStateId state); + +/** + * Delete a lookahead iterator freeing all the memory used. +*/ +void ts_lookahead_iterator_delete(TSLookaheadIterator *self); + +/** + * Reset the lookahead iterator to another state. + * + * This returns `true` if the iterator was reset to the given state and `false` + * otherwise. +*/ +bool ts_lookahead_iterator_reset_state(TSLookaheadIterator *self, TSStateId state); + +/** + * Reset the lookahead iterator. + * + * This returns `true` if the language was set successfully and `false` + * otherwise. +*/ +bool ts_lookahead_iterator_reset(TSLookaheadIterator *self, const TSLanguage *language, TSStateId state); + +/** + * Get the current language of the lookahead iterator. +*/ +const TSLanguage *ts_lookahead_iterator_language(const TSLookaheadIterator *self); + +/** + * Advance the lookahead iterator to the next symbol. + * + * This returns `true` if there is a new symbol and `false` otherwise. +*/ +bool ts_lookahead_iterator_next(TSLookaheadIterator *self); + +/** + * Get the current symbol of the lookahead iterator; +*/ +TSSymbol ts_lookahead_iterator_current_symbol(const TSLookaheadIterator *self); + +/** + * Get the current symbol type of the lookahead iterator as a null terminated + * string. +*/ +const char *ts_lookahead_iterator_current_symbol_name(const TSLookaheadIterator *self); + +/*************************************/ +/* Section - WebAssembly Integration */ +/************************************/ + +typedef struct wasm_engine_t TSWasmEngine; +typedef struct TSWasmStore TSWasmStore; + +typedef enum { + TSWasmErrorKindNone = 0, + TSWasmErrorKindParse, + TSWasmErrorKindCompile, + TSWasmErrorKindInstantiate, + TSWasmErrorKindAllocate, +} TSWasmErrorKind; + +typedef struct { + TSWasmErrorKind kind; + char *message; +} TSWasmError; + +/** + * Create a Wasm store. + */ +TSWasmStore *ts_wasm_store_new( + TSWasmEngine *engine, + TSWasmError *error +); + +/** + * Free the memory associated with the given Wasm store. + */ +void ts_wasm_store_delete(TSWasmStore *); + +/** + * Create a language from a buffer of Wasm. The resulting language behaves + * like any other Tree-sitter language, except that in order to use it with + * a parser, that parser must have a Wasm store. Note that the language + * can be used with any Wasm store, it doesn't need to be the same store that + * was used to originally load it. + */ +const TSLanguage *ts_wasm_store_load_language( + TSWasmStore *, + const char *name, + const char *wasm, + uint32_t wasm_len, + TSWasmError *error +); + +/** + * Get the number of languages instantiated in the given wasm store. + */ +size_t ts_wasm_store_language_count(const TSWasmStore *); + +/** + * Check if the language came from a Wasm module. If so, then in order to use + * this language with a Parser, that parser must have a Wasm store assigned. + */ +bool ts_language_is_wasm(const TSLanguage *); + +/** + * Assign the given Wasm store to the parser. A parser must have a Wasm store + * in order to use Wasm languages. + */ +void ts_parser_set_wasm_store(TSParser *, TSWasmStore *); + +/** + * Remove the parser's current Wasm store and return it. This returns NULL if + * the parser doesn't have a Wasm store. + */ +TSWasmStore *ts_parser_take_wasm_store(TSParser *); + +/**********************************/ +/* Section - Global Configuration */ +/**********************************/ + +/** + * Set the allocation functions used by the library. + * + * By default, Tree-sitter uses the standard libc allocation functions, + * but aborts the process when an allocation fails. This function lets + * you supply alternative allocation functions at runtime. + * + * If you pass `NULL` for any parameter, Tree-sitter will switch back to + * its default implementation of that function. + * + * If you call this function after the library has already been used, then + * you must ensure that either: + * 1. All the existing objects have been freed. + * 2. The new allocator shares its state with the old one, so it is capable + * of freeing memory that was allocated by the old allocator. + */ +void ts_set_allocator( + void *(*new_malloc)(size_t), + void *(*new_calloc)(size_t, size_t), + void *(*new_realloc)(void *, size_t), + void (*new_free)(void *) +); + +#ifdef __cplusplus +} +#endif + +#ifndef TREE_SITTER_HIDE_SYMBOLS +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC visibility pop +#endif +#endif + +#endif // TREE_SITTER_API_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/alloc.c b/codegraph-kernel/vendor/tree-sitter/src/alloc.c new file mode 100644 index 0000000000..e5cb1d5eab --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/alloc.c @@ -0,0 +1,48 @@ +#include "alloc.h" +#include "tree_sitter/api.h" +#include + +static void *ts_malloc_default(size_t size) { + void *result = malloc(size); + if (size > 0 && !result) { + fprintf(stderr, "tree-sitter failed to allocate %zu bytes", size); + abort(); + } + return result; +} + +static void *ts_calloc_default(size_t count, size_t size) { + void *result = calloc(count, size); + if (count > 0 && !result) { + fprintf(stderr, "tree-sitter failed to allocate %zu bytes", count * size); + abort(); + } + return result; +} + +static void *ts_realloc_default(void *buffer, size_t size) { + void *result = realloc(buffer, size); + if (size > 0 && !result) { + fprintf(stderr, "tree-sitter failed to reallocate %zu bytes", size); + abort(); + } + return result; +} + +// Allow clients to override allocation functions dynamically +TS_PUBLIC void *(*ts_current_malloc)(size_t) = ts_malloc_default; +TS_PUBLIC void *(*ts_current_calloc)(size_t, size_t) = ts_calloc_default; +TS_PUBLIC void *(*ts_current_realloc)(void *, size_t) = ts_realloc_default; +TS_PUBLIC void (*ts_current_free)(void *) = free; + +void ts_set_allocator( + void *(*new_malloc)(size_t size), + void *(*new_calloc)(size_t count, size_t size), + void *(*new_realloc)(void *ptr, size_t size), + void (*new_free)(void *ptr) +) { + ts_current_malloc = new_malloc ? new_malloc : ts_malloc_default; + ts_current_calloc = new_calloc ? new_calloc : ts_calloc_default; + ts_current_realloc = new_realloc ? new_realloc : ts_realloc_default; + ts_current_free = new_free ? new_free : free; +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/alloc.h b/codegraph-kernel/vendor/tree-sitter/src/alloc.h new file mode 100644 index 0000000000..a27b8a6334 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/alloc.h @@ -0,0 +1,41 @@ +#ifndef TREE_SITTER_ALLOC_H_ +#define TREE_SITTER_ALLOC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#if defined(TREE_SITTER_HIDDEN_SYMBOLS) || defined(_WIN32) +#define TS_PUBLIC +#else +#define TS_PUBLIC __attribute__((visibility("default"))) +#endif + +TS_PUBLIC extern void *(*ts_current_malloc)(size_t size); +TS_PUBLIC extern void *(*ts_current_calloc)(size_t count, size_t size); +TS_PUBLIC extern void *(*ts_current_realloc)(void *ptr, size_t size); +TS_PUBLIC extern void (*ts_current_free)(void *ptr); + +// Allow clients to override allocation functions +#ifndef ts_malloc +#define ts_malloc ts_current_malloc +#endif +#ifndef ts_calloc +#define ts_calloc ts_current_calloc +#endif +#ifndef ts_realloc +#define ts_realloc ts_current_realloc +#endif +#ifndef ts_free +#define ts_free ts_current_free +#endif + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_ALLOC_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/array.h b/codegraph-kernel/vendor/tree-sitter/src/array.h new file mode 100644 index 0000000000..d965c6170c --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/array.h @@ -0,0 +1,291 @@ +#ifndef TREE_SITTER_ARRAY_H_ +#define TREE_SITTER_ARRAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./alloc.h" +#include "./ts_assert.h" + +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4101) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +#define Array(T) \ + struct { \ + T *contents; \ + uint32_t size; \ + uint32_t capacity; \ + } + +/// Initialize an array. +#define array_init(self) \ + ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) + +/// Create an empty array. +#define array_new() \ + { NULL, 0, 0 } + +/// Get a pointer to the element at a given `index` in the array. +#define array_get(self, _index) \ + (ts_assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) + +/// Get a pointer to the first element in the array. +#define array_front(self) array_get(self, 0) + +/// Get a pointer to the last element in the array. +#define array_back(self) array_get(self, (self)->size - 1) + +/// Clear the array, setting its size to zero. Note that this does not free any +/// memory allocated for the array's contents. +#define array_clear(self) ((self)->size = 0) + +/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is +/// less than the array's current capacity, this function has no effect. +#define array_reserve(self, new_capacity) \ + _array__reserve((Array *)(self), array_elem_size(self), new_capacity) + +/// Free any memory allocated for this array. Note that this does not free any +/// memory allocated for the array's contents. +#define array_delete(self) _array__delete((Array *)(self)) + +/// Push a new `element` onto the end of the array. +#define array_push(self, element) \ + (_array__grow((Array *)(self), 1, array_elem_size(self)), \ + (self)->contents[(self)->size++] = (element)) + +/// Increase the array's size by `count` elements. +/// New elements are zero-initialized. +#define array_grow_by(self, count) \ + do { \ + if ((count) == 0) break; \ + _array__grow((Array *)(self), count, array_elem_size(self)); \ + memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ + (self)->size += (count); \ + } while (0) + +/// Append all elements from one array to the end of another. +#define array_push_all(self, other) \ + array_extend((self), (other)->size, (other)->contents) + +/// Append `count` elements to the end of the array, reading their values from the +/// `contents` pointer. +#define array_extend(self, count, contents) \ + _array__splice( \ + (Array *)(self), array_elem_size(self), (self)->size, \ + 0, count, contents \ + ) + +/// Remove `old_count` elements from the array starting at the given `index`. At +/// the same index, insert `new_count` new elements, reading their values from the +/// `new_contents` pointer. +#define array_splice(self, _index, old_count, new_count, new_contents) \ + _array__splice( \ + (Array *)(self), array_elem_size(self), _index, \ + old_count, new_count, new_contents \ + ) + +/// Insert one `element` into the array at the given `index`. +#define array_insert(self, _index, element) \ + _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) + +/// Remove one element from the array at the given `index`. +#define array_erase(self, _index) \ + _array__erase((Array *)(self), array_elem_size(self), _index) + +/// Pop the last element off the array, returning the element by value. +#define array_pop(self) ((self)->contents[--(self)->size]) + +/// Assign the contents of one array to another, reallocating if necessary. +#define array_assign(self, other) \ + _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) + +/// Swap one array with another +#define array_swap(self, other) \ + _array__swap((Array *)(self), (Array *)(other)) + +/// Get the size of the array contents +#define array_elem_size(self) (sizeof *(self)->contents) + +/// Search a sorted array for a given `needle` value, using the given `compare` +/// callback to determine the order. +/// +/// If an existing element is found to be equal to `needle`, then the `index` +/// out-parameter is set to the existing value's index, and the `exists` +/// out-parameter is set to true. Otherwise, `index` is set to an index where +/// `needle` should be inserted in order to preserve the sorting, and `exists` +/// is set to false. +#define array_search_sorted_with(self, compare, needle, _index, _exists) \ + _array__search_sorted(self, 0, compare, , needle, _index, _exists) + +/// Search a sorted array for a given `needle` value, using integer comparisons +/// of a given struct field (specified with a leading dot) to determine the order. +/// +/// See also `array_search_sorted_with`. +#define array_search_sorted_by(self, field, needle, _index, _exists) \ + _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) + +/// Insert a given `value` into a sorted array, using the given `compare` +/// callback to determine the order. +#define array_insert_sorted_with(self, compare, value) \ + do { \ + unsigned _index, _exists; \ + array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ + if (!_exists) array_insert(self, _index, value); \ + } while (0) + +/// Insert a given `value` into a sorted array, using integer comparisons of +/// a given struct field (specified with a leading dot) to determine the order. +/// +/// See also `array_search_sorted_by`. +#define array_insert_sorted_by(self, field, value) \ + do { \ + unsigned _index, _exists; \ + array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ + if (!_exists) array_insert(self, _index, value); \ + } while (0) + +// Private + +typedef Array(void) Array; + +/// This is not what you're looking for, see `array_delete`. +static inline void _array__delete(Array *self) { + if (self->contents) { + ts_free(self->contents); + self->contents = NULL; + self->size = 0; + self->capacity = 0; + } +} + +/// This is not what you're looking for, see `array_erase`. +static inline void _array__erase(Array *self, size_t element_size, + uint32_t index) { + ts_assert(index < self->size); + char *contents = (char *)self->contents; + memmove(contents + index * element_size, contents + (index + 1) * element_size, + (self->size - index - 1) * element_size); + self->size--; +} + +/// This is not what you're looking for, see `array_reserve`. +static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { + if (new_capacity > self->capacity) { + if (self->contents) { + self->contents = ts_realloc(self->contents, new_capacity * element_size); + } else { + self->contents = ts_malloc(new_capacity * element_size); + } + self->capacity = new_capacity; + } +} + +/// This is not what you're looking for, see `array_assign`. +static inline void _array__assign(Array *self, const Array *other, size_t element_size) { + _array__reserve(self, element_size, other->size); + self->size = other->size; + memcpy(self->contents, other->contents, self->size * element_size); +} + +/// This is not what you're looking for, see `array_swap`. +static inline void _array__swap(Array *self, Array *other) { + Array swap = *other; + *other = *self; + *self = swap; +} + +/// This is not what you're looking for, see `array_push` or `array_grow_by`. +static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { + uint32_t new_size = self->size + count; + if (new_size > self->capacity) { + uint32_t new_capacity = self->capacity * 2; + if (new_capacity < 8) new_capacity = 8; + if (new_capacity < new_size) new_capacity = new_size; + _array__reserve(self, element_size, new_capacity); + } +} + +/// This is not what you're looking for, see `array_splice`. +static inline void _array__splice(Array *self, size_t element_size, + uint32_t index, uint32_t old_count, + uint32_t new_count, const void *elements) { + uint32_t new_size = self->size + new_count - old_count; + uint32_t old_end = index + old_count; + uint32_t new_end = index + new_count; + ts_assert(old_end <= self->size); + + _array__reserve(self, element_size, new_size); + + char *contents = (char *)self->contents; + if (self->size > old_end) { + memmove( + contents + new_end * element_size, + contents + old_end * element_size, + (self->size - old_end) * element_size + ); + } + if (new_count > 0) { + if (elements) { + memcpy( + (contents + index * element_size), + elements, + new_count * element_size + ); + } else { + memset( + (contents + index * element_size), + 0, + new_count * element_size + ); + } + } + self->size += new_count - old_count; +} + +/// A binary search routine, based on Rust's `std::slice::binary_search_by`. +/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. +#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ + do { \ + *(_index) = start; \ + *(_exists) = false; \ + uint32_t size = (self)->size - *(_index); \ + if (size == 0) break; \ + int comparison; \ + while (size > 1) { \ + uint32_t half_size = size / 2; \ + uint32_t mid_index = *(_index) + half_size; \ + comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ + if (comparison <= 0) *(_index) = mid_index; \ + size -= half_size; \ + } \ + comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ + if (comparison == 0) *(_exists) = true; \ + else if (comparison < 0) *(_index) += 1; \ + } while (0) + +/// Helper macro for the `_sorted_by` routines below. This takes the left (existing) +/// parameter by reference in order to work with the generic sorting function above. +#define _compare_int(a, b) ((int)*(a) - (int)(b)) + +#ifdef _MSC_VER +#pragma warning(pop) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_ARRAY_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/atomic.h b/codegraph-kernel/vendor/tree-sitter/src/atomic.h new file mode 100644 index 0000000000..e680b60e52 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/atomic.h @@ -0,0 +1,68 @@ +#ifndef TREE_SITTER_ATOMIC_H_ +#define TREE_SITTER_ATOMIC_H_ + +#include +#include +#include + +#ifdef __TINYC__ + +static inline size_t atomic_load(const volatile size_t *p) { + return *p; +} + +static inline uint32_t atomic_inc(volatile uint32_t *p) { + *p += 1; + return *p; +} + +static inline uint32_t atomic_dec(volatile uint32_t *p) { + *p-= 1; + return *p; +} + +#elif defined(_WIN32) + +#include + +static inline size_t atomic_load(const volatile size_t *p) { + return *p; +} + +static inline uint32_t atomic_inc(volatile uint32_t *p) { + return InterlockedIncrement((long volatile *)p); +} + +static inline uint32_t atomic_dec(volatile uint32_t *p) { + return InterlockedDecrement((long volatile *)p); +} + +#else + +static inline size_t atomic_load(const volatile size_t *p) { +#ifdef __ATOMIC_RELAXED + return __atomic_load_n(p, __ATOMIC_RELAXED); +#else + return __sync_fetch_and_add((volatile size_t *)p, 0); +#endif +} + +static inline uint32_t atomic_inc(volatile uint32_t *p) { + #ifdef __ATOMIC_RELAXED + return __atomic_add_fetch(p, 1U, __ATOMIC_SEQ_CST); + #else + return __sync_add_and_fetch(p, 1U); + #endif +} + +static inline uint32_t atomic_dec(volatile uint32_t *p) { + #ifdef __ATOMIC_RELAXED + return __atomic_sub_fetch(p, 1U, __ATOMIC_SEQ_CST); + #else + return __sync_sub_and_fetch(p, 1U); + #endif +} + +#endif + +#endif // TREE_SITTER_ATOMIC_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/clock.h b/codegraph-kernel/vendor/tree-sitter/src/clock.h new file mode 100644 index 0000000000..7a13185ec7 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/clock.h @@ -0,0 +1,146 @@ +#ifndef TREE_SITTER_CLOCK_H_ +#define TREE_SITTER_CLOCK_H_ + +#include +#include + +typedef uint64_t TSDuration; + +#ifdef _WIN32 + +// Windows: +// * Represent a time as a performance counter value. +// * Represent a duration as a number of performance counter ticks. + +#include +typedef uint64_t TSClock; + +static inline TSDuration duration_from_micros(uint64_t micros) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return micros * (uint64_t)frequency.QuadPart / 1000000; +} + +static inline uint64_t duration_to_micros(TSDuration self) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return self * 1000000 / (uint64_t)frequency.QuadPart; +} + +static inline TSClock clock_null(void) { + return 0; +} + +static inline TSClock clock_now(void) { + LARGE_INTEGER result; + QueryPerformanceCounter(&result); + return (uint64_t)result.QuadPart; +} + +static inline TSClock clock_after(TSClock base, TSDuration duration) { + return base + duration; +} + +static inline bool clock_is_null(TSClock self) { + return !self; +} + +static inline bool clock_is_gt(TSClock self, TSClock other) { + return self > other; +} + +#elif defined(CLOCK_MONOTONIC) + +// POSIX with monotonic clock support (Linux, macOS) +// * Represent a time as a monotonic (seconds, nanoseconds) pair. +// * Represent a duration as a number of microseconds. +// +// On these platforms, parse timeouts will correspond accurately to +// real time, regardless of what other processes are running. + +#include +typedef struct timespec TSClock; + +static inline TSDuration duration_from_micros(uint64_t micros) { + return micros; +} + +static inline uint64_t duration_to_micros(TSDuration self) { + return self; +} + +static inline TSClock clock_now(void) { + TSClock result; + clock_gettime(CLOCK_MONOTONIC, &result); + return result; +} + +static inline TSClock clock_null(void) { + return (TSClock) {0, 0}; +} + +static inline TSClock clock_after(TSClock base, TSDuration duration) { + TSClock result = base; + result.tv_sec += duration / 1000000; + result.tv_nsec += (duration % 1000000) * 1000; + if (result.tv_nsec >= 1000000000) { + result.tv_nsec -= 1000000000; + ++(result.tv_sec); + } + return result; +} + +static inline bool clock_is_null(TSClock self) { + return !self.tv_sec && !self.tv_nsec; +} + +static inline bool clock_is_gt(TSClock self, TSClock other) { + if (self.tv_sec > other.tv_sec) return true; + if (self.tv_sec < other.tv_sec) return false; + return self.tv_nsec > other.tv_nsec; +} + +#else + +// POSIX without monotonic clock support +// * Represent a time as a process clock value. +// * Represent a duration as a number of process clock ticks. +// +// On these platforms, parse timeouts may be affected by other processes, +// which is not ideal, but is better than using a non-monotonic time API +// like `gettimeofday`. + +#include +typedef uint64_t TSClock; + +static inline TSDuration duration_from_micros(uint64_t micros) { + return micros * (uint64_t)CLOCKS_PER_SEC / 1000000; +} + +static inline uint64_t duration_to_micros(TSDuration self) { + return self * 1000000 / (uint64_t)CLOCKS_PER_SEC; +} + +static inline TSClock clock_null(void) { + return 0; +} + +static inline TSClock clock_now(void) { + return (uint64_t)clock(); +} + +static inline TSClock clock_after(TSClock base, TSDuration duration) { + return base + duration; +} + +static inline bool clock_is_null(TSClock self) { + return !self; +} + +static inline bool clock_is_gt(TSClock self, TSClock other) { + return self > other; +} + +#endif + +#endif // TREE_SITTER_CLOCK_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/error_costs.h b/codegraph-kernel/vendor/tree-sitter/src/error_costs.h new file mode 100644 index 0000000000..32d3666a66 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/error_costs.h @@ -0,0 +1,11 @@ +#ifndef TREE_SITTER_ERROR_COSTS_H_ +#define TREE_SITTER_ERROR_COSTS_H_ + +#define ERROR_STATE 0 +#define ERROR_COST_PER_RECOVERY 500 +#define ERROR_COST_PER_MISSING_TREE 110 +#define ERROR_COST_PER_SKIPPED_TREE 100 +#define ERROR_COST_PER_SKIPPED_LINE 30 +#define ERROR_COST_PER_SKIPPED_CHAR 1 + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.c b/codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.c new file mode 100644 index 0000000000..11084c33d7 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.c @@ -0,0 +1,523 @@ +#include "./get_changed_ranges.h" +#include "./subtree.h" +#include "./language.h" +#include "./error_costs.h" +#include "./tree_cursor.h" +#include "./ts_assert.h" + +// #define DEBUG_GET_CHANGED_RANGES + +static void ts_range_array_add( + TSRangeArray *self, + Length start, + Length end +) { + if (self->size > 0) { + TSRange *last_range = array_back(self); + if (start.bytes <= last_range->end_byte) { + last_range->end_byte = end.bytes; + last_range->end_point = end.extent; + return; + } + } + + if (start.bytes < end.bytes) { + TSRange range = { start.extent, end.extent, start.bytes, end.bytes }; + array_push(self, range); + } +} + +bool ts_range_array_intersects( + const TSRangeArray *self, + unsigned start_index, + uint32_t start_byte, + uint32_t end_byte +) { + for (unsigned i = start_index; i < self->size; i++) { + TSRange *range = array_get(self, i); + if (range->end_byte > start_byte) { + if (range->start_byte >= end_byte) break; + return true; + } + } + return false; +} + +void ts_range_array_get_changed_ranges( + const TSRange *old_ranges, unsigned old_range_count, + const TSRange *new_ranges, unsigned new_range_count, + TSRangeArray *differences +) { + unsigned new_index = 0; + unsigned old_index = 0; + Length current_position = length_zero(); + bool in_old_range = false; + bool in_new_range = false; + + while (old_index < old_range_count || new_index < new_range_count) { + const TSRange *old_range = &old_ranges[old_index]; + const TSRange *new_range = &new_ranges[new_index]; + + Length next_old_position; + if (in_old_range) { + next_old_position = (Length) {old_range->end_byte, old_range->end_point}; + } else if (old_index < old_range_count) { + next_old_position = (Length) {old_range->start_byte, old_range->start_point}; + } else { + next_old_position = LENGTH_MAX; + } + + Length next_new_position; + if (in_new_range) { + next_new_position = (Length) {new_range->end_byte, new_range->end_point}; + } else if (new_index < new_range_count) { + next_new_position = (Length) {new_range->start_byte, new_range->start_point}; + } else { + next_new_position = LENGTH_MAX; + } + + if (next_old_position.bytes < next_new_position.bytes) { + if (in_old_range != in_new_range) { + ts_range_array_add(differences, current_position, next_old_position); + } + if (in_old_range) old_index++; + current_position = next_old_position; + in_old_range = !in_old_range; + } else if (next_new_position.bytes < next_old_position.bytes) { + if (in_old_range != in_new_range) { + ts_range_array_add(differences, current_position, next_new_position); + } + if (in_new_range) new_index++; + current_position = next_new_position; + in_new_range = !in_new_range; + } else { + if (in_old_range != in_new_range) { + ts_range_array_add(differences, current_position, next_new_position); + } + if (in_old_range) old_index++; + if (in_new_range) new_index++; + in_old_range = !in_old_range; + in_new_range = !in_new_range; + current_position = next_new_position; + } + } +} + +typedef struct { + TreeCursor cursor; + const TSLanguage *language; + unsigned visible_depth; + bool in_padding; + Subtree prev_external_token; +} Iterator; + +static Iterator iterator_new( + TreeCursor *cursor, + const Subtree *tree, + const TSLanguage *language +) { + array_clear(&cursor->stack); + array_push(&cursor->stack, ((TreeCursorEntry) { + .subtree = tree, + .position = length_zero(), + .child_index = 0, + .structural_child_index = 0, + })); + return (Iterator) { + .cursor = *cursor, + .language = language, + .visible_depth = 1, + .in_padding = false, + .prev_external_token = NULL_SUBTREE, + }; +} + +static bool iterator_done(Iterator *self) { + return self->cursor.stack.size == 0; +} + +static Length iterator_start_position(Iterator *self) { + TreeCursorEntry entry = *array_back(&self->cursor.stack); + if (self->in_padding) { + return entry.position; + } else { + return length_add(entry.position, ts_subtree_padding(*entry.subtree)); + } +} + +static Length iterator_end_position(Iterator *self) { + TreeCursorEntry entry = *array_back(&self->cursor.stack); + Length result = length_add(entry.position, ts_subtree_padding(*entry.subtree)); + if (self->in_padding) { + return result; + } else { + return length_add(result, ts_subtree_size(*entry.subtree)); + } +} + +static bool iterator_tree_is_visible(const Iterator *self) { + TreeCursorEntry entry = *array_back(&self->cursor.stack); + if (ts_subtree_visible(*entry.subtree)) return true; + if (self->cursor.stack.size > 1) { + Subtree parent = *array_get(&self->cursor.stack, self->cursor.stack.size - 2)->subtree; + return ts_language_alias_at( + self->language, + parent.ptr->production_id, + entry.structural_child_index + ) != 0; + } + return false; +} + +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; + + if (self->in_padding) { + if (i == 0) return; + i--; + } + + for (; i + 1 > 0; i--) { + TreeCursorEntry entry = *array_get(&self->cursor.stack, i); + + if (i > 0) { + const Subtree *parent = array_get(&self->cursor.stack, i - 1)->subtree; + *alias_symbol = ts_language_alias_at( + self->language, + parent->ptr->production_id, + entry.structural_child_index + ); + } + + if (ts_subtree_visible(*entry.subtree) || *alias_symbol) { + *tree = *entry.subtree; + *start_byte = entry.position.bytes; + break; + } + } +} + +static void iterator_ascend(Iterator *self) { + if (iterator_done(self)) return; + if (iterator_tree_is_visible(self) && !self->in_padding) self->visible_depth--; + if (array_back(&self->cursor.stack)->child_index > 0) self->in_padding = false; + self->cursor.stack.size--; +} + +static bool iterator_descend(Iterator *self, uint32_t goal_position) { + if (self->in_padding) return false; + + bool did_descend = false; + do { + did_descend = false; + TreeCursorEntry entry = *array_back(&self->cursor.stack); + Length position = entry.position; + uint32_t structural_child_index = 0; + for (uint32_t i = 0, n = ts_subtree_child_count(*entry.subtree); i < n; i++) { + const Subtree *child = &ts_subtree_children(*entry.subtree)[i]; + Length child_left = length_add(position, ts_subtree_padding(*child)); + Length child_right = length_add(child_left, ts_subtree_size(*child)); + + if (child_right.bytes > goal_position) { + array_push(&self->cursor.stack, ((TreeCursorEntry) { + .subtree = child, + .position = position, + .child_index = i, + .structural_child_index = structural_child_index, + })); + + if (iterator_tree_is_visible(self)) { + if (child_left.bytes > goal_position) { + self->in_padding = true; + } else { + self->visible_depth++; + } + return true; + } + + did_descend = true; + break; + } + + position = child_right; + if (!ts_subtree_extra(*child)) structural_child_index++; + Subtree last_external_token = ts_subtree_last_external_token(*child); + if (last_external_token.ptr) { + self->prev_external_token = last_external_token; + } + } + } while (did_descend); + + return false; +} + +static void iterator_advance(Iterator *self) { + if (self->in_padding) { + self->in_padding = false; + if (iterator_tree_is_visible(self)) { + self->visible_depth++; + } else { + iterator_descend(self, 0); + } + return; + } + + for (;;) { + if (iterator_tree_is_visible(self)) self->visible_depth--; + TreeCursorEntry entry = array_pop(&self->cursor.stack); + if (iterator_done(self)) return; + + const Subtree *parent = array_back(&self->cursor.stack)->subtree; + uint32_t child_index = entry.child_index + 1; + Subtree last_external_token = ts_subtree_last_external_token(*entry.subtree); + if (last_external_token.ptr) { + self->prev_external_token = last_external_token; + } + if (ts_subtree_child_count(*parent) > child_index) { + Length position = length_add(entry.position, ts_subtree_total_size(*entry.subtree)); + uint32_t structural_child_index = entry.structural_child_index; + if (!ts_subtree_extra(*entry.subtree)) structural_child_index++; + const Subtree *next_child = &ts_subtree_children(*parent)[child_index]; + + array_push(&self->cursor.stack, ((TreeCursorEntry) { + .subtree = next_child, + .position = position, + .child_index = child_index, + .structural_child_index = structural_child_index, + })); + + if (iterator_tree_is_visible(self)) { + if (ts_subtree_padding(*next_child).bytes > 0) { + self->in_padding = true; + } else { + self->visible_depth++; + } + } else { + iterator_descend(self, 0); + } + break; + } + } +} + +typedef enum { + IteratorDiffers, + IteratorMayDiffer, + IteratorMatches, +} IteratorComparison; + +static IteratorComparison iterator_compare( + const Iterator *old_iter, + const Iterator *new_iter +) { + Subtree old_tree = NULL_SUBTREE; + Subtree new_tree = NULL_SUBTREE; + uint32_t old_start = 0; + uint32_t new_start = 0; + TSSymbol old_alias_symbol = 0; + TSSymbol new_alias_symbol = 0; + iterator_get_visible_state(old_iter, &old_tree, &old_alias_symbol, &old_start); + iterator_get_visible_state(new_iter, &new_tree, &new_alias_symbol, &new_start); + TSSymbol old_symbol = ts_subtree_symbol(old_tree); + TSSymbol new_symbol = ts_subtree_symbol(new_tree); + + if (!old_tree.ptr && !new_tree.ptr) return IteratorMatches; + if (!old_tree.ptr || !new_tree.ptr) return IteratorDiffers; + if (old_alias_symbol != new_alias_symbol || old_symbol != new_symbol) return IteratorDiffers; + + uint32_t old_size = ts_subtree_size(old_tree).bytes; + uint32_t new_size = ts_subtree_size(new_tree).bytes; + TSStateId old_state = ts_subtree_parse_state(old_tree); + TSStateId new_state = ts_subtree_parse_state(new_tree); + bool old_has_external_tokens = ts_subtree_has_external_tokens(old_tree); + bool new_has_external_tokens = ts_subtree_has_external_tokens(new_tree); + uint32_t old_error_cost = ts_subtree_error_cost(old_tree); + uint32_t new_error_cost = ts_subtree_error_cost(new_tree); + + if ( + old_start != new_start || + old_symbol == ts_builtin_sym_error || + old_size != new_size || + old_state == TS_TREE_STATE_NONE || + new_state == TS_TREE_STATE_NONE || + ((old_state == ERROR_STATE) != (new_state == ERROR_STATE)) || + old_error_cost != new_error_cost || + old_has_external_tokens != new_has_external_tokens || + ts_subtree_has_changes(old_tree) || + ( + old_has_external_tokens && + !ts_subtree_external_scanner_state_eq(old_iter->prev_external_token, new_iter->prev_external_token) + ) + ) { + return IteratorMayDiffer; + } + + return IteratorMatches; +} + +#ifdef DEBUG_GET_CHANGED_RANGES +static inline void iterator_print_state(Iterator *self) { + TreeCursorEntry entry = *array_back(&self->cursor.stack); + TSPoint start = iterator_start_position(self).extent; + TSPoint end = iterator_end_position(self).extent; + const char *name = ts_language_symbol_name(self->language, ts_subtree_symbol(*entry.subtree)); + printf( + "(%-25s %s\t depth:%u [%u, %u] - [%u, %u])", + name, self->in_padding ? "(p)" : " ", + self->visible_depth, + start.row, start.column, + end.row, end.column + ); +} +#endif + +unsigned ts_subtree_get_changed_ranges( + const Subtree *old_tree, const Subtree *new_tree, + TreeCursor *cursor1, TreeCursor *cursor2, + const TSLanguage *language, + const TSRangeArray *included_range_differences, + TSRange **ranges +) { + TSRangeArray results = array_new(); + + Iterator old_iter = iterator_new(cursor1, old_tree, language); + Iterator new_iter = iterator_new(cursor2, new_tree, language); + + unsigned included_range_difference_index = 0; + + Length position = iterator_start_position(&old_iter); + Length next_position = iterator_start_position(&new_iter); + if (position.bytes < next_position.bytes) { + ts_range_array_add(&results, position, next_position); + position = next_position; + } else if (position.bytes > next_position.bytes) { + ts_range_array_add(&results, next_position, position); + next_position = position; + } + + do { + #ifdef DEBUG_GET_CHANGED_RANGES + printf("At [%-2u, %-2u] Compare ", position.extent.row, position.extent.column); + iterator_print_state(&old_iter); + printf("\tvs\t"); + iterator_print_state(&new_iter); + puts(""); + #endif + + // Compare the old and new subtrees. + IteratorComparison comparison = iterator_compare(&old_iter, &new_iter); + + // Even if the two subtrees appear to be identical, they could differ + // internally if they contain a range of text that was previously + // excluded from the parse, and is now included, or vice-versa. + if (comparison == IteratorMatches && ts_range_array_intersects( + included_range_differences, + included_range_difference_index, + position.bytes, + iterator_end_position(&old_iter).bytes + )) { + comparison = IteratorMayDiffer; + } + + bool is_changed = false; + switch (comparison) { + // If the subtrees are definitely identical, move to the end + // of both subtrees. + case IteratorMatches: + next_position = iterator_end_position(&old_iter); + break; + + // If the subtrees might differ internally, descend into both + // subtrees, finding the first child that spans the current position. + case IteratorMayDiffer: + if (iterator_descend(&old_iter, position.bytes)) { + if (!iterator_descend(&new_iter, position.bytes)) { + is_changed = true; + next_position = iterator_end_position(&old_iter); + } + } else if (iterator_descend(&new_iter, position.bytes)) { + is_changed = true; + next_position = iterator_end_position(&new_iter); + } else { + next_position = length_min( + iterator_end_position(&old_iter), + iterator_end_position(&new_iter) + ); + } + break; + + // If the subtrees are different, record a change and then move + // to the end of both subtrees. + case IteratorDiffers: + is_changed = true; + next_position = length_min( + iterator_end_position(&old_iter), + iterator_end_position(&new_iter) + ); + break; + } + + // Ensure that both iterators are caught up to the current position. + while ( + !iterator_done(&old_iter) && + iterator_end_position(&old_iter).bytes <= next_position.bytes + ) iterator_advance(&old_iter); + while ( + !iterator_done(&new_iter) && + iterator_end_position(&new_iter).bytes <= next_position.bytes + ) iterator_advance(&new_iter); + + // Ensure that both iterators are at the same depth in the tree. + while (old_iter.visible_depth > new_iter.visible_depth) { + iterator_ascend(&old_iter); + } + while (new_iter.visible_depth > old_iter.visible_depth) { + iterator_ascend(&new_iter); + } + + if (is_changed) { + #ifdef DEBUG_GET_CHANGED_RANGES + printf( + " change: [[%u, %u] - [%u, %u]]\n", + position.extent.row + 1, position.extent.column, + next_position.extent.row + 1, next_position.extent.column + ); + #endif + + ts_range_array_add(&results, position, next_position); + } + + position = next_position; + + // Keep track of the current position in the included range differences + // array in order to avoid scanning the entire array on each iteration. + while (included_range_difference_index < included_range_differences->size) { + const TSRange *range = array_get(included_range_differences, + included_range_difference_index + ); + if (range->end_byte <= position.bytes) { + included_range_difference_index++; + } else { + break; + } + } + } while (!iterator_done(&old_iter) && !iterator_done(&new_iter)); + + Length old_size = ts_subtree_total_size(*old_tree); + Length new_size = ts_subtree_total_size(*new_tree); + if (old_size.bytes < new_size.bytes) { + ts_range_array_add(&results, old_size, new_size); + } else if (new_size.bytes < old_size.bytes) { + ts_range_array_add(&results, new_size, old_size); + } + + *cursor1 = old_iter.cursor; + *cursor2 = new_iter.cursor; + *ranges = results.contents; + return results.size; +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.h b/codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.h new file mode 100644 index 0000000000..a1f1dbb430 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/get_changed_ranges.h @@ -0,0 +1,36 @@ +#ifndef TREE_SITTER_GET_CHANGED_RANGES_H_ +#define TREE_SITTER_GET_CHANGED_RANGES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./tree_cursor.h" +#include "./subtree.h" + +typedef Array(TSRange) TSRangeArray; + +void ts_range_array_get_changed_ranges( + const TSRange *old_ranges, unsigned old_range_count, + const TSRange *new_ranges, unsigned new_range_count, + TSRangeArray *differences +); + +bool ts_range_array_intersects( + const TSRangeArray *self, unsigned start_index, + uint32_t start_byte, uint32_t end_byte +); + +unsigned ts_subtree_get_changed_ranges( + const Subtree *old_tree, const Subtree *new_tree, + TreeCursor *cursor1, TreeCursor *cursor2, + const TSLanguage *language, + const TSRangeArray *included_range_differences, + TSRange **ranges +); + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_GET_CHANGED_RANGES_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/host.h b/codegraph-kernel/vendor/tree-sitter/src/host.h new file mode 100644 index 0000000000..a07e9f8949 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/host.h @@ -0,0 +1,21 @@ + +// Determine endian and pointer size based on known defines. +// TS_BIG_ENDIAN and TS_PTR_SIZE can be set as -D compiler arguments +// to override this. + +#if !defined(TS_BIG_ENDIAN) +#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \ + || (defined( __APPLE_CC__) && (defined(__ppc__) || defined(__ppc64__))) +#define TS_BIG_ENDIAN 1 +#else +#define TS_BIG_ENDIAN 0 +#endif +#endif + +#if !defined(TS_PTR_SIZE) +#if UINTPTR_MAX == 0xFFFFFFFF +#define TS_PTR_SIZE 32 +#else +#define TS_PTR_SIZE 64 +#endif +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/language.c b/codegraph-kernel/vendor/tree-sitter/src/language.c new file mode 100644 index 0000000000..2dce699839 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/language.c @@ -0,0 +1,293 @@ +#include "./language.h" +#include "./wasm_store.h" +#include "tree_sitter/api.h" +#include + +const TSLanguage *ts_language_copy(const TSLanguage *self) { + if (self && ts_language_is_wasm(self)) { + ts_wasm_language_retain(self); + } + return self; +} + +void ts_language_delete(const TSLanguage *self) { + if (self && ts_language_is_wasm(self)) { + ts_wasm_language_release(self); + } +} + +uint32_t ts_language_symbol_count(const TSLanguage *self) { + return self->symbol_count + self->alias_count; +} + +uint32_t ts_language_state_count(const TSLanguage *self) { + return self->state_count; +} + +const TSSymbol *ts_language_supertypes(const TSLanguage *self, uint32_t *length) { + if (self->abi_version >= LANGUAGE_VERSION_WITH_RESERVED_WORDS) { + *length = self->supertype_count; + return self->supertype_symbols; + } else { + *length = 0; + return NULL; + } +} + +const TSSymbol *ts_language_subtypes( + const TSLanguage *self, + TSSymbol supertype, + uint32_t *length +) { + if (self->abi_version < LANGUAGE_VERSION_WITH_RESERVED_WORDS || !ts_language_symbol_metadata(self, supertype).supertype) { + *length = 0; + return NULL; + } + + TSMapSlice slice = self->supertype_map_slices[supertype]; + *length = slice.length; + return &self->supertype_map_entries[slice.index]; +} + +uint32_t ts_language_version(const TSLanguage *self) { + return self->abi_version; +} + +uint32_t ts_language_abi_version(const TSLanguage *self) { + return self->abi_version; +} + +const TSLanguageMetadata *ts_language_metadata(const TSLanguage *self) { + return self->abi_version >= LANGUAGE_VERSION_WITH_RESERVED_WORDS ? &self->metadata : NULL; +} + +const char *ts_language_name(const TSLanguage *self) { + return self->abi_version >= LANGUAGE_VERSION_WITH_RESERVED_WORDS ? self->name : NULL; +} + +uint32_t ts_language_field_count(const TSLanguage *self) { + return self->field_count; +} + +void ts_language_table_entry( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol, + TableEntry *result +) { + if (symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat) { + result->action_count = 0; + result->is_reusable = false; + result->actions = NULL; + } else { + ts_assert(symbol < self->token_count); + uint32_t action_index = ts_language_lookup(self, state, symbol); + const TSParseActionEntry *entry = &self->parse_actions[action_index]; + result->action_count = entry->entry.count; + result->is_reusable = entry->entry.reusable; + result->actions = (const TSParseAction *)(entry + 1); + } +} + +TSLexerMode ts_language_lex_mode_for_state( + const TSLanguage *self, + TSStateId state +) { + if (self->abi_version < 15) { + TSLexMode mode = ((const TSLexMode *)self->lex_modes)[state]; + return (TSLexerMode) { + .lex_state = mode.lex_state, + .external_lex_state = mode.external_lex_state, + .reserved_word_set_id = 0, + }; + } else { + return self->lex_modes[state]; + } +} + +bool ts_language_is_reserved_word( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol +) { + TSLexerMode lex_mode = ts_language_lex_mode_for_state(self, state); + if (lex_mode.reserved_word_set_id > 0) { + unsigned start = lex_mode.reserved_word_set_id * self->max_reserved_word_set_size; + unsigned end = start + self->max_reserved_word_set_size; + for (unsigned i = start; i < end; i++) { + if (self->reserved_words[i] == symbol) return true; + if (self->reserved_words[i] == 0) break; + } + } + return false; +} + +TSSymbolMetadata ts_language_symbol_metadata( + const TSLanguage *self, + TSSymbol symbol +) { + if (symbol == ts_builtin_sym_error) { + return (TSSymbolMetadata) {.visible = true, .named = true}; + } else if (symbol == ts_builtin_sym_error_repeat) { + return (TSSymbolMetadata) {.visible = false, .named = false}; + } else { + return self->symbol_metadata[symbol]; + } +} + +TSSymbol ts_language_public_symbol( + const TSLanguage *self, + TSSymbol symbol +) { + if (symbol == ts_builtin_sym_error) return symbol; + return self->public_symbol_map[symbol]; +} + +TSStateId ts_language_next_state( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol +) { + if (symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat) { + return 0; + } else if (symbol < self->token_count) { + uint32_t count; + const TSParseAction *actions = ts_language_actions(self, state, symbol, &count); + if (count > 0) { + TSParseAction action = actions[count - 1]; + if (action.type == TSParseActionTypeShift) { + return action.shift.extra ? state : action.shift.state; + } + } + return 0; + } else { + return ts_language_lookup(self, state, symbol); + } +} + +const char *ts_language_symbol_name( + const TSLanguage *self, + TSSymbol symbol +) { + if (symbol == ts_builtin_sym_error) { + return "ERROR"; + } else if (symbol == ts_builtin_sym_error_repeat) { + return "_ERROR"; + } else if (symbol < ts_language_symbol_count(self)) { + return self->symbol_names[symbol]; + } else { + return NULL; + } +} + +TSSymbol ts_language_symbol_for_name( + const TSLanguage *self, + const char *string, + uint32_t length, + bool is_named +) { + if (is_named && !strncmp(string, "ERROR", length)) return ts_builtin_sym_error; + uint16_t count = (uint16_t)ts_language_symbol_count(self); + for (TSSymbol i = 0; i < count; i++) { + TSSymbolMetadata metadata = ts_language_symbol_metadata(self, i); + if ((!metadata.visible && !metadata.supertype) || metadata.named != is_named) continue; + const char *symbol_name = self->symbol_names[i]; + if (!strncmp(symbol_name, string, length) && !symbol_name[length]) { + return self->public_symbol_map[i]; + } + } + return 0; +} + +TSSymbolType ts_language_symbol_type( + const TSLanguage *self, + TSSymbol symbol +) { + TSSymbolMetadata metadata = ts_language_symbol_metadata(self, symbol); + if (metadata.named && metadata.visible) { + return TSSymbolTypeRegular; + } else if (metadata.visible) { + return TSSymbolTypeAnonymous; + } else if (metadata.supertype) { + return TSSymbolTypeSupertype; + } else { + return TSSymbolTypeAuxiliary; + } +} + +const char *ts_language_field_name_for_id( + const TSLanguage *self, + TSFieldId id +) { + uint32_t count = ts_language_field_count(self); + if (count && id <= count) { + return self->field_names[id]; + } else { + return NULL; + } +} + +TSFieldId ts_language_field_id_for_name( + const TSLanguage *self, + const char *name, + uint32_t name_length +) { + uint16_t count = (uint16_t)ts_language_field_count(self); + for (TSSymbol i = 1; i < count + 1; i++) { + switch (strncmp(name, self->field_names[i], name_length)) { + case 0: + if (self->field_names[i][name_length] == 0) return i; + break; + case -1: + return 0; + default: + break; + } + } + return 0; +} + +TSLookaheadIterator *ts_lookahead_iterator_new(const TSLanguage *self, TSStateId state) { + if (state >= self->state_count) return NULL; + LookaheadIterator *iterator = ts_malloc(sizeof(LookaheadIterator)); + *iterator = ts_language_lookaheads(self, state); + return (TSLookaheadIterator *)iterator; +} + +void ts_lookahead_iterator_delete(TSLookaheadIterator *self) { + ts_free(self); +} + +bool ts_lookahead_iterator_reset_state(TSLookaheadIterator * self, TSStateId state) { + LookaheadIterator *iterator = (LookaheadIterator *)self; + if (state >= iterator->language->state_count) return false; + *iterator = ts_language_lookaheads(iterator->language, state); + return true; +} + +const TSLanguage *ts_lookahead_iterator_language(const TSLookaheadIterator *self) { + const LookaheadIterator *iterator = (const LookaheadIterator *)self; + return iterator->language; +} + +bool ts_lookahead_iterator_reset(TSLookaheadIterator *self, const TSLanguage *language, TSStateId state) { + if (state >= language->state_count) return false; + LookaheadIterator *iterator = (LookaheadIterator *)self; + *iterator = ts_language_lookaheads(language, state); + return true; +} + +bool ts_lookahead_iterator_next(TSLookaheadIterator *self) { + LookaheadIterator *iterator = (LookaheadIterator *)self; + return ts_lookahead_iterator__next(iterator); +} + +TSSymbol ts_lookahead_iterator_current_symbol(const TSLookaheadIterator *self) { + const LookaheadIterator *iterator = (const LookaheadIterator *)self; + return iterator->symbol; +} + +const char *ts_lookahead_iterator_current_symbol_name(const TSLookaheadIterator *self) { + const LookaheadIterator *iterator = (const LookaheadIterator *)self; + return ts_language_symbol_name(iterator->language, iterator->symbol); +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/language.h b/codegraph-kernel/vendor/tree-sitter/src/language.h new file mode 100644 index 0000000000..518c06bfc5 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/language.h @@ -0,0 +1,293 @@ +#ifndef TREE_SITTER_LANGUAGE_H_ +#define TREE_SITTER_LANGUAGE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./subtree.h" +#include "./parser.h" + +#define ts_builtin_sym_error_repeat (ts_builtin_sym_error - 1) + +#define LANGUAGE_VERSION_WITH_RESERVED_WORDS 15 +#define LANGUAGE_VERSION_WITH_PRIMARY_STATES 14 + +typedef struct { + const TSParseAction *actions; + uint32_t action_count; + bool is_reusable; +} TableEntry; + +typedef struct { + const TSLanguage *language; + const uint16_t *data; + const uint16_t *group_end; + TSStateId state; + uint16_t table_value; + uint16_t section_index; + uint16_t group_count; + bool is_small_state; + + const TSParseAction *actions; + TSSymbol symbol; + TSStateId next_state; + uint16_t action_count; +} LookaheadIterator; + +void ts_language_table_entry(const TSLanguage *self, TSStateId state, TSSymbol symbol, TableEntry *result); +TSLexerMode ts_language_lex_mode_for_state(const TSLanguage *self, TSStateId state); +bool ts_language_is_reserved_word(const TSLanguage *self, TSStateId state, TSSymbol symbol); +TSSymbolMetadata ts_language_symbol_metadata(const TSLanguage *self, TSSymbol symbol); +TSSymbol ts_language_public_symbol(const TSLanguage *self, TSSymbol symbol); + +static inline const TSParseAction *ts_language_actions( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol, + uint32_t *count +) { + TableEntry entry; + ts_language_table_entry(self, state, symbol, &entry); + *count = entry.action_count; + return entry.actions; +} + +static inline bool ts_language_has_reduce_action( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol +) { + TableEntry entry; + ts_language_table_entry(self, state, symbol, &entry); + return entry.action_count > 0 && entry.actions[0].type == TSParseActionTypeReduce; +} + +// Lookup the table value for a given symbol and state. +// +// For non-terminal symbols, the table value represents a successor state. +// For terminal symbols, it represents an index in the actions table. +// For 'large' parse states, this is a direct lookup. For 'small' parse +// states, this requires searching through the symbol groups to find +// the given symbol. +static inline uint16_t ts_language_lookup( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol +) { + if (state >= self->large_state_count) { + uint32_t index = self->small_parse_table_map[state - self->large_state_count]; + const uint16_t *data = &self->small_parse_table[index]; + uint16_t group_count = *(data++); + for (unsigned i = 0; i < group_count; i++) { + uint16_t section_value = *(data++); + uint16_t symbol_count = *(data++); + for (unsigned j = 0; j < symbol_count; j++) { + if (*(data++) == symbol) return section_value; + } + } + return 0; + } else { + return self->parse_table[state * self->symbol_count + symbol]; + } +} + +static inline bool ts_language_has_actions( + const TSLanguage *self, + TSStateId state, + TSSymbol symbol +) { + return ts_language_lookup(self, state, symbol) != 0; +} + +// Iterate over all of the symbols that are valid in the given state. +// +// For 'large' parse states, this just requires iterating through +// all possible symbols and checking the parse table for each one. +// For 'small' parse states, this exploits the structure of the +// table to only visit the valid symbols. +static inline LookaheadIterator ts_language_lookaheads( + const TSLanguage *self, + TSStateId state +) { + bool is_small_state = state >= self->large_state_count; + const uint16_t *data; + const uint16_t *group_end = NULL; + uint16_t group_count = 0; + if (is_small_state) { + uint32_t index = self->small_parse_table_map[state - self->large_state_count]; + data = &self->small_parse_table[index]; + group_end = data + 1; + group_count = *data; + } else { + data = &self->parse_table[state * self->symbol_count] - 1; + } + return (LookaheadIterator) { + .language = self, + .data = data, + .group_end = group_end, + .group_count = group_count, + .is_small_state = is_small_state, + .symbol = UINT16_MAX, + .next_state = 0, + }; +} + +static inline bool ts_lookahead_iterator__next(LookaheadIterator *self) { + // For small parse states, valid symbols are listed explicitly, + // grouped by their value. There's no need to look up the actions + // again until moving to the next group. + if (self->is_small_state) { + self->data++; + if (self->data == self->group_end) { + if (self->group_count == 0) return false; + self->group_count--; + self->table_value = *(self->data++); + unsigned symbol_count = *(self->data++); + self->group_end = self->data + symbol_count; + self->symbol = *self->data; + } else { + self->symbol = *self->data; + return true; + } + } + + // For large parse states, iterate through every symbol until one + // is found that has valid actions. + else { + do { + self->data++; + self->symbol++; + if (self->symbol >= self->language->symbol_count) return false; + self->table_value = *self->data; + } while (!self->table_value); + } + + // Depending on if the symbols is terminal or non-terminal, the table value either + // represents a list of actions or a successor state. + if (self->symbol < self->language->token_count) { + const TSParseActionEntry *entry = &self->language->parse_actions[self->table_value]; + self->action_count = entry->entry.count; + self->actions = (const TSParseAction *)(entry + 1); + self->next_state = 0; + } else { + self->action_count = 0; + self->next_state = self->table_value; + } + return true; +} + +// Whether the state is a "primary state". If this returns false, it indicates that there exists +// another state that behaves identically to this one with respect to query analysis. +static inline bool ts_language_state_is_primary( + const TSLanguage *self, + TSStateId state +) { + if (self->abi_version >= LANGUAGE_VERSION_WITH_PRIMARY_STATES) { + return state == self->primary_state_ids[state]; + } else { + return true; + } +} + +static inline const bool *ts_language_enabled_external_tokens( + const TSLanguage *self, + unsigned external_scanner_state +) { + if (external_scanner_state == 0) { + return NULL; + } else { + return self->external_scanner.states + self->external_token_count * external_scanner_state; + } +} + +static inline const TSSymbol *ts_language_alias_sequence( + const TSLanguage *self, + uint32_t production_id +) { + return production_id ? + &self->alias_sequences[production_id * self->max_alias_sequence_length] : + NULL; +} + +static inline TSSymbol ts_language_alias_at( + const TSLanguage *self, + uint32_t production_id, + uint32_t child_index +) { + return production_id ? + self->alias_sequences[production_id * self->max_alias_sequence_length + child_index] : + 0; +} + +static inline void ts_language_field_map( + const TSLanguage *self, + uint32_t production_id, + const TSFieldMapEntry **start, + const TSFieldMapEntry **end +) { + if (self->field_count == 0) { + *start = NULL; + *end = NULL; + return; + } + + TSMapSlice slice = self->field_map_slices[production_id]; + *start = &self->field_map_entries[slice.index]; + *end = &self->field_map_entries[slice.index] + slice.length; +} + +static inline void ts_language_aliases_for_symbol( + const TSLanguage *self, + TSSymbol original_symbol, + const TSSymbol **start, + const TSSymbol **end +) { + *start = &self->public_symbol_map[original_symbol]; + *end = *start + 1; + + unsigned idx = 0; + for (;;) { + TSSymbol symbol = self->alias_map[idx++]; + if (symbol == 0 || symbol > original_symbol) break; + uint16_t count = self->alias_map[idx++]; + if (symbol == original_symbol) { + *start = &self->alias_map[idx]; + *end = &self->alias_map[idx + count]; + break; + } + idx += count; + } +} + +static inline void ts_language_write_symbol_as_dot_string( + const TSLanguage *self, + FILE *f, + TSSymbol symbol +) { + const char *name = ts_language_symbol_name(self, symbol); + for (const char *chr = name; *chr; chr++) { + switch (*chr) { + case '"': + case '\\': + fputc('\\', f); + fputc(*chr, f); + break; + case '\n': + fputs("\\n", f); + break; + case '\t': + fputs("\\t", f); + break; + default: + fputc(*chr, f); + break; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_LANGUAGE_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/length.h b/codegraph-kernel/vendor/tree-sitter/src/length.h new file mode 100644 index 0000000000..ddf156ce09 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/length.h @@ -0,0 +1,52 @@ +#ifndef TREE_SITTER_LENGTH_H_ +#define TREE_SITTER_LENGTH_H_ + +#include +#include +#include "./point.h" +#include "tree_sitter/api.h" + +typedef struct { + uint32_t bytes; + TSPoint extent; +} Length; + +static const Length LENGTH_UNDEFINED = {0, {0, 1}}; +static const Length LENGTH_MAX = {UINT32_MAX, {UINT32_MAX, UINT32_MAX}}; + +static inline bool length_is_undefined(Length length) { + return length.bytes == 0 && length.extent.column != 0; +} + +static inline Length length_min(Length len1, Length len2) { + return (len1.bytes < len2.bytes) ? len1 : len2; +} + +static inline Length length_add(Length len1, Length len2) { + Length result; + result.bytes = len1.bytes + len2.bytes; + result.extent = point_add(len1.extent, len2.extent); + return result; +} + +static inline Length length_sub(Length len1, Length len2) { + Length result; + result.bytes = (len1.bytes >= len2.bytes) ? len1.bytes - len2.bytes : 0; + result.extent = point_sub(len1.extent, len2.extent); + return result; +} + +static inline Length length_zero(void) { + Length result = {0, {0, 0}}; + return result; +} + +static inline Length length_saturating_sub(Length len1, Length len2) { + if (len1.bytes > len2.bytes) { + return length_sub(len1, len2); + } else { + return length_zero(); + } +} + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/lexer.c b/codegraph-kernel/vendor/tree-sitter/src/lexer.c new file mode 100644 index 0000000000..94124fd1d5 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/lexer.c @@ -0,0 +1,483 @@ +#include "./length.h" +#include "./lexer.h" +#include "./unicode.h" + +#include "tree_sitter/api.h" + +#include +#include + +#define LOG(message, character) \ + if (self->logger.log) { \ + snprintf( \ + self->debug_buffer, \ + TREE_SITTER_SERIALIZATION_BUFFER_SIZE, \ + 32 <= character && character < 127 ? \ + message " character:'%c'" : \ + message " character:%d", \ + character \ + ); \ + self->logger.log( \ + self->logger.payload, \ + TSLogTypeLex, \ + self->debug_buffer \ + ); \ + } + +static const int32_t BYTE_ORDER_MARK = 0xFEFF; + +static const TSRange DEFAULT_RANGE = { + .start_point = { + .row = 0, + .column = 0, + }, + .end_point = { + .row = UINT32_MAX, + .column = UINT32_MAX, + }, + .start_byte = 0, + .end_byte = UINT32_MAX +}; + +/** + * Sets the column data to the given value and marks it valid. + * @param self The lexer state. + * @param val The new value of the column data. + */ +static void ts_lexer__set_column_data(Lexer *self, uint32_t val) { + self->column_data.valid = true; + self->column_data.value = val; +} + +/** + * Increments the value of the column data; no-op if invalid. + * @param self The lexer state. + */ +static void ts_lexer__increment_column_data(Lexer *self) { + if (self->column_data.valid) { + self->column_data.value++; + } +} + +/** + * Marks the column data as invalid. + * @param self The lexer state. + */ +static void ts_lexer__invalidate_column_data(Lexer *self) { + self->column_data.valid = false; + self->column_data.value = 0; +} + +// Check if the lexer has reached EOF. This state is stored +// by setting the lexer's `current_included_range_index` such that +// it has consumed all of its available ranges. +static bool ts_lexer__eof(const TSLexer *_self) { + Lexer *self = (Lexer *)_self; + return self->current_included_range_index == self->included_range_count; +} + +// Clear the currently stored chunk of source code, because the lexer's +// position has changed. +static void ts_lexer__clear_chunk(Lexer *self) { + self->chunk = NULL; + self->chunk_size = 0; + self->chunk_start = 0; +} + +// Call the lexer's input callback to obtain a new chunk of source code +// for the current position. +static void ts_lexer__get_chunk(Lexer *self) { + self->chunk_start = self->current_position.bytes; + self->chunk = self->input.read( + self->input.payload, + self->current_position.bytes, + self->current_position.extent, + &self->chunk_size + ); + if (!self->chunk_size) { + self->current_included_range_index = self->included_range_count; + self->chunk = NULL; + } +} + +// Decode the next unicode character in the current chunk of source code. +// This assumes that the lexer has already retrieved a chunk of source +// code that spans the current position. +static void ts_lexer__get_lookahead(Lexer *self) { + uint32_t position_in_chunk = self->current_position.bytes - self->chunk_start; + uint32_t size = self->chunk_size - position_in_chunk; + + if (size == 0) { + self->lookahead_size = 1; + self->data.lookahead = '\0'; + return; + } + + const uint8_t *chunk = (const uint8_t *)self->chunk + position_in_chunk; + DecodeFunction decode = + self->input.encoding == TSInputEncodingUTF8 ? ts_decode_utf8 : + self->input.encoding == TSInputEncodingUTF16LE ? ts_decode_utf16_le : + self->input.encoding == TSInputEncodingUTF16BE ? ts_decode_utf16_be : self->input.decode; + + self->lookahead_size = decode(chunk, size, &self->data.lookahead); + + // If this chunk ended in the middle of a multi-byte character, + // try again with a fresh chunk. + if (self->data.lookahead == TS_DECODE_ERROR && size < 4) { + ts_lexer__get_chunk(self); + chunk = (const uint8_t *)self->chunk; + size = self->chunk_size; + self->lookahead_size = decode(chunk, size, &self->data.lookahead); + } + + if (self->data.lookahead == TS_DECODE_ERROR) { + self->lookahead_size = 1; + } +} + +static void ts_lexer_goto(Lexer *self, Length position) { + if (position.bytes != self->current_position.bytes) { + ts_lexer__invalidate_column_data(self); + } + + self->current_position = position; + + // Move to the first valid position at or after the given position. + bool found_included_range = false; + for (unsigned i = 0; i < self->included_range_count; i++) { + TSRange *included_range = &self->included_ranges[i]; + if ( + included_range->end_byte > self->current_position.bytes && + included_range->end_byte > included_range->start_byte + ) { + if (included_range->start_byte >= self->current_position.bytes) { + self->current_position = (Length) { + .bytes = included_range->start_byte, + .extent = included_range->start_point, + }; + } + + self->current_included_range_index = i; + found_included_range = true; + break; + } + } + + if (found_included_range) { + // If the current position is outside of the current chunk of text, + // then clear out the current chunk of text. + if (self->chunk && ( + self->current_position.bytes < self->chunk_start || + self->current_position.bytes >= self->chunk_start + self->chunk_size + )) { + ts_lexer__clear_chunk(self); + } + + self->lookahead_size = 0; + self->data.lookahead = '\0'; + } + + // If the given position is beyond any of included ranges, move to the EOF + // state - past the end of the included ranges. + else { + self->current_included_range_index = self->included_range_count; + TSRange *last_included_range = &self->included_ranges[self->included_range_count - 1]; + self->current_position = (Length) { + .bytes = last_included_range->end_byte, + .extent = last_included_range->end_point, + }; + ts_lexer__clear_chunk(self); + self->lookahead_size = 1; + self->data.lookahead = '\0'; + } +} + +/** + * Actually advances the lexer. Does not log anything. + * @param self The lexer state. + * @param skip Whether to mark the consumed codepoint as whitespace. + */ +static void ts_lexer__do_advance(Lexer *self, bool skip) { + if (self->lookahead_size) { + if (self->data.lookahead == '\n') { + self->current_position.extent.row++; + self->current_position.extent.column = 0; + ts_lexer__set_column_data(self, 0); + } else { + bool is_bom = self->current_position.bytes == 0 && + self->data.lookahead == BYTE_ORDER_MARK; + if (!is_bom) ts_lexer__increment_column_data(self); + self->current_position.extent.column += self->lookahead_size; + } + self->current_position.bytes += self->lookahead_size; + } + + const TSRange *current_range = &self->included_ranges[self->current_included_range_index]; + while ( + self->current_position.bytes >= current_range->end_byte || + current_range->end_byte == current_range->start_byte + ) { + if (self->current_included_range_index < self->included_range_count) { + self->current_included_range_index++; + } + if (self->current_included_range_index < self->included_range_count) { + current_range++; + self->current_position = (Length) { + current_range->start_byte, + current_range->start_point, + }; + } else { + current_range = NULL; + break; + } + } + + if (skip) self->token_start_position = self->current_position; + + if (current_range) { + if ( + self->current_position.bytes < self->chunk_start || + self->current_position.bytes >= self->chunk_start + self->chunk_size + ) { + ts_lexer__get_chunk(self); + } + ts_lexer__get_lookahead(self); + } else { + ts_lexer__clear_chunk(self); + self->data.lookahead = '\0'; + self->lookahead_size = 1; + } +} + +// Advance to the next character in the source code, retrieving a new +// chunk of source code if needed. +static void ts_lexer__advance(TSLexer *_self, bool skip) { + Lexer *self = (Lexer *)_self; + if (!self->chunk) return; + + if (skip) { + LOG("skip", self->data.lookahead) + } else { + LOG("consume", self->data.lookahead) + } + + ts_lexer__do_advance(self, skip); +} + +// Mark that a token match has completed. This can be called multiple +// times if a longer match is found later. +static void ts_lexer__mark_end(TSLexer *_self) { + Lexer *self = (Lexer *)_self; + if (!ts_lexer__eof(&self->data)) { + // If the lexer is right at the beginning of included range, + // then the token should be considered to end at the *end* of the + // previous included range, rather than here. + TSRange *current_included_range = &self->included_ranges[ + self->current_included_range_index + ]; + if ( + self->current_included_range_index > 0 && + self->current_position.bytes == current_included_range->start_byte + ) { + TSRange *previous_included_range = current_included_range - 1; + self->token_end_position = (Length) { + previous_included_range->end_byte, + previous_included_range->end_point, + }; + return; + } + } + self->token_end_position = self->current_position; +} + +static uint32_t ts_lexer__get_column(TSLexer *_self) { + Lexer *self = (Lexer *)_self; + + self->did_get_column = true; + + if (!self->column_data.valid) { + // Record current position + uint32_t goal_byte = self->current_position.bytes; + + // Back up to the beginning of the line + Length start_of_col = { + self->current_position.bytes - self->current_position.extent.column, + {self->current_position.extent.row, 0}, + }; + ts_lexer_goto(self, start_of_col); + ts_lexer__set_column_data(self, 0); + ts_lexer__get_chunk(self); + + if (!ts_lexer__eof(_self)) { + ts_lexer__get_lookahead(self); + + // Advance to the recorded position + while (self->current_position.bytes < goal_byte && !ts_lexer__eof(_self) && self->chunk) { + ts_lexer__do_advance(self, false); + if (ts_lexer__eof(_self)) break; + } + } + } + + return self->column_data.value; +} + +// Is the lexer at a boundary between two disjoint included ranges of +// source code? This is exposed as an API because some languages' external +// scanners need to perform custom actions at these boundaries. +static bool ts_lexer__is_at_included_range_start(const TSLexer *_self) { + const Lexer *self = (const Lexer *)_self; + if (self->current_included_range_index < self->included_range_count) { + TSRange *current_range = &self->included_ranges[self->current_included_range_index]; + return self->current_position.bytes == current_range->start_byte; + } else { + return false; + } +} + +static void ts_lexer__log(const TSLexer *_self, const char *fmt, ...) { + Lexer *self = (Lexer *)_self; + va_list args; + va_start(args, fmt); + if (self->logger.log) { + vsnprintf(self->debug_buffer, TREE_SITTER_SERIALIZATION_BUFFER_SIZE, fmt, args); + self->logger.log(self->logger.payload, TSLogTypeLex, self->debug_buffer); + } + va_end(args); +} + +void ts_lexer_init(Lexer *self) { + *self = (Lexer) { + .data = { + // The lexer's methods are stored as struct fields so that generated + // parsers can call them without needing to be linked against this + // library. + .advance = ts_lexer__advance, + .mark_end = ts_lexer__mark_end, + .get_column = ts_lexer__get_column, + .is_at_included_range_start = ts_lexer__is_at_included_range_start, + .eof = ts_lexer__eof, + .log = ts_lexer__log, + .lookahead = 0, + .result_symbol = 0, + }, + .chunk = NULL, + .chunk_size = 0, + .chunk_start = 0, + .current_position = {0, {0, 0}}, + .logger = { + .payload = NULL, + .log = NULL + }, + .included_ranges = NULL, + .included_range_count = 0, + .current_included_range_index = 0, + .did_get_column = false, + .column_data = { + .valid = false, + .value = 0 + } + }; + ts_lexer_set_included_ranges(self, NULL, 0); +} + +void ts_lexer_delete(Lexer *self) { + ts_free(self->included_ranges); +} + +void ts_lexer_set_input(Lexer *self, TSInput input) { + self->input = input; + ts_lexer__clear_chunk(self); + ts_lexer_goto(self, self->current_position); +} + +// Move the lexer to the given position. This doesn't do any work +// if the parser is already at the given position. +void ts_lexer_reset(Lexer *self, Length position) { + if (position.bytes != self->current_position.bytes) { + ts_lexer_goto(self, position); + } +} + +void ts_lexer_start(Lexer *self) { + self->token_start_position = self->current_position; + self->token_end_position = LENGTH_UNDEFINED; + self->data.result_symbol = 0; + self->did_get_column = false; + if (!ts_lexer__eof(&self->data)) { + if (!self->chunk_size) ts_lexer__get_chunk(self); + if (!self->lookahead_size) ts_lexer__get_lookahead(self); + if (self->current_position.bytes == 0) { + if (self->data.lookahead == BYTE_ORDER_MARK) { + ts_lexer__advance(&self->data, true); + } + ts_lexer__set_column_data(self, 0); + } + } +} + +void ts_lexer_finish(Lexer *self, uint32_t *lookahead_end_byte) { + if (length_is_undefined(self->token_end_position)) { + ts_lexer__mark_end(&self->data); + } + + // If the token ended at an included range boundary, then its end position + // will have been reset to the end of the preceding range. Reset the start + // position to match. + if (self->token_end_position.bytes < self->token_start_position.bytes) { + self->token_start_position = self->token_end_position; + } + + uint32_t current_lookahead_end_byte = self->current_position.bytes + 1; + + // In order to determine that a byte sequence is invalid UTF8 or UTF16, + // the character decoding algorithm may have looked at the following byte. + // Therefore, the next byte *after* the current (invalid) character + // affects the interpretation of the current character. + if (self->data.lookahead == TS_DECODE_ERROR) { + current_lookahead_end_byte += 4; // the maximum number of bytes read to identify an invalid code point + } + + if (current_lookahead_end_byte > *lookahead_end_byte) { + *lookahead_end_byte = current_lookahead_end_byte; + } +} + +void ts_lexer_mark_end(Lexer *self) { + ts_lexer__mark_end(&self->data); +} + +bool ts_lexer_set_included_ranges( + Lexer *self, + const TSRange *ranges, + uint32_t count +) { + if (count == 0 || !ranges) { + ranges = &DEFAULT_RANGE; + count = 1; + } else { + uint32_t previous_byte = 0; + for (unsigned i = 0; i < count; i++) { + const TSRange *range = &ranges[i]; + if ( + range->start_byte < previous_byte || + range->end_byte < range->start_byte + ) return false; + previous_byte = range->end_byte; + } + } + + size_t size = count * sizeof(TSRange); + self->included_ranges = ts_realloc(self->included_ranges, size); + memcpy(self->included_ranges, ranges, size); + self->included_range_count = count; + ts_lexer_goto(self, self->current_position); + return true; +} + +TSRange *ts_lexer_included_ranges(const Lexer *self, uint32_t *count) { + *count = self->included_range_count; + return self->included_ranges; +} + +#undef LOG diff --git a/codegraph-kernel/vendor/tree-sitter/src/lexer.h b/codegraph-kernel/vendor/tree-sitter/src/lexer.h new file mode 100644 index 0000000000..7f451e3f93 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/lexer.h @@ -0,0 +1,54 @@ +#ifndef TREE_SITTER_LEXER_H_ +#define TREE_SITTER_LEXER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./length.h" +#include "./subtree.h" +#include "tree_sitter/api.h" +#include "./parser.h" + +typedef struct { + uint32_t value; + bool valid; +} ColumnData; + +typedef struct { + TSLexer data; + Length current_position; + Length token_start_position; + Length token_end_position; + + TSRange *included_ranges; + const char *chunk; + TSInput input; + TSLogger logger; + + uint32_t included_range_count; + uint32_t current_included_range_index; + uint32_t chunk_start; + uint32_t chunk_size; + uint32_t lookahead_size; + bool did_get_column; + ColumnData column_data; + + char debug_buffer[TREE_SITTER_SERIALIZATION_BUFFER_SIZE]; +} Lexer; + +void ts_lexer_init(Lexer *self); +void ts_lexer_delete(Lexer *self); +void ts_lexer_set_input(Lexer *self, TSInput input); +void ts_lexer_reset(Lexer *self, Length position); +void ts_lexer_start(Lexer *self); +void ts_lexer_finish(Lexer *self, uint32_t *lookahead_end_byte); +void ts_lexer_mark_end(Lexer *self); +bool ts_lexer_set_included_ranges(Lexer *self, const TSRange *ranges, uint32_t count); +TSRange *ts_lexer_included_ranges(const Lexer *self, uint32_t *count); + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_LEXER_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/lib.c b/codegraph-kernel/vendor/tree-sitter/src/lib.c new file mode 100644 index 0000000000..9bfb69f00b --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/lib.c @@ -0,0 +1,12 @@ +#include "./alloc.c" +#include "./get_changed_ranges.c" +#include "./language.c" +#include "./lexer.c" +#include "./node.c" +#include "./parser.c" +#include "./query.c" +#include "./stack.c" +#include "./subtree.c" +#include "./tree_cursor.c" +#include "./tree.c" +#include "./wasm_store.c" diff --git a/codegraph-kernel/vendor/tree-sitter/src/node.c b/codegraph-kernel/vendor/tree-sitter/src/node.c new file mode 100644 index 0000000000..d83fa90b8b --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/node.c @@ -0,0 +1,875 @@ +#include +#include "./point.h" +#include "./subtree.h" +#include "./tree.h" +#include "./language.h" + +typedef struct { + Subtree parent; + const TSTree *tree; + Length position; + uint32_t child_index; + uint32_t structural_child_index; + const TSSymbol *alias_sequence; +} NodeChildIterator; + +static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous); + +// TSNode - constructors + +TSNode ts_node_new( + const TSTree *tree, + const Subtree *subtree, + Length position, + TSSymbol alias +) { + return (TSNode) { + {position.bytes, position.extent.row, position.extent.column, alias}, + subtree, + tree, + }; +} + +static inline TSNode ts_node__null(void) { + return ts_node_new(NULL, NULL, length_zero(), 0); +} + +// TSNode - accessors + +uint32_t ts_node_start_byte(TSNode self) { + return self.context[0]; +} + +TSPoint ts_node_start_point(TSNode self) { + return (TSPoint) {self.context[1], self.context[2]}; +} + +static inline uint32_t ts_node__alias(const TSNode *self) { + return self->context[3]; +} + +static inline Subtree ts_node__subtree(TSNode self) { + return *(const Subtree *)self.id; +} + +// NodeChildIterator + +static inline NodeChildIterator ts_node_iterate_children(const TSNode *node) { + Subtree subtree = ts_node__subtree(*node); + if (ts_subtree_child_count(subtree) == 0) { + return (NodeChildIterator) {NULL_SUBTREE, node->tree, length_zero(), 0, 0, NULL}; + } + const TSSymbol *alias_sequence = ts_language_alias_sequence( + node->tree->language, + subtree.ptr->production_id + ); + return (NodeChildIterator) { + .tree = node->tree, + .parent = subtree, + .position = {ts_node_start_byte(*node), ts_node_start_point(*node)}, + .child_index = 0, + .structural_child_index = 0, + .alias_sequence = alias_sequence, + }; +} + +static inline bool ts_node_child_iterator_done(NodeChildIterator *self) { + return self->child_index == self->parent.ptr->child_count; +} + +static inline bool ts_node_child_iterator_next( + NodeChildIterator *self, + TSNode *result +) { + if (!self->parent.ptr || ts_node_child_iterator_done(self)) return false; + const Subtree *child = &ts_subtree_children(self->parent)[self->child_index]; + TSSymbol alias_symbol = 0; + if (!ts_subtree_extra(*child)) { + if (self->alias_sequence) { + alias_symbol = self->alias_sequence[self->structural_child_index]; + } + self->structural_child_index++; + } + if (self->child_index > 0) { + self->position = length_add(self->position, ts_subtree_padding(*child)); + } + *result = ts_node_new( + self->tree, + child, + self->position, + alias_symbol + ); + self->position = length_add(self->position, ts_subtree_size(*child)); + self->child_index++; + return true; +} + +// TSNode - private + +static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) { + Subtree tree = ts_node__subtree(self); + if (include_anonymous) { + return ts_subtree_visible(tree) || ts_node__alias(&self); + } else { + TSSymbol alias = ts_node__alias(&self); + if (alias) { + return ts_language_symbol_metadata(self.tree->language, alias).named; + } else { + return ts_subtree_visible(tree) && ts_subtree_named(tree); + } + } +} + +static inline uint32_t ts_node__relevant_child_count( + TSNode self, + bool include_anonymous +) { + Subtree tree = ts_node__subtree(self); + if (ts_subtree_child_count(tree) > 0) { + if (include_anonymous) { + return tree.ptr->visible_child_count; + } else { + return tree.ptr->named_child_count; + } + } else { + return 0; + } +} + +static inline TSNode ts_node__child( + TSNode self, + uint32_t child_index, + bool include_anonymous +) { + TSNode result = self; + bool did_descend = true; + + while (did_descend) { + did_descend = false; + + TSNode child; + uint32_t index = 0; + NodeChildIterator iterator = ts_node_iterate_children(&result); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (ts_node__is_relevant(child, include_anonymous)) { + if (index == child_index) { + return child; + } + index++; + } else { + uint32_t grandchild_index = child_index - index; + uint32_t grandchild_count = ts_node__relevant_child_count(child, include_anonymous); + if (grandchild_index < grandchild_count) { + did_descend = true; + result = child; + child_index = grandchild_index; + break; + } + index += grandchild_count; + } + } + } + + return ts_node__null(); +} + +static bool ts_subtree_has_trailing_empty_descendant( + Subtree self, + Subtree other +) { + for (unsigned i = ts_subtree_child_count(self) - 1; i + 1 > 0; i--) { + Subtree child = ts_subtree_children(self)[i]; + if (ts_subtree_total_bytes(child) > 0) break; + if (child.ptr == other.ptr || ts_subtree_has_trailing_empty_descendant(child, other)) { + return true; + } + } + return false; +} + +static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous) { + Subtree self_subtree = ts_node__subtree(self); + bool self_is_empty = ts_subtree_total_bytes(self_subtree) == 0; + uint32_t target_end_byte = ts_node_end_byte(self); + + TSNode node = ts_node_parent(self); + TSNode earlier_node = ts_node__null(); + bool earlier_node_is_relevant = false; + + while (!ts_node_is_null(node)) { + TSNode earlier_child = ts_node__null(); + bool earlier_child_is_relevant = false; + bool found_child_containing_target = false; + + TSNode child; + NodeChildIterator iterator = ts_node_iterate_children(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (child.id == self.id) break; + if (iterator.position.bytes > target_end_byte) { + found_child_containing_target = true; + break; + } + + if (iterator.position.bytes == target_end_byte && + (!self_is_empty || + ts_subtree_has_trailing_empty_descendant(ts_node__subtree(child), self_subtree))) { + found_child_containing_target = true; + break; + } + + if (ts_node__is_relevant(child, include_anonymous)) { + earlier_child = child; + earlier_child_is_relevant = true; + } else if (ts_node__relevant_child_count(child, include_anonymous) > 0) { + earlier_child = child; + earlier_child_is_relevant = false; + } + } + + if (found_child_containing_target) { + if (!ts_node_is_null(earlier_child)) { + earlier_node = earlier_child; + earlier_node_is_relevant = earlier_child_is_relevant; + } + node = child; + } else if (earlier_child_is_relevant) { + return earlier_child; + } else if (!ts_node_is_null(earlier_child)) { + node = earlier_child; + } else if (earlier_node_is_relevant) { + return earlier_node; + } else { + node = earlier_node; + earlier_node = ts_node__null(); + earlier_node_is_relevant = false; + } + } + + return ts_node__null(); +} + +static inline TSNode ts_node__next_sibling(TSNode self, bool include_anonymous) { + uint32_t target_end_byte = ts_node_end_byte(self); + + TSNode node = ts_node_parent(self); + TSNode later_node = ts_node__null(); + bool later_node_is_relevant = false; + + while (!ts_node_is_null(node)) { + TSNode later_child = ts_node__null(); + bool later_child_is_relevant = false; + TSNode child_containing_target = ts_node__null(); + + TSNode child; + NodeChildIterator iterator = ts_node_iterate_children(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (iterator.position.bytes <= target_end_byte) continue; + uint32_t start_byte = ts_node_start_byte(self); + uint32_t child_start_byte = ts_node_start_byte(child); + + bool is_empty = start_byte == target_end_byte; + bool contains_target = is_empty ? + child_start_byte < start_byte : + child_start_byte <= start_byte; + + if (contains_target) { + if (ts_node__subtree(child).ptr != ts_node__subtree(self).ptr) { + child_containing_target = child; + } + } else if (ts_node__is_relevant(child, include_anonymous)) { + later_child = child; + later_child_is_relevant = true; + break; + } else if (ts_node__relevant_child_count(child, include_anonymous) > 0) { + later_child = child; + later_child_is_relevant = false; + break; + } + } + + if (!ts_node_is_null(child_containing_target)) { + if (!ts_node_is_null(later_child)) { + later_node = later_child; + later_node_is_relevant = later_child_is_relevant; + } + node = child_containing_target; + } else if (later_child_is_relevant) { + return later_child; + } else if (!ts_node_is_null(later_child)) { + node = later_child; + } else if (later_node_is_relevant) { + return later_node; + } else { + node = later_node; + } + } + + return ts_node__null(); +} + +static inline TSNode ts_node__first_child_for_byte( + TSNode self, + uint32_t goal, + bool include_anonymous +) { + TSNode node = self; + bool did_descend = true; + + NodeChildIterator last_iterator; + bool has_last_iterator = false; + + while (did_descend) { + did_descend = false; + + TSNode child; + NodeChildIterator iterator = ts_node_iterate_children(&node); + loop: + while (ts_node_child_iterator_next(&iterator, &child)) { + if (ts_node_end_byte(child) > goal) { + if (ts_node__is_relevant(child, include_anonymous)) { + return child; + } else if (ts_node_child_count(child) > 0) { + if (iterator.child_index < ts_subtree_child_count(ts_node__subtree(child))) { + last_iterator = iterator; + has_last_iterator = true; + } + did_descend = true; + node = child; + break; + } + } + } + + if (!did_descend && has_last_iterator) { + iterator = last_iterator; + has_last_iterator = false; + goto loop; + } + } + + return ts_node__null(); +} + +static inline TSNode ts_node__descendant_for_byte_range( + TSNode self, + uint32_t range_start, + uint32_t range_end, + bool include_anonymous +) { + if (range_start > range_end) { + return ts_node__null(); + } + TSNode node = self; + TSNode last_visible_node = self; + + bool did_descend = true; + while (did_descend) { + did_descend = false; + + TSNode child; + NodeChildIterator iterator = ts_node_iterate_children(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + uint32_t node_end = iterator.position.bytes; + + // The end of this node must extend far enough forward to touch + // the end of the range + if (node_end < range_end) continue; + + // ...and exceed the start of the range, unless the node itself is + // empty, in which case it must at least be equal to the start of the range. + bool is_empty = ts_node_start_byte(child) == node_end; + if (is_empty ? node_end < range_start : node_end <= range_start) continue; + + // The start of this node must extend far enough backward to + // touch the start of the range. + if (range_start < ts_node_start_byte(child)) break; + + node = child; + if (ts_node__is_relevant(node, include_anonymous)) { + last_visible_node = node; + } + did_descend = true; + break; + } + } + + return last_visible_node; +} + +static inline TSNode ts_node__descendant_for_point_range( + TSNode self, + TSPoint range_start, + TSPoint range_end, + bool include_anonymous +) { + if (point_gt(range_start, range_end)) { + return ts_node__null(); + } + TSNode node = self; + TSNode last_visible_node = self; + + bool did_descend = true; + while (did_descend) { + did_descend = false; + + TSNode child; + NodeChildIterator iterator = ts_node_iterate_children(&node); + while (ts_node_child_iterator_next(&iterator, &child)) { + TSPoint node_end = iterator.position.extent; + + // The end of this node must extend far enough forward to touch + // the end of the range + if (point_lt(node_end, range_end)) continue; + + // ...and exceed the start of the range, unless the node itself is + // empty, in which case it must at least be equal to the start of the range. + bool is_empty = point_eq(ts_node_start_point(child), node_end); + if (is_empty ? point_lt(node_end, range_start) : point_lte(node_end, range_start)) { + continue; + } + + // The start of this node must extend far enough backward to + // touch the start of the range. + if (point_lt(range_start, ts_node_start_point(child))) break; + + node = child; + if (ts_node__is_relevant(node, include_anonymous)) { + last_visible_node = node; + } + did_descend = true; + break; + } + } + + return last_visible_node; +} + +// TSNode - public + +uint32_t ts_node_end_byte(TSNode self) { + return ts_node_start_byte(self) + ts_subtree_size(ts_node__subtree(self)).bytes; +} + +TSPoint ts_node_end_point(TSNode self) { + return point_add(ts_node_start_point(self), ts_subtree_size(ts_node__subtree(self)).extent); +} + +TSSymbol ts_node_symbol(TSNode self) { + TSSymbol symbol = ts_node__alias(&self); + if (!symbol) symbol = ts_subtree_symbol(ts_node__subtree(self)); + return ts_language_public_symbol(self.tree->language, symbol); +} + +const char *ts_node_type(TSNode self) { + TSSymbol symbol = ts_node__alias(&self); + if (!symbol) symbol = ts_subtree_symbol(ts_node__subtree(self)); + return ts_language_symbol_name(self.tree->language, symbol); +} + +const TSLanguage *ts_node_language(TSNode self) { + return self.tree->language; +} + +TSSymbol ts_node_grammar_symbol(TSNode self) { + return ts_subtree_symbol(ts_node__subtree(self)); +} + +const char *ts_node_grammar_type(TSNode self) { + TSSymbol symbol = ts_subtree_symbol(ts_node__subtree(self)); + return ts_language_symbol_name(self.tree->language, symbol); +} + +char *ts_node_string(TSNode self) { + TSSymbol alias_symbol = ts_node__alias(&self); + return ts_subtree_string( + ts_node__subtree(self), + alias_symbol, + ts_language_symbol_metadata(self.tree->language, alias_symbol).visible, + self.tree->language, + false + ); +} + +bool ts_node_eq(TSNode self, TSNode other) { + return self.tree == other.tree && self.id == other.id; +} + +bool ts_node_is_null(TSNode self) { + return self.id == 0; +} + +bool ts_node_is_extra(TSNode self) { + return ts_subtree_extra(ts_node__subtree(self)); +} + +bool ts_node_is_named(TSNode self) { + TSSymbol alias = ts_node__alias(&self); + return alias + ? ts_language_symbol_metadata(self.tree->language, alias).named + : ts_subtree_named(ts_node__subtree(self)); +} + +bool ts_node_is_missing(TSNode self) { + return ts_subtree_missing(ts_node__subtree(self)); +} + +bool ts_node_has_changes(TSNode self) { + return ts_subtree_has_changes(ts_node__subtree(self)); +} + +bool ts_node_has_error(TSNode self) { + return ts_subtree_error_cost(ts_node__subtree(self)) > 0; +} + +bool ts_node_is_error(TSNode self) { + TSSymbol symbol = ts_node_symbol(self); + return symbol == ts_builtin_sym_error; +} + +uint32_t ts_node_descendant_count(TSNode self) { + return ts_subtree_visible_descendant_count(ts_node__subtree(self)) + 1; +} + +TSStateId ts_node_parse_state(TSNode self) { + return ts_subtree_parse_state(ts_node__subtree(self)); +} + +TSStateId ts_node_next_parse_state(TSNode self) { + const TSLanguage *language = self.tree->language; + uint16_t state = ts_node_parse_state(self); + if (state == TS_TREE_STATE_NONE) { + return TS_TREE_STATE_NONE; + } + uint16_t symbol = ts_node_grammar_symbol(self); + return ts_language_next_state(language, state, symbol); +} + +TSNode ts_node_parent(TSNode self) { + TSNode node = ts_tree_root_node(self.tree); + if (node.id == self.id) return ts_node__null(); + + while (true) { + TSNode next_node = ts_node_child_with_descendant(node, self); + if (next_node.id == self.id || ts_node_is_null(next_node)) break; + node = next_node; + } + + return node; +} + +TSNode ts_node_child_with_descendant(TSNode self, TSNode descendant) { + uint32_t start_byte = ts_node_start_byte(descendant); + uint32_t end_byte = ts_node_end_byte(descendant); + bool is_empty = start_byte == end_byte; + + do { + NodeChildIterator iter = ts_node_iterate_children(&self); + do { + if ( + !ts_node_child_iterator_next(&iter, &self) + || ts_node_start_byte(self) > start_byte + ) { + return ts_node__null(); + } + if (self.id == descendant.id) { + return self; + } + + // If the descendant is empty, and the end byte is within `self`, + // we check whether `self` contains it or not. + if (is_empty && iter.position.bytes >= end_byte && ts_node_child_count(self) > 0) { + TSNode child = ts_node_child_with_descendant(self, descendant); + // If the child is not null, return self if it's relevant, else return the child + if (!ts_node_is_null(child)) { + return ts_node__is_relevant(self, true) ? self : child; + } + } + } while ((is_empty ? iter.position.bytes <= end_byte : iter.position.bytes < end_byte) || ts_node_child_count(self) == 0); + } while (!ts_node__is_relevant(self, true)); + + return self; +} + +TSNode ts_node_child(TSNode self, uint32_t child_index) { + return ts_node__child(self, child_index, true); +} + +TSNode ts_node_named_child(TSNode self, uint32_t child_index) { + return ts_node__child(self, child_index, false); +} + +TSNode ts_node_child_by_field_id(TSNode self, TSFieldId field_id) { +recur: + if (!field_id || ts_node_child_count(self) == 0) return ts_node__null(); + + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map( + self.tree->language, + ts_node__subtree(self).ptr->production_id, + &field_map, + &field_map_end + ); + if (field_map == field_map_end) return ts_node__null(); + + // The field mappings are sorted by their field id. Scan all + // the mappings to find the ones for the given field id. + while (field_map->field_id < field_id) { + field_map++; + if (field_map == field_map_end) return ts_node__null(); + } + while (field_map_end[-1].field_id > field_id) { + field_map_end--; + if (field_map == field_map_end) return ts_node__null(); + } + + TSNode child; + NodeChildIterator iterator = ts_node_iterate_children(&self); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (!ts_subtree_extra(ts_node__subtree(child))) { + uint32_t index = iterator.structural_child_index - 1; + if (index < field_map->child_index) continue; + + // Hidden nodes' fields are "inherited" by their visible parent. + if (field_map->inherited) { + + // If this is the *last* possible child node for this field, + // then perform a tail call to avoid recursion. + if (field_map + 1 == field_map_end) { + self = child; + goto recur; + } + + // Otherwise, descend into this child, but if it doesn't contain + // the field, continue searching subsequent children. + else { + TSNode result = ts_node_child_by_field_id(child, field_id); + if (result.id) return result; + field_map++; + if (field_map == field_map_end) return ts_node__null(); + } + } + + else if (ts_node__is_relevant(child, true)) { + return child; + } + + // If the field refers to a hidden node with visible children, + // return the first visible child. + else if (ts_node_child_count(child) > 0 ) { + return ts_node_child(child, 0); + } + + // Otherwise, continue searching subsequent children. + else { + field_map++; + if (field_map == field_map_end) return ts_node__null(); + } + } + } + + return ts_node__null(); +} + +static inline const char *ts_node__field_name_from_language(TSNode self, uint32_t structural_child_index) { + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map( + self.tree->language, + ts_node__subtree(self).ptr->production_id, + &field_map, + &field_map_end + ); + for (; field_map != field_map_end; field_map++) { + if (!field_map->inherited && field_map->child_index == structural_child_index) { + return self.tree->language->field_names[field_map->field_id]; + } + } + return NULL; +} + +const char *ts_node_field_name_for_child(TSNode self, uint32_t child_index) { + TSNode result = self; + bool did_descend = true; + const char *inherited_field_name = NULL; + + while (did_descend) { + did_descend = false; + + TSNode child; + uint32_t index = 0; + NodeChildIterator iterator = ts_node_iterate_children(&result); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (ts_node__is_relevant(child, true)) { + if (index == child_index) { + if (ts_node_is_extra(child)) { + return NULL; + } + const char *field_name = ts_node__field_name_from_language(result, iterator.structural_child_index - 1); + if (field_name) return field_name; + return inherited_field_name; + } + index++; + } else { + uint32_t grandchild_index = child_index - index; + uint32_t grandchild_count = ts_node__relevant_child_count(child, true); + if (grandchild_index < grandchild_count) { + const char *field_name = ts_node__field_name_from_language(result, iterator.structural_child_index - 1); + if (field_name) inherited_field_name = field_name; + + did_descend = true; + result = child; + child_index = grandchild_index; + break; + } + index += grandchild_count; + } + } + } + + return NULL; +} + +const char *ts_node_field_name_for_named_child(TSNode self, uint32_t named_child_index) { + TSNode result = self; + bool did_descend = true; + const char *inherited_field_name = NULL; + + while (did_descend) { + did_descend = false; + + TSNode child; + uint32_t index = 0; + NodeChildIterator iterator = ts_node_iterate_children(&result); + while (ts_node_child_iterator_next(&iterator, &child)) { + if (ts_node__is_relevant(child, false)) { + if (index == named_child_index) { + if (ts_node_is_extra(child)) { + return NULL; + } + const char *field_name = ts_node__field_name_from_language(result, iterator.structural_child_index - 1); + if (field_name) return field_name; + return inherited_field_name; + } + index++; + } else { + uint32_t named_grandchild_index = named_child_index - index; + uint32_t grandchild_count = ts_node__relevant_child_count(child, false); + if (named_grandchild_index < grandchild_count) { + const char *field_name = ts_node__field_name_from_language(result, iterator.structural_child_index - 1); + if (field_name) inherited_field_name = field_name; + + did_descend = true; + result = child; + named_child_index = named_grandchild_index; + break; + } + index += grandchild_count; + } + } + } + + return NULL; +} + +TSNode ts_node_child_by_field_name( + TSNode self, + const char *name, + uint32_t name_length +) { + TSFieldId field_id = ts_language_field_id_for_name( + self.tree->language, + name, + name_length + ); + return ts_node_child_by_field_id(self, field_id); +} + +uint32_t ts_node_child_count(TSNode self) { + Subtree tree = ts_node__subtree(self); + if (ts_subtree_child_count(tree) > 0) { + return tree.ptr->visible_child_count; + } else { + return 0; + } +} + +uint32_t ts_node_named_child_count(TSNode self) { + Subtree tree = ts_node__subtree(self); + if (ts_subtree_child_count(tree) > 0) { + return tree.ptr->named_child_count; + } else { + return 0; + } +} + +TSNode ts_node_next_sibling(TSNode self) { + return ts_node__next_sibling(self, true); +} + +TSNode ts_node_next_named_sibling(TSNode self) { + return ts_node__next_sibling(self, false); +} + +TSNode ts_node_prev_sibling(TSNode self) { + return ts_node__prev_sibling(self, true); +} + +TSNode ts_node_prev_named_sibling(TSNode self) { + return ts_node__prev_sibling(self, false); +} + +TSNode ts_node_first_child_for_byte(TSNode self, uint32_t byte) { + return ts_node__first_child_for_byte(self, byte, true); +} + +TSNode ts_node_first_named_child_for_byte(TSNode self, uint32_t byte) { + return ts_node__first_child_for_byte(self, byte, false); +} + +TSNode ts_node_descendant_for_byte_range( + TSNode self, + uint32_t start, + uint32_t end +) { + return ts_node__descendant_for_byte_range(self, start, end, true); +} + +TSNode ts_node_named_descendant_for_byte_range( + TSNode self, + uint32_t start, + uint32_t end +) { + return ts_node__descendant_for_byte_range(self, start, end, false); +} + +TSNode ts_node_descendant_for_point_range( + TSNode self, + TSPoint start, + TSPoint end +) { + return ts_node__descendant_for_point_range(self, start, end, true); +} + +TSNode ts_node_named_descendant_for_point_range( + TSNode self, + TSPoint start, + TSPoint end +) { + return ts_node__descendant_for_point_range(self, start, end, false); +} + +void ts_node_edit(TSNode *self, const TSInputEdit *edit) { + uint32_t start_byte = ts_node_start_byte(*self); + TSPoint start_point = ts_node_start_point(*self); + + if (start_byte >= edit->old_end_byte) { + start_byte = edit->new_end_byte + (start_byte - edit->old_end_byte); + start_point = point_add(edit->new_end_point, point_sub(start_point, edit->old_end_point)); + } else if (start_byte > edit->start_byte) { + start_byte = edit->new_end_byte; + start_point = edit->new_end_point; + } + + self->context[0] = start_byte; + self->context[1] = start_point.row; + self->context[2] = start_point.column; +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/parser.c b/codegraph-kernel/vendor/tree-sitter/src/parser.c new file mode 100644 index 0000000000..29b33b77d5 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/parser.c @@ -0,0 +1,2300 @@ +#include +#include +#include +#include +#include +#include "tree_sitter/api.h" +#include "./alloc.h" +#include "./array.h" +#include "./atomic.h" +#include "./clock.h" +#include "./error_costs.h" +#include "./get_changed_ranges.h" +#include "./language.h" +#include "./length.h" +#include "./lexer.h" +#include "./reduce_action.h" +#include "./reusable_node.h" +#include "./stack.h" +#include "./subtree.h" +#include "./tree.h" +#include "./ts_assert.h" +#include "./wasm_store.h" + +#define LOG(...) \ + if (self->lexer.logger.log || self->dot_graph_file) { \ + snprintf(self->lexer.debug_buffer, TREE_SITTER_SERIALIZATION_BUFFER_SIZE, __VA_ARGS__); \ + ts_parser__log(self); \ + } + +#define LOG_LOOKAHEAD(symbol_name, size) \ + if (self->lexer.logger.log || self->dot_graph_file) { \ + char *buf = self->lexer.debug_buffer; \ + const char *symbol = symbol_name; \ + int off = snprintf( \ + buf, \ + TREE_SITTER_SERIALIZATION_BUFFER_SIZE, \ + "lexed_lookahead sym:" \ + ); \ + for ( \ + int i = 0; \ + symbol[i] != '\0' \ + && off < TREE_SITTER_SERIALIZATION_BUFFER_SIZE; \ + i++ \ + ) { \ + switch (symbol[i]) { \ + case '\t': buf[off++] = '\\'; buf[off++] = 't'; break; \ + case '\n': buf[off++] = '\\'; buf[off++] = 'n'; break; \ + case '\v': buf[off++] = '\\'; buf[off++] = 'v'; break; \ + case '\f': buf[off++] = '\\'; buf[off++] = 'f'; break; \ + case '\r': buf[off++] = '\\'; buf[off++] = 'r'; break; \ + case '\\': buf[off++] = '\\'; buf[off++] = '\\'; break; \ + default: buf[off++] = symbol[i]; break; \ + } \ + } \ + snprintf( \ + buf + off, \ + TREE_SITTER_SERIALIZATION_BUFFER_SIZE - off, \ + ", size:%u", \ + size \ + ); \ + ts_parser__log(self); \ + } + +#define LOG_STACK() \ + if (self->dot_graph_file) { \ + ts_stack_print_dot_graph(self->stack, self->language, self->dot_graph_file); \ + fputs("\n\n", self->dot_graph_file); \ + } + +#define LOG_TREE(tree) \ + if (self->dot_graph_file) { \ + ts_subtree_print_dot_graph(tree, self->language, self->dot_graph_file); \ + fputs("\n", self->dot_graph_file); \ + } + +#define SYM_NAME(symbol) ts_language_symbol_name(self->language, symbol) + +#define TREE_NAME(tree) SYM_NAME(ts_subtree_symbol(tree)) + +static const unsigned MAX_VERSION_COUNT = 6; +static const unsigned MAX_VERSION_COUNT_OVERFLOW = 4; +static const unsigned MAX_SUMMARY_DEPTH = 16; +static const unsigned MAX_COST_DIFFERENCE = 18 * ERROR_COST_PER_SKIPPED_TREE; +static const unsigned OP_COUNT_PER_PARSER_TIMEOUT_CHECK = 100; + +typedef struct { + Subtree token; + Subtree last_external_token; + uint32_t byte_index; +} TokenCache; + +struct TSParser { + Lexer lexer; + Stack *stack; + SubtreePool tree_pool; + const TSLanguage *language; + TSWasmStore *wasm_store; + ReduceActionSet reduce_actions; + Subtree finished_tree; + SubtreeArray trailing_extras; + SubtreeArray trailing_extras2; + SubtreeArray scratch_trees; + TokenCache token_cache; + ReusableNode reusable_node; + void *external_scanner_payload; + FILE *dot_graph_file; + TSClock end_clock; + TSDuration timeout_duration; + unsigned accept_count; + unsigned operation_count; + const volatile size_t *cancellation_flag; + Subtree old_tree; + TSRangeArray included_range_differences; + TSParseOptions parse_options; + TSParseState parse_state; + unsigned included_range_difference_index; + bool has_scanner_error; + bool canceled_balancing; + bool has_error; +}; + +typedef struct { + unsigned cost; + unsigned node_count; + int dynamic_precedence; + bool is_in_error; +} ErrorStatus; + +typedef enum { + ErrorComparisonTakeLeft, + ErrorComparisonPreferLeft, + ErrorComparisonNone, + ErrorComparisonPreferRight, + ErrorComparisonTakeRight, +} ErrorComparison; + +typedef struct { + const char *string; + uint32_t length; +} TSStringInput; + +// StringInput + +static const char *ts_string_input_read( + void *_self, + uint32_t byte, + TSPoint point, + uint32_t *length +) { + (void)point; + TSStringInput *self = (TSStringInput *)_self; + if (byte >= self->length) { + *length = 0; + return ""; + } else { + *length = self->length - byte; + return self->string + byte; + } +} + +// Parser - Private + +static void ts_parser__log(TSParser *self) { + if (self->lexer.logger.log) { + self->lexer.logger.log( + self->lexer.logger.payload, + TSLogTypeParse, + self->lexer.debug_buffer + ); + } + + if (self->dot_graph_file) { + fprintf(self->dot_graph_file, "graph {\nlabel=\""); + for (char *chr = &self->lexer.debug_buffer[0]; *chr != 0; chr++) { + if (*chr == '"' || *chr == '\\') fputc('\\', self->dot_graph_file); + fputc(*chr, self->dot_graph_file); + } + fprintf(self->dot_graph_file, "\"\n}\n\n"); + } +} + +static bool ts_parser__breakdown_top_of_stack( + TSParser *self, + StackVersion version +) { + bool did_break_down = false; + bool pending = false; + + do { + StackSliceArray pop = ts_stack_pop_pending(self->stack, version); + if (!pop.size) break; + + did_break_down = true; + pending = false; + for (uint32_t i = 0; i < pop.size; i++) { + StackSlice slice = *array_get(&pop, i); + TSStateId state = ts_stack_state(self->stack, slice.version); + Subtree parent = *array_front(&slice.subtrees); + + for (uint32_t j = 0, n = ts_subtree_child_count(parent); j < n; j++) { + Subtree child = ts_subtree_children(parent)[j]; + pending = ts_subtree_child_count(child) > 0; + + if (ts_subtree_is_error(child)) { + state = ERROR_STATE; + } else if (!ts_subtree_extra(child)) { + state = ts_language_next_state(self->language, state, ts_subtree_symbol(child)); + } + + ts_subtree_retain(child); + ts_stack_push(self->stack, slice.version, child, pending, state); + } + + for (uint32_t j = 1; j < slice.subtrees.size; j++) { + Subtree tree = *array_get(&slice.subtrees, j); + ts_stack_push(self->stack, slice.version, tree, false, state); + } + + ts_subtree_release(&self->tree_pool, parent); + array_delete(&slice.subtrees); + + LOG("breakdown_top_of_stack tree:%s", TREE_NAME(parent)); + LOG_STACK(); + } + } while (pending); + + return did_break_down; +} + +static void ts_parser__breakdown_lookahead( + TSParser *self, + Subtree *lookahead, + TSStateId state, + ReusableNode *reusable_node +) { + bool did_descend = false; + Subtree tree = reusable_node_tree(reusable_node); + while (ts_subtree_child_count(tree) > 0 && ts_subtree_parse_state(tree) != state) { + LOG("state_mismatch sym:%s", TREE_NAME(tree)); + reusable_node_descend(reusable_node); + tree = reusable_node_tree(reusable_node); + did_descend = true; + } + + if (did_descend) { + ts_subtree_release(&self->tree_pool, *lookahead); + *lookahead = tree; + ts_subtree_retain(*lookahead); + } +} + +static ErrorComparison ts_parser__compare_versions( + TSParser *self, + ErrorStatus a, + ErrorStatus b +) { + (void)self; + if (!a.is_in_error && b.is_in_error) { + if (a.cost < b.cost) { + return ErrorComparisonTakeLeft; + } else { + return ErrorComparisonPreferLeft; + } + } + + if (a.is_in_error && !b.is_in_error) { + if (b.cost < a.cost) { + return ErrorComparisonTakeRight; + } else { + return ErrorComparisonPreferRight; + } + } + + if (a.cost < b.cost) { + if ((b.cost - a.cost) * (1 + a.node_count) > MAX_COST_DIFFERENCE) { + return ErrorComparisonTakeLeft; + } else { + return ErrorComparisonPreferLeft; + } + } + + if (b.cost < a.cost) { + if ((a.cost - b.cost) * (1 + b.node_count) > MAX_COST_DIFFERENCE) { + return ErrorComparisonTakeRight; + } else { + return ErrorComparisonPreferRight; + } + } + + if (a.dynamic_precedence > b.dynamic_precedence) return ErrorComparisonPreferLeft; + if (b.dynamic_precedence > a.dynamic_precedence) return ErrorComparisonPreferRight; + return ErrorComparisonNone; +} + +static ErrorStatus ts_parser__version_status( + TSParser *self, + StackVersion version +) { + unsigned cost = ts_stack_error_cost(self->stack, version); + bool is_paused = ts_stack_is_paused(self->stack, version); + if (is_paused) cost += ERROR_COST_PER_SKIPPED_TREE; + return (ErrorStatus) { + .cost = cost, + .node_count = ts_stack_node_count_since_error(self->stack, version), + .dynamic_precedence = ts_stack_dynamic_precedence(self->stack, version), + .is_in_error = is_paused || ts_stack_state(self->stack, version) == ERROR_STATE + }; +} + +static bool ts_parser__better_version_exists( + TSParser *self, + StackVersion version, + bool is_in_error, + unsigned cost +) { + if (self->finished_tree.ptr && ts_subtree_error_cost(self->finished_tree) <= cost) { + return true; + } + + Length position = ts_stack_position(self->stack, version); + ErrorStatus status = { + .cost = cost, + .is_in_error = is_in_error, + .dynamic_precedence = ts_stack_dynamic_precedence(self->stack, version), + .node_count = ts_stack_node_count_since_error(self->stack, version), + }; + + for (StackVersion i = 0, n = ts_stack_version_count(self->stack); i < n; i++) { + if (i == version || + !ts_stack_is_active(self->stack, i) || + ts_stack_position(self->stack, i).bytes < position.bytes) continue; + ErrorStatus status_i = ts_parser__version_status(self, i); + switch (ts_parser__compare_versions(self, status, status_i)) { + case ErrorComparisonTakeRight: + return true; + case ErrorComparisonPreferRight: + if (ts_stack_can_merge(self->stack, i, version)) return true; + break; + default: + break; + } + } + + return false; +} + +static bool ts_parser__call_main_lex_fn(TSParser *self, TSLexerMode lex_mode) { + if (ts_language_is_wasm(self->language)) { + return ts_wasm_store_call_lex_main(self->wasm_store, lex_mode.lex_state); + } else { + return self->language->lex_fn(&self->lexer.data, lex_mode.lex_state); + } +} + +static bool ts_parser__call_keyword_lex_fn(TSParser *self) { + if (ts_language_is_wasm(self->language)) { + return ts_wasm_store_call_lex_keyword(self->wasm_store, 0); + } else { + return self->language->keyword_lex_fn(&self->lexer.data, 0); + } +} + +static void ts_parser__external_scanner_create( + TSParser *self +) { + if (self->language && self->language->external_scanner.states) { + if (ts_language_is_wasm(self->language)) { + self->external_scanner_payload = (void *)(uintptr_t)ts_wasm_store_call_scanner_create( + self->wasm_store + ); + if (ts_wasm_store_has_error(self->wasm_store)) { + self->has_scanner_error = true; + } + } else if (self->language->external_scanner.create) { + self->external_scanner_payload = self->language->external_scanner.create(); + } + } +} + +static void ts_parser__external_scanner_destroy( + TSParser *self +) { + if ( + self->language && + self->external_scanner_payload && + self->language->external_scanner.destroy && + !ts_language_is_wasm(self->language) + ) { + self->language->external_scanner.destroy( + self->external_scanner_payload + ); + } + self->external_scanner_payload = NULL; +} + +static unsigned ts_parser__external_scanner_serialize( + TSParser *self +) { + uint32_t length; + if (ts_language_is_wasm(self->language)) { + length = ts_wasm_store_call_scanner_serialize( + self->wasm_store, + (uintptr_t)self->external_scanner_payload, + self->lexer.debug_buffer + ); + if (ts_wasm_store_has_error(self->wasm_store)) { + self->has_scanner_error = true; + } + } else { + length = self->language->external_scanner.serialize( + self->external_scanner_payload, + self->lexer.debug_buffer + ); + } + ts_assert(length <= TREE_SITTER_SERIALIZATION_BUFFER_SIZE); + return length; +} + +static void ts_parser__external_scanner_deserialize( + TSParser *self, + Subtree external_token +) { + const char *data = NULL; + uint32_t length = 0; + if (external_token.ptr) { + data = ts_external_scanner_state_data(&external_token.ptr->external_scanner_state); + length = external_token.ptr->external_scanner_state.length; + } + + if (ts_language_is_wasm(self->language)) { + ts_wasm_store_call_scanner_deserialize( + self->wasm_store, + (uintptr_t)self->external_scanner_payload, + data, + length + ); + if (ts_wasm_store_has_error(self->wasm_store)) { + self->has_scanner_error = true; + } + } else { + self->language->external_scanner.deserialize( + self->external_scanner_payload, + data, + length + ); + } +} + +static bool ts_parser__external_scanner_scan( + TSParser *self, + TSStateId external_lex_state +) { + if (ts_language_is_wasm(self->language)) { + bool result = ts_wasm_store_call_scanner_scan( + self->wasm_store, + (uintptr_t)self->external_scanner_payload, + external_lex_state * self->language->external_token_count + ); + if (ts_wasm_store_has_error(self->wasm_store)) { + self->has_scanner_error = true; + } + return result; + } else { + const bool *valid_external_tokens = ts_language_enabled_external_tokens( + self->language, + external_lex_state + ); + return self->language->external_scanner.scan( + self->external_scanner_payload, + &self->lexer.data, + valid_external_tokens + ); + } +} + +static bool ts_parser__can_reuse_first_leaf( + TSParser *self, + TSStateId state, + Subtree tree, + TableEntry *table_entry +) { + TSSymbol leaf_symbol = ts_subtree_leaf_symbol(tree); + TSStateId leaf_state = ts_subtree_leaf_parse_state(tree); + TSLexerMode current_lex_mode = ts_language_lex_mode_for_state(self->language, state); + TSLexerMode leaf_lex_mode = ts_language_lex_mode_for_state(self->language, leaf_state); + + // At the end of a non-terminal extra node, the lexer normally returns + // NULL, which indicates that the parser should look for a reduce action + // at symbol `0`. Avoid reusing tokens in this situation to ensure that + // the same thing happens when incrementally reparsing. + if (current_lex_mode.lex_state == (uint16_t)(-1)) return false; + + // If the token was created in a state with the same set of lookaheads, it is reusable. + if ( + table_entry->action_count > 0 && + memcmp(&leaf_lex_mode, ¤t_lex_mode, sizeof(TSLexerMode)) == 0 && + ( + leaf_symbol != self->language->keyword_capture_token || + (!ts_subtree_is_keyword(tree) && ts_subtree_parse_state(tree) == state) + ) + ) return true; + + // Empty tokens are not reusable in states with different lookaheads. + if (ts_subtree_size(tree).bytes == 0 && leaf_symbol != ts_builtin_sym_end) return false; + + // If the current state allows external tokens or other tokens that conflict with this + // token, this token is not reusable. + return current_lex_mode.external_lex_state == 0 && table_entry->is_reusable; +} + +static Subtree ts_parser__lex( + TSParser *self, + StackVersion version, + TSStateId parse_state +) { + TSLexerMode lex_mode = ts_language_lex_mode_for_state(self->language, parse_state); + if (lex_mode.lex_state == (uint16_t)-1) { + LOG("no_lookahead_after_non_terminal_extra"); + return NULL_SUBTREE; + } + + const Length start_position = ts_stack_position(self->stack, version); + const Subtree external_token = ts_stack_last_external_token(self->stack, version); + + bool found_external_token = false; + bool error_mode = parse_state == ERROR_STATE; + bool skipped_error = false; + bool called_get_column = false; + int32_t first_error_character = 0; + Length error_start_position = length_zero(); + Length error_end_position = length_zero(); + uint32_t lookahead_end_byte = 0; + uint32_t external_scanner_state_len = 0; + bool external_scanner_state_changed = false; + ts_lexer_reset(&self->lexer, start_position); + + for (;;) { + bool found_token = false; + Length current_position = self->lexer.current_position; + ColumnData column_data = self->lexer.column_data; + + if (lex_mode.external_lex_state != 0) { + LOG( + "lex_external state:%d, row:%u, column:%u", + lex_mode.external_lex_state, + current_position.extent.row, + current_position.extent.column + ); + ts_lexer_start(&self->lexer); + ts_parser__external_scanner_deserialize(self, external_token); + found_token = ts_parser__external_scanner_scan(self, lex_mode.external_lex_state); + if (self->has_scanner_error) return NULL_SUBTREE; + ts_lexer_finish(&self->lexer, &lookahead_end_byte); + + if (found_token) { + external_scanner_state_len = ts_parser__external_scanner_serialize(self); + external_scanner_state_changed = !ts_external_scanner_state_eq( + ts_subtree_external_scanner_state(external_token), + self->lexer.debug_buffer, + external_scanner_state_len + ); + + // Avoid infinite loops caused by the external scanner returning empty tokens. + // Empty tokens are needed in some circumstances, e.g. indent/dedent tokens + // in Python. Ignore the following classes of empty tokens: + // + // * Tokens produced during error recovery. When recovering from an error, + // all tokens are allowed, so it's easy to accidentally return unwanted + // empty tokens. + // * Tokens that are marked as 'extra' in the grammar. These don't change + // the parse state, so they would definitely cause an infinite loop. + if ( + self->lexer.token_end_position.bytes <= current_position.bytes && + !external_scanner_state_changed + ) { + TSSymbol symbol = self->language->external_scanner.symbol_map[self->lexer.data.result_symbol]; + TSStateId next_parse_state = ts_language_next_state(self->language, parse_state, symbol); + bool token_is_extra = (next_parse_state == parse_state); + if (error_mode || !ts_stack_has_advanced_since_error(self->stack, version) || token_is_extra) { + LOG( + "ignore_empty_external_token symbol:%s", + SYM_NAME(self->language->external_scanner.symbol_map[self->lexer.data.result_symbol]) + ); + found_token = false; + } + } + } + + if (found_token) { + found_external_token = true; + called_get_column = self->lexer.did_get_column; + break; + } + + ts_lexer_reset(&self->lexer, current_position); + self->lexer.column_data = column_data; + } + + LOG( + "lex_internal state:%d, row:%u, column:%u", + lex_mode.lex_state, + current_position.extent.row, + current_position.extent.column + ); + ts_lexer_start(&self->lexer); + found_token = ts_parser__call_main_lex_fn(self, lex_mode); + ts_lexer_finish(&self->lexer, &lookahead_end_byte); + if (found_token) break; + + if (!error_mode) { + error_mode = true; + lex_mode = ts_language_lex_mode_for_state(self->language, ERROR_STATE); + ts_lexer_reset(&self->lexer, start_position); + continue; + } + + if (!skipped_error) { + LOG("skip_unrecognized_character"); + skipped_error = true; + error_start_position = self->lexer.token_start_position; + error_end_position = self->lexer.token_start_position; + first_error_character = self->lexer.data.lookahead; + } + + if (self->lexer.current_position.bytes == error_end_position.bytes) { + if (self->lexer.data.eof(&self->lexer.data)) { + self->lexer.data.result_symbol = ts_builtin_sym_error; + break; + } + self->lexer.data.advance(&self->lexer.data, false); + } + + error_end_position = self->lexer.current_position; + } + + Subtree result; + if (skipped_error) { + Length padding = length_sub(error_start_position, start_position); + Length size = length_sub(error_end_position, error_start_position); + uint32_t lookahead_bytes = lookahead_end_byte - error_end_position.bytes; + result = ts_subtree_new_error( + &self->tree_pool, + first_error_character, + padding, + size, + lookahead_bytes, + parse_state, + self->language + ); + } else { + bool is_keyword = false; + TSSymbol symbol = self->lexer.data.result_symbol; + Length padding = length_sub(self->lexer.token_start_position, start_position); + Length size = length_sub(self->lexer.token_end_position, self->lexer.token_start_position); + uint32_t lookahead_bytes = lookahead_end_byte - self->lexer.token_end_position.bytes; + + if (found_external_token) { + symbol = self->language->external_scanner.symbol_map[symbol]; + } else if (symbol == self->language->keyword_capture_token && symbol != 0) { + uint32_t end_byte = self->lexer.token_end_position.bytes; + ts_lexer_reset(&self->lexer, self->lexer.token_start_position); + ts_lexer_start(&self->lexer); + + is_keyword = ts_parser__call_keyword_lex_fn(self); + + if ( + is_keyword && + self->lexer.token_end_position.bytes == end_byte && + ( + ts_language_has_actions(self->language, parse_state, self->lexer.data.result_symbol) || + ts_language_is_reserved_word(self->language, parse_state, self->lexer.data.result_symbol) + ) + ) { + symbol = self->lexer.data.result_symbol; + } + } + + result = ts_subtree_new_leaf( + &self->tree_pool, + symbol, + padding, + size, + lookahead_bytes, + parse_state, + found_external_token, + called_get_column, + is_keyword, + self->language + ); + + if (found_external_token) { + MutableSubtree mut_result = ts_subtree_to_mut_unsafe(result); + ts_external_scanner_state_init( + &mut_result.ptr->external_scanner_state, + self->lexer.debug_buffer, + external_scanner_state_len + ); + mut_result.ptr->has_external_scanner_state_change = external_scanner_state_changed; + } + } + + LOG_LOOKAHEAD( + SYM_NAME(ts_subtree_symbol(result)), + ts_subtree_total_size(result).bytes + ); + return result; +} + +static Subtree ts_parser__get_cached_token( + TSParser *self, + TSStateId state, + size_t position, + Subtree last_external_token, + TableEntry *table_entry +) { + TokenCache *cache = &self->token_cache; + if ( + cache->token.ptr && cache->byte_index == position && + ts_subtree_external_scanner_state_eq(cache->last_external_token, last_external_token) + ) { + ts_language_table_entry(self->language, state, ts_subtree_symbol(cache->token), table_entry); + if (ts_parser__can_reuse_first_leaf(self, state, cache->token, table_entry)) { + ts_subtree_retain(cache->token); + return cache->token; + } + } + return NULL_SUBTREE; +} + +static void ts_parser__set_cached_token( + TSParser *self, + uint32_t byte_index, + Subtree last_external_token, + Subtree token +) { + TokenCache *cache = &self->token_cache; + if (token.ptr) ts_subtree_retain(token); + if (last_external_token.ptr) ts_subtree_retain(last_external_token); + if (cache->token.ptr) ts_subtree_release(&self->tree_pool, cache->token); + if (cache->last_external_token.ptr) 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 ts_parser__has_included_range_difference( + const TSParser *self, + uint32_t start_position, + uint32_t end_position +) { + return ts_range_array_intersects( + &self->included_range_differences, + self->included_range_difference_index, + start_position, + end_position + ); +} + +static Subtree ts_parser__reuse_node( + TSParser *self, + StackVersion version, + TSStateId *state, + uint32_t position, + Subtree last_external_token, + TableEntry *table_entry +) { + Subtree result; + while ((result = reusable_node_tree(&self->reusable_node)).ptr) { + uint32_t byte_offset = reusable_node_byte_offset(&self->reusable_node); + uint32_t end_byte_offset = byte_offset + ts_subtree_total_bytes(result); + + // Do not reuse an EOF node if the included ranges array has changes + // later on in the file. + if (ts_subtree_is_eof(result)) end_byte_offset = UINT32_MAX; + + if (byte_offset > position) { + LOG("before_reusable_node symbol:%s", TREE_NAME(result)); + break; + } + + if (byte_offset < position) { + LOG("past_reusable_node symbol:%s", TREE_NAME(result)); + if (end_byte_offset <= position || !reusable_node_descend(&self->reusable_node)) { + reusable_node_advance(&self->reusable_node); + } + continue; + } + + if (!ts_subtree_external_scanner_state_eq(self->reusable_node.last_external_token, last_external_token)) { + LOG("reusable_node_has_different_external_scanner_state symbol:%s", TREE_NAME(result)); + reusable_node_advance(&self->reusable_node); + continue; + } + + const char *reason = NULL; + if (ts_subtree_has_changes(result)) { + reason = "has_changes"; + } else if (ts_subtree_is_error(result)) { + reason = "is_error"; + } else if (ts_subtree_missing(result)) { + reason = "is_missing"; + } else if (ts_subtree_is_fragile(result)) { + reason = "is_fragile"; + } else if (ts_parser__has_included_range_difference(self, byte_offset, end_byte_offset)) { + reason = "contains_different_included_range"; + } + + if (reason) { + LOG("cant_reuse_node_%s tree:%s", reason, TREE_NAME(result)); + if (!reusable_node_descend(&self->reusable_node)) { + reusable_node_advance(&self->reusable_node); + ts_parser__breakdown_top_of_stack(self, version); + *state = ts_stack_state(self->stack, version); + } + continue; + } + + TSSymbol leaf_symbol = ts_subtree_leaf_symbol(result); + ts_language_table_entry(self->language, *state, leaf_symbol, table_entry); + if (!ts_parser__can_reuse_first_leaf(self, *state, result, table_entry)) { + LOG( + "cant_reuse_node symbol:%s, first_leaf_symbol:%s", + TREE_NAME(result), + SYM_NAME(leaf_symbol) + ); + reusable_node_advance_past_leaf(&self->reusable_node); + break; + } + + LOG("reuse_node symbol:%s", TREE_NAME(result)); + ts_subtree_retain(result); + return result; + } + + return NULL_SUBTREE; +} + +// Determine if a given tree should be replaced by an alternative tree. +// +// The decision is based on the trees' error costs (if any), their dynamic precedence, +// and finally, as a default, by a recursive comparison of the trees' symbols. +static bool ts_parser__select_tree(TSParser *self, Subtree left, Subtree right) { + if (!left.ptr) return true; + if (!right.ptr) return false; + + if (ts_subtree_error_cost(right) < ts_subtree_error_cost(left)) { + LOG("select_smaller_error symbol:%s, over_symbol:%s", TREE_NAME(right), TREE_NAME(left)); + return true; + } + + if (ts_subtree_error_cost(left) < ts_subtree_error_cost(right)) { + LOG("select_smaller_error symbol:%s, over_symbol:%s", TREE_NAME(left), TREE_NAME(right)); + return false; + } + + if (ts_subtree_dynamic_precedence(right) > ts_subtree_dynamic_precedence(left)) { + LOG("select_higher_precedence symbol:%s, prec:%" PRId32 ", over_symbol:%s, other_prec:%" PRId32, + TREE_NAME(right), ts_subtree_dynamic_precedence(right), TREE_NAME(left), + ts_subtree_dynamic_precedence(left)); + return true; + } + + if (ts_subtree_dynamic_precedence(left) > ts_subtree_dynamic_precedence(right)) { + LOG("select_higher_precedence symbol:%s, prec:%" PRId32 ", over_symbol:%s, other_prec:%" PRId32, + TREE_NAME(left), ts_subtree_dynamic_precedence(left), TREE_NAME(right), + ts_subtree_dynamic_precedence(right)); + return false; + } + + if (ts_subtree_error_cost(left) > 0) return true; + + int comparison = ts_subtree_compare(left, right, &self->tree_pool); + switch (comparison) { + case -1: + LOG("select_earlier symbol:%s, over_symbol:%s", TREE_NAME(left), TREE_NAME(right)); + return false; + break; + case 1: + LOG("select_earlier symbol:%s, over_symbol:%s", TREE_NAME(right), TREE_NAME(left)); + return true; + default: + LOG("select_existing symbol:%s, over_symbol:%s", TREE_NAME(left), TREE_NAME(right)); + return false; + } +} + +// Determine if a given tree's children should be replaced by an alternative +// array of children. +static bool ts_parser__select_children( + TSParser *self, + Subtree left, + const SubtreeArray *children +) { + array_assign(&self->scratch_trees, children); + + // Create a temporary subtree using the scratch trees array. This node does + // not perform any allocation except for possibly growing the array to make + // room for its own heap data. The scratch tree is never explicitly released, + // so the same 'scratch trees' array can be reused again later. + MutableSubtree scratch_tree = ts_subtree_new_node( + ts_subtree_symbol(left), + &self->scratch_trees, + 0, + self->language + ); + + return ts_parser__select_tree( + self, + left, + ts_subtree_from_mut(scratch_tree) + ); +} + +static void ts_parser__shift( + TSParser *self, + StackVersion version, + TSStateId state, + Subtree lookahead, + bool extra +) { + bool is_leaf = ts_subtree_child_count(lookahead) == 0; + Subtree subtree_to_push = lookahead; + if (extra != ts_subtree_extra(lookahead) && is_leaf) { + MutableSubtree result = ts_subtree_make_mut(&self->tree_pool, lookahead); + ts_subtree_set_extra(&result, extra); + subtree_to_push = ts_subtree_from_mut(result); + } + + ts_stack_push(self->stack, version, subtree_to_push, !is_leaf, state); + if (ts_subtree_has_external_tokens(subtree_to_push)) { + ts_stack_set_last_external_token( + self->stack, version, ts_subtree_last_external_token(subtree_to_push) + ); + } +} + +static StackVersion ts_parser__reduce( + TSParser *self, + StackVersion version, + TSSymbol symbol, + uint32_t count, + int dynamic_precedence, + uint16_t production_id, + bool is_fragile, + bool end_of_non_terminal_extra +) { + uint32_t initial_version_count = ts_stack_version_count(self->stack); + + // Pop the given number of nodes from the given version of the parse stack. + // If stack versions have previously merged, then there may be more than one + // path back through the stack. For each path, create a new parent node to + // contain the popped children, and push it onto the stack in place of the + // children. + StackSliceArray pop = ts_stack_pop_count(self->stack, version, count); + uint32_t removed_version_count = 0; + uint32_t halted_version_count = ts_stack_halted_version_count(self->stack); + for (uint32_t i = 0; i < pop.size; i++) { + StackSlice slice = *array_get(&pop, i); + StackVersion slice_version = slice.version - removed_version_count; + + // This is where new versions are added to the parse stack. The versions + // will all be sorted and truncated at the end of the outer parsing loop. + // Allow the maximum version count to be temporarily exceeded, but only + // by a limited threshold. + if (slice_version > MAX_VERSION_COUNT + MAX_VERSION_COUNT_OVERFLOW + halted_version_count) { + ts_stack_remove_version(self->stack, slice_version); + ts_subtree_array_delete(&self->tree_pool, &slice.subtrees); + removed_version_count++; + while (i + 1 < pop.size) { + LOG("aborting reduce with too many versions") + StackSlice next_slice = *array_get(&pop, i + 1); + if (next_slice.version != slice.version) break; + ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees); + i++; + } + continue; + } + + // 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. + SubtreeArray children = slice.subtrees; + ts_subtree_array_remove_trailing_extras(&children, &self->trailing_extras); + + MutableSubtree parent = ts_subtree_new_node( + symbol, &children, production_id, self->language + ); + + // This pop operation may have caused multiple stack versions to collapse + // into one, because they all diverged from a common state. In that case, + // choose one of the arrays of trees to be the parent node's children, and + // delete the rest of the tree arrays. + while (i + 1 < pop.size) { + StackSlice next_slice = *array_get(&pop, i + 1); + if (next_slice.version != slice.version) break; + i++; + + SubtreeArray next_slice_children = next_slice.subtrees; + ts_subtree_array_remove_trailing_extras(&next_slice_children, &self->trailing_extras2); + + if (ts_parser__select_children( + self, + ts_subtree_from_mut(parent), + &next_slice_children + )) { + ts_subtree_array_clear(&self->tree_pool, &self->trailing_extras); + ts_subtree_release(&self->tree_pool, ts_subtree_from_mut(parent)); + array_swap(&self->trailing_extras, &self->trailing_extras2); + parent = ts_subtree_new_node( + symbol, &next_slice_children, production_id, self->language + ); + } else { + array_clear(&self->trailing_extras2); + ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees); + } + } + + TSStateId state = ts_stack_state(self->stack, slice_version); + TSStateId next_state = ts_language_next_state(self->language, state, symbol); + if (end_of_non_terminal_extra && next_state == state) { + parent.ptr->extra = true; + } + if (is_fragile || pop.size > 1 || initial_version_count > 1) { + parent.ptr->fragile_left = true; + parent.ptr->fragile_right = true; + parent.ptr->parse_state = TS_TREE_STATE_NONE; + } else { + parent.ptr->parse_state = state; + } + parent.ptr->dynamic_precedence += dynamic_precedence; + + // 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, ts_subtree_from_mut(parent), false, next_state); + for (uint32_t j = 0; j < self->trailing_extras.size; j++) { + ts_stack_push(self->stack, slice_version, *array_get(&self->trailing_extras, j), false, next_state); + } + + for (StackVersion j = 0; j < slice_version; j++) { + if (j == version) continue; + if (ts_stack_merge(self->stack, j, slice_version)) { + removed_version_count++; + break; + } + } + } + + // Return the first new stack version that was created. + return ts_stack_version_count(self->stack) > initial_version_count + ? initial_version_count + : STACK_VERSION_NONE; +} + +static void ts_parser__accept( + TSParser *self, + StackVersion version, + Subtree lookahead +) { + ts_assert(ts_subtree_is_eof(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++) { + SubtreeArray trees = array_get(&pop, i)->subtrees; + + Subtree root = NULL_SUBTREE; + for (uint32_t j = trees.size - 1; j + 1 > 0; j--) { + Subtree tree = *array_get(&trees, j); + if (!ts_subtree_extra(tree)) { + ts_assert(!tree.data.is_inline); + uint32_t child_count = ts_subtree_child_count(tree); + const Subtree *children = ts_subtree_children(tree); + for (uint32_t k = 0; k < child_count; k++) { + ts_subtree_retain(children[k]); + } + array_splice(&trees, j, 1, child_count, children); + root = ts_subtree_from_mut(ts_subtree_new_node( + ts_subtree_symbol(tree), + &trees, + tree.ptr->production_id, + self->language + )); + ts_subtree_release(&self->tree_pool, tree); + break; + } + } + + ts_assert(root.ptr); + self->accept_count++; + + if (self->finished_tree.ptr) { + if (ts_parser__select_tree(self, self->finished_tree, root)) { + ts_subtree_release(&self->tree_pool, self->finished_tree); + self->finished_tree = root; + } else { + ts_subtree_release(&self->tree_pool, root); + } + } else { + self->finished_tree = root; + } + } + + ts_stack_remove_version(self->stack, array_get(&pop, 0)->version); + ts_stack_halt(self->stack, version); +} + +static bool ts_parser__do_all_potential_reductions( + TSParser *self, + StackVersion starting_version, + TSSymbol lookahead_symbol +) { + uint32_t initial_version_count = ts_stack_version_count(self->stack); + + bool can_shift_lookahead_symbol = false; + StackVersion version = starting_version; + for (unsigned i = 0; true; i++) { + uint32_t version_count = ts_stack_version_count(self->stack); + if (version >= version_count) break; + + bool merged = false; + for (StackVersion j = initial_version_count; j < version; j++) { + if (ts_stack_merge(self->stack, j, version)) { + merged = true; + break; + } + } + if (merged) continue; + + TSStateId state = ts_stack_state(self->stack, version); + bool has_shift_action = false; + array_clear(&self->reduce_actions); + + TSSymbol first_symbol, end_symbol; + if (lookahead_symbol != 0) { + first_symbol = lookahead_symbol; + end_symbol = lookahead_symbol + 1; + } else { + first_symbol = 1; + end_symbol = self->language->token_count; + } + + for (TSSymbol symbol = first_symbol; symbol < end_symbol; symbol++) { + TableEntry entry; + ts_language_table_entry(self->language, state, symbol, &entry); + for (uint32_t j = 0; j < entry.action_count; j++) { + TSParseAction action = entry.actions[j]; + switch (action.type) { + case TSParseActionTypeShift: + case TSParseActionTypeRecover: + if (!action.shift.extra && !action.shift.repetition) has_shift_action = true; + break; + case TSParseActionTypeReduce: + if (action.reduce.child_count > 0) + ts_reduce_action_set_add(&self->reduce_actions, (ReduceAction) { + .symbol = action.reduce.symbol, + .count = action.reduce.child_count, + .dynamic_precedence = action.reduce.dynamic_precedence, + .production_id = action.reduce.production_id, + }); + break; + default: + break; + } + } + } + + StackVersion reduction_version = STACK_VERSION_NONE; + for (uint32_t j = 0; j < self->reduce_actions.size; j++) { + ReduceAction action = *array_get(&self->reduce_actions, j); + + reduction_version = ts_parser__reduce( + self, version, action.symbol, action.count, + action.dynamic_precedence, action.production_id, + true, false + ); + } + + if (has_shift_action) { + can_shift_lookahead_symbol = true; + } else if (reduction_version != STACK_VERSION_NONE && i < MAX_VERSION_COUNT) { + ts_stack_renumber_version(self->stack, reduction_version, version); + continue; + } else if (lookahead_symbol != 0) { + ts_stack_remove_version(self->stack, version); + // Removing this version shifts the next reduction version into its slot. + // Check that version before advancing. + continue; + } + + if (version == starting_version) { + version = version_count; + } else { + version++; + } + } + + return can_shift_lookahead_symbol; +} + +static bool ts_parser__recover_to_state( + TSParser *self, + StackVersion version, + unsigned depth, + TSStateId goal_state +) { + StackSliceArray pop = ts_stack_pop_count(self->stack, version, depth); + StackVersion previous_version = STACK_VERSION_NONE; + + for (unsigned i = 0; i < pop.size; i++) { + StackSlice slice = *array_get(&pop, i); + + if (slice.version == previous_version) { + 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_subtree_array_delete(&self->tree_pool, &slice.subtrees); + array_erase(&pop, i--); + continue; + } + + SubtreeArray error_trees = ts_stack_pop_error(self->stack, slice.version); + if (error_trees.size > 0) { + ts_assert(error_trees.size == 1); + Subtree error_tree = *array_get(&error_trees, 0); + uint32_t error_child_count = ts_subtree_child_count(error_tree); + if (error_child_count > 0) { + array_splice(&slice.subtrees, 0, 0, error_child_count, ts_subtree_children(error_tree)); + for (unsigned j = 0; j < error_child_count; j++) { + ts_subtree_retain(*array_get(&slice.subtrees, j)); + } + } + ts_subtree_array_delete(&self->tree_pool, &error_trees); + } + + ts_subtree_array_remove_trailing_extras(&slice.subtrees, &self->trailing_extras); + + if (slice.subtrees.size > 0) { + Subtree error = ts_subtree_new_error_node(&slice.subtrees, true, self->language); + ts_stack_push(self->stack, slice.version, error, false, goal_state); + } else { + array_delete(&slice.subtrees); + } + + for (unsigned j = 0; j < self->trailing_extras.size; j++) { + Subtree tree = *array_get(&self->trailing_extras, j); + ts_stack_push(self->stack, slice.version, tree, false, goal_state); + } + + previous_version = slice.version; + } + + return previous_version != STACK_VERSION_NONE; +} + +static void ts_parser__recover( + TSParser *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); + StackSummary *summary = ts_stack_get_summary(self->stack, version); + unsigned node_count_since_error = ts_stack_node_count_since_error(self->stack, version); + unsigned current_error_cost = ts_stack_error_cost(self->stack, version); + + // When the parser is in the error state, there are two strategies for recovering with a + // given lookahead token: + // 1. Find a previous state on the stack in which that lookahead token would be valid. Then, + // create a new stack version that is in that state again. This entails popping all of the + // subtrees that have been pushed onto the stack since that previous state, and wrapping + // them in an ERROR node. + // 2. Wrap the lookahead token in an ERROR node, push that ERROR node onto the stack, and + // move on to the next lookahead token, remaining in the error state. + // + // First, try the strategy 1. Upon entering the error state, the parser recorded a summary + // of the previous parse states and their depths. Look at each state in the summary, to see + // if the current lookahead token would be valid in that state. + if (summary && !ts_subtree_is_error(lookahead)) { + for (unsigned i = 0; i < summary->size; i++) { + StackSummaryEntry entry = *array_get(summary, i); + + if (entry.state == ERROR_STATE) continue; + if (entry.position.bytes == position.bytes) continue; + unsigned depth = entry.depth; + if (node_count_since_error > 0) depth++; + + // Do not recover in ways that create redundant stack versions. + bool would_merge = false; + for (unsigned j = 0; j < previous_version_count; j++) { + if ( + ts_stack_state(self->stack, j) == entry.state && + ts_stack_position(self->stack, j).bytes == position.bytes + ) { + would_merge = true; + break; + } + } + if (would_merge) continue; + + // Do not recover if the result would clearly be worse than some existing stack version. + unsigned new_cost = + current_error_cost + + entry.depth * ERROR_COST_PER_SKIPPED_TREE + + (position.bytes - entry.position.bytes) * ERROR_COST_PER_SKIPPED_CHAR + + (position.extent.row - entry.position.extent.row) * ERROR_COST_PER_SKIPPED_LINE; + if (ts_parser__better_version_exists(self, version, false, new_cost)) break; + + // If the current lookahead token is valid in some previous state, recover to that state. + // Then stop looking for further recoveries. + if (ts_language_has_actions(self->language, entry.state, ts_subtree_symbol(lookahead))) { + if (ts_parser__recover_to_state(self, version, depth, entry.state)) { + did_recover = true; + LOG("recover_to_previous state:%u, depth:%u", entry.state, depth); + LOG_STACK(); + break; + } + } + } + } + + // In the process of attempting to recover, some stack versions may have been created + // and subsequently halted. Remove those versions. + for (unsigned i = previous_version_count; i < ts_stack_version_count(self->stack); i++) { + if (!ts_stack_is_active(self->stack, i)) { + LOG("removed paused version:%u", i); + ts_stack_remove_version(self->stack, i--); + LOG_STACK(); + } + } + + // If the parser is still in the error state at the end of the file, just wrap everything + // in an ERROR node and terminate. + if (ts_subtree_is_eof(lookahead)) { + LOG("recover_eof"); + SubtreeArray children = array_new(); + Subtree parent = ts_subtree_new_error_node(&children, false, self->language); + ts_stack_push(self->stack, version, parent, false, 1); + ts_parser__accept(self, version, lookahead); + return; + } + + // If strategy 1 succeeded, a new stack version will have been created which is able to handle + // the current lookahead token. Now, in addition, try strategy 2 described above: skip the + // current lookahead token by wrapping it in an ERROR node. + + // Don't pursue this additional strategy if there are already too many stack versions. + if (did_recover && ts_stack_version_count(self->stack) > MAX_VERSION_COUNT) { + ts_stack_halt(self->stack, version); + ts_subtree_release(&self->tree_pool, lookahead); + return; + } + + if ( + did_recover && + ts_subtree_has_external_scanner_state_change(lookahead) + ) { + ts_stack_halt(self->stack, version); + ts_subtree_release(&self->tree_pool, lookahead); + return; + } + + // Do not recover if the result would clearly be worse than some existing stack version. + unsigned new_cost = + current_error_cost + ERROR_COST_PER_SKIPPED_TREE + + ts_subtree_total_bytes(lookahead) * ERROR_COST_PER_SKIPPED_CHAR + + ts_subtree_total_size(lookahead).extent.row * ERROR_COST_PER_SKIPPED_LINE; + if (ts_parser__better_version_exists(self, version, false, new_cost)) { + ts_stack_halt(self->stack, version); + ts_subtree_release(&self->tree_pool, lookahead); + return; + } + + // If the current lookahead token is an extra token, mark it as extra. This means it won't + // be counted in error cost calculations. + unsigned n; + const TSParseAction *actions = ts_language_actions(self->language, 1, ts_subtree_symbol(lookahead), &n); + if (n > 0 && actions[n - 1].type == TSParseActionTypeShift && actions[n - 1].shift.extra) { + MutableSubtree mutable_lookahead = ts_subtree_make_mut(&self->tree_pool, lookahead); + ts_subtree_set_extra(&mutable_lookahead, true); + lookahead = ts_subtree_from_mut(mutable_lookahead); + } + + // Wrap the lookahead token in an ERROR. + LOG("skip_token symbol:%s", TREE_NAME(lookahead)); + SubtreeArray children = array_new(); + array_reserve(&children, 1); + array_push(&children, lookahead); + MutableSubtree error_repeat = ts_subtree_new_node( + ts_builtin_sym_error_repeat, + &children, + 0, + self->language + ); + + // If other tokens have already been skipped, so there is already an ERROR at the top of the + // stack, then pop that ERROR off the stack and wrap the two ERRORs together into one larger + // ERROR. + if (node_count_since_error > 0) { + StackSliceArray pop = ts_stack_pop_count(self->stack, version, 1); + + // TODO: Figure out how to make this condition occur. + // See https://github.com/atom/atom/issues/18450#issuecomment-439579778 + // If multiple stack versions have merged at this point, just pick one of the errors + // arbitrarily and discard the rest. + if (pop.size > 1) { + for (unsigned i = 1; i < pop.size; i++) { + ts_subtree_array_delete(&self->tree_pool, &array_get(&pop, i)->subtrees); + } + while (ts_stack_version_count(self->stack) > array_get(&pop, 0)->version + 1) { + ts_stack_remove_version(self->stack, array_get(&pop, 0)->version + 1); + } + } + + ts_stack_renumber_version(self->stack, array_get(&pop, 0)->version, version); + array_push(&array_get(&pop, 0)->subtrees, ts_subtree_from_mut(error_repeat)); + error_repeat = ts_subtree_new_node( + ts_builtin_sym_error_repeat, + &array_get(&pop, 0)->subtrees, + 0, + self->language + ); + } + + // Push the new ERROR onto the stack. + ts_stack_push(self->stack, version, ts_subtree_from_mut(error_repeat), false, ERROR_STATE); + if (ts_subtree_has_external_tokens(lookahead)) { + ts_stack_set_last_external_token( + self->stack, version, ts_subtree_last_external_token(lookahead) + ); + } + + bool has_error = true; + for (unsigned i = 0; i < ts_stack_version_count(self->stack); i++) { + ErrorStatus status = ts_parser__version_status(self, i); + if (!status.is_in_error) { + has_error = false; + break; + } + } + self->has_error = has_error; +} + +static void ts_parser__handle_error( + TSParser *self, + StackVersion version, + Subtree lookahead +) { + uint32_t previous_version_count = ts_stack_version_count(self->stack); + + // Perform any reductions that can happen in this state, regardless of the lookahead. After + // skipping one or more invalid tokens, the parser might find a token that would have allowed + // a reduction to take place. + ts_parser__do_all_potential_reductions(self, version, 0); + uint32_t version_count = ts_stack_version_count(self->stack); + Length position = ts_stack_position(self->stack, version); + + // Push a discontinuity onto the stack. Merge all of the stack versions that + // were created in the previous step. + bool did_insert_missing_token = false; + for (StackVersion v = version; v < version_count;) { + if (!did_insert_missing_token) { + TSStateId state = ts_stack_state(self->stack, v); + for ( + TSSymbol missing_symbol = 1; + missing_symbol < (uint16_t)self->language->token_count; + missing_symbol++ + ) { + TSStateId state_after_missing_symbol = ts_language_next_state( + self->language, state, missing_symbol + ); + if (state_after_missing_symbol == 0 || state_after_missing_symbol == state) { + continue; + } + + if (ts_language_has_reduce_action( + self->language, + state_after_missing_symbol, + ts_subtree_leaf_symbol(lookahead) + )) { + // In case the parser is currently outside of any included range, the lexer will + // snap to the beginning of the next included range. The missing token's padding + // must be assigned to position it within the next included range. + ts_lexer_reset(&self->lexer, position); + ts_lexer_mark_end(&self->lexer); + Length padding = length_sub(self->lexer.token_end_position, position); + uint32_t lookahead_bytes = ts_subtree_total_bytes(lookahead) + ts_subtree_lookahead_bytes(lookahead); + + StackVersion version_with_missing_tree = ts_stack_copy_version(self->stack, v); + Subtree missing_tree = ts_subtree_new_missing_leaf( + &self->tree_pool, missing_symbol, + padding, lookahead_bytes, + self->language + ); + ts_stack_push( + self->stack, version_with_missing_tree, + missing_tree, false, + state_after_missing_symbol + ); + + if (ts_parser__do_all_potential_reductions( + self, version_with_missing_tree, + ts_subtree_leaf_symbol(lookahead) + )) { + LOG( + "recover_with_missing symbol:%s, state:%u", + SYM_NAME(missing_symbol), + ts_stack_state(self->stack, version_with_missing_tree) + ); + did_insert_missing_token = true; + break; + } + } + } + } + + ts_stack_push(self->stack, v, NULL_SUBTREE, false, ERROR_STATE); + v = (v == version) ? previous_version_count : v + 1; + } + + for (unsigned i = previous_version_count; i < version_count; i++) { + bool did_merge = ts_stack_merge(self->stack, version, previous_version_count); + ts_assert(did_merge); + } + + ts_stack_record_summary(self->stack, version, MAX_SUMMARY_DEPTH); + + // Begin recovery with the current lookahead node, rather than waiting for the + // next turn of the parse loop. This ensures that the tree accounts for the + // current lookahead token's "lookahead bytes" value, which describes how far + // the lexer needed to look ahead beyond the content of the token in order to + // recognize it. + if (ts_subtree_child_count(lookahead) > 0) { + ts_parser__breakdown_lookahead(self, &lookahead, ERROR_STATE, &self->reusable_node); + } + ts_parser__recover(self, version, lookahead); + + LOG_STACK(); +} + +static bool ts_parser__check_progress(TSParser *self, Subtree *lookahead, const uint32_t *position, unsigned operations) { + self->operation_count += operations; + if (self->operation_count >= OP_COUNT_PER_PARSER_TIMEOUT_CHECK) { + self->operation_count = 0; + } + if (position != NULL) { + self->parse_state.current_byte_offset = *position; + self->parse_state.has_error = self->has_error; + } + if ( + self->operation_count == 0 && + ( + // TODO(amaanq): remove cancellation flag & clock checks before 0.26 + (self->cancellation_flag && atomic_load(self->cancellation_flag)) || + (!clock_is_null(self->end_clock) && clock_is_gt(clock_now(), self->end_clock)) || + (self->parse_options.progress_callback && self->parse_options.progress_callback(&self->parse_state)) + ) + ) { + if (lookahead && lookahead->ptr) { + ts_subtree_release(&self->tree_pool, *lookahead); + } + return false; + } + return true; +} + +static bool ts_parser__advance( + TSParser *self, + StackVersion version, + bool allow_node_reuse +) { + TSStateId state = ts_stack_state(self->stack, version); + uint32_t position = ts_stack_position(self->stack, version).bytes; + Subtree last_external_token = ts_stack_last_external_token(self->stack, version); + + bool did_reuse = true; + Subtree lookahead = NULL_SUBTREE; + TableEntry table_entry = {.action_count = 0}; + + // If possible, reuse a node from the previous syntax tree. + if (allow_node_reuse) { + lookahead = ts_parser__reuse_node( + self, version, &state, position, last_external_token, &table_entry + ); + } + + // If no node from the previous syntax tree could be reused, then try to + // reuse the token previously returned by the lexer. + if (!lookahead.ptr) { + did_reuse = false; + lookahead = ts_parser__get_cached_token( + self, state, position, last_external_token, &table_entry + ); + } + + bool needs_lex = !lookahead.ptr; + for (;;) { + // Otherwise, re-run the lexer. + if (needs_lex) { + needs_lex = false; + lookahead = ts_parser__lex(self, version, state); + if (self->has_scanner_error) return false; + + if (lookahead.ptr) { + ts_parser__set_cached_token(self, position, last_external_token, lookahead); + ts_language_table_entry(self->language, state, ts_subtree_symbol(lookahead), &table_entry); + } + + // When parsing a non-terminal extra, a null lookahead indicates the + // end of the rule. The reduction is stored in the EOF table entry. + // After the reduction, the lexer needs to be run again. + else { + ts_language_table_entry(self->language, state, ts_builtin_sym_end, &table_entry); + } + } + + // If a cancellation flag, timeout, or progress callback was provided, then check every + // time a fixed number of parse actions has been processed. + if (!ts_parser__check_progress(self, &lookahead, &position, 1)) { + return false; + } + + // Process each parse action for the current lookahead token in + // the current state. If there are multiple actions, then this is + // an ambiguous state. REDUCE actions always create a new stack + // version, whereas SHIFT actions update the existing stack version + // and terminate this loop. + bool did_reduce = false; + StackVersion last_reduction_version = STACK_VERSION_NONE; + for (uint32_t i = 0; i < table_entry.action_count; i++) { + TSParseAction action = table_entry.actions[i]; + + switch (action.type) { + case TSParseActionTypeShift: { + if (action.shift.repetition) break; + TSStateId next_state; + if (action.shift.extra) { + next_state = state; + LOG("shift_extra"); + } else { + next_state = action.shift.state; + LOG("shift state:%u", next_state); + } + + if (ts_subtree_child_count(lookahead) > 0) { + ts_parser__breakdown_lookahead(self, &lookahead, state, &self->reusable_node); + next_state = ts_language_next_state(self->language, state, ts_subtree_symbol(lookahead)); + } + + ts_parser__shift(self, version, next_state, lookahead, action.shift.extra); + if (did_reuse) reusable_node_advance(&self->reusable_node); + return true; + } + + case TSParseActionTypeReduce: { + bool is_fragile = table_entry.action_count > 1; + bool end_of_non_terminal_extra = lookahead.ptr == NULL; + LOG("reduce sym:%s, child_count:%u", SYM_NAME(action.reduce.symbol), action.reduce.child_count); + StackVersion reduction_version = ts_parser__reduce( + self, version, action.reduce.symbol, action.reduce.child_count, + action.reduce.dynamic_precedence, action.reduce.production_id, + is_fragile, end_of_non_terminal_extra + ); + did_reduce = true; + if (reduction_version != STACK_VERSION_NONE) { + last_reduction_version = reduction_version; + } + break; + } + + case TSParseActionTypeAccept: { + LOG("accept"); + ts_parser__accept(self, version, lookahead); + return true; + } + + case TSParseActionTypeRecover: { + if (ts_subtree_child_count(lookahead) > 0) { + ts_parser__breakdown_lookahead(self, &lookahead, ERROR_STATE, &self->reusable_node); + } + + ts_parser__recover(self, version, lookahead); + if (did_reuse) reusable_node_advance(&self->reusable_node); + return true; + } + } + } + + // If a reduction was performed, then replace the current stack version + // with one of the stack versions created by a reduction, and continue + // processing this version of the stack with the same lookahead symbol. + if (last_reduction_version != STACK_VERSION_NONE) { + ts_stack_renumber_version(self->stack, last_reduction_version, version); + LOG_STACK(); + state = ts_stack_state(self->stack, version); + + // At the end of a non-terminal extra rule, the lexer will return a + // null subtree, because the parser needs to perform a fixed reduction + // regardless of the lookahead node. After performing that reduction, + // (and completing the non-terminal extra rule) run the lexer again based + // on the current parse state. + if (!lookahead.ptr) { + needs_lex = true; + } else { + ts_language_table_entry( + self->language, + state, + ts_subtree_leaf_symbol(lookahead), + &table_entry + ); + } + + continue; + } + + // A reduction was performed, but was merged into an existing stack version. + // This version can be discarded. + if (did_reduce) { + if (lookahead.ptr) { + ts_subtree_release(&self->tree_pool, lookahead); + } + ts_stack_halt(self->stack, version); + return true; + } + + // If the current lookahead token is a keyword that is not valid, but the + // default word token *is* valid, then treat the lookahead token as the word + // token instead. + if ( + ts_subtree_is_keyword(lookahead) && + ts_subtree_symbol(lookahead) != self->language->keyword_capture_token && + !ts_language_is_reserved_word(self->language, state, ts_subtree_symbol(lookahead)) + ) { + ts_language_table_entry( + self->language, + state, + self->language->keyword_capture_token, + &table_entry + ); + if (table_entry.action_count > 0) { + LOG( + "switch from_keyword:%s, to_word_token:%s", + TREE_NAME(lookahead), + SYM_NAME(self->language->keyword_capture_token) + ); + + MutableSubtree mutable_lookahead = ts_subtree_make_mut(&self->tree_pool, lookahead); + ts_subtree_set_symbol(&mutable_lookahead, self->language->keyword_capture_token, self->language); + lookahead = ts_subtree_from_mut(mutable_lookahead); + continue; + } + } + + // If the current lookahead token is not valid and the previous subtree on + // the stack was reused from an old tree, then it wasn't actually valid to + // reuse that previous subtree. Remove it from the stack, and in its place, + // push each of its children. Then try again to process the current lookahead. + if (ts_parser__breakdown_top_of_stack(self, version)) { + state = ts_stack_state(self->stack, version); + ts_subtree_release(&self->tree_pool, lookahead); + needs_lex = true; + continue; + } + + // Otherwise, there is definitely an error in this version of the parse stack. + // Mark this version as paused and continue processing any other stack + // versions that exist. If some other version advances successfully, then + // this version can simply be removed. But if all versions end up paused, + // then error recovery is needed. + LOG("detect_error lookahead:%s", TREE_NAME(lookahead)); + ts_stack_pause(self->stack, version, lookahead); + return true; + } +} + +static unsigned ts_parser__condense_stack(TSParser *self) { + bool made_changes = false; + unsigned min_error_cost = UINT_MAX; + for (StackVersion i = 0; i < ts_stack_version_count(self->stack); i++) { + // Prune any versions that have been marked for removal. + if (ts_stack_is_halted(self->stack, i)) { + ts_stack_remove_version(self->stack, i); + i--; + continue; + } + + // Keep track of the minimum error cost of any stack version so + // that it can be returned. + ErrorStatus status_i = ts_parser__version_status(self, i); + if (!status_i.is_in_error && status_i.cost < min_error_cost) { + min_error_cost = status_i.cost; + } + + // Examine each pair of stack versions, removing any versions that + // are clearly worse than another version. Ensure that the versions + // are ordered from most promising to least promising. + for (StackVersion j = 0; j < i; j++) { + ErrorStatus status_j = ts_parser__version_status(self, j); + + switch (ts_parser__compare_versions(self, status_j, status_i)) { + case ErrorComparisonTakeLeft: + made_changes = true; + ts_stack_remove_version(self->stack, i); + i--; + j = i; + break; + + case ErrorComparisonPreferLeft: + case ErrorComparisonNone: + if (ts_stack_merge(self->stack, j, i)) { + made_changes = true; + i--; + j = i; + } + break; + + case ErrorComparisonPreferRight: + made_changes = true; + if (ts_stack_merge(self->stack, j, i)) { + i--; + j = i; + } else { + ts_stack_swap_versions(self->stack, i, j); + } + break; + + case ErrorComparisonTakeRight: + made_changes = true; + ts_stack_remove_version(self->stack, j); + i--; + j--; + break; + } + } + } + + // Enforce a hard upper bound on the number of stack versions by + // discarding the least promising versions. + while (ts_stack_version_count(self->stack) > MAX_VERSION_COUNT) { + ts_stack_remove_version(self->stack, MAX_VERSION_COUNT); + made_changes = true; + } + + // If the best-performing stack version is currently paused, or all + // versions are paused, then resume the best paused version and begin + // the error recovery process. Otherwise, remove the paused versions. + if (ts_stack_version_count(self->stack) > 0) { + bool has_unpaused_version = false; + for (StackVersion i = 0, n = ts_stack_version_count(self->stack); i < n; i++) { + if (ts_stack_is_paused(self->stack, i)) { + if (!has_unpaused_version && self->accept_count < MAX_VERSION_COUNT) { + LOG("resume version:%u", i); + min_error_cost = ts_stack_error_cost(self->stack, i); + Subtree lookahead = ts_stack_resume(self->stack, i); + ts_parser__handle_error(self, i, lookahead); + has_unpaused_version = true; + } else { + ts_stack_remove_version(self->stack, i); + made_changes = true; + i--; + n--; + } + } else { + has_unpaused_version = true; + } + } + } + + if (made_changes) { + LOG("condense"); + LOG_STACK(); + } + + return min_error_cost; +} + +static bool ts_parser__balance_subtree(TSParser *self) { + Subtree finished_tree = self->finished_tree; + + // If we haven't canceled balancing in progress before, then we want to clear the tree stack and + // push the initial finished tree onto it. Otherwise, if we're resuming balancing after a + // cancellation, we don't want to clear the tree stack. + if (!self->canceled_balancing) { + array_clear(&self->tree_pool.tree_stack); + if (ts_subtree_child_count(finished_tree) > 0 && finished_tree.ptr->ref_count == 1) { + array_push(&self->tree_pool.tree_stack, ts_subtree_to_mut_unsafe(finished_tree)); + } + } + + while (self->tree_pool.tree_stack.size > 0) { + if (!ts_parser__check_progress(self, NULL, NULL, 1)) { + return false; + } + + MutableSubtree tree = *array_get(&self->tree_pool.tree_stack, + self->tree_pool.tree_stack.size - 1 + ); + + if (tree.ptr->repeat_depth > 0) { + Subtree child1 = ts_subtree_children(tree)[0]; + Subtree child2 = ts_subtree_children(tree)[tree.ptr->child_count - 1]; + long repeat_delta = (long)ts_subtree_repeat_depth(child1) - (long)ts_subtree_repeat_depth(child2); + if (repeat_delta > 0) { + unsigned n = (unsigned)repeat_delta; + + for (unsigned i = n / 2; i > 0; i /= 2) { + ts_subtree_compress(tree, i, self->language, &self->tree_pool.tree_stack); + n -= i; + + // We scale the operation count increment in `ts_parser__check_progress` proportionately to the compression + // size since larger values of i take longer to process. Shifting by 4 empirically provides good check + // intervals (e.g. 193 operations when i=3100) to prevent blocking during large compressions. + uint8_t operations = i >> 4 > 0 ? i >> 4 : 1; + if (!ts_parser__check_progress(self, NULL, NULL, operations)) { + return false; + } + } + } + } + + (void)array_pop(&self->tree_pool.tree_stack); + + for (uint32_t i = 0; i < tree.ptr->child_count; i++) { + Subtree child = ts_subtree_children(tree)[i]; + if (ts_subtree_child_count(child) > 0 && child.ptr->ref_count == 1) { + array_push(&self->tree_pool.tree_stack, ts_subtree_to_mut_unsafe(child)); + } + } + } + + return true; +} + +static bool ts_parser_has_outstanding_parse(TSParser *self) { + return ( + self->canceled_balancing || + self->external_scanner_payload || + ts_stack_state(self->stack, 0) != 1 || + ts_stack_node_count_since_error(self->stack, 0) != 0 + ); +} + +// Parser - Public + +TSParser *ts_parser_new(void) { + TSParser *self = ts_calloc(1, sizeof(TSParser)); + ts_lexer_init(&self->lexer); + array_init(&self->reduce_actions); + array_reserve(&self->reduce_actions, 4); + self->tree_pool = ts_subtree_pool_new(32); + self->stack = ts_stack_new(&self->tree_pool); + self->finished_tree = NULL_SUBTREE; + self->reusable_node = reusable_node_new(); + self->dot_graph_file = NULL; + self->cancellation_flag = NULL; + self->timeout_duration = 0; + self->language = NULL; + self->has_scanner_error = false; + self->has_error = false; + self->canceled_balancing = false; + self->external_scanner_payload = NULL; + self->end_clock = clock_null(); + self->operation_count = 0; + self->old_tree = NULL_SUBTREE; + self->included_range_differences = (TSRangeArray) array_new(); + self->included_range_difference_index = 0; + ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE); + return self; +} + +void ts_parser_delete(TSParser *self) { + if (!self) return; + + ts_parser_set_language(self, NULL); + ts_stack_delete(self->stack); + if (self->reduce_actions.contents) { + array_delete(&self->reduce_actions); + } + if (self->included_range_differences.contents) { + array_delete(&self->included_range_differences); + } + if (self->old_tree.ptr) { + ts_subtree_release(&self->tree_pool, self->old_tree); + self->old_tree = NULL_SUBTREE; + } + ts_wasm_store_delete(self->wasm_store); + ts_lexer_delete(&self->lexer); + ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE); + ts_subtree_pool_delete(&self->tree_pool); + reusable_node_delete(&self->reusable_node); + array_delete(&self->trailing_extras); + array_delete(&self->trailing_extras2); + array_delete(&self->scratch_trees); + ts_free(self); +} + +const TSLanguage *ts_parser_language(const TSParser *self) { + return self->language; +} + +bool ts_parser_set_language(TSParser *self, const TSLanguage *language) { + ts_parser_reset(self); + ts_language_delete(self->language); + self->language = NULL; + + if (language) { + if ( + language->abi_version > TREE_SITTER_LANGUAGE_VERSION || + language->abi_version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION + ) return false; + + if (ts_language_is_wasm(language)) { + if ( + !self->wasm_store || + !ts_wasm_store_start(self->wasm_store, &self->lexer.data, language) + ) return false; + } + } + + self->language = ts_language_copy(language); + return true; +} + +TSLogger ts_parser_logger(const TSParser *self) { + return self->lexer.logger; +} + +void ts_parser_set_logger(TSParser *self, TSLogger logger) { + self->lexer.logger = logger; +} + +void ts_parser_print_dot_graphs(TSParser *self, int fd) { + if (self->dot_graph_file) { + fclose(self->dot_graph_file); + } + + if (fd >= 0) { + #ifdef _WIN32 + self->dot_graph_file = _fdopen(fd, "a"); + #else + self->dot_graph_file = fdopen(fd, "a"); + #endif + } else { + self->dot_graph_file = NULL; + } +} + +const size_t *ts_parser_cancellation_flag(const TSParser *self) { + return (const size_t *)self->cancellation_flag; +} + +void ts_parser_set_cancellation_flag(TSParser *self, const size_t *flag) { + self->cancellation_flag = (const volatile size_t *)flag; +} + +uint64_t ts_parser_timeout_micros(const TSParser *self) { + return duration_to_micros(self->timeout_duration); +} + +void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout_micros) { + self->timeout_duration = duration_from_micros(timeout_micros); +} + +bool ts_parser_set_included_ranges( + TSParser *self, + const TSRange *ranges, + uint32_t count +) { + return ts_lexer_set_included_ranges(&self->lexer, ranges, count); +} + +const TSRange *ts_parser_included_ranges(const TSParser *self, uint32_t *count) { + return ts_lexer_included_ranges(&self->lexer, count); +} + +void ts_parser_reset(TSParser *self) { + ts_parser__external_scanner_destroy(self); + if (self->wasm_store) { + ts_wasm_store_reset(self->wasm_store); + } + + if (self->old_tree.ptr) { + ts_subtree_release(&self->tree_pool, self->old_tree); + self->old_tree = NULL_SUBTREE; + } + + reusable_node_clear(&self->reusable_node); + ts_lexer_reset(&self->lexer, length_zero()); + ts_stack_clear(self->stack); + ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE); + if (self->finished_tree.ptr) { + ts_subtree_release(&self->tree_pool, self->finished_tree); + self->finished_tree = NULL_SUBTREE; + } + self->accept_count = 0; + self->has_scanner_error = false; + self->has_error = false; + self->canceled_balancing = false; + self->parse_options = (TSParseOptions) {0}; + self->parse_state = (TSParseState) {0}; +} + +TSTree *ts_parser_parse( + TSParser *self, + const TSTree *old_tree, + TSInput input +) { + TSTree *result = NULL; + if (!self->language || !input.read) return NULL; + + if (ts_language_is_wasm(self->language)) { + if (!self->wasm_store) return NULL; + ts_wasm_store_start(self->wasm_store, &self->lexer.data, self->language); + } + + ts_lexer_set_input(&self->lexer, input); + array_clear(&self->included_range_differences); + self->included_range_difference_index = 0; + + self->operation_count = 0; + if (self->timeout_duration) { + self->end_clock = clock_after(clock_now(), self->timeout_duration); + } else { + self->end_clock = clock_null(); + } + + if (ts_parser_has_outstanding_parse(self)) { + LOG("resume_parsing"); + if (self->canceled_balancing) goto balance; + } else { + ts_parser__external_scanner_create(self); + if (self->has_scanner_error) goto exit; + + if (old_tree) { + ts_subtree_retain(old_tree->root); + self->old_tree = old_tree->root; + ts_range_array_get_changed_ranges( + old_tree->included_ranges, old_tree->included_range_count, + self->lexer.included_ranges, self->lexer.included_range_count, + &self->included_range_differences + ); + reusable_node_reset(&self->reusable_node, old_tree->root); + LOG("parse_after_edit"); + LOG_TREE(self->old_tree); + for (unsigned i = 0; i < self->included_range_differences.size; i++) { + TSRange *range = array_get(&self->included_range_differences, i); + LOG("different_included_range %u - %u", range->start_byte, range->end_byte); + } + } else { + reusable_node_clear(&self->reusable_node); + LOG("new_parse"); + } + } + + uint32_t position = 0, last_position = 0, version_count = 0; + do { + for ( + StackVersion version = 0; + version_count = ts_stack_version_count(self->stack), + version < version_count; + version++ + ) { + bool allow_node_reuse = version_count == 1; + while (ts_stack_is_active(self->stack, version)) { + LOG( + "process version:%u, version_count:%u, state:%d, row:%u, col:%u", + version, + ts_stack_version_count(self->stack), + ts_stack_state(self->stack, version), + ts_stack_position(self->stack, version).extent.row, + ts_stack_position(self->stack, version).extent.column + ); + + if (!ts_parser__advance(self, version, allow_node_reuse)) { + if (self->has_scanner_error) goto exit; + return NULL; + } + + LOG_STACK(); + + position = ts_stack_position(self->stack, version).bytes; + if (position > last_position || (version > 0 && position == last_position)) { + last_position = position; + break; + } + } + } + + // After advancing each version of the stack, re-sort the versions by their cost, + // removing any versions that are no longer worth pursuing. + unsigned min_error_cost = ts_parser__condense_stack(self); + + // If there's already a finished parse tree that's better than any in-progress version, + // then terminate parsing. Clear the parse stack to remove any extra references to subtrees + // within the finished tree, ensuring that these subtrees can be safely mutated in-place + // for rebalancing. + if (self->finished_tree.ptr && ts_subtree_error_cost(self->finished_tree) < min_error_cost) { + ts_stack_clear(self->stack); + break; + } + + while (self->included_range_difference_index < self->included_range_differences.size) { + TSRange *range = array_get(&self->included_range_differences, self->included_range_difference_index); + if (range->end_byte <= position) { + self->included_range_difference_index++; + } else { + break; + } + } + } while (version_count != 0); + +balance: + ts_assert(self->finished_tree.ptr); + if (!ts_parser__balance_subtree(self)) { + self->canceled_balancing = true; + return false; + } + self->canceled_balancing = false; + LOG("done"); + LOG_TREE(self->finished_tree); + + result = ts_tree_new( + self->finished_tree, + self->language, + self->lexer.included_ranges, + self->lexer.included_range_count + ); + self->finished_tree = NULL_SUBTREE; + +exit: + ts_parser_reset(self); + return result; +} + +TSTree *ts_parser_parse_with_options( + TSParser *self, + const TSTree *old_tree, + TSInput input, + TSParseOptions parse_options +) { + self->parse_options = parse_options; + self->parse_state.payload = parse_options.payload; + TSTree *result = ts_parser_parse(self, old_tree, input); + // Reset parser options before further parse calls. + self->parse_options = (TSParseOptions) {0}; + return result; +} + +TSTree *ts_parser_parse_string( + TSParser *self, + const TSTree *old_tree, + const char *string, + uint32_t length +) { + return ts_parser_parse_string_encoding(self, old_tree, string, length, TSInputEncodingUTF8); +} + +TSTree *ts_parser_parse_string_encoding( + TSParser *self, + const TSTree *old_tree, + const char *string, + uint32_t length, + TSInputEncoding encoding +) { + TSStringInput input = {string, length}; + return ts_parser_parse(self, old_tree, (TSInput) { + &input, + ts_string_input_read, + encoding, + NULL, + }); +} + +void ts_parser_set_wasm_store(TSParser *self, TSWasmStore *store) { + if (self->language && ts_language_is_wasm(self->language)) { + // Copy the assigned language into the new store. + const TSLanguage *copy = ts_language_copy(self->language); + ts_parser_set_language(self, copy); + ts_language_delete(copy); + } + + ts_wasm_store_delete(self->wasm_store); + self->wasm_store = store; +} + +TSWasmStore *ts_parser_take_wasm_store(TSParser *self) { + if (self->language && ts_language_is_wasm(self->language)) { + ts_parser_set_language(self, NULL); + } + + TSWasmStore *result = self->wasm_store; + self->wasm_store = NULL; + return result; +} + +#undef LOG diff --git a/codegraph-kernel/vendor/tree-sitter/src/parser.h b/codegraph-kernel/vendor/tree-sitter/src/parser.h new file mode 100644 index 0000000000..858107deb9 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/parser.h @@ -0,0 +1,286 @@ +#ifndef TREE_SITTER_PARSER_H_ +#define TREE_SITTER_PARSER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define ts_builtin_sym_error ((TSSymbol)-1) +#define ts_builtin_sym_end 0 +#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 + +#ifndef TREE_SITTER_API_H_ +typedef uint16_t TSStateId; +typedef uint16_t TSSymbol; +typedef uint16_t TSFieldId; +typedef struct TSLanguage TSLanguage; +typedef struct TSLanguageMetadata { + uint8_t major_version; + uint8_t minor_version; + uint8_t patch_version; +} TSLanguageMetadata; +#endif + +typedef struct { + TSFieldId field_id; + uint8_t child_index; + bool inherited; +} TSFieldMapEntry; + +// Used to index the field and supertype maps. +typedef struct { + uint16_t index; + uint16_t length; +} TSMapSlice; + +typedef struct { + bool visible; + bool named; + bool supertype; +} TSSymbolMetadata; + +typedef struct TSLexer TSLexer; + +struct TSLexer { + int32_t lookahead; + TSSymbol result_symbol; + void (*advance)(TSLexer *, bool); + void (*mark_end)(TSLexer *); + uint32_t (*get_column)(TSLexer *); + bool (*is_at_included_range_start)(const TSLexer *); + bool (*eof)(const TSLexer *); + void (*log)(const TSLexer *, const char *, ...); +}; + +typedef enum { + TSParseActionTypeShift, + TSParseActionTypeReduce, + TSParseActionTypeAccept, + TSParseActionTypeRecover, +} TSParseActionType; + +typedef union { + struct { + uint8_t type; + TSStateId state; + bool extra; + bool repetition; + } shift; + struct { + uint8_t type; + uint8_t child_count; + TSSymbol symbol; + int16_t dynamic_precedence; + uint16_t production_id; + } reduce; + uint8_t type; +} TSParseAction; + +typedef struct { + uint16_t lex_state; + uint16_t external_lex_state; +} TSLexMode; + +typedef struct { + uint16_t lex_state; + uint16_t external_lex_state; + uint16_t reserved_word_set_id; +} TSLexerMode; + +typedef union { + TSParseAction action; + struct { + uint8_t count; + bool reusable; + } entry; +} TSParseActionEntry; + +typedef struct { + int32_t start; + int32_t end; +} TSCharacterRange; + +struct TSLanguage { + uint32_t abi_version; + uint32_t symbol_count; + uint32_t alias_count; + uint32_t token_count; + uint32_t external_token_count; + uint32_t state_count; + uint32_t large_state_count; + uint32_t production_id_count; + uint32_t field_count; + uint16_t max_alias_sequence_length; + const uint16_t *parse_table; + const uint16_t *small_parse_table; + const uint32_t *small_parse_table_map; + const TSParseActionEntry *parse_actions; + const char * const *symbol_names; + const char * const *field_names; + const TSMapSlice *field_map_slices; + const TSFieldMapEntry *field_map_entries; + const TSSymbolMetadata *symbol_metadata; + const TSSymbol *public_symbol_map; + const uint16_t *alias_map; + const TSSymbol *alias_sequences; + const TSLexerMode *lex_modes; + bool (*lex_fn)(TSLexer *, TSStateId); + bool (*keyword_lex_fn)(TSLexer *, TSStateId); + TSSymbol keyword_capture_token; + struct { + const bool *states; + const TSSymbol *symbol_map; + void *(*create)(void); + void (*destroy)(void *); + bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); + unsigned (*serialize)(void *, char *); + void (*deserialize)(void *, const char *, unsigned); + } external_scanner; + const TSStateId *primary_state_ids; + const char *name; + const TSSymbol *reserved_words; + uint16_t max_reserved_word_set_size; + uint32_t supertype_count; + const TSSymbol *supertype_symbols; + const TSMapSlice *supertype_map_slices; + const TSSymbol *supertype_map_entries; + TSLanguageMetadata metadata; +}; + +static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { + uint32_t index = 0; + uint32_t size = len - index; + while (size > 1) { + uint32_t half_size = size / 2; + uint32_t mid_index = index + half_size; + const TSCharacterRange *range = &ranges[mid_index]; + if (lookahead >= range->start && lookahead <= range->end) { + return true; + } else if (lookahead > range->end) { + index = mid_index; + } + size -= half_size; + } + const TSCharacterRange *range = &ranges[index]; + return (lookahead >= range->start && lookahead <= range->end); +} + +/* + * Lexer Macros + */ + +#ifdef _MSC_VER +#define UNUSED __pragma(warning(suppress : 4101)) +#else +#define UNUSED __attribute__((unused)) +#endif + +#define START_LEXER() \ + bool result = false; \ + bool skip = false; \ + UNUSED \ + bool eof = false; \ + int32_t lookahead; \ + goto start; \ + next_state: \ + lexer->advance(lexer, skip); \ + start: \ + skip = false; \ + lookahead = lexer->lookahead; + +#define ADVANCE(state_value) \ + { \ + state = state_value; \ + goto next_state; \ + } + +#define ADVANCE_MAP(...) \ + { \ + static const uint16_t map[] = { __VA_ARGS__ }; \ + for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ + if (map[i] == lookahead) { \ + state = map[i + 1]; \ + goto next_state; \ + } \ + } \ + } + +#define SKIP(state_value) \ + { \ + skip = true; \ + state = state_value; \ + goto next_state; \ + } + +#define ACCEPT_TOKEN(symbol_value) \ + result = true; \ + lexer->result_symbol = symbol_value; \ + lexer->mark_end(lexer); + +#define END_STATE() return result; + +/* + * Parse Table Macros + */ + +#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) + +#define STATE(id) id + +#define ACTIONS(id) id + +#define SHIFT(state_value) \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .state = (state_value) \ + } \ + }} + +#define SHIFT_REPEAT(state_value) \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .state = (state_value), \ + .repetition = true \ + } \ + }} + +#define SHIFT_EXTRA() \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .extra = true \ + } \ + }} + +#define REDUCE(symbol_name, children, precedence, prod_id) \ + {{ \ + .reduce = { \ + .type = TSParseActionTypeReduce, \ + .symbol = symbol_name, \ + .child_count = children, \ + .dynamic_precedence = precedence, \ + .production_id = prod_id \ + }, \ + }} + +#define RECOVER() \ + {{ \ + .type = TSParseActionTypeRecover \ + }} + +#define ACCEPT_INPUT() \ + {{ \ + .type = TSParseActionTypeAccept \ + }} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_PARSER_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/point.h b/codegraph-kernel/vendor/tree-sitter/src/point.h new file mode 100644 index 0000000000..3958198843 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/point.h @@ -0,0 +1,48 @@ +#ifndef TREE_SITTER_POINT_H_ +#define TREE_SITTER_POINT_H_ + +#include "tree_sitter/api.h" + +#define POINT_ZERO ((TSPoint) {0, 0}) +#define POINT_MAX ((TSPoint) {UINT32_MAX, UINT32_MAX}) + +static inline TSPoint point__new(unsigned row, unsigned column) { + TSPoint result = {row, column}; + return result; +} + +static inline TSPoint point_add(TSPoint a, TSPoint b) { + if (b.row > 0) + return point__new(a.row + b.row, b.column); + else + return point__new(a.row, a.column + b.column); +} + +static inline TSPoint point_sub(TSPoint a, TSPoint b) { + if (a.row > b.row) + return point__new(a.row - b.row, a.column); + else + return point__new(0, (a.column >= b.column) ? a.column - b.column : 0); +} + +static inline bool point_lte(TSPoint a, TSPoint b) { + return (a.row < b.row) || (a.row == b.row && a.column <= b.column); +} + +static inline bool point_lt(TSPoint a, TSPoint b) { + return (a.row < b.row) || (a.row == b.row && a.column < b.column); +} + +static inline bool point_gt(TSPoint a, TSPoint b) { + return (a.row > b.row) || (a.row == b.row && a.column > b.column); +} + +static inline bool point_gte(TSPoint a, TSPoint b) { + return (a.row > b.row) || (a.row == b.row && a.column >= b.column); +} + +static inline bool point_eq(TSPoint a, TSPoint b) { + return a.row == b.row && a.column == b.column; +} + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/portable/endian.h b/codegraph-kernel/vendor/tree-sitter/src/portable/endian.h new file mode 100644 index 0000000000..a6560826a4 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/portable/endian.h @@ -0,0 +1,241 @@ +// "License": Public Domain +// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to +// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it +// an example on how to get the endian conversion functions on different platforms. + +// updates from https://github.com/mikepb/endian.h/issues/4 + +#ifndef ENDIAN_H +#define ENDIAN_H + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(HAVE_ENDIAN_H) || \ + defined(__linux__) || \ + defined(__GNU__) || \ + defined(__HAIKU__) || \ + defined(__illumos__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) || \ + defined(__CYGWIN__) || \ + defined(__MSYS__) || \ + defined(__EMSCRIPTEN__) || \ + defined(__wasi__) || \ + defined(__wasm__) + +#if defined(__NetBSD__) +#define _NETBSD_SOURCE 1 +#endif + +# include + +#elif defined(HAVE_SYS_ENDIAN_H) || \ + defined(__FreeBSD__) || \ + defined(__DragonFly__) + +# include + +#elif defined(__APPLE__) +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +# if !defined(_POSIX_C_SOURCE) +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) +# else +# if BYTE_ORDER == LITTLE_ENDIAN +# define htobe16(x) __builtin_bswap16(x) +# define htole16(x) (x) +# define be16toh(x) __builtin_bswap16(x) +# define le16toh(x) (x) + +# define htobe32(x) __builtin_bswap32(x) +# define htole32(x) (x) +# define be32toh(x) __builtin_bswap32(x) +# define le32toh(x) (x) + +# define htobe64(x) __builtin_bswap64(x) +# define htole64(x) (x) +# define be64toh(x) __builtin_bswap64(x) +# define le64toh(x) (x) +# elif BYTE_ORDER == BIG_ENDIAN +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) +# else +# error byte order not supported +# endif +# endif + +#elif defined(__WINDOWS__) + +# if defined(_MSC_VER) && !defined(__clang__) +# include +# define B_SWAP_16(x) _byteswap_ushort(x) +# define B_SWAP_32(x) _byteswap_ulong(x) +# define B_SWAP_64(x) _byteswap_uint64(x) +# else +# define B_SWAP_16(x) __builtin_bswap16(x) +# define B_SWAP_32(x) __builtin_bswap32(x) +# define B_SWAP_64(x) __builtin_bswap64(x) +# endif + +# if defined(__MINGW32__) || defined(HAVE_SYS_PARAM_H) +# include +# endif + +# ifndef BIG_ENDIAN +# ifdef __BIG_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# elif defined(__ORDER_BIG_ENDIAN__) +# define BIG_ENDIAN __ORDER_BIG_ENDIAN__ +# else +# define BIG_ENDIAN 4321 +# endif +# endif + +# ifndef LITTLE_ENDIAN +# ifdef __LITTLE_ENDIAN +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# elif defined(__ORDER_LITTLE_ENDIAN__) +# define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +# else +# define LITTLE_ENDIAN 1234 +# endif +# endif + +# ifndef BYTE_ORDER +# ifdef __BYTE_ORDER +# define BYTE_ORDER __BYTE_ORDER +# elif defined(__BYTE_ORDER__) +# define BYTE_ORDER __BYTE_ORDER__ +# else + /* assume LE on Windows if nothing was defined */ +# define BYTE_ORDER LITTLE_ENDIAN +# endif +# endif + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) B_SWAP_16(x) +# define htole16(x) (x) +# define be16toh(x) B_SWAP_16(x) +# define le16toh(x) (x) + +# define htobe32(x) B_SWAP_32(x) +# define htole32(x) (x) +# define be32toh(x) B_SWAP_32(x) +# define le32toh(x) (x) + +# define htobe64(x) B_SWAP_64(x) +# define htole64(x) (x) +# define be64toh(x) B_SWAP_64(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + +# define htobe16(x) (x) +# define htole16(x) B_SWAP_16(x) +# define be16toh(x) (x) +# define le16toh(x) B_SWAP_16(x) + +# define htobe32(x) (x) +# define htole32(x) B_SWAP_32(x) +# define be32toh(x) (x) +# define le32toh(x) B_SWAP_32(x) + +# define htobe64(x) (x) +# define htole64(x) B_SWAP_64(x) +# define be64toh(x) (x) +# define le64toh(x) B_SWAP_64(x) + +# else + +# error byte order not supported + +# endif + +#elif defined(__QNXNTO__) + +# include + +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 + +# if defined(__BIGENDIAN__) + +# define __BYTE_ORDER __BIG_ENDIAN + +# define htobe16(x) (x) +# define htobe32(x) (x) +# define htobe64(x) (x) + +# define htole16(x) ENDIAN_SWAP16(x) +# define htole32(x) ENDIAN_SWAP32(x) +# define htole64(x) ENDIAN_SWAP64(x) + +# elif defined(__LITTLEENDIAN__) + +# define __BYTE_ORDER __LITTLE_ENDIAN + +# define htole16(x) (x) +# define htole32(x) (x) +# define htole64(x) (x) + +# define htobe16(x) ENDIAN_SWAP16(x) +# define htobe32(x) ENDIAN_SWAP32(x) +# define htobe64(x) ENDIAN_SWAP64(x) + +# else + +# error byte order not supported + +# endif + +# define be16toh(x) ENDIAN_BE16(x) +# define be32toh(x) ENDIAN_BE32(x) +# define be64toh(x) ENDIAN_BE64(x) +# define le16toh(x) ENDIAN_LE16(x) +# define le32toh(x) ENDIAN_LE32(x) +# define le64toh(x) ENDIAN_LE64(x) + +#else + +# error platform not supported + +#endif + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/query.c b/codegraph-kernel/vendor/tree-sitter/src/query.c new file mode 100644 index 0000000000..6c514887e0 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/query.c @@ -0,0 +1,4347 @@ +/* + * On NetBSD, defining standard requirements like this removes symbols + * from the namespace; however, we need non-standard symbols for + * endian.h. + */ +#if defined(__NetBSD__) && defined(_POSIX_C_SOURCE) +#undef _POSIX_C_SOURCE +#endif + +#include "tree_sitter/api.h" +#include "./alloc.h" +#include "./array.h" +#include "./clock.h" +#include "./language.h" +#include "./point.h" +#include "./tree_cursor.h" +#include "./unicode.h" +#include + +// #define DEBUG_ANALYZE_QUERY +// #define DEBUG_EXECUTE_QUERY + +#define MAX_STEP_CAPTURE_COUNT 3 +#define MAX_NEGATED_FIELD_COUNT 8 +#define MAX_STATE_PREDECESSOR_COUNT 256 +#define MAX_ANALYSIS_STATE_DEPTH 8 +#define MAX_ANALYSIS_ITERATION_COUNT 256 + +/* + * Stream - A sequence of unicode characters derived from a UTF8 string. + * This struct is used in parsing queries from S-expressions. + */ +typedef struct { + const char *input; + const char *start; + const char *end; + int32_t next; + uint8_t next_size; +} Stream; + +/* + * QueryStep - A step in the process of matching a query. Each node within + * a query S-expression corresponds to one of these steps. An entire pattern + * is represented as a sequence of these steps. The basic properties of a + * node are represented by these fields: + * - `symbol` - The grammar symbol to match. A zero value represents the + * wildcard symbol, '_'. + * - `field` - The field name to match. A zero value means that a field name + * was not specified. + * - `capture_ids` - An array of integers representing the names of captures + * associated with this node in the pattern, terminated by a `NONE` value. + * - `depth` - The depth where this node occurs in the pattern. The root node + * of the pattern has depth zero. + * - `negated_field_list_id` - An id representing a set of fields that must + * not be present on a node matching this step. + * + * Steps have some additional fields in order to handle the `.` (or "anchor") operator, + * which forbids additional child nodes: + * - `is_immediate` - Indicates that the node matching this step cannot be preceded + * by other sibling nodes that weren't specified in the pattern. + * - `is_last_child` - Indicates that the node matching this step cannot have any + * subsequent named siblings. + * + * For simple patterns, steps are matched in sequential order. But in order to + * handle alternative/repeated/optional sub-patterns, query steps are not always + * structured as a linear sequence; they sometimes need to split and merge. This + * is done using the following fields: + * - `alternative_index` - The index of a different query step that serves as + * an alternative to this step. A `NONE` value represents no alternative. + * When a query state reaches a step with an alternative index, the state + * is duplicated, with one copy remaining at the original step, and one copy + * moving to the alternative step. The alternative may have its own alternative + * step, so this splitting is an iterative process. + * - `is_dead_end` - Indicates that this state cannot be passed directly, and + * exists only in order to redirect to an alternative index, with no splitting. + * - `is_pass_through` - Indicates that state has no matching logic of its own, + * and exists only to split a state. One copy of the state advances immediately + * to the next step, and one moves to the alternative step. + * - `alternative_is_immediate` - Indicates that this step's alternative step + * should be treated as if `is_immediate` is true. + * + * Steps also store some derived state that summarizes how they relate to other + * steps within the same pattern. This is used to optimize the matching process: + * - `contains_captures` - Indicates that this step or one of its child steps + * has a non-empty `capture_ids` list. + * - `parent_pattern_guaranteed` - Indicates that if this step is reached, then + * it and all of its subsequent sibling steps within the same parent pattern + * are guaranteed to match. + * - `root_pattern_guaranteed` - Similar to `parent_pattern_guaranteed`, but + * for the entire top-level pattern. When iterating through a query's + * captures using `ts_query_cursor_next_capture`, this field is used to + * detect that a capture can safely be returned from a match that has not + * even completed yet. + */ +typedef struct { + TSSymbol symbol; + TSSymbol supertype_symbol; + TSFieldId field; + uint16_t capture_ids[MAX_STEP_CAPTURE_COUNT]; + uint16_t depth; + uint16_t alternative_index; + uint16_t negated_field_list_id; + bool is_named: 1; + bool is_immediate: 1; + bool is_last_child: 1; + bool is_pass_through: 1; + bool is_dead_end: 1; + bool alternative_is_immediate: 1; + bool contains_captures: 1; + bool root_pattern_guaranteed: 1; + bool parent_pattern_guaranteed: 1; + bool is_missing: 1; +} QueryStep; + +/* + * Slice - A slice of an external array. Within a query, capture names, + * literal string values, and predicate step information are stored in three + * contiguous arrays. Individual captures, string values, and predicates are + * represented as slices of these three arrays. + */ +typedef struct { + uint32_t offset; + uint32_t length; +} Slice; + +/* + * SymbolTable - a two-way mapping of strings to ids. + */ +typedef struct { + Array(char) characters; + Array(Slice) slices; +} SymbolTable; + +/** + * CaptureQuantifiers - a data structure holding the quantifiers of pattern captures. + */ +typedef Array(uint8_t) CaptureQuantifiers; + +/* + * PatternEntry - Information about the starting point for matching a particular + * pattern. These entries are stored in a 'pattern map' - a sorted array that + * makes it possible to efficiently lookup patterns based on the symbol for their + * first step. The entry consists of the following fields: + * - `pattern_index` - the index of the pattern within the query + * - `step_index` - the index of the pattern's first step in the shared `steps` array + * - `is_rooted` - whether or not the pattern has a single root node. This property + * affects decisions about whether or not to start the pattern for nodes outside + * of a QueryCursor's range restriction. + */ +typedef struct { + uint16_t step_index; + uint16_t pattern_index; + bool is_rooted; +} PatternEntry; + +typedef struct { + Slice steps; + Slice predicate_steps; + uint32_t start_byte; + uint32_t end_byte; + bool is_non_local; +} QueryPattern; + +typedef struct { + uint32_t byte_offset; + uint16_t step_index; +} StepOffset; + +/* + * QueryState - The state of an in-progress match of a particular pattern + * 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. Fields: + * - `id` - A numeric id that is exposed to the public API. This allows the + * caller to remove a given match, preventing any more of its captures + * from being returned. + * - `start_depth` - The depth in the tree where the first step of the state's + * pattern was matched. + * - `pattern_index` - The pattern that the state is matching. + * - `consumed_capture_count` - The number of captures from this match that + * have already been returned. + * - `capture_list_id` - A numeric id that can be used to retrieve the state's + * list of captures from the `CaptureListPool`. + * - `seeking_immediate_match` - A flag that indicates that the state's next + * step must be matched by the very next sibling. This is used when + * processing repetitions, or when processing a wildcard node followed by + * an anchor. + * - `has_in_progress_alternatives` - A flag that indicates that there is are + * other states that have the same captures as this state, but are at + * different steps in their pattern. This means that in order to obey the + * 'longest-match' rule, this state should not be returned as a match until + * it is clear that there can be no other alternative match with more captures. + */ +typedef struct { + uint32_t id; + uint32_t capture_list_id; + uint16_t start_depth; + uint16_t step_index; + uint16_t pattern_index; + uint16_t consumed_capture_count: 12; + bool seeking_immediate_match: 1; + bool has_in_progress_alternatives: 1; + bool dead: 1; + bool needs_parent: 1; +} QueryState; + +typedef Array(TSQueryCapture) CaptureList; + +/* + * CaptureListPool - A collection of *lists* of captures. Each query state needs + * to maintain its own list of captures. To avoid repeated allocations, this struct + * maintains a fixed set of capture lists, and keeps track of which ones are + * currently in use by a query state. + */ +typedef struct { + Array(CaptureList) list; + CaptureList empty_list; + // The maximum number of capture lists that we are allowed to allocate. We + // never allow `list` to allocate more entries than this, dropping pending + // matches if needed to stay under the limit. + uint32_t max_capture_list_count; + // The number of capture lists allocated in `list` that are not currently in + // use. We reuse those existing-but-unused capture lists before trying to + // allocate any new ones. We use an invalid value (UINT32_MAX) for a capture + // list's length to indicate that it's not in use. + uint32_t free_capture_list_count; +} CaptureListPool; + +/* + * AnalysisState - The state needed for walking the parse table when analyzing + * a query pattern, to determine at which steps the pattern might fail to match. + */ +typedef struct { + TSStateId parse_state; + TSSymbol parent_symbol; + uint16_t child_index; + TSFieldId field_id: 15; + bool done: 1; +} AnalysisStateEntry; + +typedef struct { + AnalysisStateEntry stack[MAX_ANALYSIS_STATE_DEPTH]; + uint16_t depth; + uint16_t step_index; + TSSymbol root_symbol; +} AnalysisState; + +typedef Array(AnalysisState *) AnalysisStateSet; + +typedef struct { + AnalysisStateSet states; + AnalysisStateSet next_states; + AnalysisStateSet deeper_states; + AnalysisStateSet state_pool; + Array(uint16_t) final_step_indices; + Array(TSSymbol) finished_parent_symbols; + bool did_abort; +} QueryAnalysis; + +/* + * AnalysisSubgraph - A subset of the states in the parse table that are used + * in constructing nodes with a certain symbol. Each state is accompanied by + * some information about the possible node that could be produced in + * downstream states. + */ +typedef struct { + TSStateId state; + uint16_t production_id; + uint8_t child_index: 7; + bool done: 1; +} AnalysisSubgraphNode; + +typedef struct { + TSSymbol symbol; + Array(TSStateId) start_states; + Array(AnalysisSubgraphNode) nodes; +} AnalysisSubgraph; + +typedef Array(AnalysisSubgraph) AnalysisSubgraphArray; + +/* + * StatePredecessorMap - A map that stores the predecessors of each parse state. + * This is used during query analysis to determine which parse states can lead + * to which reduce actions. + */ +typedef struct { + TSStateId *contents; +} StatePredecessorMap; + +/* + * 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 `TSQueryCursor`. + */ +struct TSQuery { + SymbolTable captures; + SymbolTable predicate_values; + Array(CaptureQuantifiers) capture_quantifiers; + Array(QueryStep) steps; + Array(PatternEntry) pattern_map; + Array(TSQueryPredicateStep) predicate_steps; + Array(QueryPattern) patterns; + Array(StepOffset) step_offsets; + Array(TSFieldId) negated_fields; + Array(char) string_buffer; + Array(TSSymbol) repeat_symbols_with_rootless_patterns; + const TSLanguage *language; + uint16_t wildcard_root_pattern_count; +}; + +/* + * TSQueryCursor - A stateful struct used to execute a query on a tree. + */ +struct TSQueryCursor { + const TSQuery *query; + TSTreeCursor cursor; + Array(QueryState) states; + Array(QueryState) finished_states; + CaptureListPool capture_list_pool; + uint32_t depth; + uint32_t max_start_depth; + uint32_t start_byte; + uint32_t end_byte; + TSPoint start_point; + TSPoint end_point; + uint32_t next_state_id; + TSClock end_clock; + TSDuration timeout_duration; + const TSQueryCursorOptions *query_options; + TSQueryCursorState query_state; + unsigned operation_count; + bool on_visible_node; + bool ascending; + bool halted; + bool did_exceed_match_limit; +}; + +static const TSQueryError PARENT_DONE = -1; +static const uint16_t PATTERN_DONE_MARKER = UINT16_MAX; +static const uint16_t NONE = UINT16_MAX; +static const TSSymbol WILDCARD_SYMBOL = 0; +static const unsigned OP_COUNT_PER_QUERY_TIMEOUT_CHECK = 100; + +/********** + * Stream + **********/ + +// Advance to the next unicode code point in the stream. +static bool stream_advance(Stream *self) { + self->input += self->next_size; + if (self->input < self->end) { + uint32_t size = ts_decode_utf8( + (const uint8_t *)self->input, + (uint32_t)(self->end - self->input), + &self->next + ); + if (size > 0) { + self->next_size = size; + return true; + } + } else { + self->next_size = 0; + self->next = '\0'; + } + return false; +} + +// Reset the stream to the given input position, represented as a pointer +// into the input string. +static void stream_reset(Stream *self, const char *input) { + self->input = input; + self->next_size = 0; + stream_advance(self); +} + +static Stream stream_new(const char *string, uint32_t length) { + Stream self = { + .next = 0, + .input = string, + .start = string, + .end = string + length, + }; + stream_advance(&self); + return self; +} + +static void stream_skip_whitespace(Stream *self) { + for (;;) { + if (iswspace(self->next)) { + stream_advance(self); + } else if (self->next == ';') { + // skip over comments + stream_advance(self); + while (self->next && self->next != '\n') { + if (!stream_advance(self)) break; + } + } else { + break; + } + } +} + +static bool stream_is_ident_start(Stream *self) { + return iswalnum(self->next) || self->next == '_' || self->next == '-'; +} + +static void stream_scan_identifier(Stream *stream) { + do { + stream_advance(stream); + } while ( + iswalnum(stream->next) || + stream->next == '_' || + stream->next == '-' || + stream->next == '.' || + stream->next == '?' || + stream->next == '!' + ); +} + +static uint32_t stream_offset(Stream *self) { + return (uint32_t)(self->input - self->start); +} + +/****************** + * CaptureListPool + ******************/ + +static CaptureListPool capture_list_pool_new(void) { + return (CaptureListPool) { + .list = array_new(), + .empty_list = array_new(), + .max_capture_list_count = UINT32_MAX, + .free_capture_list_count = 0, + }; +} + +static void capture_list_pool_reset(CaptureListPool *self) { + for (uint16_t i = 0; i < (uint16_t)self->list.size; i++) { + // This invalid size means that the list is not in use. + array_get(&self->list, i)->size = UINT32_MAX; + } + self->free_capture_list_count = self->list.size; +} + +static void capture_list_pool_delete(CaptureListPool *self) { + for (uint16_t i = 0; i < (uint16_t)self->list.size; i++) { + array_delete(array_get(&self->list, i)); + } + array_delete(&self->list); +} + +static const CaptureList *capture_list_pool_get(const CaptureListPool *self, uint16_t id) { + if (id >= self->list.size) return &self->empty_list; + return array_get(&self->list, id); +} + +static CaptureList *capture_list_pool_get_mut(CaptureListPool *self, uint16_t id) { + ts_assert(id < self->list.size); + return array_get(&self->list, id); +} + +static bool capture_list_pool_is_empty(const CaptureListPool *self) { + // The capture list pool is empty if all allocated lists are in use, and we + // have reached the maximum allowed number of allocated lists. + return self->free_capture_list_count == 0 && self->list.size >= self->max_capture_list_count; +} + +static uint16_t capture_list_pool_acquire(CaptureListPool *self) { + // First see if any already allocated capture list is currently unused. + if (self->free_capture_list_count > 0) { + for (uint16_t i = 0; i < (uint16_t)self->list.size; i++) { + if (array_get(&self->list, i)->size == UINT32_MAX) { + array_clear(array_get(&self->list, i)); + self->free_capture_list_count--; + return i; + } + } + } + + // Otherwise allocate and initialize a new capture list, as long as that + // doesn't put us over the requested maximum. + uint32_t i = self->list.size; + if (i >= self->max_capture_list_count) { + return NONE; + } + CaptureList list; + array_init(&list); + array_push(&self->list, list); + return i; +} + +static void capture_list_pool_release(CaptureListPool *self, uint16_t id) { + if (id >= self->list.size) return; + array_get(&self->list, id)->size = UINT32_MAX; + self->free_capture_list_count++; +} + +/************** + * Quantifiers + **************/ + +static TSQuantifier quantifier_mul( + TSQuantifier left, + TSQuantifier right +) { + switch (left) + { + case TSQuantifierZero: + return TSQuantifierZero; + case TSQuantifierZeroOrOne: + switch (right) { + case TSQuantifierZero: + return TSQuantifierZero; + case TSQuantifierZeroOrOne: + case TSQuantifierOne: + return TSQuantifierZeroOrOne; + case TSQuantifierZeroOrMore: + case TSQuantifierOneOrMore: + return TSQuantifierZeroOrMore; + }; + break; + case TSQuantifierZeroOrMore: + switch (right) { + case TSQuantifierZero: + return TSQuantifierZero; + case TSQuantifierZeroOrOne: + case TSQuantifierZeroOrMore: + case TSQuantifierOne: + case TSQuantifierOneOrMore: + return TSQuantifierZeroOrMore; + }; + break; + case TSQuantifierOne: + return right; + case TSQuantifierOneOrMore: + switch (right) { + case TSQuantifierZero: + return TSQuantifierZero; + case TSQuantifierZeroOrOne: + case TSQuantifierZeroOrMore: + return TSQuantifierZeroOrMore; + case TSQuantifierOne: + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + }; + break; + } + return TSQuantifierZero; // to make compiler happy, but all cases should be covered above! +} + +static TSQuantifier quantifier_join( + TSQuantifier left, + TSQuantifier right +) { + switch (left) + { + case TSQuantifierZero: + switch (right) { + case TSQuantifierZero: + return TSQuantifierZero; + case TSQuantifierZeroOrOne: + case TSQuantifierOne: + return TSQuantifierZeroOrOne; + case TSQuantifierZeroOrMore: + case TSQuantifierOneOrMore: + return TSQuantifierZeroOrMore; + }; + break; + case TSQuantifierZeroOrOne: + switch (right) { + case TSQuantifierZero: + case TSQuantifierZeroOrOne: + case TSQuantifierOne: + return TSQuantifierZeroOrOne; + break; + case TSQuantifierZeroOrMore: + case TSQuantifierOneOrMore: + return TSQuantifierZeroOrMore; + break; + }; + break; + case TSQuantifierZeroOrMore: + return TSQuantifierZeroOrMore; + case TSQuantifierOne: + switch (right) { + case TSQuantifierZero: + case TSQuantifierZeroOrOne: + return TSQuantifierZeroOrOne; + case TSQuantifierZeroOrMore: + return TSQuantifierZeroOrMore; + case TSQuantifierOne: + return TSQuantifierOne; + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + }; + break; + case TSQuantifierOneOrMore: + switch (right) { + case TSQuantifierZero: + case TSQuantifierZeroOrOne: + case TSQuantifierZeroOrMore: + return TSQuantifierZeroOrMore; + case TSQuantifierOne: + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + }; + break; + } + return TSQuantifierZero; // to make compiler happy, but all cases should be covered above! +} + +static TSQuantifier quantifier_add( + TSQuantifier left, + TSQuantifier right +) { + switch (left) + { + case TSQuantifierZero: + return right; + case TSQuantifierZeroOrOne: + switch (right) { + case TSQuantifierZero: + return TSQuantifierZeroOrOne; + case TSQuantifierZeroOrOne: + case TSQuantifierZeroOrMore: + return TSQuantifierZeroOrMore; + case TSQuantifierOne: + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + }; + break; + case TSQuantifierZeroOrMore: + switch (right) { + case TSQuantifierZero: + return TSQuantifierZeroOrMore; + case TSQuantifierZeroOrOne: + case TSQuantifierZeroOrMore: + return TSQuantifierZeroOrMore; + case TSQuantifierOne: + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + }; + break; + case TSQuantifierOne: + switch (right) { + case TSQuantifierZero: + return TSQuantifierOne; + case TSQuantifierZeroOrOne: + case TSQuantifierZeroOrMore: + case TSQuantifierOne: + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + }; + break; + case TSQuantifierOneOrMore: + return TSQuantifierOneOrMore; + } + return TSQuantifierZero; // to make compiler happy, but all cases should be covered above! +} + +// Create new capture quantifiers structure +static CaptureQuantifiers capture_quantifiers_new(void) { + return (CaptureQuantifiers) array_new(); +} + +// Delete capture quantifiers structure +static void capture_quantifiers_delete( + CaptureQuantifiers *self +) { + array_delete(self); +} + +// Clear capture quantifiers structure +static void capture_quantifiers_clear( + CaptureQuantifiers *self +) { + array_clear(self); +} + +// Replace capture quantifiers with the given quantifiers +static void capture_quantifiers_replace( + CaptureQuantifiers *self, + CaptureQuantifiers *quantifiers +) { + array_clear(self); + array_push_all(self, quantifiers); +} + +// Return capture quantifier for the given capture id +static TSQuantifier capture_quantifier_for_id( + const CaptureQuantifiers *self, + uint16_t id +) { + return (self->size <= id) ? TSQuantifierZero : (TSQuantifier) *array_get(self, id); +} + +// Add the given quantifier to the current value for id +static void capture_quantifiers_add_for_id( + CaptureQuantifiers *self, + uint16_t id, + TSQuantifier quantifier +) { + if (self->size <= id) { + array_grow_by(self, id + 1 - self->size); + } + uint8_t *own_quantifier = array_get(self, id); + *own_quantifier = (uint8_t) quantifier_add((TSQuantifier) *own_quantifier, quantifier); +} + +// Point-wise add the given quantifiers to the current values +static void capture_quantifiers_add_all( + CaptureQuantifiers *self, + CaptureQuantifiers *quantifiers +) { + if (self->size < quantifiers->size) { + array_grow_by(self, quantifiers->size - self->size); + } + for (uint16_t id = 0; id < (uint16_t)quantifiers->size; id++) { + uint8_t *quantifier = array_get(quantifiers, id); + uint8_t *own_quantifier = array_get(self, id); + *own_quantifier = (uint8_t) quantifier_add((TSQuantifier) *own_quantifier, (TSQuantifier) *quantifier); + } +} + +// Join the given quantifier with the current values +static void capture_quantifiers_mul( + CaptureQuantifiers *self, + TSQuantifier quantifier +) { + for (uint16_t id = 0; id < (uint16_t)self->size; id++) { + uint8_t *own_quantifier = array_get(self, id); + *own_quantifier = (uint8_t) quantifier_mul((TSQuantifier) *own_quantifier, quantifier); + } +} + +// Point-wise join the quantifiers from a list of alternatives with the current values +static void capture_quantifiers_join_all( + CaptureQuantifiers *self, + CaptureQuantifiers *quantifiers +) { + if (self->size < quantifiers->size) { + array_grow_by(self, quantifiers->size - self->size); + } + for (uint32_t id = 0; id < quantifiers->size; id++) { + uint8_t *quantifier = array_get(quantifiers, id); + uint8_t *own_quantifier = array_get(self, id); + *own_quantifier = (uint8_t) quantifier_join((TSQuantifier) *own_quantifier, (TSQuantifier) *quantifier); + } + for (uint32_t id = quantifiers->size; id < self->size; id++) { + uint8_t *own_quantifier = array_get(self, id); + *own_quantifier = (uint8_t) quantifier_join((TSQuantifier) *own_quantifier, TSQuantifierZero); + } +} + +/************** + * SymbolTable + **************/ + +static SymbolTable symbol_table_new(void) { + return (SymbolTable) { + .characters = array_new(), + .slices = array_new(), + }; +} + +static void symbol_table_delete(SymbolTable *self) { + array_delete(&self->characters); + array_delete(&self->slices); +} + +static int symbol_table_id_for_name( + const SymbolTable *self, + const char *name, + uint32_t length +) { + for (unsigned i = 0; i < self->slices.size; i++) { + Slice slice = *array_get(&self->slices, i); + if ( + slice.length == length && + !strncmp(array_get(&self->characters, slice.offset), name, length) + ) return i; + } + return -1; +} + +static const char *symbol_table_name_for_id( + const SymbolTable *self, + uint16_t id, + uint32_t *length +) { + Slice slice = *(array_get(&self->slices,id)); + *length = slice.length; + return array_get(&self->characters, slice.offset); +} + +static uint16_t symbol_table_insert_name( + SymbolTable *self, + const char *name, + uint32_t length +) { + int id = symbol_table_id_for_name(self, name, length); + if (id >= 0) return (uint16_t)id; + Slice slice = { + .offset = self->characters.size, + .length = length, + }; + array_grow_by(&self->characters, length + 1); + memcpy(array_get(&self->characters, slice.offset), name, length); + *array_get(&self->characters, self->characters.size - 1) = 0; + array_push(&self->slices, slice); + return self->slices.size - 1; +} + +/************ + * QueryStep + ************/ + +static QueryStep query_step__new( + TSSymbol symbol, + uint16_t depth, + bool is_immediate +) { + QueryStep step = { + .symbol = symbol, + .depth = depth, + .field = 0, + .alternative_index = NONE, + .negated_field_list_id = 0, + .contains_captures = false, + .is_last_child = false, + .is_named = false, + .is_pass_through = false, + .is_dead_end = false, + .root_pattern_guaranteed = false, + .is_immediate = is_immediate, + .alternative_is_immediate = false, + }; + for (unsigned i = 0; i < MAX_STEP_CAPTURE_COUNT; i++) { + step.capture_ids[i] = NONE; + } + return step; +} + +static void query_step__add_capture(QueryStep *self, uint16_t capture_id) { + for (unsigned i = 0; i < MAX_STEP_CAPTURE_COUNT; i++) { + if (self->capture_ids[i] == NONE) { + self->capture_ids[i] = capture_id; + break; + } + } +} + +static void query_step__remove_capture(QueryStep *self, uint16_t capture_id) { + for (unsigned i = 0; i < MAX_STEP_CAPTURE_COUNT; i++) { + if (self->capture_ids[i] == capture_id) { + self->capture_ids[i] = NONE; + while (i + 1 < MAX_STEP_CAPTURE_COUNT) { + if (self->capture_ids[i + 1] == NONE) break; + self->capture_ids[i] = self->capture_ids[i + 1]; + self->capture_ids[i + 1] = NONE; + i++; + } + break; + } + } +} + +/********************** + * StatePredecessorMap + **********************/ + +static inline StatePredecessorMap state_predecessor_map_new( + const TSLanguage *language +) { + return (StatePredecessorMap) { + .contents = ts_calloc( + (size_t)language->state_count * (MAX_STATE_PREDECESSOR_COUNT + 1), + sizeof(TSStateId) + ), + }; +} + +static inline void state_predecessor_map_delete(StatePredecessorMap *self) { + ts_free(self->contents); +} + +static inline void state_predecessor_map_add( + StatePredecessorMap *self, + TSStateId state, + TSStateId predecessor +) { + size_t index = (size_t)state * (MAX_STATE_PREDECESSOR_COUNT + 1); + TSStateId *count = &self->contents[index]; + if ( + *count == 0 || + (*count < MAX_STATE_PREDECESSOR_COUNT && self->contents[index + *count] != predecessor) + ) { + (*count)++; + self->contents[index + *count] = predecessor; + } +} + +static inline const TSStateId *state_predecessor_map_get( + const StatePredecessorMap *self, + TSStateId state, + unsigned *count +) { + size_t index = (size_t)state * (MAX_STATE_PREDECESSOR_COUNT + 1); + *count = self->contents[index]; + return &self->contents[index + 1]; +} + +/**************** + * AnalysisState + ****************/ + +static unsigned analysis_state__recursion_depth(const AnalysisState *self) { + unsigned result = 0; + for (unsigned i = 0; i < self->depth; i++) { + TSSymbol symbol = self->stack[i].parent_symbol; + for (unsigned j = 0; j < i; j++) { + if (self->stack[j].parent_symbol == symbol) { + result++; + break; + } + } + } + return result; +} + +static inline int analysis_state__compare( + AnalysisState *const *self, + AnalysisState *const *other +) { + if ((*self)->depth < (*other)->depth) return 1; + for (unsigned i = 0; i < (*self)->depth; i++) { + if (i >= (*other)->depth) return -1; + AnalysisStateEntry s1 = (*self)->stack[i]; + AnalysisStateEntry s2 = (*other)->stack[i]; + if (s1.child_index < s2.child_index) return -1; + if (s1.child_index > s2.child_index) return 1; + if (s1.parent_symbol < s2.parent_symbol) return -1; + if (s1.parent_symbol > s2.parent_symbol) return 1; + if (s1.parse_state < s2.parse_state) return -1; + if (s1.parse_state > s2.parse_state) return 1; + if (s1.field_id < s2.field_id) return -1; + if (s1.field_id > s2.field_id) return 1; + } + if ((*self)->step_index < (*other)->step_index) return -1; + if ((*self)->step_index > (*other)->step_index) return 1; + return 0; +} + +static inline AnalysisStateEntry *analysis_state__top(AnalysisState *self) { + if (self->depth == 0) { + return &self->stack[0]; + } + return &self->stack[self->depth - 1]; +} + +static inline bool analysis_state__has_supertype(AnalysisState *self, TSSymbol symbol) { + for (unsigned i = 0; i < self->depth; i++) { + if (self->stack[i].parent_symbol == symbol) return true; + } + return false; +} + +/****************** + * AnalysisStateSet + ******************/ + +// Obtains an `AnalysisState` instance, either by consuming one from this set's object pool, or by +// cloning one from scratch. +static inline AnalysisState *analysis_state_pool__clone_or_reuse( + AnalysisStateSet *self, + AnalysisState *borrowed_item +) { + AnalysisState *new_item; + if (self->size) { + new_item = array_pop(self); + } else { + new_item = ts_malloc(sizeof(AnalysisState)); + } + *new_item = *borrowed_item; + return new_item; +} + +// Inserts a clone of the passed-in item at the appropriate position to maintain ordering in this +// set. The set does not contain duplicates, so if the item is already present, it will not be +// inserted, and no clone will be made. +// +// The caller retains ownership of the passed-in memory. However, the clone that is created by this +// function will be managed by the state set. +static inline void analysis_state_set__insert_sorted( + AnalysisStateSet *self, + AnalysisStateSet *pool, + AnalysisState *borrowed_item +) { + unsigned index, exists; + array_search_sorted_with(self, analysis_state__compare, &borrowed_item, &index, &exists); + if (!exists) { + AnalysisState *new_item = analysis_state_pool__clone_or_reuse(pool, borrowed_item); + array_insert(self, index, new_item); + } +} + +// Inserts a clone of the passed-in item at the end position of this list. +// +// IMPORTANT: The caller MUST ENSURE that this item is larger (by the comparison function +// `analysis_state__compare`) than largest item already in this set. If items are inserted in the +// wrong order, the set will not function properly for future use. +// +// The caller retains ownership of the passed-in memory. However, the clone that is created by this +// function will be managed by the state set. +static inline void analysis_state_set__push( + AnalysisStateSet *self, + AnalysisStateSet *pool, + AnalysisState *borrowed_item +) { + AnalysisState *new_item = analysis_state_pool__clone_or_reuse(pool, borrowed_item); + array_push(self, new_item); +} + +// Removes all items from this set, returning it to an empty state. +static inline void analysis_state_set__clear(AnalysisStateSet *self, AnalysisStateSet *pool) { + array_push_all(pool, self); + array_clear(self); +} + +// Releases all memory that is managed with this state set, including any items currently present. +// After calling this function, the set is no longer suitable for use. +static inline void analysis_state_set__delete(AnalysisStateSet *self) { + for (unsigned i = 0; i < self->size; i++) { + ts_free(self->contents[i]); + } + array_delete(self); +} + +/**************** + * QueryAnalyzer + ****************/ + +static inline QueryAnalysis query_analysis__new(void) { + return (QueryAnalysis) { + .states = array_new(), + .next_states = array_new(), + .deeper_states = array_new(), + .state_pool = array_new(), + .final_step_indices = array_new(), + .finished_parent_symbols = array_new(), + .did_abort = false, + }; +} + +static inline void query_analysis__delete(QueryAnalysis *self) { + analysis_state_set__delete(&self->states); + analysis_state_set__delete(&self->next_states); + analysis_state_set__delete(&self->deeper_states); + analysis_state_set__delete(&self->state_pool); + array_delete(&self->final_step_indices); + array_delete(&self->finished_parent_symbols); +} + +/*********************** + * AnalysisSubgraphNode + ***********************/ + +static inline int analysis_subgraph_node__compare(const AnalysisSubgraphNode *self, const AnalysisSubgraphNode *other) { + if (self->state < other->state) return -1; + if (self->state > other->state) return 1; + if (self->child_index < other->child_index) return -1; + if (self->child_index > other->child_index) return 1; + if (self->done < other->done) return -1; + if (self->done > other->done) return 1; + if (self->production_id < other->production_id) return -1; + if (self->production_id > other->production_id) return 1; + return 0; +} + +/********* + * Query + *********/ + +// The `pattern_map` contains a mapping from TSSymbol values to indices in the +// `steps` array. For a given syntax node, the `pattern_map` makes it possible +// to quickly find the starting steps of all of the patterns whose root matches +// that node. Each entry has two fields: a `pattern_index`, which identifies one +// of the patterns in the query, and a `step_index`, which indicates the start +// offset of that pattern's steps within the `steps` array. +// +// The entries are sorted by the patterns' root symbols, and lookups use a +// binary search. This ensures that the cost of this initial lookup step +// scales logarithmically with the number of patterns in the query. +// +// This returns `true` if the symbol is present and `false` otherwise. +// If the symbol is not present `*result` is set to the index where the +// symbol should be inserted. +static inline bool ts_query__pattern_map_search( + const TSQuery *self, + TSSymbol needle, + uint32_t *result +) { + uint32_t base_index = self->wildcard_root_pattern_count; + uint32_t size = self->pattern_map.size - base_index; + if (size == 0) { + *result = base_index; + return false; + } + while (size > 1) { + uint32_t half_size = size / 2; + uint32_t mid_index = base_index + half_size; + TSSymbol mid_symbol = array_get(&self->steps, + array_get(&self->pattern_map, mid_index)->step_index + )->symbol; + if (needle > mid_symbol) base_index = mid_index; + size -= half_size; + } + + TSSymbol symbol = array_get(&self->steps, + array_get(&self->pattern_map, base_index)->step_index + )->symbol; + + if (needle > symbol) { + base_index++; + if (base_index < self->pattern_map.size) { + symbol = array_get(&self->steps, + array_get(&self->pattern_map, base_index)->step_index + )->symbol; + } + } + + *result = base_index; + return needle == symbol; +} + +// Insert a new pattern's start index into the pattern map, maintaining +// the pattern map's ordering invariant. +static inline void ts_query__pattern_map_insert( + TSQuery *self, + TSSymbol symbol, + PatternEntry new_entry +) { + uint32_t index; + ts_query__pattern_map_search(self, symbol, &index); + + // Ensure that the entries are sorted not only by symbol, but also + // by pattern_index. This way, states for earlier patterns will be + // initiated first, which allows the ordering of the states array + // to be maintained more efficiently. + while (index < self->pattern_map.size) { + PatternEntry *entry = array_get(&self->pattern_map, index); + if ( + array_get(&self->steps, entry->step_index)->symbol == symbol && + entry->pattern_index < new_entry.pattern_index + ) { + index++; + } else { + break; + } + } + + array_insert(&self->pattern_map, index, new_entry); +} + +// Walk the subgraph for this non-terminal, tracking all of the possible +// sequences of progress within the pattern. +static void ts_query__perform_analysis( + TSQuery *self, + const AnalysisSubgraphArray *subgraphs, + QueryAnalysis *analysis +) { + unsigned recursion_depth_limit = 0; + unsigned prev_final_step_count = 0; + array_clear(&analysis->final_step_indices); + array_clear(&analysis->finished_parent_symbols); + + for (unsigned iteration = 0;; iteration++) { + if (iteration == MAX_ANALYSIS_ITERATION_COUNT) { + analysis->did_abort = true; + break; + } + + #ifdef DEBUG_ANALYZE_QUERY + printf("Iteration: %u. Final step indices:", iteration); + for (unsigned j = 0; j < analysis->final_step_indices.size; j++) { + printf(" %4u", *array_get(&analysis->final_step_indices, j)); + } + printf("\n"); + for (unsigned j = 0; j < analysis->states.size; j++) { + AnalysisState *state = *array_get(&analysis->states, j); + printf(" %3u: step: %u, stack: [", j, state->step_index); + for (unsigned k = 0; k < state->depth; k++) { + printf( + " {%s, child: %u, state: %4u", + self->language->symbol_names[state->stack[k].parent_symbol], + state->stack[k].child_index, + state->stack[k].parse_state + ); + if (state->stack[k].field_id) printf(", field: %s", self->language->field_names[state->stack[k].field_id]); + if (state->stack[k].done) printf(", DONE"); + printf("}"); + } + printf(" ]\n"); + } + #endif + + // If no further progress can be made within the current recursion depth limit, then + // bump the depth limit by one, and continue to process the states the exceeded the + // limit. But only allow this if progress has been made since the last time the depth + // limit was increased. + if (analysis->states.size == 0) { + if ( + analysis->deeper_states.size > 0 && + analysis->final_step_indices.size > prev_final_step_count + ) { + #ifdef DEBUG_ANALYZE_QUERY + printf("Increase recursion depth limit to %u\n", recursion_depth_limit + 1); + #endif + + prev_final_step_count = analysis->final_step_indices.size; + recursion_depth_limit++; + AnalysisStateSet _states = analysis->states; + analysis->states = analysis->deeper_states; + analysis->deeper_states = _states; + continue; + } + + break; + } + + analysis_state_set__clear(&analysis->next_states, &analysis->state_pool); + for (unsigned j = 0; j < analysis->states.size; j++) { + AnalysisState * const state = *array_get(&analysis->states, j); + + // For efficiency, it's important to avoid processing the same analysis state more + // than once. To achieve this, keep the states in order of ascending position within + // their hypothetical syntax trees. In each iteration of this loop, start by advancing + // the states that have made the least progress. Avoid advancing states that have already + // made more progress. + if (analysis->next_states.size > 0) { + int comparison = analysis_state__compare( + &state, + array_back(&analysis->next_states) + ); + if (comparison == 0) { + analysis_state_set__insert_sorted(&analysis->next_states, &analysis->state_pool, state); + continue; + } else if (comparison > 0) { + #ifdef DEBUG_ANALYZE_QUERY + printf("Terminate iteration at state %u\n", j); + #endif + while (j < analysis->states.size) { + analysis_state_set__push( + &analysis->next_states, + &analysis->state_pool, + *array_get(&analysis->states, j) + ); + j++; + } + break; + } + } + + const TSStateId parse_state = analysis_state__top(state)->parse_state; + const TSSymbol parent_symbol = analysis_state__top(state)->parent_symbol; + const TSFieldId parent_field_id = analysis_state__top(state)->field_id; + const unsigned child_index = analysis_state__top(state)->child_index; + const QueryStep * const step = array_get(&self->steps, state->step_index); + + unsigned subgraph_index, exists; + array_search_sorted_by(subgraphs, .symbol, parent_symbol, &subgraph_index, &exists); + if (!exists) continue; + const AnalysisSubgraph *subgraph = array_get(subgraphs, subgraph_index); + + // Follow every possible path in the parse table, but only visit states that + // are part of the subgraph for the current symbol. + LookaheadIterator lookahead_iterator = ts_language_lookaheads(self->language, parse_state); + while (ts_lookahead_iterator__next(&lookahead_iterator)) { + TSSymbol sym = lookahead_iterator.symbol; + + AnalysisSubgraphNode successor = { + .state = parse_state, + .child_index = child_index, + }; + if (lookahead_iterator.action_count) { + const TSParseAction *action = &lookahead_iterator.actions[lookahead_iterator.action_count - 1]; + if (action->type == TSParseActionTypeShift) { + if (!action->shift.extra) { + successor.state = action->shift.state; + successor.child_index++; + } + } else { + continue; + } + } else if (lookahead_iterator.next_state != 0) { + successor.state = lookahead_iterator.next_state; + successor.child_index++; + } else { + continue; + } + + unsigned node_index; + array_search_sorted_with( + &subgraph->nodes, + analysis_subgraph_node__compare, &successor, + &node_index, &exists + ); + while (node_index < subgraph->nodes.size) { + AnalysisSubgraphNode *node = array_get(&subgraph->nodes, node_index); + node_index++; + if (node->state != successor.state || node->child_index != successor.child_index) break; + + // Use the subgraph to determine what alias and field will eventually be applied + // to this child node. + TSSymbol alias = ts_language_alias_at(self->language, node->production_id, child_index); + TSSymbol visible_symbol = alias + ? alias + : self->language->symbol_metadata[sym].visible + ? self->language->public_symbol_map[sym] + : 0; + TSFieldId field_id = parent_field_id; + if (!field_id) { + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map(self->language, node->production_id, &field_map, &field_map_end); + for (; field_map != field_map_end; field_map++) { + if (!field_map->inherited && field_map->child_index == child_index) { + field_id = field_map->field_id; + break; + } + } + } + + // Create a new state that has advanced past this hypothetical subtree. + AnalysisState next_state = *state; + AnalysisStateEntry *next_state_top = analysis_state__top(&next_state); + next_state_top->child_index = successor.child_index; + next_state_top->parse_state = successor.state; + if (node->done) next_state_top->done = true; + + // Determine if this hypothetical child node would match the current step + // of the query pattern. + bool does_match = false; + + // ERROR nodes can appear anywhere, so if the step is + // looking for an ERROR node, consider it potentially matchable. + if (step->symbol == ts_builtin_sym_error) { + does_match = true; + } else if (visible_symbol) { + does_match = true; + if (step->symbol == WILDCARD_SYMBOL) { + if ( + step->is_named && + !self->language->symbol_metadata[visible_symbol].named + ) does_match = false; + } else if (step->symbol != visible_symbol) { + does_match = false; + } + if (step->field && step->field != field_id) { + does_match = false; + } + if ( + step->supertype_symbol && + !analysis_state__has_supertype(state, step->supertype_symbol) + ) does_match = false; + } + + // If this child is hidden, then descend into it and walk through its children. + // If the top entry of the stack is at the end of its rule, then that entry can + // be replaced. Otherwise, push a new entry onto the stack. + else if (sym >= self->language->token_count) { + if (!next_state_top->done) { + if (next_state.depth + 1 >= MAX_ANALYSIS_STATE_DEPTH) { + #ifdef DEBUG_ANALYZE_QUERY + printf("Exceeded depth limit for state %u\n", j); + #endif + + analysis->did_abort = true; + continue; + } + + next_state.depth++; + next_state_top = analysis_state__top(&next_state); + } + + *next_state_top = (AnalysisStateEntry) { + .parse_state = parse_state, + .parent_symbol = sym, + .child_index = 0, + .field_id = field_id, + .done = false, + }; + + if (analysis_state__recursion_depth(&next_state) > recursion_depth_limit) { + analysis_state_set__insert_sorted( + &analysis->deeper_states, + &analysis->state_pool, + &next_state + ); + continue; + } + } + + // Pop from the stack when this state reached the end of its current syntax node. + while (next_state.depth > 0 && next_state_top->done) { + next_state.depth--; + next_state_top = analysis_state__top(&next_state); + } + + // If this hypothetical child did match the current step of the query pattern, + // then advance to the next step at the current depth. This involves skipping + // over any descendant steps of the current child. + const QueryStep *next_step = step; + if (does_match) { + for (;;) { + next_state.step_index++; + next_step = array_get(&self->steps, next_state.step_index); + if ( + next_step->depth == PATTERN_DONE_MARKER || + next_step->depth <= step->depth + ) break; + } + } else if (successor.state == parse_state) { + continue; + } + + for (;;) { + // Skip pass-through states. Although these states have alternatives, they are only + // used to implement repetitions, and query analysis does not need to process + // repetitions in order to determine whether steps are possible and definite. + if (next_step->is_pass_through) { + next_state.step_index++; + next_step++; + continue; + } + + // If the pattern is finished or hypothetical parent node is complete, then + // record that matching can terminate at this step of the pattern. Otherwise, + // add this state to the list of states to process on the next iteration. + if (!next_step->is_dead_end) { + bool did_finish_pattern = array_get(&self->steps, next_state.step_index)->depth != step->depth; + if (did_finish_pattern) { + array_insert_sorted_by(&analysis->finished_parent_symbols, , state->root_symbol); + } else if (next_state.depth == 0) { + array_insert_sorted_by(&analysis->final_step_indices, , next_state.step_index); + } else { + analysis_state_set__insert_sorted(&analysis->next_states, &analysis->state_pool, &next_state); + } + } + + // If the state has advanced to a step with an alternative step, then add another state + // at that alternative step. This process is simpler than the process of actually matching a + // pattern during query execution, because for the purposes of query analysis, there is no + // need to process repetitions. + if ( + does_match && + next_step->alternative_index != NONE && + next_step->alternative_index > next_state.step_index + ) { + next_state.step_index = next_step->alternative_index; + next_step = array_get(&self->steps, next_state.step_index); + } else { + break; + } + } + } + } + } + + AnalysisStateSet _states = analysis->states; + analysis->states = analysis->next_states; + analysis->next_states = _states; + } +} + +static bool ts_query__analyze_patterns(TSQuery *self, unsigned *error_offset) { + Array(uint16_t) non_rooted_pattern_start_steps = array_new(); + for (unsigned i = 0; i < self->pattern_map.size; i++) { + PatternEntry *pattern = array_get(&self->pattern_map, i); + if (!pattern->is_rooted) { + QueryStep *step = array_get(&self->steps, pattern->step_index); + if (step->symbol != WILDCARD_SYMBOL) { + array_push(&non_rooted_pattern_start_steps, i); + } + } + } + + // Walk forward through all of the steps in the query, computing some + // basic information about each step. Mark all of the steps that contain + // captures, and record the indices of all of the steps that have child steps. + Array(uint32_t) parent_step_indices = array_new(); + for (unsigned i = 0; i < self->steps.size; i++) { + QueryStep *step = array_get(&self->steps, i); + if (step->depth == PATTERN_DONE_MARKER) { + step->parent_pattern_guaranteed = true; + step->root_pattern_guaranteed = true; + continue; + } + + bool has_children = false; + bool is_wildcard = step->symbol == WILDCARD_SYMBOL; + step->contains_captures = step->capture_ids[0] != NONE; + for (unsigned j = i + 1; j < self->steps.size; j++) { + QueryStep *next_step = array_get(&self->steps, j); + if ( + next_step->depth == PATTERN_DONE_MARKER || + next_step->depth <= step->depth + ) break; + if (next_step->capture_ids[0] != NONE) { + step->contains_captures = true; + } + if (!is_wildcard) { + next_step->root_pattern_guaranteed = true; + next_step->parent_pattern_guaranteed = true; + } + has_children = true; + } + + if (has_children && !is_wildcard) { + array_push(&parent_step_indices, i); + } + } + + // For every parent symbol in the query, initialize an 'analysis subgraph'. + // This subgraph lists all of the states in the parse table that are directly + // involved in building subtrees for this symbol. + // + // In addition to the parent symbols in the query, construct subgraphs for all + // of the hidden symbols in the grammar, because these might occur within + // one of the parent nodes, such that their children appear to belong to the + // parent. + AnalysisSubgraphArray subgraphs = array_new(); + for (unsigned i = 0; i < parent_step_indices.size; i++) { + uint32_t parent_step_index = *array_get(&parent_step_indices, i); + TSSymbol parent_symbol = array_get(&self->steps, parent_step_index)->symbol; + AnalysisSubgraph subgraph = { .symbol = parent_symbol }; + array_insert_sorted_by(&subgraphs, .symbol, subgraph); + } + for (TSSymbol sym = (uint16_t)self->language->token_count; sym < (uint16_t)self->language->symbol_count; sym++) { + if (!ts_language_symbol_metadata(self->language, sym).visible) { + AnalysisSubgraph subgraph = { .symbol = sym }; + array_insert_sorted_by(&subgraphs, .symbol, subgraph); + } + } + + // Scan the parse table to find the data needed to populate these subgraphs. + // Collect three things during this scan: + // 1) All of the parse states where one of these symbols can start. + // 2) All of the parse states where one of these symbols can end, along + // with information about the node that would be created. + // 3) A list of predecessor states for each state. + StatePredecessorMap predecessor_map = state_predecessor_map_new(self->language); + for (TSStateId state = 1; state < (uint16_t)self->language->state_count; state++) { + unsigned subgraph_index, exists; + LookaheadIterator lookahead_iterator = ts_language_lookaheads(self->language, state); + while (ts_lookahead_iterator__next(&lookahead_iterator)) { + if (lookahead_iterator.action_count) { + for (unsigned i = 0; i < lookahead_iterator.action_count; i++) { + const TSParseAction *action = &lookahead_iterator.actions[i]; + if (action->type == TSParseActionTypeReduce) { + const TSSymbol *aliases, *aliases_end; + ts_language_aliases_for_symbol( + self->language, + action->reduce.symbol, + &aliases, + &aliases_end + ); + for (const TSSymbol *symbol = aliases; symbol < aliases_end; symbol++) { + array_search_sorted_by( + &subgraphs, + .symbol, + *symbol, + &subgraph_index, + &exists + ); + if (exists) { + AnalysisSubgraph *subgraph = array_get(&subgraphs, subgraph_index); + if (subgraph->nodes.size == 0 || array_back(&subgraph->nodes)->state != state) { + array_push(&subgraph->nodes, ((AnalysisSubgraphNode) { + .state = state, + .production_id = action->reduce.production_id, + .child_index = action->reduce.child_count, + .done = true, + })); + } + } + } + } else if (action->type == TSParseActionTypeShift && !action->shift.extra) { + TSStateId next_state = action->shift.state; + state_predecessor_map_add(&predecessor_map, next_state, state); + } + } + } else if (lookahead_iterator.next_state != 0) { + if (lookahead_iterator.next_state != state) { + state_predecessor_map_add(&predecessor_map, lookahead_iterator.next_state, state); + } + if (ts_language_state_is_primary(self->language, state)) { + const TSSymbol *aliases, *aliases_end; + ts_language_aliases_for_symbol( + self->language, + lookahead_iterator.symbol, + &aliases, + &aliases_end + ); + for (const TSSymbol *symbol = aliases; symbol < aliases_end; symbol++) { + array_search_sorted_by( + &subgraphs, + .symbol, + *symbol, + &subgraph_index, + &exists + ); + if (exists) { + AnalysisSubgraph *subgraph = array_get(&subgraphs, subgraph_index); + if ( + subgraph->start_states.size == 0 || + *array_back(&subgraph->start_states) != state + ) + array_push(&subgraph->start_states, state); + } + } + } + } + } + } + + // For each subgraph, compute the preceding states by walking backward + // from the end states using the predecessor map. + Array(AnalysisSubgraphNode) next_nodes = array_new(); + for (unsigned i = 0; i < subgraphs.size; i++) { + AnalysisSubgraph *subgraph = array_get(&subgraphs, i); + if (subgraph->nodes.size == 0) { + array_delete(&subgraph->start_states); + array_erase(&subgraphs, i); + i--; + continue; + } + array_assign(&next_nodes, &subgraph->nodes); + while (next_nodes.size > 0) { + AnalysisSubgraphNode node = array_pop(&next_nodes); + if (node.child_index > 1) { + unsigned predecessor_count; + const TSStateId *predecessors = state_predecessor_map_get( + &predecessor_map, + node.state, + &predecessor_count + ); + for (unsigned j = 0; j < predecessor_count; j++) { + AnalysisSubgraphNode predecessor_node = { + .state = predecessors[j], + .child_index = node.child_index - 1, + .production_id = node.production_id, + .done = false, + }; + unsigned index, exists; + array_search_sorted_with( + &subgraph->nodes, analysis_subgraph_node__compare, &predecessor_node, + &index, &exists + ); + if (!exists) { + array_insert(&subgraph->nodes, index, predecessor_node); + array_push(&next_nodes, predecessor_node); + } + } + } + } + } + + #ifdef DEBUG_ANALYZE_QUERY + printf("\nSubgraphs:\n"); + for (unsigned i = 0; i < subgraphs.size; i++) { + AnalysisSubgraph *subgraph = array_get(&subgraphs, i); + printf(" %u, %s:\n", subgraph->symbol, ts_language_symbol_name(self->language, subgraph->symbol)); + for (unsigned j = 0; j < subgraph->start_states.size; j++) { + printf( + " {state: %u}\n", + *array_get(&subgraph->start_states, j) + ); + } + for (unsigned j = 0; j < subgraph->nodes.size; j++) { + AnalysisSubgraphNode *node = array_get(&subgraph->nodes, j); + printf( + " {state: %u, child_index: %u, production_id: %u, done: %d}\n", + node->state, node->child_index, node->production_id, node->done + ); + } + printf("\n"); + } + #endif + + // For each non-terminal pattern, determine if the pattern can successfully match, + // and identify all of the possible children within the pattern where matching could fail. + bool all_patterns_are_valid = true; + QueryAnalysis analysis = query_analysis__new(); + for (unsigned i = 0; i < parent_step_indices.size; i++) { + uint16_t parent_step_index = *array_get(&parent_step_indices, i); + uint16_t parent_depth = array_get(&self->steps, parent_step_index)->depth; + TSSymbol parent_symbol = array_get(&self->steps, parent_step_index)->symbol; + if (parent_symbol == ts_builtin_sym_error) continue; + + // Find the subgraph that corresponds to this pattern's root symbol. If the pattern's + // root symbol is a terminal, then return an error. + unsigned subgraph_index, exists; + array_search_sorted_by(&subgraphs, .symbol, parent_symbol, &subgraph_index, &exists); + if (!exists) { + unsigned first_child_step_index = parent_step_index + 1; + uint32_t j, child_exists; + array_search_sorted_by(&self->step_offsets, .step_index, first_child_step_index, &j, &child_exists); + ts_assert(child_exists); + *error_offset = array_get(&self->step_offsets, j)->byte_offset; + all_patterns_are_valid = false; + break; + } + + // Initialize an analysis state at every parse state in the table where + // this parent symbol can occur. + AnalysisSubgraph *subgraph = array_get(&subgraphs, subgraph_index); + analysis_state_set__clear(&analysis.states, &analysis.state_pool); + analysis_state_set__clear(&analysis.deeper_states, &analysis.state_pool); + for (unsigned j = 0; j < subgraph->start_states.size; j++) { + TSStateId parse_state = *array_get(&subgraph->start_states, j); + analysis_state_set__push(&analysis.states, &analysis.state_pool, &((AnalysisState) { + .step_index = parent_step_index + 1, + .stack = { + [0] = { + .parse_state = parse_state, + .parent_symbol = parent_symbol, + .child_index = 0, + .field_id = 0, + .done = false, + }, + }, + .depth = 1, + .root_symbol = parent_symbol, + })); + } + + #ifdef DEBUG_ANALYZE_QUERY + printf( + "\nWalk states for %s:\n", + ts_language_symbol_name(self->language, (*array_get(&analysis.states, 0))->stack[0].parent_symbol) + ); + #endif + + analysis.did_abort = false; + ts_query__perform_analysis(self, &subgraphs, &analysis); + + // If this pattern could not be fully analyzed, then every step should + // be considered fallible. + if (analysis.did_abort) { + for (unsigned j = parent_step_index + 1; j < self->steps.size; j++) { + QueryStep *step = array_get(&self->steps, j); + if ( + step->depth <= parent_depth || + step->depth == PATTERN_DONE_MARKER + ) break; + if (!step->is_dead_end) { + step->parent_pattern_guaranteed = false; + step->root_pattern_guaranteed = false; + } + } + continue; + } + + // If this pattern cannot match, store the pattern index so that it can be + // returned to the caller. + if (analysis.finished_parent_symbols.size == 0) { + ts_assert(analysis.final_step_indices.size > 0); + uint16_t impossible_step_index = *array_back(&analysis.final_step_indices); + uint32_t j, impossible_exists; + array_search_sorted_by(&self->step_offsets, .step_index, impossible_step_index, &j, &impossible_exists); + if (j >= self->step_offsets.size) j = self->step_offsets.size - 1; + *error_offset = array_get(&self->step_offsets, j)->byte_offset; + all_patterns_are_valid = false; + break; + } + + // Mark as fallible any step where a match terminated. + // Later, this property will be propagated to all of the step's predecessors. + for (unsigned j = 0; j < analysis.final_step_indices.size; j++) { + uint32_t final_step_index = *array_get(&analysis.final_step_indices, j); + QueryStep *step = array_get(&self->steps, final_step_index); + if ( + step->depth != PATTERN_DONE_MARKER && + step->depth > parent_depth && + !step->is_dead_end + ) { + step->parent_pattern_guaranteed = false; + step->root_pattern_guaranteed = false; + } + } + } + + // Mark as indefinite any step with captures that are used in predicates. + Array(uint16_t) predicate_capture_ids = array_new(); + for (unsigned i = 0; i < self->patterns.size; i++) { + QueryPattern *pattern = array_get(&self->patterns, i); + + // Gather all of the captures that are used in predicates for this pattern. + array_clear(&predicate_capture_ids); + for ( + unsigned start = pattern->predicate_steps.offset, + end = start + pattern->predicate_steps.length, + j = start; j < end; j++ + ) { + TSQueryPredicateStep *step = array_get(&self->predicate_steps, j); + if (step->type == TSQueryPredicateStepTypeCapture) { + uint16_t value_id = step->value_id; + array_insert_sorted_by(&predicate_capture_ids, , value_id); + } + } + + // Find all of the steps that have these captures. + for ( + unsigned start = pattern->steps.offset, + end = start + pattern->steps.length, + j = start; j < end; j++ + ) { + QueryStep *step = array_get(&self->steps, j); + for (unsigned k = 0; k < MAX_STEP_CAPTURE_COUNT; k++) { + uint16_t capture_id = step->capture_ids[k]; + if (capture_id == NONE) break; + unsigned index, exists; + array_search_sorted_by(&predicate_capture_ids, , capture_id, &index, &exists); + if (exists) { + step->root_pattern_guaranteed = false; + break; + } + } + } + } + + // Propagate fallibility. If a pattern is fallible at a given step, then it is + // fallible at all of its preceding steps. + bool done = self->steps.size == 0; + while (!done) { + done = true; + for (unsigned i = self->steps.size - 1; i > 0; i--) { + QueryStep *step = array_get(&self->steps, i); + if (step->depth == PATTERN_DONE_MARKER) continue; + + // Determine if this step is definite or has definite alternatives. + bool parent_pattern_guaranteed = false; + for (;;) { + if (step->root_pattern_guaranteed) { + parent_pattern_guaranteed = true; + break; + } + if (step->alternative_index == NONE || step->alternative_index < i) { + break; + } + step = array_get(&self->steps, step->alternative_index); + } + + // If not, mark its predecessor as indefinite. + if (!parent_pattern_guaranteed) { + QueryStep *prev_step = array_get(&self->steps, i - 1); + if ( + !prev_step->is_dead_end && + prev_step->depth != PATTERN_DONE_MARKER && + prev_step->root_pattern_guaranteed + ) { + prev_step->root_pattern_guaranteed = false; + done = false; + } + } + } + } + + #ifdef DEBUG_ANALYZE_QUERY + printf("Steps:\n"); + for (unsigned i = 0; i < self->steps.size; i++) { + QueryStep *step = array_get(&self->steps, i); + if (step->depth == PATTERN_DONE_MARKER) { + printf(" %u: DONE\n", i); + } else { + printf( + " %u: {symbol: %s, field: %s, depth: %u, parent_pattern_guaranteed: %d, root_pattern_guaranteed: %d}\n", + i, + (step->symbol == WILDCARD_SYMBOL) + ? "ANY" + : ts_language_symbol_name(self->language, step->symbol), + (step->field ? ts_language_field_name_for_id(self->language, step->field) : "-"), + step->depth, + step->parent_pattern_guaranteed, + step->root_pattern_guaranteed + ); + } + } + #endif + + // Determine which repetition symbols in this language have the possibility + // of matching non-rooted patterns in this query. These repetition symbols + // prevent certain optimizations with range restrictions. + analysis.did_abort = false; + for (uint32_t i = 0; i < non_rooted_pattern_start_steps.size; i++) { + uint16_t pattern_entry_index = *array_get(&non_rooted_pattern_start_steps, i); + PatternEntry *pattern_entry = array_get(&self->pattern_map, pattern_entry_index); + + analysis_state_set__clear(&analysis.states, &analysis.state_pool); + analysis_state_set__clear(&analysis.deeper_states, &analysis.state_pool); + for (unsigned j = 0; j < subgraphs.size; j++) { + AnalysisSubgraph *subgraph = array_get(&subgraphs, j); + TSSymbolMetadata metadata = ts_language_symbol_metadata(self->language, subgraph->symbol); + if (metadata.visible || metadata.named) continue; + + for (uint32_t k = 0; k < subgraph->start_states.size; k++) { + TSStateId parse_state = *array_get(&subgraph->start_states, k); + analysis_state_set__push(&analysis.states, &analysis.state_pool, &((AnalysisState) { + .step_index = pattern_entry->step_index, + .stack = { + [0] = { + .parse_state = parse_state, + .parent_symbol = subgraph->symbol, + .child_index = 0, + .field_id = 0, + .done = false, + }, + }, + .root_symbol = subgraph->symbol, + .depth = 1, + })); + } + } + + #ifdef DEBUG_ANALYZE_QUERY + printf("\nWalk states for rootless pattern step %u:\n", pattern_entry->step_index); + #endif + + ts_query__perform_analysis( + self, + &subgraphs, + &analysis + ); + + if (analysis.finished_parent_symbols.size > 0) { + array_get(&self->patterns, pattern_entry->pattern_index)->is_non_local = true; + } + + for (unsigned k = 0; k < analysis.finished_parent_symbols.size; k++) { + TSSymbol symbol = *array_get(&analysis.finished_parent_symbols, k); + array_insert_sorted_by(&self->repeat_symbols_with_rootless_patterns, , symbol); + } + } + + #ifdef DEBUG_ANALYZE_QUERY + if (self->repeat_symbols_with_rootless_patterns.size > 0) { + printf("\nRepetition symbols with rootless patterns:\n"); + printf("aborted analysis: %d\n", analysis.did_abort); + for (unsigned i = 0; i < self->repeat_symbols_with_rootless_patterns.size; i++) { + TSSymbol symbol = *array_get(&self->repeat_symbols_with_rootless_patterns, i); + printf(" %u, %s\n", symbol, ts_language_symbol_name(self->language, symbol)); + } + printf("\n"); + } + #endif + + // Cleanup + for (unsigned i = 0; i < subgraphs.size; i++) { + array_delete(&array_get(&subgraphs, i)->start_states); + array_delete(&array_get(&subgraphs, i)->nodes); + } + array_delete(&subgraphs); + query_analysis__delete(&analysis); + array_delete(&next_nodes); + array_delete(&non_rooted_pattern_start_steps); + array_delete(&parent_step_indices); + array_delete(&predicate_capture_ids); + state_predecessor_map_delete(&predecessor_map); + + return all_patterns_are_valid; +} + +static void ts_query__add_negated_fields( + TSQuery *self, + uint16_t step_index, + TSFieldId *field_ids, + uint16_t field_count +) { + QueryStep *step = array_get(&self->steps, step_index); + + // The negated field array stores a list of field lists, separated by zeros. + // Try to find the start index of an existing list that matches this new list. + bool failed_match = false; + unsigned match_count = 0; + unsigned start_i = 0; + for (unsigned i = 0; i < self->negated_fields.size; i++) { + TSFieldId existing_field_id = *array_get(&self->negated_fields, i); + + // At each zero value, terminate the match attempt. If we've exactly + // matched the new field list, then reuse this index. Otherwise, + // start over the matching process. + if (existing_field_id == 0) { + if (match_count == field_count) { + step->negated_field_list_id = start_i; + return; + } else { + start_i = i + 1; + match_count = 0; + failed_match = false; + } + } + + // If the existing list matches our new list so far, then advance + // to the next element of the new list. + else if ( + match_count < field_count && + existing_field_id == field_ids[match_count] && + !failed_match + ) { + match_count++; + } + + // Otherwise, this existing list has failed to match. + else { + match_count = 0; + failed_match = true; + } + } + + step->negated_field_list_id = self->negated_fields.size; + array_extend(&self->negated_fields, field_count, field_ids); + array_push(&self->negated_fields, 0); +} + +static TSQueryError ts_query__parse_string_literal( + TSQuery *self, + Stream *stream +) { + const char *string_start = stream->input; + if (stream->next != '"') return TSQueryErrorSyntax; + stream_advance(stream); + const char *prev_position = stream->input; + + bool is_escaped = false; + array_clear(&self->string_buffer); + for (;;) { + if (is_escaped) { + is_escaped = false; + switch (stream->next) { + case 'n': + array_push(&self->string_buffer, '\n'); + break; + case 'r': + array_push(&self->string_buffer, '\r'); + break; + case 't': + array_push(&self->string_buffer, '\t'); + break; + case '0': + array_push(&self->string_buffer, '\0'); + break; + default: + array_extend(&self->string_buffer, stream->next_size, stream->input); + break; + } + prev_position = stream->input + stream->next_size; + } else { + if (stream->next == '\\') { + array_extend(&self->string_buffer, (uint32_t)(stream->input - prev_position), prev_position); + prev_position = stream->input + 1; + is_escaped = true; + } else if (stream->next == '"') { + array_extend(&self->string_buffer, (uint32_t)(stream->input - prev_position), prev_position); + stream_advance(stream); + return TSQueryErrorNone; + } else if (stream->next == '\n') { + stream_reset(stream, string_start); + return TSQueryErrorSyntax; + } + } + if (!stream_advance(stream)) { + stream_reset(stream, string_start); + return TSQueryErrorSyntax; + } + } +} + +// Parse a single predicate associated with a pattern, adding it to the +// query's internal `predicate_steps` array. Predicates are arbitrary +// S-expressions associated with a pattern which are meant to be handled at +// a higher level of abstraction, such as the Rust/JavaScript bindings. They +// can contain '@'-prefixed capture names, double-quoted strings, and bare +// symbols, which also represent strings. +static TSQueryError ts_query__parse_predicate( + TSQuery *self, + Stream *stream +) { + if (!stream_is_ident_start(stream)) return TSQueryErrorSyntax; + const char *predicate_name = stream->input; + stream_scan_identifier(stream); + uint32_t length = (uint32_t)(stream->input - predicate_name); + uint16_t id = symbol_table_insert_name( + &self->predicate_values, + predicate_name, + length + ); + array_push(&self->predicate_steps, ((TSQueryPredicateStep) { + .type = TSQueryPredicateStepTypeString, + .value_id = id, + })); + stream_skip_whitespace(stream); + + for (;;) { + if (stream->next == ')') { + stream_advance(stream); + stream_skip_whitespace(stream); + array_push(&self->predicate_steps, ((TSQueryPredicateStep) { + .type = TSQueryPredicateStepTypeDone, + .value_id = 0, + })); + break; + } + + // Parse an '@'-prefixed capture name + else if (stream->next == '@') { + stream_advance(stream); + + // Parse the capture name + if (!stream_is_ident_start(stream)) return TSQueryErrorSyntax; + const char *capture_name = stream->input; + stream_scan_identifier(stream); + uint32_t capture_length = (uint32_t)(stream->input - capture_name); + + // Add the capture id to the first step of the pattern + int capture_id = symbol_table_id_for_name( + &self->captures, + capture_name, + capture_length + ); + if (capture_id == -1) { + stream_reset(stream, capture_name); + return TSQueryErrorCapture; + } + + array_push(&self->predicate_steps, ((TSQueryPredicateStep) { + .type = TSQueryPredicateStepTypeCapture, + .value_id = capture_id, + })); + } + + // Parse a string literal + else if (stream->next == '"') { + TSQueryError e = ts_query__parse_string_literal(self, stream); + if (e) return e; + uint16_t query_id = symbol_table_insert_name( + &self->predicate_values, + self->string_buffer.contents, + self->string_buffer.size + ); + array_push(&self->predicate_steps, ((TSQueryPredicateStep) { + .type = TSQueryPredicateStepTypeString, + .value_id = query_id, + })); + } + + // Parse a bare symbol + else if (stream_is_ident_start(stream)) { + const char *symbol_start = stream->input; + stream_scan_identifier(stream); + uint32_t symbol_length = (uint32_t)(stream->input - symbol_start); + uint16_t query_id = symbol_table_insert_name( + &self->predicate_values, + symbol_start, + symbol_length + ); + array_push(&self->predicate_steps, ((TSQueryPredicateStep) { + .type = TSQueryPredicateStepTypeString, + .value_id = query_id, + })); + } + + else { + return TSQueryErrorSyntax; + } + + stream_skip_whitespace(stream); + } + + return 0; +} + +// Read one S-expression pattern from the stream, and incorporate it into +// the query's internal state machine representation. For nested patterns, +// this function calls itself recursively. +// +// The caller is responsible for passing in a dedicated CaptureQuantifiers. +// These should not be shared between different calls to ts_query__parse_pattern! +static TSQueryError ts_query__parse_pattern( + TSQuery *self, + Stream *stream, + uint32_t depth, + bool is_immediate, + CaptureQuantifiers *capture_quantifiers +) { + if (stream->next == 0) return TSQueryErrorSyntax; + if (stream->next == ')' || stream->next == ']') return PARENT_DONE; + + const uint32_t starting_step_index = self->steps.size; + + // Store the byte offset of each step in the query. + if ( + self->step_offsets.size == 0 || + array_back(&self->step_offsets)->step_index != starting_step_index + ) { + array_push(&self->step_offsets, ((StepOffset) { + .step_index = starting_step_index, + .byte_offset = stream_offset(stream), + })); + } + + // An open bracket is the start of an alternation. + if (stream->next == '[') { + stream_advance(stream); + stream_skip_whitespace(stream); + + // Parse each branch, and add a placeholder step in between the branches. + Array(uint32_t) branch_step_indices = array_new(); + CaptureQuantifiers branch_capture_quantifiers = capture_quantifiers_new(); + for (;;) { + uint32_t start_index = self->steps.size; + TSQueryError e = ts_query__parse_pattern( + self, + stream, + depth, + is_immediate, + &branch_capture_quantifiers + ); + + if (e == PARENT_DONE) { + if (stream->next == ']' && branch_step_indices.size > 0) { + stream_advance(stream); + break; + } + e = TSQueryErrorSyntax; + } + if (e) { + capture_quantifiers_delete(&branch_capture_quantifiers); + array_delete(&branch_step_indices); + return e; + } + + if (start_index == starting_step_index) { + capture_quantifiers_replace(capture_quantifiers, &branch_capture_quantifiers); + } else { + capture_quantifiers_join_all(capture_quantifiers, &branch_capture_quantifiers); + } + + array_push(&branch_step_indices, start_index); + array_push(&self->steps, query_step__new(0, depth, false)); + capture_quantifiers_clear(&branch_capture_quantifiers); + } + (void)array_pop(&self->steps); + + // For all of the branches except for the last one, add the subsequent branch as an + // alternative, and link the end of the branch to the current end of the steps. + for (unsigned i = 0; i < branch_step_indices.size - 1; i++) { + uint32_t step_index = *array_get(&branch_step_indices, i); + uint32_t next_step_index = *array_get(&branch_step_indices, i + 1); + QueryStep *start_step = array_get(&self->steps, step_index); + QueryStep *end_step = array_get(&self->steps, next_step_index - 1); + start_step->alternative_index = next_step_index; + end_step->alternative_index = self->steps.size; + end_step->is_dead_end = true; + } + + capture_quantifiers_delete(&branch_capture_quantifiers); + array_delete(&branch_step_indices); + } + + // An open parenthesis can be the start of three possible constructs: + // * A grouped sequence + // * A predicate + // * A named node + else if (stream->next == '(') { + stream_advance(stream); + stream_skip_whitespace(stream); + + // If this parenthesis is followed by a node, then it represents a grouped sequence. + if (stream->next == '(' || stream->next == '"' || stream->next == '[') { + bool child_is_immediate = is_immediate; + CaptureQuantifiers child_capture_quantifiers = capture_quantifiers_new(); + for (;;) { + if (stream->next == '.') { + child_is_immediate = true; + stream_advance(stream); + stream_skip_whitespace(stream); + } + TSQueryError e = ts_query__parse_pattern( + self, + stream, + depth, + child_is_immediate, + &child_capture_quantifiers + ); + if (e == PARENT_DONE) { + if (stream->next == ')') { + stream_advance(stream); + break; + } + e = TSQueryErrorSyntax; + } + if (e) { + capture_quantifiers_delete(&child_capture_quantifiers); + return e; + } + + capture_quantifiers_add_all(capture_quantifiers, &child_capture_quantifiers); + capture_quantifiers_clear(&child_capture_quantifiers); + child_is_immediate = false; + } + + capture_quantifiers_delete(&child_capture_quantifiers); + } + + // A dot/pound character indicates the start of a predicate. + else if (stream->next == '.' || stream->next == '#') { + stream_advance(stream); + return ts_query__parse_predicate(self, stream); + } + + // Otherwise, this parenthesis is the start of a named node. + else { + TSSymbol symbol; + bool is_missing = false; + const char *node_name = stream->input; + + // Parse a normal node name + if (stream_is_ident_start(stream)) { + stream_scan_identifier(stream); + uint32_t length = (uint32_t)(stream->input - node_name); + + // Parse the wildcard symbol + if (length == 1 && node_name[0] == '_') { + symbol = WILDCARD_SYMBOL; + } else if (!strncmp(node_name, "MISSING", length)) { + is_missing = true; + stream_skip_whitespace(stream); + + if (stream_is_ident_start(stream)) { + const char *missing_node_name = stream->input; + stream_scan_identifier(stream); + uint32_t missing_node_length = (uint32_t)(stream->input - missing_node_name); + symbol = ts_language_symbol_for_name( + self->language, + missing_node_name, + missing_node_length, + true + ); + if (!symbol) { + stream_reset(stream, missing_node_name); + return TSQueryErrorNodeType; + } + } + + else if (stream->next == '"') { + const char *string_start = stream->input; + TSQueryError e = ts_query__parse_string_literal(self, stream); + if (e) return e; + + symbol = ts_language_symbol_for_name( + self->language, + self->string_buffer.contents, + self->string_buffer.size, + false + ); + if (!symbol) { + stream_reset(stream, string_start + 1); + return TSQueryErrorNodeType; + } + } + + else if (stream->next == ')') { + symbol = WILDCARD_SYMBOL; + } + + else { + stream_reset(stream, stream->input); + return TSQueryErrorSyntax; + } + } + + else { + symbol = ts_language_symbol_for_name( + self->language, + node_name, + length, + true + ); + if (!symbol) { + stream_reset(stream, node_name); + return TSQueryErrorNodeType; + } + } + } else { + return TSQueryErrorSyntax; + } + + // Add a step for the node. + array_push(&self->steps, query_step__new(symbol, depth, is_immediate)); + QueryStep *step = array_back(&self->steps); + if (ts_language_symbol_metadata(self->language, symbol).supertype) { + step->supertype_symbol = step->symbol; + step->symbol = WILDCARD_SYMBOL; + } + if (is_missing) { + step->is_missing = true; + } + if (symbol == WILDCARD_SYMBOL) { + step->is_named = true; + } + + stream_skip_whitespace(stream); + + if (stream->next == '/') { + if (!step->supertype_symbol) { + stream_reset(stream, node_name - 1); // reset to the start of the node + return TSQueryErrorStructure; + } + + stream_advance(stream); + if (!stream_is_ident_start(stream)) { + return TSQueryErrorSyntax; + } + + const char *subtype_node_name = stream->input; + stream_scan_identifier(stream); + uint32_t length = (uint32_t)(stream->input - subtype_node_name); + + step->symbol = ts_language_symbol_for_name( + self->language, + subtype_node_name, + length, + true + ); + if (!step->symbol) { + stream_reset(stream, subtype_node_name); + return TSQueryErrorNodeType; + } + + // Get all the possible subtypes for the given supertype, + // and check if the given subtype is valid. + if (self->language->abi_version >= LANGUAGE_VERSION_WITH_RESERVED_WORDS) { + uint32_t subtype_length; + const TSSymbol *subtypes = ts_language_subtypes( + self->language, + step->supertype_symbol, + &subtype_length + ); + + bool subtype_is_valid = false; + for (uint32_t i = 0; i < subtype_length; i++) { + if (subtypes[i] == step->symbol) { + subtype_is_valid = true; + break; + } + } + + // This subtype is not valid for the given supertype. + if (!subtype_is_valid) { + stream_reset(stream, node_name - 1); // reset to the start of the node + return TSQueryErrorStructure; + } + } + + stream_skip_whitespace(stream); + } + + // Parse the child patterns + bool child_is_immediate = false; + uint16_t last_child_step_index = 0; + uint16_t negated_field_count = 0; + TSFieldId negated_field_ids[MAX_NEGATED_FIELD_COUNT]; + CaptureQuantifiers child_capture_quantifiers = capture_quantifiers_new(); + for (;;) { + // Parse a negated field assertion + if (stream->next == '!') { + stream_advance(stream); + stream_skip_whitespace(stream); + if (!stream_is_ident_start(stream)) { + capture_quantifiers_delete(&child_capture_quantifiers); + return TSQueryErrorSyntax; + } + const char *field_name = stream->input; + stream_scan_identifier(stream); + uint32_t length = (uint32_t)(stream->input - field_name); + stream_skip_whitespace(stream); + + TSFieldId field_id = ts_language_field_id_for_name( + self->language, + field_name, + length + ); + if (!field_id) { + stream->input = field_name; + capture_quantifiers_delete(&child_capture_quantifiers); + return TSQueryErrorField; + } + + // Keep the field ids sorted. + if (negated_field_count < MAX_NEGATED_FIELD_COUNT) { + negated_field_ids[negated_field_count] = field_id; + negated_field_count++; + } + + continue; + } + + // Parse a sibling anchor + if (stream->next == '.') { + child_is_immediate = true; + stream_advance(stream); + stream_skip_whitespace(stream); + } + + uint16_t step_index = self->steps.size; + TSQueryError e = ts_query__parse_pattern( + self, + stream, + depth + 1, + child_is_immediate, + &child_capture_quantifiers + ); + // In the event we only parsed a predicate, meaning no new steps were added, + // then subtract one so we're not indexing past the end of the array + if (step_index == self->steps.size) step_index--; + if (e == PARENT_DONE) { + if (stream->next == ')') { + if (child_is_immediate) { + if (last_child_step_index == 0) { + capture_quantifiers_delete(&child_capture_quantifiers); + return TSQueryErrorSyntax; + } + // Mark this step *and* its alternatives as the last child of the parent. + QueryStep *last_child_step = array_get(&self->steps, last_child_step_index); + last_child_step->is_last_child = true; + if ( + last_child_step->alternative_index != NONE && + last_child_step->alternative_index < self->steps.size + ) { + QueryStep *alternative_step = array_get(&self->steps, last_child_step->alternative_index); + alternative_step->is_last_child = true; + while ( + alternative_step->alternative_index != NONE && + alternative_step->alternative_index < self->steps.size + ) { + alternative_step = array_get(&self->steps, alternative_step->alternative_index); + alternative_step->is_last_child = true; + } + } + } + + if (negated_field_count) { + ts_query__add_negated_fields( + self, + starting_step_index, + negated_field_ids, + negated_field_count + ); + } + + stream_advance(stream); + break; + } + e = TSQueryErrorSyntax; + } + if (e) { + capture_quantifiers_delete(&child_capture_quantifiers); + return e; + } + + capture_quantifiers_add_all(capture_quantifiers, &child_capture_quantifiers); + + last_child_step_index = step_index; + child_is_immediate = false; + capture_quantifiers_clear(&child_capture_quantifiers); + } + capture_quantifiers_delete(&child_capture_quantifiers); + } + } + + // Parse a wildcard pattern + else if (stream->next == '_') { + stream_advance(stream); + stream_skip_whitespace(stream); + + // Add a step that matches any kind of node + array_push(&self->steps, query_step__new(WILDCARD_SYMBOL, depth, is_immediate)); + } + + // Parse a double-quoted anonymous leaf node expression + else if (stream->next == '"') { + const char *string_start = stream->input; + TSQueryError e = ts_query__parse_string_literal(self, stream); + if (e) return e; + + // Add a step for the node + TSSymbol symbol = ts_language_symbol_for_name( + self->language, + self->string_buffer.contents, + self->string_buffer.size, + false + ); + if (!symbol) { + stream_reset(stream, string_start + 1); + return TSQueryErrorNodeType; + } + array_push(&self->steps, query_step__new(symbol, depth, is_immediate)); + } + + // Parse a field-prefixed pattern + else if (stream_is_ident_start(stream)) { + // Parse the field name + const char *field_name = stream->input; + stream_scan_identifier(stream); + uint32_t length = (uint32_t)(stream->input - field_name); + stream_skip_whitespace(stream); + + if (stream->next != ':') { + stream_reset(stream, field_name); + return TSQueryErrorSyntax; + } + stream_advance(stream); + stream_skip_whitespace(stream); + + // Parse the pattern + CaptureQuantifiers field_capture_quantifiers = capture_quantifiers_new(); + TSQueryError e = ts_query__parse_pattern( + self, + stream, + depth, + is_immediate, + &field_capture_quantifiers + ); + if (e) { + capture_quantifiers_delete(&field_capture_quantifiers); + if (e == PARENT_DONE) e = TSQueryErrorSyntax; + return e; + } + + // Add the field name to the first step of the pattern + TSFieldId field_id = ts_language_field_id_for_name( + self->language, + field_name, + length + ); + if (!field_id) { + stream->input = field_name; + return TSQueryErrorField; + } + + uint32_t step_index = starting_step_index; + QueryStep *step = array_get(&self->steps, step_index); + for (;;) { + step->field = field_id; + if ( + step->alternative_index != NONE && + step->alternative_index > step_index && + step->alternative_index < self->steps.size + ) { + step_index = step->alternative_index; + step = array_get(&self->steps, step_index); + } else { + break; + } + } + + capture_quantifiers_add_all(capture_quantifiers, &field_capture_quantifiers); + capture_quantifiers_delete(&field_capture_quantifiers); + } + + else { + return TSQueryErrorSyntax; + } + + stream_skip_whitespace(stream); + + // Parse suffixes modifiers for this pattern + TSQuantifier quantifier = TSQuantifierOne; + for (;;) { + // Parse the one-or-more operator. + if (stream->next == '+') { + quantifier = quantifier_join(TSQuantifierOneOrMore, quantifier); + + stream_advance(stream); + stream_skip_whitespace(stream); + + QueryStep repeat_step = query_step__new(WILDCARD_SYMBOL, depth, false); + repeat_step.alternative_index = starting_step_index; + repeat_step.is_pass_through = true; + repeat_step.alternative_is_immediate = true; + array_push(&self->steps, repeat_step); + } + + // Parse the zero-or-more repetition operator. + else if (stream->next == '*') { + quantifier = quantifier_join(TSQuantifierZeroOrMore, quantifier); + + stream_advance(stream); + stream_skip_whitespace(stream); + + QueryStep repeat_step = query_step__new(WILDCARD_SYMBOL, depth, false); + repeat_step.alternative_index = starting_step_index; + repeat_step.is_pass_through = true; + repeat_step.alternative_is_immediate = true; + array_push(&self->steps, repeat_step); + + // Stop when `step->alternative_index` is `NONE` or it points to + // `repeat_step` or beyond. Note that having just been pushed, + // `repeat_step` occupies slot `self->steps.size - 1`. + QueryStep *step = array_get(&self->steps, starting_step_index); + while (step->alternative_index != NONE && step->alternative_index < self->steps.size - 1) { + step = array_get(&self->steps, step->alternative_index); + } + step->alternative_index = self->steps.size; + } + + // Parse the optional operator. + else if (stream->next == '?') { + quantifier = quantifier_join(TSQuantifierZeroOrOne, quantifier); + + stream_advance(stream); + stream_skip_whitespace(stream); + + QueryStep *step = array_get(&self->steps, starting_step_index); + while (step->alternative_index != NONE && step->alternative_index < self->steps.size) { + step = array_get(&self->steps, step->alternative_index); + } + step->alternative_index = self->steps.size; + } + + // Parse an '@'-prefixed capture pattern + else if (stream->next == '@') { + stream_advance(stream); + if (!stream_is_ident_start(stream)) return TSQueryErrorSyntax; + const char *capture_name = stream->input; + stream_scan_identifier(stream); + uint32_t length = (uint32_t)(stream->input - capture_name); + stream_skip_whitespace(stream); + + // Add the capture id to the first step of the pattern + uint16_t capture_id = symbol_table_insert_name( + &self->captures, + capture_name, + length + ); + + // Add the capture quantifier + capture_quantifiers_add_for_id(capture_quantifiers, capture_id, TSQuantifierOne); + + uint32_t step_index = starting_step_index; + for (;;) { + QueryStep *step = array_get(&self->steps, step_index); + query_step__add_capture(step, capture_id); + if ( + step->alternative_index != NONE && + step->alternative_index > step_index && + step->alternative_index < self->steps.size + ) { + step_index = step->alternative_index; + } else { + break; + } + } + } + + // No more suffix modifiers + else { + break; + } + } + + capture_quantifiers_mul(capture_quantifiers, quantifier); + + return 0; +} + +TSQuery *ts_query_new( + const TSLanguage *language, + const char *source, + uint32_t source_len, + uint32_t *error_offset, + TSQueryError *error_type +) { + if ( + !language || + language->abi_version > TREE_SITTER_LANGUAGE_VERSION || + language->abi_version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION + ) { + *error_type = TSQueryErrorLanguage; + return NULL; + } + + TSQuery *self = ts_malloc(sizeof(TSQuery)); + *self = (TSQuery) { + .steps = array_new(), + .pattern_map = array_new(), + .captures = symbol_table_new(), + .capture_quantifiers = array_new(), + .predicate_values = symbol_table_new(), + .predicate_steps = array_new(), + .patterns = array_new(), + .step_offsets = array_new(), + .string_buffer = array_new(), + .negated_fields = array_new(), + .repeat_symbols_with_rootless_patterns = array_new(), + .wildcard_root_pattern_count = 0, + .language = ts_language_copy(language), + }; + + array_push(&self->negated_fields, 0); + + // Parse all of the S-expressions in the given string. + Stream stream = stream_new(source, source_len); + stream_skip_whitespace(&stream); + while (stream.input < stream.end) { + uint32_t pattern_index = self->patterns.size; + uint32_t start_step_index = self->steps.size; + uint32_t start_predicate_step_index = self->predicate_steps.size; + array_push(&self->patterns, ((QueryPattern) { + .steps = (Slice) {.offset = start_step_index}, + .predicate_steps = (Slice) {.offset = start_predicate_step_index}, + .start_byte = stream_offset(&stream), + .is_non_local = false, + })); + CaptureQuantifiers capture_quantifiers = capture_quantifiers_new(); + *error_type = ts_query__parse_pattern(self, &stream, 0, false, &capture_quantifiers); + array_push(&self->steps, query_step__new(0, PATTERN_DONE_MARKER, false)); + + QueryPattern *pattern = array_back(&self->patterns); + pattern->steps.length = self->steps.size - start_step_index; + pattern->predicate_steps.length = self->predicate_steps.size - start_predicate_step_index; + pattern->end_byte = stream_offset(&stream); + + // If any pattern could not be parsed, then report the error information + // and terminate. + if (*error_type) { + if (*error_type == PARENT_DONE) *error_type = TSQueryErrorSyntax; + *error_offset = stream_offset(&stream); + capture_quantifiers_delete(&capture_quantifiers); + ts_query_delete(self); + return NULL; + } + + // Maintain a list of capture quantifiers for each pattern + array_push(&self->capture_quantifiers, capture_quantifiers); + + // Maintain a map that can look up patterns for a given root symbol. + uint16_t wildcard_root_alternative_index = NONE; + for (;;) { + QueryStep *step = array_get(&self->steps, start_step_index); + + // If a pattern has a wildcard at its root, but it has a non-wildcard child, + // then optimize the matching process by skipping matching the wildcard. + // Later, during the matching process, the query cursor will check that + // there is a parent node, and capture it if necessary. + if (step->symbol == WILDCARD_SYMBOL && step->depth == 0 && !step->field) { + QueryStep *second_step = array_get(&self->steps, start_step_index + 1); + if (second_step->symbol != WILDCARD_SYMBOL && second_step->depth == 1 && !second_step->is_immediate) { + wildcard_root_alternative_index = step->alternative_index; + start_step_index += 1; + step = second_step; + } + } + + // Determine whether the pattern has a single root node. This affects + // decisions about whether or not to start matching the pattern when + // a query cursor has a range restriction or when immediately within an + // error node. + uint32_t start_depth = step->depth; + bool is_rooted = start_depth == 0; + for (uint32_t step_index = start_step_index + 1; step_index < self->steps.size; step_index++) { + QueryStep *child_step = array_get(&self->steps, step_index); + if (child_step->is_dead_end) break; + if (child_step->depth == start_depth) { + is_rooted = false; + break; + } + } + + ts_query__pattern_map_insert(self, step->symbol, (PatternEntry) { + .step_index = start_step_index, + .pattern_index = pattern_index, + .is_rooted = is_rooted + }); + if (step->symbol == WILDCARD_SYMBOL) { + self->wildcard_root_pattern_count++; + } + + // If there are alternatives or options at the root of the pattern, + // then add multiple entries to the pattern map. + if (step->alternative_index != NONE) { + start_step_index = step->alternative_index; + } else if (wildcard_root_alternative_index != NONE) { + start_step_index = wildcard_root_alternative_index; + wildcard_root_alternative_index = NONE; + } else { + break; + } + } + } + + if (!ts_query__analyze_patterns(self, error_offset)) { + *error_type = TSQueryErrorStructure; + ts_query_delete(self); + return NULL; + } + + array_delete(&self->string_buffer); + return self; +} + +void ts_query_delete(TSQuery *self) { + if (self) { + array_delete(&self->steps); + array_delete(&self->pattern_map); + array_delete(&self->predicate_steps); + array_delete(&self->patterns); + array_delete(&self->step_offsets); + array_delete(&self->string_buffer); + array_delete(&self->negated_fields); + array_delete(&self->repeat_symbols_with_rootless_patterns); + ts_language_delete(self->language); + symbol_table_delete(&self->captures); + symbol_table_delete(&self->predicate_values); + for (uint32_t index = 0; index < self->capture_quantifiers.size; index++) { + CaptureQuantifiers *capture_quantifiers = array_get(&self->capture_quantifiers, index); + capture_quantifiers_delete(capture_quantifiers); + } + array_delete(&self->capture_quantifiers); + ts_free(self); + } +} + +uint32_t ts_query_pattern_count(const TSQuery *self) { + return self->patterns.size; +} + +uint32_t ts_query_capture_count(const TSQuery *self) { + return self->captures.slices.size; +} + +uint32_t ts_query_string_count(const TSQuery *self) { + return self->predicate_values.slices.size; +} + +const char *ts_query_capture_name_for_id( + const TSQuery *self, + uint32_t index, + uint32_t *length +) { + return symbol_table_name_for_id(&self->captures, index, length); +} + +TSQuantifier ts_query_capture_quantifier_for_id( + const TSQuery *self, + uint32_t pattern_index, + uint32_t capture_index +) { + CaptureQuantifiers *capture_quantifiers = array_get(&self->capture_quantifiers, pattern_index); + return capture_quantifier_for_id(capture_quantifiers, capture_index); +} + +const char *ts_query_string_value_for_id( + const TSQuery *self, + uint32_t index, + uint32_t *length +) { + return symbol_table_name_for_id(&self->predicate_values, index, length); +} + +const TSQueryPredicateStep *ts_query_predicates_for_pattern( + const TSQuery *self, + uint32_t pattern_index, + uint32_t *step_count +) { + Slice slice = array_get(&self->patterns, pattern_index)->predicate_steps; + *step_count = slice.length; + if (slice.length == 0) return NULL; + return array_get(&self->predicate_steps, slice.offset); +} + +uint32_t ts_query_start_byte_for_pattern( + const TSQuery *self, + uint32_t pattern_index +) { + return array_get(&self->patterns, pattern_index)->start_byte; +} + +uint32_t ts_query_end_byte_for_pattern( + const TSQuery *self, + uint32_t pattern_index +) { + return array_get(&self->patterns, pattern_index)->end_byte; +} + +bool ts_query_is_pattern_rooted( + const TSQuery *self, + uint32_t pattern_index +) { + for (unsigned i = 0; i < self->pattern_map.size; i++) { + PatternEntry *entry = array_get(&self->pattern_map, i); + if (entry->pattern_index == pattern_index) { + if (!entry->is_rooted) return false; + } + } + return true; +} + +bool ts_query_is_pattern_non_local( + const TSQuery *self, + uint32_t pattern_index +) { + if (pattern_index < self->patterns.size) { + return array_get(&self->patterns, pattern_index)->is_non_local; + } else { + return false; + } +} + +bool ts_query_is_pattern_guaranteed_at_step( + const TSQuery *self, + uint32_t byte_offset +) { + uint32_t step_index = UINT32_MAX; + for (unsigned i = 0; i < self->step_offsets.size; i++) { + StepOffset *step_offset = array_get(&self->step_offsets, i); + if (step_offset->byte_offset > byte_offset) break; + step_index = step_offset->step_index; + } + if (step_index < self->steps.size) { + return array_get(&self->steps, step_index)->root_pattern_guaranteed; + } else { + return false; + } +} + +bool ts_query__step_is_fallible( + const TSQuery *self, + uint16_t step_index +) { + ts_assert((uint32_t)step_index + 1 < self->steps.size); + QueryStep *step = array_get(&self->steps, step_index); + QueryStep *next_step = array_get(&self->steps, step_index + 1); + return ( + next_step->depth != PATTERN_DONE_MARKER && + next_step->depth > step->depth && + (!next_step->parent_pattern_guaranteed || step->symbol == WILDCARD_SYMBOL) + ); +} + +void ts_query_disable_capture( + TSQuery *self, + const char *name, + uint32_t length +) { + // Remove capture information for any pattern step that previously + // captured with the given name. + int id = symbol_table_id_for_name(&self->captures, name, length); + if (id != -1) { + for (unsigned i = 0; i < self->steps.size; i++) { + QueryStep *step = array_get(&self->steps, i); + query_step__remove_capture(step, id); + } + } +} + +void ts_query_disable_pattern( + TSQuery *self, + uint32_t pattern_index +) { + // Remove the given pattern from the pattern map. Its steps will still + // be in the `steps` array, but they will never be read. + for (unsigned i = 0; i < self->pattern_map.size; i++) { + PatternEntry *pattern = array_get(&self->pattern_map, i); + if (pattern->pattern_index == pattern_index) { + array_erase(&self->pattern_map, i); + i--; + } + } +} + +/*************** + * QueryCursor + ***************/ + +TSQueryCursor *ts_query_cursor_new(void) { + TSQueryCursor *self = ts_malloc(sizeof(TSQueryCursor)); + *self = (TSQueryCursor) { + .did_exceed_match_limit = false, + .ascending = false, + .halted = false, + .states = array_new(), + .finished_states = array_new(), + .capture_list_pool = capture_list_pool_new(), + .start_byte = 0, + .end_byte = UINT32_MAX, + .start_point = {0, 0}, + .end_point = POINT_MAX, + .max_start_depth = UINT32_MAX, + .timeout_duration = 0, + .end_clock = clock_null(), + .operation_count = 0, + }; + array_reserve(&self->states, 8); + array_reserve(&self->finished_states, 8); + return self; +} + +void ts_query_cursor_delete(TSQueryCursor *self) { + array_delete(&self->states); + array_delete(&self->finished_states); + ts_tree_cursor_delete(&self->cursor); + capture_list_pool_delete(&self->capture_list_pool); + ts_free(self); +} + +bool ts_query_cursor_did_exceed_match_limit(const TSQueryCursor *self) { + return self->did_exceed_match_limit; +} + +uint32_t ts_query_cursor_match_limit(const TSQueryCursor *self) { + return self->capture_list_pool.max_capture_list_count; +} + +void ts_query_cursor_set_match_limit(TSQueryCursor *self, uint32_t limit) { + self->capture_list_pool.max_capture_list_count = limit; +} + +uint64_t ts_query_cursor_timeout_micros(const TSQueryCursor *self) { + return duration_to_micros(self->timeout_duration); +} + +void ts_query_cursor_set_timeout_micros(TSQueryCursor *self, uint64_t timeout_micros) { + self->timeout_duration = duration_from_micros(timeout_micros); +} + +#ifdef DEBUG_EXECUTE_QUERY +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LOG(...) +#endif + +void ts_query_cursor_exec( + TSQueryCursor *self, + const TSQuery *query, + TSNode node +) { + if (query) { + LOG("query steps:\n"); + for (unsigned i = 0; i < query->steps.size; i++) { + QueryStep *step = array_get(&query->steps, i); + LOG(" %u: {", i); + if (step->depth == PATTERN_DONE_MARKER) { + LOG("DONE"); + } else if (step->is_dead_end) { + LOG("dead_end"); + } else if (step->is_pass_through) { + LOG("pass_through"); + } else if (step->symbol != WILDCARD_SYMBOL) { + LOG("symbol: %s", query->language->symbol_names[step->symbol]); + } else { + LOG("symbol: *"); + } + if (step->field) { + LOG(", field: %s", query->language->field_names[step->field]); + } + if (step->alternative_index != NONE) { + LOG(", alternative: %u", step->alternative_index); + } + LOG("},\n"); + } + } + + array_clear(&self->states); + array_clear(&self->finished_states); + ts_tree_cursor_reset(&self->cursor, node); + capture_list_pool_reset(&self->capture_list_pool); + self->on_visible_node = true; + self->next_state_id = 0; + self->depth = 0; + self->ascending = false; + self->halted = false; + self->query = query; + self->did_exceed_match_limit = false; + self->operation_count = 0; + if (self->timeout_duration) { + self->end_clock = clock_after(clock_now(), self->timeout_duration); + } else { + self->end_clock = clock_null(); + } + self->query_options = NULL; + self->query_state = (TSQueryCursorState) {0}; +} + +void ts_query_cursor_exec_with_options( + TSQueryCursor *self, + const TSQuery *query, + TSNode node, + const TSQueryCursorOptions *query_options +) { + ts_query_cursor_exec(self, query, node); + if (query_options) { + self->query_options = query_options; + self->query_state = (TSQueryCursorState) { + .payload = query_options->payload + }; + } +} + +bool ts_query_cursor_set_byte_range( + TSQueryCursor *self, + uint32_t start_byte, + uint32_t end_byte +) { + if (end_byte == 0) { + end_byte = UINT32_MAX; + } + if (start_byte > end_byte) { + return false; + } + self->start_byte = start_byte; + self->end_byte = end_byte; + return true; +} + +bool ts_query_cursor_set_point_range( + TSQueryCursor *self, + TSPoint start_point, + TSPoint end_point +) { + if (end_point.row == 0 && end_point.column == 0) { + end_point = POINT_MAX; + } + if (point_gt(start_point, end_point)) { + return false; + } + self->start_point = start_point; + self->end_point = end_point; + return true; +} + +// Search through all of the in-progress states, and find the captured +// node that occurs earliest in the document. +static bool ts_query_cursor__first_in_progress_capture( + TSQueryCursor *self, + uint32_t *state_index, + uint32_t *byte_offset, + uint32_t *pattern_index, + bool *is_definite +) { + bool result = false; + *state_index = UINT32_MAX; + *byte_offset = UINT32_MAX; + *pattern_index = UINT32_MAX; + for (unsigned i = 0; i < self->states.size; i++) { + QueryState *state = array_get(&self->states, i); + if (state->dead) continue; + + const CaptureList *captures = capture_list_pool_get( + &self->capture_list_pool, + state->capture_list_id + ); + if (state->consumed_capture_count >= captures->size) { + continue; + } + + TSNode node = array_get(captures, state->consumed_capture_count)->node; + if ( + ts_node_end_byte(node) <= self->start_byte || + point_lte(ts_node_end_point(node), self->start_point) + ) { + state->consumed_capture_count++; + i--; + continue; + } + + uint32_t node_start_byte = ts_node_start_byte(node); + if ( + !result || + node_start_byte < *byte_offset || + (node_start_byte == *byte_offset && state->pattern_index < *pattern_index) + ) { + QueryStep *step = array_get(&self->query->steps, state->step_index); + if (is_definite) { + // We're being a bit conservative here by asserting that the following step + // is not immediate, because this capture might end up being discarded if the + // following symbol in the tree isn't the required symbol for this step. + *is_definite = step->root_pattern_guaranteed && !step->is_immediate; + } else if (step->root_pattern_guaranteed) { + continue; + } + + result = true; + *state_index = i; + *byte_offset = node_start_byte; + *pattern_index = state->pattern_index; + } + } + return result; +} + +// Determine which node is first in a depth-first traversal +int ts_query_cursor__compare_nodes(TSNode left, TSNode right) { + if (left.id != right.id) { + uint32_t left_start = ts_node_start_byte(left); + uint32_t right_start = ts_node_start_byte(right); + if (left_start < right_start) return -1; + if (left_start > right_start) return 1; + uint32_t left_node_count = ts_node_end_byte(left); + uint32_t right_node_count = ts_node_end_byte(right); + if (left_node_count > right_node_count) return -1; + if (left_node_count < right_node_count) return 1; + } + return 0; +} + +// Determine if either state contains a superset of the other state's captures. +void ts_query_cursor__compare_captures( + TSQueryCursor *self, + QueryState *left_state, + QueryState *right_state, + bool *left_contains_right, + bool *right_contains_left +) { + const CaptureList *left_captures = capture_list_pool_get( + &self->capture_list_pool, + left_state->capture_list_id + ); + const CaptureList *right_captures = capture_list_pool_get( + &self->capture_list_pool, + right_state->capture_list_id + ); + *left_contains_right = true; + *right_contains_left = true; + unsigned i = 0, j = 0; + for (;;) { + if (i < left_captures->size) { + if (j < right_captures->size) { + TSQueryCapture *left = array_get(left_captures, i); + TSQueryCapture *right = array_get(right_captures, j); + if (left->node.id == right->node.id && left->index == right->index) { + i++; + j++; + } else { + switch (ts_query_cursor__compare_nodes(left->node, right->node)) { + case -1: + *right_contains_left = false; + i++; + break; + case 1: + *left_contains_right = false; + j++; + break; + default: + *right_contains_left = false; + *left_contains_right = false; + i++; + j++; + break; + } + } + } else { + *right_contains_left = false; + break; + } + } else { + if (j < right_captures->size) { + *left_contains_right = false; + } + break; + } + } +} + +static void ts_query_cursor__add_state( + TSQueryCursor *self, + const PatternEntry *pattern +) { + QueryStep *step = array_get(&self->query->steps, pattern->step_index); + uint32_t start_depth = self->depth - step->depth; + + // Keep the states array in ascending order of start_depth and pattern_index, + // so that it can be processed more efficiently elsewhere. Usually, there is + // no work to do here because of two facts: + // * States with lower start_depth are naturally added first due to the + // order in which nodes are visited. + // * Earlier patterns are naturally added first because of the ordering of the + // pattern_map data structure that's used to initiate matches. + // + // This loop is only needed in cases where two conditions hold: + // * A pattern consists of more than one sibling node, so that its states + // remain in progress after exiting the node that started the match. + // * The first node in the pattern matches against multiple nodes at the + // same depth. + // + // An example of this is the pattern '((comment)* (function))'. If multiple + // `comment` nodes appear in a row, then we may initiate a new state for this + // pattern while another state for the same pattern is already in progress. + // If there are multiple patterns like this in a query, then this loop will + // need to execute in order to keep the states ordered by pattern_index. + uint32_t index = self->states.size; + while (index > 0) { + QueryState *prev_state = array_get(&self->states, index - 1); + if (prev_state->start_depth < start_depth) break; + if (prev_state->start_depth == start_depth) { + // Avoid inserting an unnecessary duplicate state, which would be + // immediately pruned by the longest-match criteria. + if ( + prev_state->pattern_index == pattern->pattern_index && + prev_state->step_index == pattern->step_index + ) return; + if (prev_state->pattern_index <= pattern->pattern_index) break; + } + index--; + } + + LOG( + " start state. pattern:%u, step:%u\n", + pattern->pattern_index, + pattern->step_index + ); + array_insert(&self->states, index, ((QueryState) { + .id = UINT32_MAX, + .capture_list_id = NONE, + .step_index = pattern->step_index, + .pattern_index = pattern->pattern_index, + .start_depth = start_depth, + .consumed_capture_count = 0, + .seeking_immediate_match = true, + .has_in_progress_alternatives = false, + .needs_parent = step->depth == 1, + .dead = false, + })); +} + +// Acquire a capture list for this state. If there are no capture lists left in the +// pool, this will steal the capture list from another existing state, and mark that +// other state as 'dead'. +static CaptureList *ts_query_cursor__prepare_to_capture( + TSQueryCursor *self, + QueryState *state, + unsigned state_index_to_preserve +) { + if (state->capture_list_id == NONE) { + state->capture_list_id = capture_list_pool_acquire(&self->capture_list_pool); + + // If there are no capture lists left in the pool, then terminate whichever + // state has captured the earliest node in the document, and steal its + // capture list. + if (state->capture_list_id == NONE) { + self->did_exceed_match_limit = true; + uint32_t state_index, byte_offset, pattern_index; + if ( + ts_query_cursor__first_in_progress_capture( + self, + &state_index, + &byte_offset, + &pattern_index, + NULL + ) && + state_index != state_index_to_preserve + ) { + LOG( + " abandon state. index:%u, pattern:%u, offset:%u.\n", + state_index, pattern_index, byte_offset + ); + QueryState *other_state = array_get(&self->states, state_index); + state->capture_list_id = other_state->capture_list_id; + other_state->capture_list_id = NONE; + other_state->dead = true; + CaptureList *list = capture_list_pool_get_mut( + &self->capture_list_pool, + state->capture_list_id + ); + array_clear(list); + return list; + } else { + LOG(" ran out of capture lists"); + return NULL; + } + } + } + return capture_list_pool_get_mut(&self->capture_list_pool, state->capture_list_id); +} + +static void ts_query_cursor__capture( + TSQueryCursor *self, + QueryState *state, + QueryStep *step, + TSNode node +) { + if (state->dead) return; + CaptureList *capture_list = ts_query_cursor__prepare_to_capture(self, state, UINT32_MAX); + if (!capture_list) { + state->dead = true; + return; + } + + for (unsigned j = 0; j < MAX_STEP_CAPTURE_COUNT; j++) { + uint16_t capture_id = step->capture_ids[j]; + if (step->capture_ids[j] == NONE) break; + array_push(capture_list, ((TSQueryCapture) { node, capture_id })); + LOG( + " capture node. type:%s, pattern:%u, capture_id:%u, capture_count:%u\n", + ts_node_type(node), + state->pattern_index, + capture_id, + capture_list->size + ); + } +} + +// Duplicate the given state and insert the newly-created state immediately after +// the given state in the `states` array. Ensures that the given state reference is +// still valid, even if the states array is reallocated. +static QueryState *ts_query_cursor__copy_state( + TSQueryCursor *self, + QueryState **state_ref +) { + const QueryState *state = *state_ref; + uint32_t state_index = (uint32_t)(state - self->states.contents); + QueryState copy = *state; + copy.capture_list_id = NONE; + + // If the state has captures, copy its capture list. + if (state->capture_list_id != NONE) { + CaptureList *new_captures = ts_query_cursor__prepare_to_capture(self, ©, state_index); + if (!new_captures) return NULL; + const CaptureList *old_captures = capture_list_pool_get( + &self->capture_list_pool, + state->capture_list_id + ); + array_push_all(new_captures, old_captures); + } + + array_insert(&self->states, state_index + 1, copy); + *state_ref = array_get(&self->states, state_index); + return array_get(&self->states, state_index + 1); +} + +static inline bool ts_query_cursor__should_descend( + TSQueryCursor *self, + bool node_intersects_range +) { + + if (node_intersects_range && self->depth < self->max_start_depth) { + return true; + } + + // If there are in-progress matches whose remaining steps occur + // deeper in the tree, then descend. + for (unsigned i = 0; i < self->states.size; i++) { + QueryState *state = array_get(&self->states, i); + QueryStep *next_step = array_get(&self->query->steps, state->step_index); + if ( + next_step->depth != PATTERN_DONE_MARKER && + state->start_depth + next_step->depth > self->depth + ) { + return true; + } + } + + if (self->depth >= self->max_start_depth) { + return false; + } + + // If the current node is hidden, then a non-rooted pattern might match + // one if its roots inside of this node, and match another of its roots + // as part of a sibling node, so we may need to descend. + if (!self->on_visible_node) { + // Descending into a repetition node outside of the range can be + // expensive, because these nodes can have many visible children. + // Avoid descending into repetition nodes unless we have already + // determined that this query can match rootless patterns inside + // of this type of repetition node. + Subtree subtree = ts_tree_cursor_current_subtree(&self->cursor); + if (ts_subtree_is_repetition(subtree)) { + bool exists; + uint32_t index; + array_search_sorted_by( + &self->query->repeat_symbols_with_rootless_patterns,, + ts_subtree_symbol(subtree), + &index, + &exists + ); + return exists; + } + + return true; + } + + return false; +} + +// Walk the tree, processing patterns until at least one pattern finishes, +// If one or more patterns finish, return `true` and store their states in the +// `finished_states` array. Multiple patterns can finish on the same node. If +// there are no more matches, return `false`. +static inline bool ts_query_cursor__advance( + TSQueryCursor *self, + bool stop_on_definite_step +) { + bool did_match = false; + for (;;) { + if (self->halted) { + while (self->states.size > 0) { + QueryState state = array_pop(&self->states); + capture_list_pool_release( + &self->capture_list_pool, + state.capture_list_id + ); + } + } + + if (++self->operation_count == OP_COUNT_PER_QUERY_TIMEOUT_CHECK) { + self->operation_count = 0; + } + + if (self->query_options && self->query_options->progress_callback) { + self->query_state.current_byte_offset = ts_node_start_byte(ts_tree_cursor_current_node(&self->cursor)); + } + if ( + did_match || + self->halted || + ( + self->operation_count == 0 && + ( + (!clock_is_null(self->end_clock) && clock_is_gt(clock_now(), self->end_clock)) || + (self->query_options && self->query_options->progress_callback && self->query_options->progress_callback(&self->query_state)) + ) + ) + ) { + return did_match; + } + + // Exit the current node. + if (self->ascending) { + if (self->on_visible_node) { + LOG( + "leave node. depth:%u, type:%s\n", + self->depth, + ts_node_type(ts_tree_cursor_current_node(&self->cursor)) + ); + + // After leaving a node, remove any states that cannot make further progress. + uint32_t deleted_count = 0; + for (unsigned i = 0, n = self->states.size; i < n; i++) { + QueryState *state = array_get(&self->states, i); + QueryStep *step = array_get(&self->query->steps, state->step_index); + + // If a state completed its pattern inside of this node, but was deferred from finishing + // in order to search for longer matches, mark it as finished. + if ( + step->depth == PATTERN_DONE_MARKER && + (state->start_depth > self->depth || self->depth == 0) + ) { + LOG(" finish pattern %u\n", state->pattern_index); + array_push(&self->finished_states, *state); + did_match = true; + deleted_count++; + } + + // If a state needed to match something within this node, then remove that state + // as it has failed to match. + else if ( + step->depth != PATTERN_DONE_MARKER && + (uint32_t)state->start_depth + (uint32_t)step->depth > self->depth + ) { + LOG( + " failed to match. pattern:%u, step:%u\n", + state->pattern_index, + state->step_index + ); + capture_list_pool_release( + &self->capture_list_pool, + state->capture_list_id + ); + deleted_count++; + } + + else if (deleted_count > 0) { + *array_get(&self->states, i - deleted_count) = *state; + } + } + self->states.size -= deleted_count; + } + + // Leave this node by stepping to its next sibling or to its parent. + switch (ts_tree_cursor_goto_next_sibling_internal(&self->cursor)) { + case TreeCursorStepVisible: + if (!self->on_visible_node) { + self->depth++; + self->on_visible_node = true; + } + self->ascending = false; + break; + case TreeCursorStepHidden: + if (self->on_visible_node) { + self->depth--; + self->on_visible_node = false; + } + self->ascending = false; + break; + default: + if (ts_tree_cursor_goto_parent(&self->cursor)) { + self->depth--; + } else { + LOG("halt at root\n"); + self->halted = true; + } + } + } + + // Enter a new node. + else { + // Get the properties of the current node. + TSNode node = ts_tree_cursor_current_node(&self->cursor); + TSNode parent_node = ts_tree_cursor_parent_node(&self->cursor); + + uint32_t start_byte = ts_node_start_byte(node); + uint32_t end_byte = ts_node_end_byte(node); + TSPoint start_point = ts_node_start_point(node); + TSPoint end_point = ts_node_end_point(node); + bool is_empty = start_byte == end_byte; + + bool parent_precedes_range = !ts_node_is_null(parent_node) && ( + ts_node_end_byte(parent_node) <= self->start_byte || + point_lte(ts_node_end_point(parent_node), self->start_point) + ); + bool parent_follows_range = !ts_node_is_null(parent_node) && ( + ts_node_start_byte(parent_node) >= self->end_byte || + point_gte(ts_node_start_point(parent_node), self->end_point) + ); + bool node_precedes_range = + parent_precedes_range || + end_byte < self->start_byte || + point_lt(end_point, self->start_point) || + (!is_empty && end_byte == self->start_byte) || + (!is_empty && point_eq(end_point, self->start_point)); + + bool node_follows_range = parent_follows_range || ( + start_byte >= self->end_byte || + point_gte(start_point, self->end_point) + ); + bool parent_intersects_range = !parent_precedes_range && !parent_follows_range; + bool node_intersects_range = !node_precedes_range && !node_follows_range; + + if (self->on_visible_node) { + TSSymbol symbol = ts_node_symbol(node); + bool is_named = ts_node_is_named(node); + bool is_missing = ts_node_is_missing(node); + bool has_later_siblings; + bool has_later_named_siblings; + bool can_have_later_siblings_with_this_field; + TSFieldId field_id = 0; + TSSymbol supertypes[8] = {0}; + unsigned supertype_count = 8; + ts_tree_cursor_current_status( + &self->cursor, + &field_id, + &has_later_siblings, + &has_later_named_siblings, + &can_have_later_siblings_with_this_field, + supertypes, + &supertype_count + ); + LOG( + "enter node. depth:%u, type:%s, field:%s, row:%u state_count:%u, finished_state_count:%u\n", + self->depth, + ts_node_type(node), + ts_language_field_name_for_id(self->query->language, field_id), + ts_node_start_point(node).row, + self->states.size, + self->finished_states.size + ); + + bool node_is_error = symbol == ts_builtin_sym_error; + bool parent_is_error = + !ts_node_is_null(parent_node) && + ts_node_symbol(parent_node) == ts_builtin_sym_error; + + // Add new states for any patterns whose root node is a wildcard. + if (!node_is_error) { + for (unsigned i = 0; i < self->query->wildcard_root_pattern_count; i++) { + PatternEntry *pattern = array_get(&self->query->pattern_map, i); + + // If this node matches the first step of the pattern, then add a new + // state at the start of this pattern. + QueryStep *step = array_get(&self->query->steps, pattern->step_index); + uint32_t start_depth = self->depth - step->depth; + if ( + (pattern->is_rooted ? + node_intersects_range : + (parent_intersects_range && !parent_is_error)) && + (!step->field || field_id == step->field) && + (!step->supertype_symbol || supertype_count > 0) && + (start_depth <= self->max_start_depth) + ) { + ts_query_cursor__add_state(self, pattern); + } + } + } + + // Add new states for any patterns whose root node matches this node. + unsigned i; + if (ts_query__pattern_map_search(self->query, symbol, &i)) { + PatternEntry *pattern = array_get(&self->query->pattern_map, i); + + QueryStep *step = array_get(&self->query->steps, pattern->step_index); + uint32_t start_depth = self->depth - step->depth; + do { + // If this node matches the first step of the pattern, then add a new + // state at the start of this pattern. + if ( + (pattern->is_rooted ? + node_intersects_range : + (parent_intersects_range && !parent_is_error)) && + (!step->field || field_id == step->field) && + (start_depth <= self->max_start_depth) + ) { + ts_query_cursor__add_state(self, pattern); + } + + // Advance to the next pattern whose root node matches this node. + i++; + if (i == self->query->pattern_map.size) break; + pattern = array_get(&self->query->pattern_map, i); + step = array_get(&self->query->steps, pattern->step_index); + } while (step->symbol == symbol); + } + + // Update all of the in-progress states with current node. + for (unsigned j = 0, copy_count = 0; j < self->states.size; j += 1 + copy_count) { + QueryState *state = array_get(&self->states, j); + QueryStep *step = array_get(&self->query->steps, state->step_index); + state->has_in_progress_alternatives = false; + copy_count = 0; + + // Check that the node matches all of the criteria for the next + // step of the pattern. + if ((uint32_t)state->start_depth + (uint32_t)step->depth != self->depth) continue; + + // Determine if this node matches this step of the pattern, and also + // if this node can have later siblings that match this step of the + // pattern. + bool node_does_match = false; + if (step->symbol == WILDCARD_SYMBOL) { + if (step->is_missing) { + node_does_match = is_missing; + } else { + node_does_match = !node_is_error && (is_named || !step->is_named); + } + } else { + node_does_match = symbol == step->symbol && (!step->is_missing || is_missing); + } + bool later_sibling_can_match = has_later_siblings; + if ((step->is_immediate && is_named) || state->seeking_immediate_match) { + later_sibling_can_match = false; + } + if (step->is_last_child && has_later_named_siblings) { + node_does_match = false; + } + if (step->supertype_symbol) { + bool has_supertype = false; + for (unsigned k = 0; k < supertype_count; k++) { + if (supertypes[k] == step->supertype_symbol) { + has_supertype = true; + break; + } + } + if (!has_supertype) node_does_match = false; + } + if (step->field) { + if (step->field == field_id) { + if (!can_have_later_siblings_with_this_field) { + later_sibling_can_match = false; + } + } else { + node_does_match = false; + } + } + + if (step->negated_field_list_id) { + TSFieldId *negated_field_ids = array_get(&self->query->negated_fields, step->negated_field_list_id); + for (;;) { + TSFieldId negated_field_id = *negated_field_ids; + if (negated_field_id) { + negated_field_ids++; + if (ts_node_child_by_field_id(node, negated_field_id).id) { + node_does_match = false; + break; + } + } else { + break; + } + } + } + + // Remove states immediately if it is ever clear that they cannot match. + if (!node_does_match) { + if (!later_sibling_can_match) { + LOG( + " discard state. pattern:%u, step:%u\n", + state->pattern_index, + state->step_index + ); + capture_list_pool_release( + &self->capture_list_pool, + state->capture_list_id + ); + array_erase(&self->states, j); + j--; + } + continue; + } + + // Some patterns can match their root node in multiple ways, capturing different + // children. If this pattern step could match later children within the same + // parent, then this query state cannot simply be updated in place. It must be + // split into two states: one that matches this node, and one which skips over + // this node, to preserve the possibility of matching later siblings. + if (later_sibling_can_match && ( + step->contains_captures || + ts_query__step_is_fallible(self->query, state->step_index) + )) { + if (ts_query_cursor__copy_state(self, &state)) { + LOG( + " split state for capture. pattern:%u, step:%u\n", + state->pattern_index, + state->step_index + ); + copy_count++; + } + } + + // If this pattern started with a wildcard, such that the pattern map + // actually points to the *second* step of the pattern, then check + // that the node has a parent, and capture the parent node if necessary. + if (state->needs_parent) { + TSNode parent = ts_tree_cursor_parent_node(&self->cursor); + if (ts_node_is_null(parent)) { + LOG(" missing parent node\n"); + state->dead = true; + } else { + state->needs_parent = false; + QueryStep *skipped_wildcard_step = step; + do { + skipped_wildcard_step--; + } while ( + skipped_wildcard_step->is_dead_end || + skipped_wildcard_step->is_pass_through || + skipped_wildcard_step->depth > 0 + ); + if (skipped_wildcard_step->capture_ids[0] != NONE) { + LOG(" capture wildcard parent\n"); + ts_query_cursor__capture( + self, + state, + skipped_wildcard_step, + parent + ); + } + } + } + + // If the current node is captured in this pattern, add it to the capture list. + if (step->capture_ids[0] != NONE) { + ts_query_cursor__capture(self, state, step, node); + } + + if (state->dead) { + array_erase(&self->states, j); + j--; + continue; + } + + // Advance this state to the next step of its pattern. + state->step_index++; + LOG( + " advance state. pattern:%u, step:%u\n", + state->pattern_index, + state->step_index + ); + + QueryStep *next_step = array_get(&self->query->steps, state->step_index); + + // For a given step, if the current symbol is the wildcard symbol, `_`, and it is **not** + // named, meaning it should capture anonymous nodes, **and** the next step is immediate, + // we reuse the `seeking_immediate_match` flag to indicate that we are looking for an + // immediate match due to an unnamed wildcard symbol. + // + // The reason for this is that typically, anchors will not consider anonymous nodes, + // but we're special casing the wildcard symbol to allow for any immediate matches, + // regardless of whether they are named or not. + if (step->symbol == WILDCARD_SYMBOL && !step->is_named && next_step->is_immediate) { + state->seeking_immediate_match = true; + } else { + state->seeking_immediate_match = false; + } + + if (stop_on_definite_step && next_step->root_pattern_guaranteed) did_match = true; + + // If this state's next step has an alternative step, then copy the state in order + // to pursue both alternatives. The alternative step itself may have an alternative, + // so this is an interactive process. + unsigned end_index = j + 1; + for (unsigned k = j; k < end_index; k++) { + QueryState *child_state = array_get(&self->states, k); + QueryStep *child_step = array_get(&self->query->steps, child_state->step_index); + if (child_step->alternative_index != NONE) { + // A "dead-end" step exists only to add a non-sequential jump into the step sequence, + // via its alternative index. When a state reaches a dead-end step, it jumps straight + // to the step's alternative. + if (child_step->is_dead_end) { + child_state->step_index = child_step->alternative_index; + k--; + continue; + } + + // A "pass-through" step exists only to add a branch into the step sequence, + // via its alternative_index. When a state reaches a pass-through step, it splits + // in order to process the alternative step, and then it advances to the next step. + if (child_step->is_pass_through) { + child_state->step_index++; + k--; + } + + QueryState *copy = ts_query_cursor__copy_state(self, &child_state); + if (copy) { + LOG( + " split state for branch. pattern:%u, from_step:%u, to_step:%u, immediate:%d, capture_count: %u\n", + copy->pattern_index, + copy->step_index, + next_step->alternative_index, + next_step->alternative_is_immediate, + capture_list_pool_get(&self->capture_list_pool, copy->capture_list_id)->size + ); + end_index++; + copy_count++; + copy->step_index = child_step->alternative_index; + if (child_step->alternative_is_immediate) { + copy->seeking_immediate_match = true; + } + } + } + } + } + + for (unsigned j = 0; j < self->states.size; j++) { + QueryState *state = array_get(&self->states, j); + if (state->dead) { + array_erase(&self->states, j); + j--; + continue; + } + + // Enforce the longest-match criteria. When a query pattern contains optional or + // repeated nodes, this is necessary to avoid multiple redundant states, where + // one state has a strict subset of another state's captures. + bool did_remove = false; + for (unsigned k = j + 1; k < self->states.size; k++) { + QueryState *other_state = array_get(&self->states, k); + + // Query states are kept in ascending order of start_depth and pattern_index. + // Since the longest-match criteria is only used for deduping matches of the same + // pattern and root node, we only need to perform pairwise comparisons within a + // small slice of the states array. + if ( + other_state->start_depth != state->start_depth || + other_state->pattern_index != state->pattern_index + ) break; + + bool left_contains_right, right_contains_left; + ts_query_cursor__compare_captures( + self, + state, + other_state, + &left_contains_right, + &right_contains_left + ); + if (left_contains_right) { + if (state->step_index == other_state->step_index) { + LOG( + " drop shorter state. pattern: %u, step_index: %u\n", + state->pattern_index, + state->step_index + ); + capture_list_pool_release(&self->capture_list_pool, other_state->capture_list_id); + array_erase(&self->states, k); + k--; + continue; + } + other_state->has_in_progress_alternatives = true; + } + if (right_contains_left) { + if (state->step_index == other_state->step_index) { + LOG( + " drop shorter state. pattern: %u, step_index: %u\n", + state->pattern_index, + state->step_index + ); + capture_list_pool_release(&self->capture_list_pool, state->capture_list_id); + array_erase(&self->states, j); + j--; + did_remove = true; + break; + } + state->has_in_progress_alternatives = true; + } + } + + // If the state is at the end of its pattern, remove it from the list + // of in-progress states and add it to the list of finished states. + if (!did_remove) { + LOG( + " keep state. pattern: %u, start_depth: %u, step_index: %u, capture_count: %u\n", + state->pattern_index, + state->start_depth, + state->step_index, + capture_list_pool_get(&self->capture_list_pool, state->capture_list_id)->size + ); + QueryStep *next_step = array_get(&self->query->steps, state->step_index); + if (next_step->depth == PATTERN_DONE_MARKER) { + if (state->has_in_progress_alternatives) { + LOG(" defer finishing pattern %u\n", state->pattern_index); + } else { + LOG(" finish pattern %u\n", state->pattern_index); + array_push(&self->finished_states, *state); + array_erase(&self->states, (uint32_t)(state - self->states.contents)); + did_match = true; + j--; + } + } + } + } + } + + if (ts_query_cursor__should_descend(self, node_intersects_range)) { + switch (ts_tree_cursor_goto_first_child_internal(&self->cursor)) { + case TreeCursorStepVisible: + self->depth++; + self->on_visible_node = true; + continue; + case TreeCursorStepHidden: + self->on_visible_node = false; + continue; + default: + break; + } + } + + self->ascending = true; + } + } +} + +bool ts_query_cursor_next_match( + TSQueryCursor *self, + TSQueryMatch *match +) { + if (self->finished_states.size == 0) { + if (!ts_query_cursor__advance(self, false)) { + return false; + } + } + + QueryState *state = array_get(&self->finished_states, 0); + if (state->id == UINT32_MAX) state->id = self->next_state_id++; + match->id = state->id; + match->pattern_index = state->pattern_index; + const CaptureList *captures = capture_list_pool_get( + &self->capture_list_pool, + state->capture_list_id + ); + match->captures = captures->contents; + match->capture_count = captures->size; + capture_list_pool_release(&self->capture_list_pool, state->capture_list_id); + array_erase(&self->finished_states, 0); + return true; +} + +void ts_query_cursor_remove_match( + TSQueryCursor *self, + uint32_t match_id +) { + for (unsigned i = 0; i < self->finished_states.size; i++) { + const QueryState *state = array_get(&self->finished_states, i); + if (state->id == match_id) { + capture_list_pool_release( + &self->capture_list_pool, + state->capture_list_id + ); + array_erase(&self->finished_states, i); + return; + } + } + + // Remove unfinished query states as well to prevent future + // captures for a match being removed. + for (unsigned i = 0; i < self->states.size; i++) { + const QueryState *state = array_get(&self->states, i); + if (state->id == match_id) { + capture_list_pool_release( + &self->capture_list_pool, + state->capture_list_id + ); + array_erase(&self->states, i); + return; + } + } +} + +bool ts_query_cursor_next_capture( + TSQueryCursor *self, + TSQueryMatch *match, + uint32_t *capture_index +) { + // The goal here is to return captures in order, even though they may not + // be discovered in order, because patterns can overlap. Search for matches + // until there is a finished capture that is before any unfinished capture. + for (;;) { + // First, find the earliest capture in an unfinished match. + uint32_t first_unfinished_capture_byte; + uint32_t first_unfinished_pattern_index; + uint32_t first_unfinished_state_index; + bool first_unfinished_state_is_definite = false; + bool found_unfinished_state = ts_query_cursor__first_in_progress_capture( + self, + &first_unfinished_state_index, + &first_unfinished_capture_byte, + &first_unfinished_pattern_index, + &first_unfinished_state_is_definite + ); + + // Then find the earliest capture in a finished match. It must occur + // before the first capture in an *unfinished* match. + QueryState *first_finished_state = NULL; + uint32_t first_finished_capture_byte = first_unfinished_capture_byte; + uint32_t first_finished_pattern_index = first_unfinished_pattern_index; + for (unsigned i = 0; i < self->finished_states.size;) { + QueryState *state = array_get(&self->finished_states, i); + const CaptureList *captures = capture_list_pool_get( + &self->capture_list_pool, + state->capture_list_id + ); + + // Remove states whose captures are all consumed. + if (state->consumed_capture_count >= captures->size) { + capture_list_pool_release( + &self->capture_list_pool, + state->capture_list_id + ); + array_erase(&self->finished_states, i); + continue; + } + + TSNode node = array_get(captures, state->consumed_capture_count)->node; + + bool node_precedes_range = ( + ts_node_end_byte(node) <= self->start_byte || + point_lte(ts_node_end_point(node), self->start_point) + ); + bool node_follows_range = ( + ts_node_start_byte(node) >= self->end_byte || + point_gte(ts_node_start_point(node), self->end_point) + ); + bool node_outside_of_range = node_precedes_range || node_follows_range; + + // Skip captures that are outside of the cursor's range. + if (node_outside_of_range) { + state->consumed_capture_count++; + continue; + } + + uint32_t node_start_byte = ts_node_start_byte(node); + if ( + node_start_byte < first_finished_capture_byte || + ( + node_start_byte == first_finished_capture_byte && + state->pattern_index < first_finished_pattern_index + ) + ) { + first_finished_state = state; + first_finished_capture_byte = node_start_byte; + first_finished_pattern_index = state->pattern_index; + } + i++; + } + + // If there is finished capture that is clearly before any unfinished + // capture, then return its match, and its capture index. Internally + // record the fact that the capture has been 'consumed'. + QueryState *state; + if (first_finished_state) { + state = first_finished_state; + } else if (first_unfinished_state_is_definite) { + state = array_get(&self->states, first_unfinished_state_index); + } else { + state = NULL; + } + + if (state) { + if (state->id == UINT32_MAX) state->id = self->next_state_id++; + match->id = state->id; + match->pattern_index = state->pattern_index; + const CaptureList *captures = capture_list_pool_get( + &self->capture_list_pool, + state->capture_list_id + ); + match->captures = captures->contents; + match->capture_count = captures->size; + *capture_index = state->consumed_capture_count; + state->consumed_capture_count++; + return true; + } + + if (capture_list_pool_is_empty(&self->capture_list_pool) && found_unfinished_state) { + LOG( + " abandon state. index:%u, pattern:%u, offset:%u.\n", + first_unfinished_state_index, + first_unfinished_pattern_index, + first_unfinished_capture_byte + ); + capture_list_pool_release( + &self->capture_list_pool, + array_get(&self->states, first_unfinished_state_index)->capture_list_id + ); + array_erase(&self->states, first_unfinished_state_index); + } + + // If there are no finished matches that are ready to be returned, then + // continue finding more matches. + if ( + !ts_query_cursor__advance(self, true) && + self->finished_states.size == 0 + ) return false; + } +} + +void ts_query_cursor_set_max_start_depth( + TSQueryCursor *self, + uint32_t max_start_depth +) { + self->max_start_depth = max_start_depth; +} + +#undef LOG diff --git a/codegraph-kernel/vendor/tree-sitter/src/reduce_action.h b/codegraph-kernel/vendor/tree-sitter/src/reduce_action.h new file mode 100644 index 0000000000..72aff08d73 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/reduce_action.h @@ -0,0 +1,34 @@ +#ifndef TREE_SITTER_REDUCE_ACTION_H_ +#define TREE_SITTER_REDUCE_ACTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./array.h" +#include "tree_sitter/api.h" + +typedef struct { + uint32_t count; + TSSymbol symbol; + int dynamic_precedence; + unsigned short production_id; +} ReduceAction; + +typedef Array(ReduceAction) ReduceActionSet; + +static inline void ts_reduce_action_set_add(ReduceActionSet *self, + ReduceAction new_action) { + for (uint32_t i = 0; i < self->size; i++) { + ReduceAction action = self->contents[i]; + if (action.symbol == new_action.symbol && action.count == new_action.count) + return; + } + array_push(self, new_action); +} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_REDUCE_ACTION_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/reusable_node.h b/codegraph-kernel/vendor/tree-sitter/src/reusable_node.h new file mode 100644 index 0000000000..63fe3c1a36 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/reusable_node.h @@ -0,0 +1,95 @@ +#include "./subtree.h" + +typedef struct { + Subtree tree; + uint32_t child_index; + uint32_t byte_offset; +} StackEntry; + +typedef struct { + Array(StackEntry) stack; + Subtree last_external_token; +} ReusableNode; + +static inline ReusableNode reusable_node_new(void) { + return (ReusableNode) {array_new(), NULL_SUBTREE}; +} + +static inline void reusable_node_clear(ReusableNode *self) { + array_clear(&self->stack); + self->last_external_token = NULL_SUBTREE; +} + +static inline Subtree reusable_node_tree(ReusableNode *self) { + return self->stack.size > 0 + ? self->stack.contents[self->stack.size - 1].tree + : NULL_SUBTREE; +} + +static inline uint32_t reusable_node_byte_offset(ReusableNode *self) { + return self->stack.size > 0 + ? self->stack.contents[self->stack.size - 1].byte_offset + : UINT32_MAX; +} + +static inline void reusable_node_delete(ReusableNode *self) { + array_delete(&self->stack); +} + +static inline void reusable_node_advance(ReusableNode *self) { + StackEntry last_entry = *array_back(&self->stack); + uint32_t byte_offset = last_entry.byte_offset + ts_subtree_total_bytes(last_entry.tree); + if (ts_subtree_has_external_tokens(last_entry.tree)) { + self->last_external_token = ts_subtree_last_external_token(last_entry.tree); + } + + Subtree tree; + uint32_t next_index; + do { + StackEntry popped_entry = array_pop(&self->stack); + next_index = popped_entry.child_index + 1; + if (self->stack.size == 0) return; + tree = array_back(&self->stack)->tree; + } while (ts_subtree_child_count(tree) <= next_index); + + array_push(&self->stack, ((StackEntry) { + .tree = ts_subtree_children(tree)[next_index], + .child_index = next_index, + .byte_offset = byte_offset, + })); +} + +static inline bool reusable_node_descend(ReusableNode *self) { + StackEntry last_entry = *array_back(&self->stack); + if (ts_subtree_child_count(last_entry.tree) > 0) { + array_push(&self->stack, ((StackEntry) { + .tree = ts_subtree_children(last_entry.tree)[0], + .child_index = 0, + .byte_offset = last_entry.byte_offset, + })); + return true; + } else { + return false; + } +} + +static inline void reusable_node_advance_past_leaf(ReusableNode *self) { + while (reusable_node_descend(self)) {} + reusable_node_advance(self); +} + +static inline void reusable_node_reset(ReusableNode *self, Subtree tree) { + reusable_node_clear(self); + array_push(&self->stack, ((StackEntry) { + .tree = tree, + .child_index = 0, + .byte_offset = 0, + })); + + // Never reuse the root node, because it has a non-standard internal structure + // due to transformations that are applied when it is accepted: adding the EOF + // child and any extra children. + if (!reusable_node_descend(self)) { + reusable_node_clear(self); + } +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/stack.c b/codegraph-kernel/vendor/tree-sitter/src/stack.c new file mode 100644 index 0000000000..9142007476 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/stack.c @@ -0,0 +1,912 @@ +#include "./alloc.h" +#include "./language.h" +#include "./subtree.h" +#include "./array.h" +#include "./stack.h" +#include "./length.h" +#include +#include +#include + +#define MAX_LINK_COUNT 8 +#define MAX_NODE_POOL_SIZE 50 +#define MAX_ITERATOR_COUNT 64 + +#if defined _WIN32 && !defined __GNUC__ +#define forceinline __forceinline +#else +#define forceinline static inline __attribute__((always_inline)) +#endif + +typedef struct StackNode StackNode; + +typedef struct { + StackNode *node; + Subtree subtree; + bool is_pending; +} StackLink; + +struct StackNode { + TSStateId state; + Length position; + StackLink links[MAX_LINK_COUNT]; + short unsigned int link_count; + uint32_t ref_count; + unsigned error_cost; + unsigned node_count; + int dynamic_precedence; +}; + +typedef struct { + StackNode *node; + SubtreeArray subtrees; + uint32_t subtree_count; + bool is_pending; +} StackIterator; + +typedef Array(StackNode *) StackNodeArray; + +typedef enum { + StackStatusActive, + StackStatusPaused, + StackStatusHalted, +} StackStatus; + +typedef struct { + StackNode *node; + StackSummary *summary; + unsigned node_count_at_last_error; + Subtree last_external_token; + Subtree lookahead_when_paused; + StackStatus status; +} StackHead; + +struct Stack { + Array(StackHead) heads; + StackSliceArray slices; + Array(StackIterator) iterators; + StackNodeArray node_pool; + StackNode *base_node; + SubtreePool *subtree_pool; +}; + +typedef unsigned StackAction; +enum { + StackActionNone, + StackActionStop = 1, + StackActionPop = 2, +}; + +typedef StackAction (*StackCallback)(void *, const StackIterator *); + +static void stack_node_retain(StackNode *self) { + if (!self) + return; + ts_assert(self->ref_count > 0); + self->ref_count++; + ts_assert(self->ref_count != 0); +} + +static void stack_node_release( + StackNode *self, + StackNodeArray *pool, + SubtreePool *subtree_pool +) { +recur: + ts_assert(self->ref_count != 0); + self->ref_count--; + if (self->ref_count > 0) return; + + StackNode *first_predecessor = NULL; + if (self->link_count > 0) { + for (unsigned i = self->link_count - 1; i > 0; i--) { + StackLink link = self->links[i]; + if (link.subtree.ptr) ts_subtree_release(subtree_pool, link.subtree); + stack_node_release(link.node, pool, subtree_pool); + } + StackLink link = self->links[0]; + if (link.subtree.ptr) ts_subtree_release(subtree_pool, link.subtree); + first_predecessor = self->links[0].node; + } + + if (pool->size < MAX_NODE_POOL_SIZE) { + array_push(pool, self); + } else { + ts_free(self); + } + + if (first_predecessor) { + self = first_predecessor; + goto recur; + } +} + +/// Get the number of nodes in the subtree, for the purpose of measuring +/// how much progress has been made by a given version of the stack. +static uint32_t stack__subtree_node_count(Subtree subtree) { + uint32_t count = ts_subtree_visible_descendant_count(subtree); + if (ts_subtree_visible(subtree)) count++; + + // Count intermediate error nodes even though they are not visible, + // 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. + if (ts_subtree_symbol(subtree) == ts_builtin_sym_error_repeat) count++; + + return count; +} + +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) + : ts_malloc(sizeof(StackNode)); + *node = (StackNode) { + .ref_count = 1, + .link_count = 0, + .state = state + }; + + if (previous_node) { + node->link_count = 1; + node->links[0] = (StackLink) { + .node = previous_node, + .subtree = subtree, + .is_pending = is_pending, + }; + + node->position = previous_node->position; + node->error_cost = previous_node->error_cost; + node->dynamic_precedence = previous_node->dynamic_precedence; + node->node_count = previous_node->node_count; + + if (subtree.ptr) { + node->error_cost += ts_subtree_error_cost(subtree); + node->position = length_add(node->position, ts_subtree_total_size(subtree)); + node->node_count += stack__subtree_node_count(subtree); + node->dynamic_precedence += ts_subtree_dynamic_precedence(subtree); + } + } else { + node->position = length_zero(); + node->error_cost = 0; + } + + return node; +} + +static bool stack__subtree_is_equivalent(Subtree left, Subtree right) { + if (left.ptr == right.ptr) return true; + if (!left.ptr || !right.ptr) return false; + + // Symbols must match + if (ts_subtree_symbol(left) != ts_subtree_symbol(right)) return false; + + // If both have errors, don't bother keeping both. + if (ts_subtree_error_cost(left) > 0 && ts_subtree_error_cost(right) > 0) return true; + + return ( + ts_subtree_padding(left).bytes == ts_subtree_padding(right).bytes && + ts_subtree_size(left).bytes == ts_subtree_size(right).bytes && + ts_subtree_child_count(left) == ts_subtree_child_count(right) && + ts_subtree_extra(left) == ts_subtree_extra(right) && + ts_subtree_external_scanner_state_eq(left, right) + ); +} + +static void stack_node_add_link( + StackNode *self, + StackLink link, + SubtreePool *subtree_pool +) { + if (link.node == self) return; + + for (int i = 0; i < self->link_count; i++) { + StackLink *existing_link = &self->links[i]; + if (stack__subtree_is_equivalent(existing_link->subtree, link.subtree)) { + // In general, we preserve ambiguities until they are removed from the stack + // during a pop operation where multiple paths lead to the same node. But in + // 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. + if (existing_link->node == link.node) { + if ( + ts_subtree_dynamic_precedence(link.subtree) > + ts_subtree_dynamic_precedence(existing_link->subtree) + ) { + ts_subtree_retain(link.subtree); + ts_subtree_release(subtree_pool, existing_link->subtree); + existing_link->subtree = link.subtree; + self->dynamic_precedence = + link.node->dynamic_precedence + ts_subtree_dynamic_precedence(link.subtree); + } + return; + } + + // If the previous nodes are mergeable, merge them recursively. + if ( + existing_link->node->state == link.node->state && + existing_link->node->position.bytes == link.node->position.bytes && + existing_link->node->error_cost == link.node->error_cost + ) { + for (int j = 0; j < link.node->link_count; j++) { + stack_node_add_link(existing_link->node, link.node->links[j], subtree_pool); + } + int32_t dynamic_precedence = link.node->dynamic_precedence; + if (link.subtree.ptr) { + dynamic_precedence += ts_subtree_dynamic_precedence(link.subtree); + } + if (dynamic_precedence > self->dynamic_precedence) { + self->dynamic_precedence = dynamic_precedence; + } + return; + } + } + } + + if (self->link_count == MAX_LINK_COUNT) return; + + stack_node_retain(link.node); + unsigned node_count = link.node->node_count; + int dynamic_precedence = link.node->dynamic_precedence; + self->links[self->link_count++] = link; + + if (link.subtree.ptr) { + ts_subtree_retain(link.subtree); + node_count += stack__subtree_node_count(link.subtree); + dynamic_precedence += ts_subtree_dynamic_precedence(link.subtree); + } + + if (node_count > self->node_count) self->node_count = node_count; + if (dynamic_precedence > self->dynamic_precedence) self->dynamic_precedence = dynamic_precedence; +} + +static void stack_head_delete( + StackHead *self, + StackNodeArray *pool, + SubtreePool *subtree_pool +) { + if (self->node) { + if (self->last_external_token.ptr) { + ts_subtree_release(subtree_pool, self->last_external_token); + } + if (self->lookahead_when_paused.ptr) { + ts_subtree_release(subtree_pool, self->lookahead_when_paused); + } + if (self->summary) { + array_delete(self->summary); + ts_free(self->summary); + } + stack_node_release(self->node, pool, subtree_pool); + } +} + +static StackVersion ts_stack__add_version( + Stack *self, + StackVersion original_version, + StackNode *node +) { + StackHead head = { + .node = node, + .node_count_at_last_error = array_get(&self->heads, original_version)->node_count_at_last_error, + .last_external_token = array_get(&self->heads, original_version)->last_external_token, + .status = StackStatusActive, + .lookahead_when_paused = NULL_SUBTREE, + }; + array_push(&self->heads, head); + stack_node_retain(node); + if (head.last_external_token.ptr) 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, + SubtreeArray *subtrees +) { + for (uint32_t i = self->slices.size - 1; i + 1 > 0; i--) { + StackVersion version = array_get(&self->slices, i)->version; + if (array_get(&self->heads, version)->node == node) { + StackSlice slice = {*subtrees, version}; + array_insert(&self->slices, i + 1, slice); + return; + } + } + + StackVersion version = ts_stack__add_version(self, original_version, node); + StackSlice slice = { *subtrees, version }; + array_push(&self->slices, slice); +} + +static StackSliceArray stack__iter( + Stack *self, + StackVersion version, + StackCallback callback, + void *payload, + int goal_subtree_count +) { + array_clear(&self->slices); + array_clear(&self->iterators); + + StackHead *head = array_get(&self->heads, version); + StackIterator new_iterator = { + .node = head->node, + .subtrees = array_new(), + .subtree_count = 0, + .is_pending = true, + }; + + bool include_subtrees = false; + if (goal_subtree_count >= 0) { + include_subtrees = true; + array_reserve(&new_iterator.subtrees, (uint32_t)ts_subtree_alloc_size(goal_subtree_count) / sizeof(Subtree)); + } + + array_push(&self->iterators, new_iterator); + + while (self->iterators.size > 0) { + for (uint32_t i = 0, size = self->iterators.size; i < size; i++) { + StackIterator *iterator = array_get(&self->iterators, i); + StackNode *node = iterator->node; + + StackAction action = callback(payload, iterator); + bool should_pop = action & StackActionPop; + bool should_stop = action & StackActionStop || node->link_count == 0; + + if (should_pop) { + SubtreeArray subtrees = iterator->subtrees; + if (!should_stop) { + ts_subtree_array_copy(subtrees, &subtrees); + } + ts_subtree_array_reverse(&subtrees); + ts_stack__add_slice( + self, + version, + node, + &subtrees + ); + } + + if (should_stop) { + if (!should_pop) { + ts_subtree_array_delete(self->subtree_pool, &iterator->subtrees); + } + array_erase(&self->iterators, i); + i--, size--; + continue; + } + + for (uint32_t j = 1; j <= node->link_count; j++) { + StackIterator *next_iterator; + StackLink link; + if (j == node->link_count) { + link = node->links[0]; + next_iterator = array_get(&self->iterators, i); + } else { + if (self->iterators.size >= MAX_ITERATOR_COUNT) continue; + link = node->links[j]; + StackIterator current_iterator = *array_get(&self->iterators, i); + array_push(&self->iterators, current_iterator); + next_iterator = array_back(&self->iterators); + ts_subtree_array_copy(next_iterator->subtrees, &next_iterator->subtrees); + } + + next_iterator->node = link.node; + if (link.subtree.ptr) { + if (include_subtrees) { + array_push(&next_iterator->subtrees, link.subtree); + ts_subtree_retain(link.subtree); + } + + if (!ts_subtree_extra(link.subtree)) { + next_iterator->subtree_count++; + if (!link.is_pending) { + next_iterator->is_pending = false; + } + } + } else { + next_iterator->subtree_count++; + next_iterator->is_pending = false; + } + } + } + } + + return self->slices; +} + +Stack *ts_stack_new(SubtreePool *subtree_pool) { + Stack *self = ts_calloc(1, sizeof(Stack)); + + array_init(&self->heads); + array_init(&self->slices); + array_init(&self->iterators); + array_init(&self->node_pool); + array_reserve(&self->heads, 4); + array_reserve(&self->slices, 4); + array_reserve(&self->iterators, 4); + array_reserve(&self->node_pool, MAX_NODE_POOL_SIZE); + + self->subtree_pool = subtree_pool; + self->base_node = stack_node_new(NULL, NULL_SUBTREE, false, 1, &self->node_pool); + ts_stack_clear(self); + + return self; +} + +void ts_stack_delete(Stack *self) { + if (self->slices.contents) + array_delete(&self->slices); + if (self->iterators.contents) + array_delete(&self->iterators); + 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(array_get(&self->heads, i), &self->node_pool, self->subtree_pool); + } + array_clear(&self->heads); + if (self->node_pool.contents) { + for (uint32_t i = 0; i < self->node_pool.size; i++) + ts_free(*array_get(&self->node_pool, i)); + array_delete(&self->node_pool); + } + array_delete(&self->heads); + ts_free(self); +} + +uint32_t ts_stack_version_count(const Stack *self) { + return self->heads.size; +} + +uint32_t ts_stack_halted_version_count(Stack *self) { + uint32_t count = 0; + for (uint32_t i = 0; i < self->heads.size; i++) { + StackHead *head = array_get(&self->heads, i); + if (head->status == StackStatusHalted) { + count++; + } + } + return count; +} + +TSStateId ts_stack_state(const Stack *self, StackVersion version) { + return array_get(&self->heads, version)->node->state; +} + +Length ts_stack_position(const Stack *self, StackVersion version) { + return array_get(&self->heads, version)->node->position; +} + +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, Subtree token) { + StackHead *head = array_get(&self->heads, version); + if (token.ptr) 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; +} + +unsigned ts_stack_error_cost(const Stack *self, StackVersion version) { + StackHead *head = array_get(&self->heads, version); + unsigned result = head->node->error_cost; + if ( + head->status == StackStatusPaused || + (head->node->state == ERROR_STATE && !head->node->links[0].subtree.ptr)) { + result += ERROR_COST_PER_RECOVERY; + } + return result; +} + +unsigned ts_stack_node_count_since_error(const Stack *self, StackVersion version) { + StackHead *head = array_get(&self->heads, version); + if (head->node->node_count < head->node_count_at_last_error) { + head->node_count_at_last_error = head->node->node_count; + } + return head->node->node_count - head->node_count_at_last_error; +} + +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, subtree, pending, state, &self->node_pool); + if (!subtree.ptr) head->node_count_at_last_error = new_node->node_count; + head->node = new_node; +} + +forceinline StackAction pop_count_callback(void *payload, const StackIterator *iterator) { + unsigned *goal_subtree_count = payload; + if (iterator->subtree_count == *goal_subtree_count) { + return StackActionPop | StackActionStop; + } else { + return StackActionNone; + } +} + +StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t count) { + return stack__iter(self, version, pop_count_callback, &count, (int)count); +} + + +forceinline StackAction pop_pending_callback(void *payload, const StackIterator *iterator) { + (void)payload; + if (iterator->subtree_count >= 1) { + if (iterator->is_pending) { + return StackActionPop | StackActionStop; + } else { + return StackActionStop; + } + } else { + return StackActionNone; + } +} + +StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version) { + StackSliceArray pop = stack__iter(self, version, pop_pending_callback, NULL, 0); + if (pop.size > 0) { + ts_stack_renumber_version(self, array_get(&pop, 0)->version, version); + array_get(&pop, 0)->version = version; + } + return pop; +} + +forceinline StackAction pop_error_callback(void *payload, const StackIterator *iterator) { + if (iterator->subtrees.size > 0) { + bool *found_error = payload; + if (!*found_error && ts_subtree_is_error(*array_get(&iterator->subtrees, 0))) { + *found_error = true; + return StackActionPop | StackActionStop; + } else { + return StackActionStop; + } + } else { + return StackActionNone; + } +} + +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].subtree.ptr && ts_subtree_is_error(node->links[i].subtree)) { + bool found_error = false; + StackSliceArray pop = stack__iter(self, version, pop_error_callback, &found_error, 1); + if (pop.size > 0) { + ts_assert(pop.size == 1); + ts_stack_renumber_version(self, array_get(&pop, 0)->version, version); + return array_get(&pop, 0)->subtrees; + } + break; + } + } + return (SubtreeArray) {.size = 0}; +} + +forceinline StackAction pop_all_callback(void *payload, const StackIterator *iterator) { + (void)payload; + return iterator->node->link_count == 0 ? StackActionPop : StackActionNone; +} + +StackSliceArray ts_stack_pop_all(Stack *self, StackVersion version) { + return stack__iter(self, version, pop_all_callback, NULL, 0); +} + +typedef struct { + StackSummary *summary; + unsigned max_depth; +} SummarizeStackSession; + +forceinline StackAction summarize_stack_callback(void *payload, const StackIterator *iterator) { + SummarizeStackSession *session = payload; + TSStateId state = iterator->node->state; + 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 = *array_get(session->summary, i); + if (entry.depth < depth) break; + if (entry.depth == depth && entry.state == state) return StackActionNone; + } + array_push(session->summary, ((StackSummaryEntry) { + .position = iterator->node->position, + .depth = depth, + .state = state, + })); + return StackActionNone; +} + +void ts_stack_record_summary(Stack *self, StackVersion version, unsigned max_depth) { + SummarizeStackSession session = { + .summary = ts_malloc(sizeof(StackSummary)), + .max_depth = max_depth + }; + array_init(session.summary); + stack__iter(self, version, summarize_stack_callback, &session, -1); + StackHead *head = array_get(&self->heads, version); + if (head->summary) { + array_delete(head->summary); + ts_free(head->summary); + } + head->summary = session.summary; +} + +StackSummary *ts_stack_get_summary(Stack *self, StackVersion version) { + return array_get(&self->heads, version)->summary; +} + +int ts_stack_dynamic_precedence(Stack *self, StackVersion version) { + return array_get(&self->heads, version)->node->dynamic_precedence; +} + +bool ts_stack_has_advanced_since_error(const Stack *self, StackVersion version) { + const StackHead *head = array_get(&self->heads, version); + const StackNode *node = head->node; + if (node->error_cost == 0) return true; + while (node) { + if (node->link_count > 0) { + Subtree subtree = node->links[0].subtree; + if (subtree.ptr) { + if (ts_subtree_total_bytes(subtree) > 0) { + return true; + } else if ( + node->node_count > head->node_count_at_last_error && + ts_subtree_error_cost(subtree) == 0 + ) { + node = node->links[0].node; + continue; + } + } + } + break; + } + return false; +} + +void ts_stack_remove_version(Stack *self, StackVersion version) { + stack_head_delete(array_get(&self->heads, version), &self->node_pool, self->subtree_pool); + array_erase(&self->heads, version); +} + +void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2) { + if (v1 == v2) return; + ts_assert(v2 < v1); + ts_assert((uint32_t)v1 < self->heads.size); + StackHead *source_head = array_get(&self->heads, v1); + StackHead *target_head = array_get(&self->heads, v2); + if (target_head->summary && !source_head->summary) { + source_head->summary = target_head->summary; + target_head->summary = NULL; + } + stack_head_delete(target_head, &self->node_pool, self->subtree_pool); + *target_head = *source_head; + array_erase(&self->heads, v1); +} + +void ts_stack_swap_versions(Stack *self, StackVersion v1, StackVersion v2) { + StackHead temporary_head = *array_get(&self->heads, v1); + *array_get(&self->heads, v1) = *array_get(&self->heads, v2); + *array_get(&self->heads, v2) = temporary_head; +} + +StackVersion ts_stack_copy_version(Stack *self, StackVersion version) { + ts_assert(version < self->heads.size); + StackHead version_head = *array_get(&self->heads, version); + array_push(&self->heads, version_head); + StackHead *head = array_back(&self->heads); + stack_node_retain(head->node); + if (head->last_external_token.ptr) ts_subtree_retain(head->last_external_token); + head->summary = NULL; + return self->heads.size - 1; +} + +bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2) { + if (!ts_stack_can_merge(self, version1, version2)) return false; + StackHead *head1 = array_get(&self->heads, version1); + StackHead *head2 = array_get(&self->heads, version2); + for (uint32_t i = 0; i < head2->node->link_count; i++) { + stack_node_add_link(head1->node, head2->node->links[i], self->subtree_pool); + } + if (head1->node->state == ERROR_STATE) { + head1->node_count_at_last_error = head1->node->node_count; + } + ts_stack_remove_version(self, version2); + return true; +} + +bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version2) { + StackHead *head1 = array_get(&self->heads, version1); + StackHead *head2 = array_get(&self->heads, version2); + return + head1->status == StackStatusActive && + 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 && + ts_subtree_external_scanner_state_eq(head1->last_external_token, head2->last_external_token); +} + +void ts_stack_halt(Stack *self, StackVersion version) { + array_get(&self->heads, version)->status = StackStatusHalted; +} + +void ts_stack_pause(Stack *self, StackVersion version, Subtree lookahead) { + StackHead *head = array_get(&self->heads, version); + head->status = StackStatusPaused; + head->lookahead_when_paused = lookahead; + head->node_count_at_last_error = head->node->node_count; +} + +bool ts_stack_is_active(const Stack *self, StackVersion version) { + return array_get(&self->heads, version)->status == StackStatusActive; +} + +bool ts_stack_is_halted(const Stack *self, StackVersion version) { + return array_get(&self->heads, version)->status == StackStatusHalted; +} + +bool ts_stack_is_paused(const Stack *self, StackVersion version) { + return array_get(&self->heads, version)->status == StackStatusPaused; +} + +Subtree ts_stack_resume(Stack *self, StackVersion version) { + StackHead *head = array_get(&self->heads, version); + ts_assert(head->status == StackStatusPaused); + Subtree result = head->lookahead_when_paused; + head->status = StackStatusActive; + head->lookahead_when_paused = NULL_SUBTREE; + return result; +} + +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(array_get(&self->heads, i), &self->node_pool, self->subtree_pool); + } + array_clear(&self->heads); + array_push(&self->heads, ((StackHead) { + .node = self->base_node, + .status = StackStatusActive, + .last_external_token = NULL_SUBTREE, + .lookahead_when_paused = NULL_SUBTREE, + })); +} + +bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f) { + array_reserve(&self->iterators, 32); + if (!f) f = stderr; + + fprintf(f, "digraph stack {\n"); + fprintf(f, "rankdir=\"RL\";\n"); + fprintf(f, "edge [arrowhead=none]\n"); + + Array(StackNode *) visited_nodes = array_new(); + + array_clear(&self->iterators); + for (uint32_t i = 0; i < self->heads.size; i++) { + StackHead *head = array_get(&self->heads, i); + if (head->status == StackStatusHalted) continue; + + fprintf(f, "node_head_%u [shape=none, label=\"\"]\n", i); + fprintf(f, "node_head_%u -> node_%p [", i, (void *)head->node); + + if (head->status == StackStatusPaused) { + fprintf(f, "color=red "); + } + fprintf(f, + "label=%u, fontcolor=blue, weight=10000, labeltooltip=\"node_count: %u\nerror_cost: %u", + i, + ts_stack_node_count_since_error(self, i), + ts_stack_error_cost(self, i) + ); + + if (head->summary) { + fprintf(f, "\nsummary:"); + for (uint32_t j = 0; j < head->summary->size; j++) fprintf(f, " %u", array_get(head->summary, j)->state); + } + + if (head->last_external_token.ptr) { + const ExternalScannerState *state = &head->last_external_token.ptr->external_scanner_state; + const char *data = ts_external_scanner_state_data(state); + fprintf(f, "\nexternal_scanner_state:"); + for (uint32_t j = 0; j < state->length; j++) fprintf(f, " %2X", data[j]); + } + + fprintf(f, "\"]\n"); + array_push(&self->iterators, ((StackIterator) { + .node = head->node + })); + } + + bool all_iterators_done = false; + while (!all_iterators_done) { + all_iterators_done = true; + + for (uint32_t i = 0; i < self->iterators.size; i++) { + StackIterator iterator = *array_get(&self->iterators, i); + StackNode *node = iterator.node; + + for (uint32_t j = 0; j < visited_nodes.size; j++) { + if (*array_get(&visited_nodes, j) == node) { + node = NULL; + break; + } + } + + if (!node) continue; + all_iterators_done = false; + + fprintf(f, "node_%p [", (void *)node); + if (node->state == ERROR_STATE) { + fprintf(f, "label=\"?\""); + } else if ( + node->link_count == 1 && + node->links[0].subtree.ptr && + ts_subtree_extra(node->links[0].subtree) + ) { + fprintf(f, "shape=point margin=0 label=\"\""); + } else { + fprintf(f, "label=\"%d\"", node->state); + } + + fprintf( + f, + " tooltip=\"position: %u,%u\nnode_count:%u\nerror_cost: %u\ndynamic_precedence: %d\"];\n", + 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++) { + StackLink link = node->links[j]; + fprintf(f, "node_%p -> node_%p [", (void *)node, (void *)link.node); + if (link.is_pending) fprintf(f, "style=dashed "); + if (link.subtree.ptr && ts_subtree_extra(link.subtree)) fprintf(f, "fontcolor=gray "); + + if (!link.subtree.ptr) { + fprintf(f, "color=red"); + } else { + fprintf(f, "label=\""); + bool quoted = ts_subtree_visible(link.subtree) && !ts_subtree_named(link.subtree); + if (quoted) fprintf(f, "'"); + ts_language_write_symbol_as_dot_string(language, f, ts_subtree_symbol(link.subtree)); + if (quoted) fprintf(f, "'"); + fprintf(f, "\""); + fprintf( + f, + "labeltooltip=\"error_cost: %u\ndynamic_precedence: %" PRId32 "\"", + ts_subtree_error_cost(link.subtree), + ts_subtree_dynamic_precedence(link.subtree) + ); + } + + fprintf(f, "];\n"); + + StackIterator *next_iterator; + if (j == 0) { + next_iterator = array_get(&self->iterators, i); + } else { + array_push(&self->iterators, iterator); + next_iterator = array_back(&self->iterators); + } + next_iterator->node = link.node; + } + + array_push(&visited_nodes, node); + } + } + + fprintf(f, "}\n"); + + array_delete(&visited_nodes); + return true; +} + +#undef forceinline diff --git a/codegraph-kernel/vendor/tree-sitter/src/stack.h b/codegraph-kernel/vendor/tree-sitter/src/stack.h new file mode 100644 index 0000000000..2619f1e8a5 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/stack.h @@ -0,0 +1,133 @@ +#ifndef TREE_SITTER_PARSE_STACK_H_ +#define TREE_SITTER_PARSE_STACK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./array.h" +#include "./subtree.h" +#include + +typedef struct Stack Stack; + +typedef unsigned StackVersion; +#define STACK_VERSION_NONE ((StackVersion)-1) + +typedef struct { + SubtreeArray subtrees; + StackVersion version; +} StackSlice; +typedef Array(StackSlice) StackSliceArray; + +typedef struct { + Length position; + unsigned depth; + TSStateId state; +} StackSummaryEntry; +typedef Array(StackSummaryEntry) StackSummary; + +// Create a stack. +Stack *ts_stack_new(SubtreePool *subtree_pool); + +// Release the memory reserved for a given stack. +void ts_stack_delete(Stack *self); + +// Get the stack's current number of versions. +uint32_t ts_stack_version_count(const Stack *self); + +// Get the stack's current number of halted versions. +uint32_t ts_stack_halted_version_count(Stack *self); + +// Get the state at the top of the given version of the stack. If the stack is +// empty, this returns the initial state, 0. +TSStateId ts_stack_state(const Stack *self, StackVersion version); + +// Get the last external token associated with a given version of the stack. +Subtree ts_stack_last_external_token(const Stack *self, StackVersion version); + +// Set the last external token associated with a given version of the stack. +void ts_stack_set_last_external_token(Stack *self, StackVersion version, Subtree token); + +// Get the position of the given version of the stack within the document. +Length ts_stack_position(const Stack *, StackVersion); + +// Push a tree and state onto the given version of the stack. +// +// 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 *self, StackVersion version, Subtree subtree, bool pending, TSStateId state); + +// 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 +// versions which had previously been merged. It returns an array that +// specifies the index of each revealed version and the trees that were +// removed from that version. +StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t count); + +// Remove an error at the top of the given version of the stack. +SubtreeArray ts_stack_pop_error(Stack *self, StackVersion version); + +// Remove any pending trees from the top of the given version of the stack. +StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version); + +// Remove all trees from the given version of the stack. +StackSliceArray ts_stack_pop_all(Stack *self, StackVersion version); + +// Get the maximum number of tree nodes reachable from this version of the stack +// since the last error was detected. +unsigned ts_stack_node_count_since_error(const Stack *self, StackVersion version); + +int ts_stack_dynamic_precedence(Stack *self, StackVersion version); + +bool ts_stack_has_advanced_since_error(const Stack *self, StackVersion version); + +// Compute a summary of all the parse states near the top of the given +// version of the stack and store the summary for later retrieval. +void ts_stack_record_summary(Stack *self, StackVersion version, unsigned max_depth); + +// Retrieve a summary of all the parse states near the top of the +// given version of the stack. +StackSummary *ts_stack_get_summary(Stack *self, StackVersion version); + +// Get the total cost of all errors on the given version of the stack. +unsigned ts_stack_error_cost(const Stack *self, StackVersion version); + +// Merge the given two stack versions if possible, returning true +// if they were successfully merged and false otherwise. +bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2); + +// Determine whether the given two stack versions can be merged. +bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version2); + +Subtree ts_stack_resume(Stack *self, StackVersion version); + +void ts_stack_pause(Stack *self, StackVersion version, Subtree lookahead); + +void ts_stack_halt(Stack *self, StackVersion version); + +bool ts_stack_is_active(const Stack *self, StackVersion version); + +bool ts_stack_is_paused(const Stack *self, StackVersion version); + +bool ts_stack_is_halted(const Stack *self, StackVersion version); + +void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2); + +void ts_stack_swap_versions(Stack *, StackVersion v1, StackVersion v2); + +StackVersion ts_stack_copy_version(Stack *self, StackVersion version); + +// Remove the given version from the stack. +void ts_stack_remove_version(Stack *self, StackVersion version); + +void ts_stack_clear(Stack *self); + +bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f); + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_PARSE_STACK_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/subtree.c b/codegraph-kernel/vendor/tree-sitter/src/subtree.c new file mode 100644 index 0000000000..97d55c8611 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/subtree.c @@ -0,0 +1,1034 @@ +#include +#include +#include +#include +#include +#include "./alloc.h" +#include "./array.h" +#include "./atomic.h" +#include "./subtree.h" +#include "./length.h" +#include "./language.h" +#include "./error_costs.h" +#include "./ts_assert.h" +#include + +typedef struct { + Length start; + Length old_end; + Length new_end; +} Edit; + +#define TS_MAX_INLINE_TREE_LENGTH UINT8_MAX +#define TS_MAX_TREE_POOL_SIZE 32 + +// ExternalScannerState + +void ts_external_scanner_state_init(ExternalScannerState *self, const char *data, unsigned length) { + self->length = length; + if (length > sizeof(self->short_data)) { + self->long_data = ts_malloc(length); + memcpy(self->long_data, data, length); + } else { + memcpy(self->short_data, data, length); + } +} + +ExternalScannerState ts_external_scanner_state_copy(const ExternalScannerState *self) { + ExternalScannerState result = *self; + if (self->length > sizeof(self->short_data)) { + result.long_data = ts_malloc(self->length); + memcpy(result.long_data, self->long_data, self->length); + } + return result; +} + +void ts_external_scanner_state_delete(ExternalScannerState *self) { + if (self->length > sizeof(self->short_data)) { + ts_free(self->long_data); + } +} + +const char *ts_external_scanner_state_data(const ExternalScannerState *self) { + if (self->length > sizeof(self->short_data)) { + return self->long_data; + } else { + return self->short_data; + } +} + +bool ts_external_scanner_state_eq(const ExternalScannerState *self, const char *buffer, unsigned length) { + return + self->length == length && + memcmp(ts_external_scanner_state_data(self), buffer, length) == 0; +} + +// SubtreeArray + +void ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest) { + dest->size = self.size; + dest->capacity = self.capacity; + dest->contents = self.contents; + if (self.capacity > 0) { + dest->contents = ts_calloc(self.capacity, sizeof(Subtree)); + memcpy(dest->contents, self.contents, self.size * sizeof(Subtree)); + for (uint32_t i = 0; i < self.size; i++) { + ts_subtree_retain(*array_get(dest, i)); + } + } +} + +void ts_subtree_array_clear(SubtreePool *pool, SubtreeArray *self) { + for (uint32_t i = 0; i < self->size; i++) { + ts_subtree_release(pool, *array_get(self, i)); + } + array_clear(self); +} + +void ts_subtree_array_delete(SubtreePool *pool, SubtreeArray *self) { + ts_subtree_array_clear(pool, self); + array_delete(self); +} + +void ts_subtree_array_remove_trailing_extras( + SubtreeArray *self, + SubtreeArray *destination +) { + array_clear(destination); + while (self->size > 0) { + Subtree last = *array_get(self, self->size - 1); + if (ts_subtree_extra(last)) { + self->size--; + array_push(destination, last); + } else { + break; + } + } + ts_subtree_array_reverse(destination); +} + +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; + Subtree swap = *array_get(self, i); + *array_get(self, i) = *array_get(self, reverse_index); + *array_get(self, reverse_index) = swap; + } +} + +// SubtreePool + +SubtreePool ts_subtree_pool_new(uint32_t capacity) { + SubtreePool self = {array_new(), array_new()}; + array_reserve(&self.free_trees, capacity); + return 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(array_get(&self->free_trees, i)->ptr); + } + array_delete(&self->free_trees); + } + if (self->tree_stack.contents) array_delete(&self->tree_stack); +} + +static SubtreeHeapData *ts_subtree_pool_allocate(SubtreePool *self) { + if (self->free_trees.size > 0) { + return array_pop(&self->free_trees).ptr; + } else { + return ts_malloc(sizeof(SubtreeHeapData)); + } +} + +static void ts_subtree_pool_free(SubtreePool *self, SubtreeHeapData *tree) { + if (self->free_trees.capacity > 0 && self->free_trees.size + 1 <= TS_MAX_TREE_POOL_SIZE) { + array_push(&self->free_trees, (MutableSubtree) {.ptr = tree}); + } else { + ts_free(tree); + } +} + +// Subtree + +static inline bool ts_subtree_can_inline(Length padding, Length size, uint32_t lookahead_bytes) { + return + padding.bytes < TS_MAX_INLINE_TREE_LENGTH && + padding.extent.row < 16 && + padding.extent.column < TS_MAX_INLINE_TREE_LENGTH && + size.bytes < TS_MAX_INLINE_TREE_LENGTH && + size.extent.row == 0 && + size.extent.column < TS_MAX_INLINE_TREE_LENGTH && + lookahead_bytes < 16; +} + +Subtree ts_subtree_new_leaf( + SubtreePool *pool, TSSymbol symbol, Length padding, Length size, + uint32_t lookahead_bytes, TSStateId parse_state, + bool has_external_tokens, bool depends_on_column, + bool is_keyword, const TSLanguage *language +) { + TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol); + bool extra = symbol == ts_builtin_sym_end; + + bool is_inline = ( + symbol <= UINT8_MAX && + !has_external_tokens && + ts_subtree_can_inline(padding, size, lookahead_bytes) + ); + + if (is_inline) { + return (Subtree) {{ + .parse_state = parse_state, + .symbol = symbol, + .padding_bytes = padding.bytes, + .padding_rows = padding.extent.row, + .padding_columns = padding.extent.column, + .size_bytes = size.bytes, + .lookahead_bytes = lookahead_bytes, + .visible = metadata.visible, + .named = metadata.named, + .extra = extra, + .has_changes = false, + .is_missing = false, + .is_keyword = is_keyword, + .is_inline = true, + }}; + } else { + SubtreeHeapData *data = ts_subtree_pool_allocate(pool); + *data = (SubtreeHeapData) { + .ref_count = 1, + .padding = padding, + .size = size, + .lookahead_bytes = lookahead_bytes, + .error_cost = 0, + .child_count = 0, + .symbol = symbol, + .parse_state = parse_state, + .visible = metadata.visible, + .named = metadata.named, + .extra = extra, + .fragile_left = false, + .fragile_right = false, + .has_changes = false, + .has_external_tokens = has_external_tokens, + .has_external_scanner_state_change = false, + .depends_on_column = depends_on_column, + .is_missing = false, + .is_keyword = is_keyword, + {{.first_leaf = {.symbol = 0, .parse_state = 0}}} + }; + return (Subtree) {.ptr = data}; + } +} + +void ts_subtree_set_symbol( + MutableSubtree *self, + TSSymbol symbol, + const TSLanguage *language +) { + TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol); + if (self->data.is_inline) { + ts_assert(symbol < UINT8_MAX); + self->data.symbol = symbol; + self->data.named = metadata.named; + self->data.visible = metadata.visible; + } else { + self->ptr->symbol = symbol; + self->ptr->named = metadata.named; + self->ptr->visible = metadata.visible; + } +} + +Subtree ts_subtree_new_error( + SubtreePool *pool, int32_t lookahead_char, Length padding, Length size, + uint32_t bytes_scanned, TSStateId parse_state, const TSLanguage *language +) { + Subtree result = ts_subtree_new_leaf( + pool, ts_builtin_sym_error, padding, size, bytes_scanned, + parse_state, false, false, false, language + ); + SubtreeHeapData *data = (SubtreeHeapData *)result.ptr; + data->fragile_left = true; + data->fragile_right = true; + data->lookahead_char = lookahead_char; + return result; +} + +// Clone a subtree. +MutableSubtree ts_subtree_clone(Subtree self) { + size_t alloc_size = ts_subtree_alloc_size(self.ptr->child_count); + Subtree *new_children = ts_malloc(alloc_size); + Subtree *old_children = ts_subtree_children(self); + memcpy(new_children, old_children, alloc_size); + SubtreeHeapData *result = (SubtreeHeapData *)&new_children[self.ptr->child_count]; + if (self.ptr->child_count > 0) { + for (uint32_t i = 0; i < self.ptr->child_count; i++) { + ts_subtree_retain(new_children[i]); + } + } else if (self.ptr->has_external_tokens) { + result->external_scanner_state = ts_external_scanner_state_copy( + &self.ptr->external_scanner_state + ); + } + result->ref_count = 1; + return (MutableSubtree) {.ptr = result}; +} + +// Get mutable version of a subtree. +// +// This takes ownership of the subtree. If the subtree has only one owner, +// this will directly convert it into a mutable version. Otherwise, it will +// perform a copy. +MutableSubtree ts_subtree_make_mut(SubtreePool *pool, Subtree self) { + if (self.data.is_inline) return (MutableSubtree) {self.data}; + if (self.ptr->ref_count == 1) return ts_subtree_to_mut_unsafe(self); + MutableSubtree result = ts_subtree_clone(self); + ts_subtree_release(pool, self); + return result; +} + +void ts_subtree_compress( + MutableSubtree self, + unsigned count, + const TSLanguage *language, + MutableSubtreeArray *stack +) { + unsigned initial_stack_size = stack->size; + + MutableSubtree tree = self; + TSSymbol symbol = tree.ptr->symbol; + for (unsigned i = 0; i < count; i++) { + if (tree.ptr->ref_count > 1 || tree.ptr->child_count < 2) break; + + MutableSubtree child = ts_subtree_to_mut_unsafe(ts_subtree_children(tree)[0]); + if ( + child.data.is_inline || + child.ptr->child_count < 2 || + child.ptr->ref_count > 1 || + child.ptr->symbol != symbol + ) break; + + MutableSubtree grandchild = ts_subtree_to_mut_unsafe(ts_subtree_children(child)[0]); + if ( + grandchild.data.is_inline || + grandchild.ptr->child_count < 2 || + grandchild.ptr->ref_count > 1 || + grandchild.ptr->symbol != symbol + ) break; + + ts_subtree_children(tree)[0] = ts_subtree_from_mut(grandchild); + ts_subtree_children(child)[0] = ts_subtree_children(grandchild)[grandchild.ptr->child_count - 1]; + ts_subtree_children(grandchild)[grandchild.ptr->child_count - 1] = ts_subtree_from_mut(child); + array_push(stack, tree); + tree = grandchild; + } + + while (stack->size > initial_stack_size) { + tree = array_pop(stack); + MutableSubtree child = ts_subtree_to_mut_unsafe(ts_subtree_children(tree)[0]); + MutableSubtree grandchild = ts_subtree_to_mut_unsafe(ts_subtree_children(child)[child.ptr->child_count - 1]); + ts_subtree_summarize_children(grandchild, language); + ts_subtree_summarize_children(child, language); + ts_subtree_summarize_children(tree, language); + } +} + +// Assign all of the node's properties that depend on its children. +void ts_subtree_summarize_children( + MutableSubtree self, + const TSLanguage *language +) { + ts_assert(!self.data.is_inline); + + self.ptr->named_child_count = 0; + self.ptr->visible_child_count = 0; + self.ptr->error_cost = 0; + self.ptr->repeat_depth = 0; + self.ptr->visible_descendant_count = 0; + self.ptr->has_external_tokens = false; + self.ptr->depends_on_column = false; + self.ptr->has_external_scanner_state_change = false; + self.ptr->dynamic_precedence = 0; + + uint32_t structural_index = 0; + const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self.ptr->production_id); + uint32_t lookahead_end_byte = 0; + + const Subtree *children = ts_subtree_children(self); + for (uint32_t i = 0; i < self.ptr->child_count; i++) { + Subtree child = children[i]; + + if ( + self.ptr->size.extent.row == 0 && + ts_subtree_depends_on_column(child) + ) { + self.ptr->depends_on_column = true; + } + + if (ts_subtree_has_external_scanner_state_change(child)) { + self.ptr->has_external_scanner_state_change = true; + } + + if (i == 0) { + self.ptr->padding = ts_subtree_padding(child); + self.ptr->size = ts_subtree_size(child); + } else { + self.ptr->size = length_add(self.ptr->size, ts_subtree_total_size(child)); + } + + uint32_t child_lookahead_end_byte = + self.ptr->padding.bytes + + self.ptr->size.bytes + + ts_subtree_lookahead_bytes(child); + if (child_lookahead_end_byte > lookahead_end_byte) { + lookahead_end_byte = child_lookahead_end_byte; + } + + if (ts_subtree_symbol(child) != ts_builtin_sym_error_repeat) { + self.ptr->error_cost += ts_subtree_error_cost(child); + } + + uint32_t grandchild_count = ts_subtree_child_count(child); + if ( + self.ptr->symbol == ts_builtin_sym_error || + self.ptr->symbol == ts_builtin_sym_error_repeat + ) { + if (!ts_subtree_extra(child) && !(ts_subtree_is_error(child) && grandchild_count == 0)) { + if (ts_subtree_visible(child)) { + self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE; + } else if (grandchild_count > 0) { + self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE * child.ptr->visible_child_count; + } + } + } + + self.ptr->dynamic_precedence += ts_subtree_dynamic_precedence(child); + self.ptr->visible_descendant_count += ts_subtree_visible_descendant_count(child); + + if ( + !ts_subtree_extra(child) && + ts_subtree_symbol(child) != 0 && + alias_sequence && + alias_sequence[structural_index] != 0 + ) { + self.ptr->visible_descendant_count++; + self.ptr->visible_child_count++; + if (ts_language_symbol_metadata(language, alias_sequence[structural_index]).named) { + self.ptr->named_child_count++; + } + } else if (ts_subtree_visible(child)) { + self.ptr->visible_descendant_count++; + self.ptr->visible_child_count++; + if (ts_subtree_named(child)) self.ptr->named_child_count++; + } else if (grandchild_count > 0) { + self.ptr->visible_child_count += child.ptr->visible_child_count; + self.ptr->named_child_count += child.ptr->named_child_count; + } + + if (ts_subtree_has_external_tokens(child)) self.ptr->has_external_tokens = true; + + if (ts_subtree_is_error(child)) { + self.ptr->fragile_left = self.ptr->fragile_right = true; + self.ptr->parse_state = TS_TREE_STATE_NONE; + } + + if (!ts_subtree_extra(child)) structural_index++; + } + + self.ptr->lookahead_bytes = lookahead_end_byte - self.ptr->size.bytes - self.ptr->padding.bytes; + + if ( + self.ptr->symbol == ts_builtin_sym_error || + self.ptr->symbol == ts_builtin_sym_error_repeat + ) { + self.ptr->error_cost += + ERROR_COST_PER_RECOVERY + + ERROR_COST_PER_SKIPPED_CHAR * self.ptr->size.bytes + + ERROR_COST_PER_SKIPPED_LINE * self.ptr->size.extent.row; + } + + if (self.ptr->child_count > 0) { + Subtree first_child = children[0]; + Subtree last_child = children[self.ptr->child_count - 1]; + + self.ptr->first_leaf.symbol = ts_subtree_leaf_symbol(first_child); + self.ptr->first_leaf.parse_state = ts_subtree_leaf_parse_state(first_child); + + if (ts_subtree_fragile_left(first_child)) self.ptr->fragile_left = true; + if (ts_subtree_fragile_right(last_child)) self.ptr->fragile_right = true; + + if ( + self.ptr->child_count >= 2 && + !self.ptr->visible && + !self.ptr->named && + ts_subtree_symbol(first_child) == self.ptr->symbol + ) { + if (ts_subtree_repeat_depth(first_child) > ts_subtree_repeat_depth(last_child)) { + self.ptr->repeat_depth = ts_subtree_repeat_depth(first_child) + 1; + } else { + self.ptr->repeat_depth = ts_subtree_repeat_depth(last_child) + 1; + } + } + } +} + +// Create a new parent node with the given children. +// +// This takes ownership of the children array. +MutableSubtree ts_subtree_new_node( + TSSymbol symbol, + SubtreeArray *children, + unsigned production_id, + const TSLanguage *language +) { + TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol); + bool fragile = symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat; + + // Allocate the node's data at the end of the array of children. + size_t new_byte_size = ts_subtree_alloc_size(children->size); + if (children->capacity * sizeof(Subtree) < new_byte_size) { + children->contents = ts_realloc(children->contents, new_byte_size); + children->capacity = (uint32_t)(new_byte_size / sizeof(Subtree)); + } + SubtreeHeapData *data = (SubtreeHeapData *)&children->contents[children->size]; + + *data = (SubtreeHeapData) { + .ref_count = 1, + .symbol = symbol, + .child_count = children->size, + .visible = metadata.visible, + .named = metadata.named, + .has_changes = false, + .has_external_scanner_state_change = false, + .fragile_left = fragile, + .fragile_right = fragile, + .is_keyword = false, + {{ + .visible_descendant_count = 0, + .production_id = production_id, + .first_leaf = {.symbol = 0, .parse_state = 0}, + }} + }; + MutableSubtree result = {.ptr = data}; + ts_subtree_summarize_children(result, language); + return result; +} + +// Create a new error node containing the given children. +// +// This node is treated as 'extra'. Its children are prevented from having +// having any effect on the parse state. +Subtree ts_subtree_new_error_node( + SubtreeArray *children, + bool extra, + const TSLanguage *language +) { + MutableSubtree result = ts_subtree_new_node( + ts_builtin_sym_error, children, 0, language + ); + result.ptr->extra = extra; + return ts_subtree_from_mut(result); +} + +// Create a new 'missing leaf' node. +// +// This node is treated as 'extra'. Its children are prevented from having +// having any effect on the parse state. +Subtree ts_subtree_new_missing_leaf( + SubtreePool *pool, + TSSymbol symbol, + Length padding, + uint32_t lookahead_bytes, + const TSLanguage *language +) { + Subtree result = ts_subtree_new_leaf( + pool, symbol, padding, length_zero(), lookahead_bytes, + 0, false, false, false, language + ); + if (result.data.is_inline) { + result.data.is_missing = true; + } else { + ((SubtreeHeapData *)result.ptr)->is_missing = true; + } + return result; +} + +void ts_subtree_retain(Subtree self) { + if (self.data.is_inline) return; + ts_assert(self.ptr->ref_count > 0); + atomic_inc((volatile uint32_t *)&self.ptr->ref_count); + ts_assert(self.ptr->ref_count != 0); +} + +void ts_subtree_release(SubtreePool *pool, Subtree self) { + if (self.data.is_inline) return; + array_clear(&pool->tree_stack); + + ts_assert(self.ptr->ref_count > 0); + if (atomic_dec((volatile uint32_t *)&self.ptr->ref_count) == 0) { + array_push(&pool->tree_stack, ts_subtree_to_mut_unsafe(self)); + } + + while (pool->tree_stack.size > 0) { + MutableSubtree tree = array_pop(&pool->tree_stack); + if (tree.ptr->child_count > 0) { + Subtree *children = ts_subtree_children(tree); + for (uint32_t i = 0; i < tree.ptr->child_count; i++) { + Subtree child = children[i]; + if (child.data.is_inline) continue; + ts_assert(child.ptr->ref_count > 0); + if (atomic_dec((volatile uint32_t *)&child.ptr->ref_count) == 0) { + array_push(&pool->tree_stack, ts_subtree_to_mut_unsafe(child)); + } + } + ts_free(children); + } else { + if (tree.ptr->has_external_tokens) { + ts_external_scanner_state_delete(&tree.ptr->external_scanner_state); + } + ts_subtree_pool_free(pool, tree.ptr); + } + } +} + +int ts_subtree_compare(Subtree left, Subtree right, SubtreePool *pool) { + array_push(&pool->tree_stack, ts_subtree_to_mut_unsafe(left)); + array_push(&pool->tree_stack, ts_subtree_to_mut_unsafe(right)); + + while (pool->tree_stack.size > 0) { + right = ts_subtree_from_mut(array_pop(&pool->tree_stack)); + left = ts_subtree_from_mut(array_pop(&pool->tree_stack)); + + int result = 0; + if (ts_subtree_symbol(left) < ts_subtree_symbol(right)) result = -1; + else if (ts_subtree_symbol(right) < ts_subtree_symbol(left)) result = 1; + else if (ts_subtree_child_count(left) < ts_subtree_child_count(right)) result = -1; + else if (ts_subtree_child_count(right) < ts_subtree_child_count(left)) result = 1; + if (result != 0) { + array_clear(&pool->tree_stack); + return result; + } + + for (uint32_t i = ts_subtree_child_count(left); i > 0; i--) { + Subtree left_child = ts_subtree_children(left)[i - 1]; + Subtree right_child = ts_subtree_children(right)[i - 1]; + array_push(&pool->tree_stack, ts_subtree_to_mut_unsafe(left_child)); + array_push(&pool->tree_stack, ts_subtree_to_mut_unsafe(right_child)); + } + } + + return 0; +} + +static inline void ts_subtree_set_has_changes(MutableSubtree *self) { + if (self->data.is_inline) { + self->data.has_changes = true; + } else { + self->ptr->has_changes = true; + } +} + +Subtree ts_subtree_edit(Subtree self, const TSInputEdit *input_edit, SubtreePool *pool) { + typedef struct { + Subtree *tree; + Edit edit; + } EditEntry; + + Array(EditEntry) stack = array_new(); + array_push(&stack, ((EditEntry) { + .tree = &self, + .edit = (Edit) { + .start = {input_edit->start_byte, input_edit->start_point}, + .old_end = {input_edit->old_end_byte, input_edit->old_end_point}, + .new_end = {input_edit->new_end_byte, input_edit->new_end_point}, + }, + })); + + while (stack.size) { + EditEntry entry = array_pop(&stack); + Edit edit = entry.edit; + bool is_noop = edit.old_end.bytes == edit.start.bytes && edit.new_end.bytes == edit.start.bytes; + bool is_pure_insertion = edit.old_end.bytes == edit.start.bytes; + bool parent_depends_on_column = ts_subtree_depends_on_column(*entry.tree); + bool column_shifted = edit.new_end.extent.column != edit.old_end.extent.column; + + Length size = ts_subtree_size(*entry.tree); + Length padding = ts_subtree_padding(*entry.tree); + Length total_size = length_add(padding, size); + uint32_t lookahead_bytes = ts_subtree_lookahead_bytes(*entry.tree); + uint32_t end_byte = total_size.bytes + lookahead_bytes; + if (edit.start.bytes > end_byte || (is_noop && edit.start.bytes == end_byte)) continue; + + // If the edit is entirely within the space before this subtree, then shift this + // subtree over according to the edit without changing its size. + if (edit.old_end.bytes <= padding.bytes) { + padding = length_add(edit.new_end, length_sub(padding, edit.old_end)); + } + + // If the edit starts in the space before this subtree and extends into this subtree, + // shrink the subtree's content to compensate for the change in the space before it. + else if (edit.start.bytes < padding.bytes) { + size = length_saturating_sub(size, length_sub(edit.old_end, padding)); + padding = edit.new_end; + } + + // If the edit is within this subtree, resize the subtree to reflect the edit. + else if ( + edit.start.bytes < total_size.bytes || + (edit.start.bytes == total_size.bytes && is_pure_insertion) + ) { + size = length_add( + length_sub(edit.new_end, padding), + length_saturating_sub(total_size, edit.old_end) + ); + } + + MutableSubtree result = ts_subtree_make_mut(pool, *entry.tree); + + if (result.data.is_inline) { + if (ts_subtree_can_inline(padding, size, lookahead_bytes)) { + result.data.padding_bytes = padding.bytes; + result.data.padding_rows = padding.extent.row; + result.data.padding_columns = padding.extent.column; + result.data.size_bytes = size.bytes; + } else { + SubtreeHeapData *data = ts_subtree_pool_allocate(pool); + data->ref_count = 1; + data->padding = padding; + data->size = size; + data->lookahead_bytes = lookahead_bytes; + data->error_cost = 0; + data->child_count = 0; + data->symbol = result.data.symbol; + data->parse_state = result.data.parse_state; + data->visible = result.data.visible; + data->named = result.data.named; + data->extra = result.data.extra; + data->fragile_left = false; + data->fragile_right = false; + data->has_changes = false; + data->has_external_tokens = false; + data->depends_on_column = false; + data->is_missing = result.data.is_missing; + data->is_keyword = result.data.is_keyword; + result.ptr = data; + } + } else { + result.ptr->padding = padding; + result.ptr->size = size; + } + + ts_subtree_set_has_changes(&result); + *entry.tree = ts_subtree_from_mut(result); + + Length child_left, child_right = length_zero(); + for (uint32_t i = 0, n = ts_subtree_child_count(*entry.tree); i < n; i++) { + Subtree *child = &ts_subtree_children(*entry.tree)[i]; + Length child_size = ts_subtree_total_size(*child); + child_left = child_right; + child_right = length_add(child_left, child_size); + + // If this child ends before the edit, it is not affected. + if (child_right.bytes + ts_subtree_lookahead_bytes(*child) < edit.start.bytes) continue; + + // Keep editing child nodes until a node is reached that starts after the edit. + // Also, if this node's validity depends on its column position, then continue + // invalidating child nodes until reaching a line break. + if (( + (child_left.bytes > edit.old_end.bytes) || + (child_left.bytes == edit.old_end.bytes && child_size.bytes > 0 && i > 0) + ) && ( + !parent_depends_on_column || + child_left.extent.row > padding.extent.row + ) && ( + !ts_subtree_depends_on_column(*child) || + !column_shifted || + child_left.extent.row > edit.old_end.extent.row + )) { + break; + } + + // Transform edit into the child's coordinate space. + Edit child_edit = { + .start = length_saturating_sub(edit.start, child_left), + .old_end = length_saturating_sub(edit.old_end, child_left), + .new_end = length_saturating_sub(edit.new_end, child_left), + }; + + // Interpret all inserted text as applying to the *first* child that touches the edit. + // Subsequent children are only never have any text inserted into them; they are only + // shrunk to compensate for the edit. + if ( + child_right.bytes > edit.start.bytes || + (child_right.bytes == edit.start.bytes && is_pure_insertion) + ) { + edit.new_end = edit.start; + } + + // Children that occur before the edit are not reshaped by the edit. + else { + child_edit.old_end = child_edit.start; + child_edit.new_end = child_edit.start; + } + + // Queue processing of this child's subtree. + array_push(&stack, ((EditEntry) { + .tree = child, + .edit = child_edit, + })); + } + } + + array_delete(&stack); + return self; +} + +Subtree ts_subtree_last_external_token(Subtree tree) { + if (!ts_subtree_has_external_tokens(tree)) return NULL_SUBTREE; + while (tree.ptr->child_count > 0) { + for (uint32_t i = tree.ptr->child_count - 1; i + 1 > 0; i--) { + Subtree child = ts_subtree_children(tree)[i]; + if (ts_subtree_has_external_tokens(child)) { + tree = child; + break; + } + } + } + return tree; +} + +static size_t ts_subtree__write_char_to_string(char *str, size_t n, int32_t chr) { + if (chr == -1) + return snprintf(str, n, "INVALID"); + else if (chr == '\0') + return snprintf(str, n, "'\\0'"); + else if (chr == '\n') + return snprintf(str, n, "'\\n'"); + else if (chr == '\t') + return snprintf(str, n, "'\\t'"); + else if (chr == '\r') + return snprintf(str, n, "'\\r'"); + else if (0 < chr && chr < 128 && isprint(chr)) + return snprintf(str, n, "'%c'", chr); + else + return snprintf(str, n, "%d", chr); +} + +static const char *const ROOT_FIELD = "__ROOT__"; + +static size_t ts_subtree__write_to_string( + Subtree self, char *string, size_t limit, + const TSLanguage *language, bool include_all, + TSSymbol alias_symbol, bool alias_is_named, const char *field_name +) { + if (!self.ptr) return snprintf(string, limit, "(NULL)"); + + char *cursor = string; + char **writer = (limit > 1) ? &cursor : &string; + bool is_root = field_name == ROOT_FIELD; + bool is_visible = + include_all || + ts_subtree_missing(self) || + ( + alias_symbol + ? alias_is_named + : ts_subtree_visible(self) && ts_subtree_named(self) + ); + + if (is_visible) { + if (!is_root) { + cursor += snprintf(*writer, limit, " "); + if (field_name) { + cursor += snprintf(*writer, limit, "%s: ", field_name); + } + } + + if (ts_subtree_is_error(self) && ts_subtree_child_count(self) == 0 && self.ptr->size.bytes > 0) { + cursor += snprintf(*writer, limit, "(UNEXPECTED "); + cursor += ts_subtree__write_char_to_string(*writer, limit, self.ptr->lookahead_char); + } else { + TSSymbol symbol = alias_symbol ? alias_symbol : ts_subtree_symbol(self); + const char *symbol_name = ts_language_symbol_name(language, symbol); + if (ts_subtree_missing(self)) { + cursor += snprintf(*writer, limit, "(MISSING "); + if (alias_is_named || ts_subtree_named(self)) { + cursor += snprintf(*writer, limit, "%s", symbol_name); + } else { + cursor += snprintf(*writer, limit, "\"%s\"", symbol_name); + } + } else { + cursor += snprintf(*writer, limit, "(%s", symbol_name); + } + } + } else if (is_root) { + TSSymbol symbol = alias_symbol ? alias_symbol : ts_subtree_symbol(self); + const char *symbol_name = ts_language_symbol_name(language, symbol); + if (ts_subtree_child_count(self) > 0) { + cursor += snprintf(*writer, limit, "(%s", symbol_name); + } else if (ts_subtree_named(self)) { + cursor += snprintf(*writer, limit, "(%s)", symbol_name); + } else { + cursor += snprintf(*writer, limit, "(\"%s\")", symbol_name); + } + } + + if (ts_subtree_child_count(self)) { + const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self.ptr->production_id); + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map( + language, + self.ptr->production_id, + &field_map, + &field_map_end + ); + + uint32_t structural_child_index = 0; + for (uint32_t i = 0; i < self.ptr->child_count; i++) { + Subtree child = ts_subtree_children(self)[i]; + if (ts_subtree_extra(child)) { + cursor += ts_subtree__write_to_string( + child, *writer, limit, + language, include_all, + 0, false, NULL + ); + } else { + TSSymbol subtree_alias_symbol = alias_sequence + ? alias_sequence[structural_child_index] + : 0; + bool subtree_alias_is_named = subtree_alias_symbol + ? ts_language_symbol_metadata(language, subtree_alias_symbol).named + : false; + + const char *child_field_name = is_visible ? NULL : field_name; + for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) { + if (!map->inherited && map->child_index == structural_child_index) { + child_field_name = language->field_names[map->field_id]; + break; + } + } + + cursor += ts_subtree__write_to_string( + child, *writer, limit, + language, include_all, + subtree_alias_symbol, subtree_alias_is_named, child_field_name + ); + structural_child_index++; + } + } + } + + if (is_visible) cursor += snprintf(*writer, limit, ")"); + + return cursor - string; +} + +char *ts_subtree_string( + Subtree self, + TSSymbol alias_symbol, + bool alias_is_named, + const TSLanguage *language, + bool include_all +) { + char scratch_string[1]; + size_t size = ts_subtree__write_to_string( + self, scratch_string, 1, + language, include_all, + alias_symbol, alias_is_named, ROOT_FIELD + ) + 1; + char *result = ts_malloc(size * sizeof(char)); + ts_subtree__write_to_string( + self, result, size, + language, include_all, + alias_symbol, alias_is_named, ROOT_FIELD + ); + return result; +} + +void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset, + const TSLanguage *language, TSSymbol alias_symbol, + FILE *f) { + TSSymbol subtree_symbol = ts_subtree_symbol(*self); + TSSymbol symbol = alias_symbol ? alias_symbol : subtree_symbol; + uint32_t end_offset = start_offset + ts_subtree_total_bytes(*self); + fprintf(f, "tree_%p [label=\"", (void *)self); + ts_language_write_symbol_as_dot_string(language, f, symbol); + fprintf(f, "\""); + + if (ts_subtree_child_count(*self) == 0) fprintf(f, ", shape=plaintext"); + if (ts_subtree_extra(*self)) fprintf(f, ", fontcolor=gray"); + if (ts_subtree_has_changes(*self)) fprintf(f, ", color=green, penwidth=2"); + + fprintf(f, ", tooltip=\"" + "range: %u - %u\n" + "state: %d\n" + "error-cost: %u\n" + "has-changes: %u\n" + "depends-on-column: %u\n" + "descendant-count: %u\n" + "repeat-depth: %u\n" + "lookahead-bytes: %u", + start_offset, end_offset, + ts_subtree_parse_state(*self), + ts_subtree_error_cost(*self), + ts_subtree_has_changes(*self), + ts_subtree_depends_on_column(*self), + ts_subtree_visible_descendant_count(*self), + ts_subtree_repeat_depth(*self), + ts_subtree_lookahead_bytes(*self) + ); + + 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, "\"]\n"); + + uint32_t child_start_offset = start_offset; + uint32_t child_info_offset = + language->max_alias_sequence_length * + ts_subtree_production_id(*self); + for (uint32_t i = 0, n = ts_subtree_child_count(*self); i < n; i++) { + const Subtree *child = &ts_subtree_children(*self)[i]; + TSSymbol subtree_alias_symbol = 0; + if (!ts_subtree_extra(*child) && child_info_offset) { + subtree_alias_symbol = language->alias_sequences[child_info_offset]; + child_info_offset++; + } + ts_subtree__print_dot_graph(child, child_start_offset, language, subtree_alias_symbol, f); + fprintf(f, "tree_%p -> tree_%p [tooltip=%u]\n", (void *)self, (void *)child, i); + child_start_offset += ts_subtree_total_bytes(*child); + } +} + +void ts_subtree_print_dot_graph(Subtree self, const TSLanguage *language, FILE *f) { + fprintf(f, "digraph tree {\n"); + fprintf(f, "edge [arrowhead=none]\n"); + ts_subtree__print_dot_graph(&self, 0, language, 0, f); + fprintf(f, "}\n"); +} + +const ExternalScannerState *ts_subtree_external_scanner_state(Subtree self) { + static const ExternalScannerState empty_state = {{.short_data = {0}}, .length = 0}; + if ( + self.ptr && + !self.data.is_inline && + self.ptr->has_external_tokens && + self.ptr->child_count == 0 + ) { + return &self.ptr->external_scanner_state; + } else { + return &empty_state; + } +} + +bool ts_subtree_external_scanner_state_eq(Subtree self, Subtree other) { + const ExternalScannerState *state_self = ts_subtree_external_scanner_state(self); + const ExternalScannerState *state_other = ts_subtree_external_scanner_state(other); + return ts_external_scanner_state_eq( + state_self, + ts_external_scanner_state_data(state_other), + state_other->length + ); +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/subtree.h b/codegraph-kernel/vendor/tree-sitter/src/subtree.h new file mode 100644 index 0000000000..ffc5fb7a3b --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/subtree.h @@ -0,0 +1,399 @@ +#ifndef TREE_SITTER_SUBTREE_H_ +#define TREE_SITTER_SUBTREE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "./length.h" +#include "./array.h" +#include "./error_costs.h" +#include "./host.h" +#include "tree_sitter/api.h" +#include "./parser.h" + +#define TS_TREE_STATE_NONE USHRT_MAX +#define NULL_SUBTREE ((Subtree) {.ptr = NULL}) + +// The serialized state of an external scanner. +// +// Every time an external token subtree is created after a call to an +// external scanner, the scanner's `serialize` function is called to +// retrieve a serialized copy of its state. The bytes are then copied +// onto the subtree itself so that the scanner's state can later be +// restored using its `deserialize` function. +// +// Small byte arrays are stored inline, and long ones are allocated +// separately on the heap. +typedef struct { + union { + char *long_data; + char short_data[24]; + }; + uint32_t length; +} ExternalScannerState; + +// A compact representation of a subtree. +// +// This representation is used for small leaf nodes that are not +// errors, and were not created by an external scanner. +// +// The idea behind the layout of this struct is that the `is_inline` +// bit will fall exactly into the same location as the least significant +// bit of the pointer in `Subtree` or `MutableSubtree`, respectively. +// Because of alignment, for any valid pointer this will be 0, giving +// us the opportunity to make use of this bit to signify whether to use +// the pointer or the inline struct. +typedef struct SubtreeInlineData SubtreeInlineData; + +#define SUBTREE_BITS \ + bool visible : 1; \ + bool named : 1; \ + bool extra : 1; \ + bool has_changes : 1; \ + bool is_missing : 1; \ + bool is_keyword : 1; + +#define SUBTREE_SIZE \ + uint8_t padding_columns; \ + uint8_t padding_rows : 4; \ + uint8_t lookahead_bytes : 4; \ + uint8_t padding_bytes; \ + uint8_t size_bytes; + +#if TS_BIG_ENDIAN +#if TS_PTR_SIZE == 32 + +struct SubtreeInlineData { + uint16_t parse_state; + uint8_t symbol; + SUBTREE_BITS + bool unused : 1; + bool is_inline : 1; + SUBTREE_SIZE +}; + +#else + +struct SubtreeInlineData { + SUBTREE_SIZE + uint16_t parse_state; + uint8_t symbol; + SUBTREE_BITS + bool unused : 1; + bool is_inline : 1; +}; + +#endif +#else + +struct SubtreeInlineData { + bool is_inline : 1; + SUBTREE_BITS + uint8_t symbol; + uint16_t parse_state; + SUBTREE_SIZE +}; + +#endif + +#undef SUBTREE_BITS +#undef SUBTREE_SIZE + +// A heap-allocated representation of a subtree. +// +// This representation is used for parent nodes, external tokens, +// errors, and other leaf nodes whose data is too large to fit into +// the inline representation. +typedef struct { + volatile uint32_t ref_count; + Length padding; + Length size; + uint32_t lookahead_bytes; + uint32_t error_cost; + uint32_t child_count; + TSSymbol symbol; + TSStateId parse_state; + + 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 has_external_scanner_state_change : 1; + bool depends_on_column: 1; + bool is_missing : 1; + bool is_keyword : 1; + + union { + // Non-terminal subtrees (`child_count > 0`) + struct { + uint32_t visible_child_count; + uint32_t named_child_count; + uint32_t visible_descendant_count; + int32_t dynamic_precedence; + uint16_t repeat_depth; + uint16_t production_id; + struct { + TSSymbol symbol; + TSStateId parse_state; + } first_leaf; + }; + + // External terminal subtrees (`child_count == 0 && has_external_tokens`) + ExternalScannerState external_scanner_state; + + // Error terminal subtrees (`child_count == 0 && symbol == ts_builtin_sym_error`) + int32_t lookahead_char; + }; +} SubtreeHeapData; + +// The fundamental building block of a syntax tree. +typedef union { + SubtreeInlineData data; + const SubtreeHeapData *ptr; +} Subtree; + +// Like Subtree, but mutable. +typedef union { + SubtreeInlineData data; + SubtreeHeapData *ptr; +} MutableSubtree; + +typedef Array(Subtree) SubtreeArray; +typedef Array(MutableSubtree) MutableSubtreeArray; + +typedef struct { + MutableSubtreeArray free_trees; + MutableSubtreeArray tree_stack; +} SubtreePool; + +void ts_external_scanner_state_init(ExternalScannerState *self, const char *data, unsigned length); +const char *ts_external_scanner_state_data(const ExternalScannerState *self); +bool ts_external_scanner_state_eq(const ExternalScannerState *self, const char *buffer, unsigned length); +void ts_external_scanner_state_delete(ExternalScannerState *self); + +void ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest); +void ts_subtree_array_clear(SubtreePool *pool, SubtreeArray *self); +void ts_subtree_array_delete(SubtreePool *pool, SubtreeArray *self); +void ts_subtree_array_remove_trailing_extras(SubtreeArray *self, SubtreeArray *destination); +void ts_subtree_array_reverse(SubtreeArray *self); + +SubtreePool ts_subtree_pool_new(uint32_t capacity); +void ts_subtree_pool_delete(SubtreePool *self); + +Subtree ts_subtree_new_leaf( + SubtreePool *pool, TSSymbol symbol, Length padding, Length size, + uint32_t lookahead_bytes, TSStateId parse_state, + bool has_external_tokens, bool depends_on_column, + bool is_keyword, const TSLanguage *language +); +Subtree ts_subtree_new_error( + SubtreePool *pool, int32_t lookahead_char, Length padding, Length size, + uint32_t bytes_scanned, TSStateId parse_state, const TSLanguage *language +); +MutableSubtree ts_subtree_new_node( + TSSymbol symbol, + SubtreeArray *chiildren, + unsigned production_id, + const TSLanguage *language +); +Subtree ts_subtree_new_error_node( + SubtreeArray *children, + bool extra, + const TSLanguage * language +); +Subtree ts_subtree_new_missing_leaf( + SubtreePool *pool, + TSSymbol symbol, + Length padding, + uint32_t lookahead_bytes, + const TSLanguage *language +); +MutableSubtree ts_subtree_make_mut(SubtreePool *pool, Subtree self); +void ts_subtree_retain(Subtree self); +void ts_subtree_release(SubtreePool *pool, Subtree self); +int ts_subtree_compare(Subtree left, Subtree right, SubtreePool *pool); +void ts_subtree_set_symbol(MutableSubtree *self, TSSymbol symbol, const TSLanguage *language); +void ts_subtree_compress(MutableSubtree self, unsigned count, const TSLanguage *language, MutableSubtreeArray *stack); +void ts_subtree_summarize_children(MutableSubtree self, const TSLanguage *language); +Subtree ts_subtree_edit(Subtree self, const TSInputEdit *edit, SubtreePool *pool); +char *ts_subtree_string(Subtree self, TSSymbol alias_symbol, bool alias_is_named, const TSLanguage *language, bool include_all); +void ts_subtree_print_dot_graph(Subtree self, const TSLanguage *language, FILE *f); +Subtree ts_subtree_last_external_token(Subtree tree); +const ExternalScannerState *ts_subtree_external_scanner_state(Subtree self); +bool ts_subtree_external_scanner_state_eq(Subtree self, Subtree other); + +#define SUBTREE_GET(self, name) ((self).data.is_inline ? (self).data.name : (self).ptr->name) + +static inline TSSymbol ts_subtree_symbol(Subtree self) { return SUBTREE_GET(self, symbol); } +static inline bool ts_subtree_visible(Subtree self) { return SUBTREE_GET(self, visible); } +static inline bool ts_subtree_named(Subtree self) { return SUBTREE_GET(self, named); } +static inline bool ts_subtree_extra(Subtree self) { return SUBTREE_GET(self, extra); } +static inline bool ts_subtree_has_changes(Subtree self) { return SUBTREE_GET(self, has_changes); } +static inline bool ts_subtree_missing(Subtree self) { return SUBTREE_GET(self, is_missing); } +static inline bool ts_subtree_is_keyword(Subtree self) { return SUBTREE_GET(self, is_keyword); } +static inline TSStateId ts_subtree_parse_state(Subtree self) { return SUBTREE_GET(self, parse_state); } +static inline uint32_t ts_subtree_lookahead_bytes(Subtree self) { return SUBTREE_GET(self, lookahead_bytes); } + +#undef SUBTREE_GET + +// Get the size needed to store a heap-allocated subtree with the given +// number of children. +static inline size_t ts_subtree_alloc_size(uint32_t child_count) { + return child_count * sizeof(Subtree) + sizeof(SubtreeHeapData); +} + +// Get a subtree's children, which are allocated immediately before the +// tree's own heap data. +#define ts_subtree_children(self) \ + ((self).data.is_inline ? NULL : (Subtree *)((self).ptr) - (self).ptr->child_count) + +static inline void ts_subtree_set_extra(MutableSubtree *self, bool is_extra) { + if (self->data.is_inline) { + self->data.extra = is_extra; + } else { + self->ptr->extra = is_extra; + } +} + +static inline TSSymbol ts_subtree_leaf_symbol(Subtree self) { + if (self.data.is_inline) return self.data.symbol; + if (self.ptr->child_count == 0) return self.ptr->symbol; + return self.ptr->first_leaf.symbol; +} + +static inline TSStateId ts_subtree_leaf_parse_state(Subtree self) { + if (self.data.is_inline) return self.data.parse_state; + if (self.ptr->child_count == 0) return self.ptr->parse_state; + return self.ptr->first_leaf.parse_state; +} + +static inline Length ts_subtree_padding(Subtree self) { + if (self.data.is_inline) { + Length result = {self.data.padding_bytes, {self.data.padding_rows, self.data.padding_columns}}; + return result; + } else { + return self.ptr->padding; + } +} + +static inline Length ts_subtree_size(Subtree self) { + if (self.data.is_inline) { + Length result = {self.data.size_bytes, {0, self.data.size_bytes}}; + return result; + } else { + return self.ptr->size; + } +} + +static inline Length ts_subtree_total_size(Subtree self) { + return length_add(ts_subtree_padding(self), ts_subtree_size(self)); +} + +static inline uint32_t ts_subtree_total_bytes(Subtree self) { + return ts_subtree_total_size(self).bytes; +} + +static inline uint32_t ts_subtree_child_count(Subtree self) { + return self.data.is_inline ? 0 : self.ptr->child_count; +} + +static inline uint32_t ts_subtree_repeat_depth(Subtree self) { + return self.data.is_inline ? 0 : self.ptr->repeat_depth; +} + +static inline uint32_t ts_subtree_is_repetition(Subtree self) { + return self.data.is_inline + ? 0 + : !self.ptr->named && !self.ptr->visible && self.ptr->child_count != 0; +} + +static inline uint32_t ts_subtree_visible_descendant_count(Subtree self) { + return (self.data.is_inline || self.ptr->child_count == 0) + ? 0 + : self.ptr->visible_descendant_count; +} + +static inline uint32_t ts_subtree_visible_child_count(Subtree self) { + if (ts_subtree_child_count(self) > 0) { + return self.ptr->visible_child_count; + } else { + return 0; + } +} + +static inline uint32_t ts_subtree_error_cost(Subtree self) { + if (ts_subtree_missing(self)) { + return ERROR_COST_PER_MISSING_TREE + ERROR_COST_PER_RECOVERY; + } else { + return self.data.is_inline ? 0 : self.ptr->error_cost; + } +} + +static inline int32_t ts_subtree_dynamic_precedence(Subtree self) { + return (self.data.is_inline || self.ptr->child_count == 0) ? 0 : self.ptr->dynamic_precedence; +} + +static inline uint16_t ts_subtree_production_id(Subtree self) { + if (ts_subtree_child_count(self) > 0) { + return self.ptr->production_id; + } else { + return 0; + } +} + +static inline bool ts_subtree_fragile_left(Subtree self) { + return self.data.is_inline ? false : self.ptr->fragile_left; +} + +static inline bool ts_subtree_fragile_right(Subtree self) { + return self.data.is_inline ? false : self.ptr->fragile_right; +} + +static inline bool ts_subtree_has_external_tokens(Subtree self) { + return self.data.is_inline ? false : self.ptr->has_external_tokens; +} + +static inline bool ts_subtree_has_external_scanner_state_change(Subtree self) { + return self.data.is_inline ? false : self.ptr->has_external_scanner_state_change; +} + +static inline bool ts_subtree_depends_on_column(Subtree self) { + return self.data.is_inline ? false : self.ptr->depends_on_column; +} + +static inline bool ts_subtree_is_fragile(Subtree self) { + return self.data.is_inline ? false : (self.ptr->fragile_left || self.ptr->fragile_right); +} + +static inline bool ts_subtree_is_error(Subtree self) { + return ts_subtree_symbol(self) == ts_builtin_sym_error; +} + +static inline bool ts_subtree_is_eof(Subtree self) { + return ts_subtree_symbol(self) == ts_builtin_sym_end; +} + +static inline Subtree ts_subtree_from_mut(MutableSubtree self) { + Subtree result; + result.data = self.data; + return result; +} + +static inline MutableSubtree ts_subtree_to_mut_unsafe(Subtree self) { + MutableSubtree result; + result.data = self.data; + return result; +} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_SUBTREE_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/tree.c b/codegraph-kernel/vendor/tree-sitter/src/tree.c new file mode 100644 index 0000000000..bb45118000 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/tree.c @@ -0,0 +1,170 @@ +#include "tree_sitter/api.h" +#include "./array.h" +#include "./get_changed_ranges.h" +#include "./length.h" +#include "./subtree.h" +#include "./tree_cursor.h" +#include "./tree.h" + +TSTree *ts_tree_new( + Subtree root, const TSLanguage *language, + const TSRange *included_ranges, unsigned included_range_count +) { + TSTree *result = ts_malloc(sizeof(TSTree)); + result->root = root; + result->language = ts_language_copy(language); + result->included_ranges = ts_calloc(included_range_count, sizeof(TSRange)); + memcpy(result->included_ranges, included_ranges, included_range_count * sizeof(TSRange)); + result->included_range_count = included_range_count; + return result; +} + +TSTree *ts_tree_copy(const TSTree *self) { + ts_subtree_retain(self->root); + return ts_tree_new(self->root, self->language, self->included_ranges, self->included_range_count); +} + +void ts_tree_delete(TSTree *self) { + if (!self) return; + + SubtreePool pool = ts_subtree_pool_new(0); + ts_subtree_release(&pool, self->root); + ts_subtree_pool_delete(&pool); + ts_language_delete(self->language); + ts_free(self->included_ranges); + ts_free(self); +} + +TSNode ts_tree_root_node(const TSTree *self) { + return ts_node_new(self, &self->root, ts_subtree_padding(self->root), 0); +} + +TSNode ts_tree_root_node_with_offset( + const TSTree *self, + uint32_t offset_bytes, + TSPoint offset_extent +) { + Length offset = {offset_bytes, offset_extent}; + return ts_node_new(self, &self->root, length_add(offset, ts_subtree_padding(self->root)), 0); +} + +const TSLanguage *ts_tree_language(const TSTree *self) { + return self->language; +} + +void ts_tree_edit(TSTree *self, const TSInputEdit *edit) { + for (unsigned i = 0; i < self->included_range_count; i++) { + TSRange *range = &self->included_ranges[i]; + if (range->end_byte >= edit->old_end_byte) { + if (range->end_byte != UINT32_MAX) { + range->end_byte = edit->new_end_byte + (range->end_byte - edit->old_end_byte); + range->end_point = point_add( + edit->new_end_point, + point_sub(range->end_point, edit->old_end_point) + ); + if (range->end_byte < edit->new_end_byte) { + range->end_byte = UINT32_MAX; + range->end_point = POINT_MAX; + } + } + } else if (range->end_byte > edit->start_byte) { + range->end_byte = edit->start_byte; + range->end_point = edit->start_point; + } + if (range->start_byte >= edit->old_end_byte) { + range->start_byte = edit->new_end_byte + (range->start_byte - edit->old_end_byte); + range->start_point = point_add( + edit->new_end_point, + point_sub(range->start_point, edit->old_end_point) + ); + if (range->start_byte < edit->new_end_byte) { + range->start_byte = UINT32_MAX; + range->start_point = POINT_MAX; + } + } else if (range->start_byte > edit->start_byte) { + range->start_byte = edit->start_byte; + range->start_point = edit->start_point; + } + } + + SubtreePool pool = ts_subtree_pool_new(0); + self->root = ts_subtree_edit(self->root, edit, &pool); + ts_subtree_pool_delete(&pool); +} + +TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length) { + *length = self->included_range_count; + TSRange *ranges = ts_calloc(self->included_range_count, sizeof(TSRange)); + memcpy(ranges, self->included_ranges, self->included_range_count * sizeof(TSRange)); + return ranges; +} + +TSRange *ts_tree_get_changed_ranges(const TSTree *old_tree, const TSTree *new_tree, uint32_t *length) { + TreeCursor cursor1 = {NULL, array_new(), 0}; + TreeCursor cursor2 = {NULL, array_new(), 0}; + ts_tree_cursor_init(&cursor1, ts_tree_root_node(old_tree)); + ts_tree_cursor_init(&cursor2, ts_tree_root_node(new_tree)); + + TSRangeArray included_range_differences = array_new(); + ts_range_array_get_changed_ranges( + old_tree->included_ranges, old_tree->included_range_count, + new_tree->included_ranges, new_tree->included_range_count, + &included_range_differences + ); + + TSRange *result; + *length = ts_subtree_get_changed_ranges( + &old_tree->root, &new_tree->root, &cursor1, &cursor2, + old_tree->language, &included_range_differences, &result + ); + + array_delete(&included_range_differences); + array_delete(&cursor1.stack); + array_delete(&cursor2.stack); + return result; +} + +#ifdef _WIN32 + +#include +#include + +int _ts_dup(HANDLE handle) { + HANDLE dup_handle; + if (!DuplicateHandle( + GetCurrentProcess(), handle, + GetCurrentProcess(), &dup_handle, + 0, FALSE, DUPLICATE_SAME_ACCESS + )) return -1; + + return _open_osfhandle((intptr_t)dup_handle, 0); +} + +void ts_tree_print_dot_graph(const TSTree *self, int fd) { + FILE *file = _fdopen(_ts_dup((HANDLE)_get_osfhandle(fd)), "a"); + ts_subtree_print_dot_graph(self->root, self->language, file); + fclose(file); +} + +#elif !defined(__wasi__) // WASI doesn't support dup + +#include + +int _ts_dup(int file_descriptor) { + return dup(file_descriptor); +} + +void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor) { + FILE *file = fdopen(_ts_dup(file_descriptor), "a"); + ts_subtree_print_dot_graph(self->root, self->language, file); + fclose(file); +} + +#else + +void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor) { + (void)self; + (void)file_descriptor; +} + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/tree.h b/codegraph-kernel/vendor/tree-sitter/src/tree.h new file mode 100644 index 0000000000..9328f55a5b --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/tree.h @@ -0,0 +1,31 @@ +#ifndef TREE_SITTER_TREE_H_ +#define TREE_SITTER_TREE_H_ + +#include "./subtree.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const Subtree *child; + const Subtree *parent; + Length position; + TSSymbol alias_symbol; +} ParentCacheEntry; + +struct TSTree { + Subtree root; + const TSLanguage *language; + TSRange *included_ranges; + unsigned included_range_count; +}; + +TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *included_ranges, unsigned included_range_count); +TSNode ts_node_new(const TSTree *tree, const Subtree *subtree, Length position, TSSymbol alias); + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_TREE_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/tree_cursor.c b/codegraph-kernel/vendor/tree-sitter/src/tree_cursor.c new file mode 100644 index 0000000000..70ef5e39aa --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/tree_cursor.c @@ -0,0 +1,716 @@ +#include "tree_sitter/api.h" +#include "./tree_cursor.h" +#include "./language.h" +#include "./tree.h" + +typedef struct { + Subtree parent; + const TSTree *tree; + Length position; + uint32_t child_index; + uint32_t structural_child_index; + uint32_t descendant_index; + const TSSymbol *alias_sequence; +} CursorChildIterator; + +// CursorChildIterator + +static inline bool ts_tree_cursor_is_entry_visible(const TreeCursor *self, uint32_t index) { + TreeCursorEntry *entry = array_get(&self->stack, index); + if (index == 0 || ts_subtree_visible(*entry->subtree)) { + return true; + } else if (!ts_subtree_extra(*entry->subtree)) { + TreeCursorEntry *parent_entry = array_get(&self->stack, index - 1); + return ts_language_alias_at( + self->tree->language, + parent_entry->subtree->ptr->production_id, + entry->structural_child_index + ); + } else { + return false; + } +} + +static inline CursorChildIterator ts_tree_cursor_iterate_children(const TreeCursor *self) { + TreeCursorEntry *last_entry = array_back(&self->stack); + if (ts_subtree_child_count(*last_entry->subtree) == 0) { + return (CursorChildIterator) {NULL_SUBTREE, self->tree, length_zero(), 0, 0, 0, NULL}; + } + const TSSymbol *alias_sequence = ts_language_alias_sequence( + self->tree->language, + last_entry->subtree->ptr->production_id + ); + + uint32_t descendant_index = last_entry->descendant_index; + if (ts_tree_cursor_is_entry_visible(self, self->stack.size - 1)) { + descendant_index += 1; + } + + return (CursorChildIterator) { + .tree = self->tree, + .parent = *last_entry->subtree, + .position = last_entry->position, + .child_index = 0, + .structural_child_index = 0, + .descendant_index = descendant_index, + .alias_sequence = alias_sequence, + }; +} + +static inline bool ts_tree_cursor_child_iterator_next( + CursorChildIterator *self, + TreeCursorEntry *result, + bool *visible +) { + if (!self->parent.ptr || self->child_index == self->parent.ptr->child_count) return false; + const Subtree *child = &ts_subtree_children(self->parent)[self->child_index]; + *result = (TreeCursorEntry) { + .subtree = child, + .position = self->position, + .child_index = self->child_index, + .structural_child_index = self->structural_child_index, + .descendant_index = self->descendant_index, + }; + *visible = ts_subtree_visible(*child); + bool extra = ts_subtree_extra(*child); + if (!extra) { + if (self->alias_sequence) { + *visible |= self->alias_sequence[self->structural_child_index]; + } + self->structural_child_index++; + } + + self->descendant_index += ts_subtree_visible_descendant_count(*child); + if (*visible) { + self->descendant_index += 1; + } + + self->position = length_add(self->position, ts_subtree_size(*child)); + self->child_index++; + + if (self->child_index < self->parent.ptr->child_count) { + Subtree next_child = ts_subtree_children(self->parent)[self->child_index]; + self->position = length_add(self->position, ts_subtree_padding(next_child)); + } + + return true; +} + +// Return a position that, when `b` is added to it, yields `a`. This +// can only be computed if `b` has zero rows. Otherwise, this function +// returns `LENGTH_UNDEFINED`, and the caller needs to recompute +// the position some other way. +static inline Length length_backtrack(Length a, Length b) { + if (length_is_undefined(a) || b.extent.row != 0) { + return LENGTH_UNDEFINED; + } + + Length result; + result.bytes = a.bytes - b.bytes; + result.extent.row = a.extent.row; + result.extent.column = a.extent.column - b.extent.column; + return result; +} + +static inline bool ts_tree_cursor_child_iterator_previous( + CursorChildIterator *self, + TreeCursorEntry *result, + bool *visible +) { + // this is mostly a reverse `ts_tree_cursor_child_iterator_next` taking into + // account unsigned underflow + if (!self->parent.ptr || (int8_t)self->child_index == -1) return false; + const Subtree *child = &ts_subtree_children(self->parent)[self->child_index]; + *result = (TreeCursorEntry) { + .subtree = child, + .position = self->position, + .child_index = self->child_index, + .structural_child_index = self->structural_child_index, + }; + *visible = ts_subtree_visible(*child); + bool extra = ts_subtree_extra(*child); + + self->position = length_backtrack(self->position, ts_subtree_padding(*child)); + self->child_index--; + + if (!extra && self->alias_sequence) { + *visible |= self->alias_sequence[self->structural_child_index]; + if (self->structural_child_index > 0) { + self->structural_child_index--; + } + } + + // unsigned can underflow so compare it to child_count + if (self->child_index < self->parent.ptr->child_count) { + Subtree previous_child = ts_subtree_children(self->parent)[self->child_index]; + Length size = ts_subtree_size(previous_child); + self->position = length_backtrack(self->position, size); + } + + return true; +} + +// TSTreeCursor - lifecycle + +TSTreeCursor ts_tree_cursor_new(TSNode node) { + TSTreeCursor self = {NULL, NULL, {0, 0, 0}}; + ts_tree_cursor_init((TreeCursor *)&self, node); + return self; +} + +void ts_tree_cursor_reset(TSTreeCursor *_self, TSNode node) { + ts_tree_cursor_init((TreeCursor *)_self, node); +} + +void ts_tree_cursor_init(TreeCursor *self, TSNode node) { + self->tree = node.tree; + self->root_alias_symbol = node.context[3]; + array_clear(&self->stack); + array_push(&self->stack, ((TreeCursorEntry) { + .subtree = (const Subtree *)node.id, + .position = { + ts_node_start_byte(node), + ts_node_start_point(node) + }, + .child_index = 0, + .structural_child_index = 0, + .descendant_index = 0, + })); +} + +void ts_tree_cursor_delete(TSTreeCursor *_self) { + TreeCursor *self = (TreeCursor *)_self; + array_delete(&self->stack); +} + +// TSTreeCursor - walking the tree + +TreeCursorStep ts_tree_cursor_goto_first_child_internal(TSTreeCursor *_self) { + TreeCursor *self = (TreeCursor *)_self; + bool visible; + TreeCursorEntry entry; + CursorChildIterator iterator = ts_tree_cursor_iterate_children(self); + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + if (visible) { + array_push(&self->stack, entry); + return TreeCursorStepVisible; + } + if (ts_subtree_visible_child_count(*entry.subtree) > 0) { + array_push(&self->stack, entry); + return TreeCursorStepHidden; + } + } + return TreeCursorStepNone; +} + +bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) { + for (;;) { + switch (ts_tree_cursor_goto_first_child_internal(self)) { + case TreeCursorStepHidden: + continue; + case TreeCursorStepVisible: + return true; + default: + return false; + } + } +} + +TreeCursorStep ts_tree_cursor_goto_last_child_internal(TSTreeCursor *_self) { + TreeCursor *self = (TreeCursor *)_self; + bool visible; + TreeCursorEntry entry; + CursorChildIterator iterator = ts_tree_cursor_iterate_children(self); + if (!iterator.parent.ptr || iterator.parent.ptr->child_count == 0) return TreeCursorStepNone; + + TreeCursorEntry last_entry = {0}; + TreeCursorStep last_step = TreeCursorStepNone; + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + if (visible) { + last_entry = entry; + last_step = TreeCursorStepVisible; + } + else if (ts_subtree_visible_child_count(*entry.subtree) > 0) { + last_entry = entry; + last_step = TreeCursorStepHidden; + } + } + if (last_entry.subtree) { + array_push(&self->stack, last_entry); + return last_step; + } + + return TreeCursorStepNone; +} + +bool ts_tree_cursor_goto_last_child(TSTreeCursor *self) { + for (;;) { + switch (ts_tree_cursor_goto_last_child_internal(self)) { + case TreeCursorStepHidden: + continue; + case TreeCursorStepVisible: + return true; + default: + return false; + } + } +} + +static inline int64_t ts_tree_cursor_goto_first_child_for_byte_and_point( + TSTreeCursor *_self, + uint32_t goal_byte, + TSPoint goal_point +) { + TreeCursor *self = (TreeCursor *)_self; + uint32_t initial_size = self->stack.size; + uint32_t visible_child_index = 0; + + bool did_descend; + do { + did_descend = false; + + bool visible; + TreeCursorEntry entry; + CursorChildIterator iterator = ts_tree_cursor_iterate_children(self); + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + Length entry_end = length_add(entry.position, ts_subtree_size(*entry.subtree)); + bool at_goal = entry_end.bytes > goal_byte && point_gt(entry_end.extent, goal_point); + uint32_t visible_child_count = ts_subtree_visible_child_count(*entry.subtree); + if (at_goal) { + if (visible) { + array_push(&self->stack, entry); + return visible_child_index; + } + if (visible_child_count > 0) { + array_push(&self->stack, entry); + did_descend = true; + break; + } + } else if (visible) { + visible_child_index++; + } else { + visible_child_index += visible_child_count; + } + } + } while (did_descend); + + self->stack.size = initial_size; + return -1; +} + +int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *self, uint32_t goal_byte) { + return ts_tree_cursor_goto_first_child_for_byte_and_point(self, goal_byte, POINT_ZERO); +} + +int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *self, TSPoint goal_point) { + return ts_tree_cursor_goto_first_child_for_byte_and_point(self, 0, goal_point); +} + +TreeCursorStep ts_tree_cursor_goto_sibling_internal( + TSTreeCursor *_self, + bool (*advance)(CursorChildIterator *, TreeCursorEntry *, bool *) +) { + TreeCursor *self = (TreeCursor *)_self; + uint32_t initial_size = self->stack.size; + + while (self->stack.size > 1) { + TreeCursorEntry entry = array_pop(&self->stack); + CursorChildIterator iterator = ts_tree_cursor_iterate_children(self); + iterator.child_index = entry.child_index; + iterator.structural_child_index = entry.structural_child_index; + iterator.position = entry.position; + iterator.descendant_index = entry.descendant_index; + + bool visible = false; + advance(&iterator, &entry, &visible); + if (visible && self->stack.size + 1 < initial_size) break; + + while (advance(&iterator, &entry, &visible)) { + if (visible) { + array_push(&self->stack, entry); + return TreeCursorStepVisible; + } + + if (ts_subtree_visible_child_count(*entry.subtree)) { + array_push(&self->stack, entry); + return TreeCursorStepHidden; + } + } + } + + self->stack.size = initial_size; + return TreeCursorStepNone; +} + +TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) { + return ts_tree_cursor_goto_sibling_internal(_self, ts_tree_cursor_child_iterator_next); +} + +bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) { + switch (ts_tree_cursor_goto_next_sibling_internal(self)) { + case TreeCursorStepHidden: + ts_tree_cursor_goto_first_child(self); + return true; + case TreeCursorStepVisible: + return true; + default: + return false; + } +} + +TreeCursorStep ts_tree_cursor_goto_previous_sibling_internal(TSTreeCursor *_self) { + // since subtracting across row loses column information, we may have to + // restore it + TreeCursor *self = (TreeCursor *)_self; + + // for that, save current position before traversing + TreeCursorStep step = ts_tree_cursor_goto_sibling_internal( + _self, ts_tree_cursor_child_iterator_previous); + if (step == TreeCursorStepNone) + return step; + + // if length is already valid, there's no need to recompute it + if (!length_is_undefined(array_back(&self->stack)->position)) + return step; + + // restore position from the parent node + const TreeCursorEntry *parent = array_get(&self->stack, self->stack.size - 2); + Length position = parent->position; + uint32_t child_index = array_back(&self->stack)->child_index; + const Subtree *children = ts_subtree_children((*(parent->subtree))); + + if (child_index > 0) { + // skip first child padding since its position should match the position of the parent + position = length_add(position, ts_subtree_size(children[0])); + for (uint32_t i = 1; i < child_index; ++i) { + position = length_add(position, ts_subtree_total_size(children[i])); + } + position = length_add(position, ts_subtree_padding(children[child_index])); + } + + array_back(&self->stack)->position = position; + + return step; +} + +bool ts_tree_cursor_goto_previous_sibling(TSTreeCursor *self) { + switch (ts_tree_cursor_goto_previous_sibling_internal(self)) { + case TreeCursorStepHidden: + ts_tree_cursor_goto_last_child(self); + return true; + case TreeCursorStepVisible: + return true; + default: + return false; + } +} + +bool ts_tree_cursor_goto_parent(TSTreeCursor *_self) { + TreeCursor *self = (TreeCursor *)_self; + for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) { + if (ts_tree_cursor_is_entry_visible(self, i)) { + self->stack.size = i + 1; + return true; + } + } + return false; +} + +void ts_tree_cursor_goto_descendant( + TSTreeCursor *_self, + uint32_t goal_descendant_index +) { + TreeCursor *self = (TreeCursor *)_self; + + // Ascend to the lowest ancestor that contains the goal node. + for (;;) { + uint32_t i = self->stack.size - 1; + TreeCursorEntry *entry = array_get(&self->stack, i); + uint32_t next_descendant_index = + entry->descendant_index + + (ts_tree_cursor_is_entry_visible(self, i) ? 1 : 0) + + ts_subtree_visible_descendant_count(*entry->subtree); + if ( + (entry->descendant_index <= goal_descendant_index) && + (next_descendant_index > goal_descendant_index) + ) { + break; + } else if (self->stack.size <= 1) { + return; + } else { + self->stack.size--; + } + } + + // Descend to the goal node. + bool did_descend = true; + do { + did_descend = false; + bool visible; + TreeCursorEntry entry; + CursorChildIterator iterator = ts_tree_cursor_iterate_children(self); + if (iterator.descendant_index > goal_descendant_index) { + return; + } + + while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { + if (iterator.descendant_index > goal_descendant_index) { + array_push(&self->stack, entry); + if (visible && entry.descendant_index == goal_descendant_index) { + return; + } else { + did_descend = true; + break; + } + } + } + } while (did_descend); +} + +uint32_t ts_tree_cursor_current_descendant_index(const TSTreeCursor *_self) { + const TreeCursor *self = (const TreeCursor *)_self; + TreeCursorEntry *last_entry = array_back(&self->stack); + return last_entry->descendant_index; +} + +TSNode ts_tree_cursor_current_node(const TSTreeCursor *_self) { + const TreeCursor *self = (const TreeCursor *)_self; + TreeCursorEntry *last_entry = array_back(&self->stack); + bool is_extra = ts_subtree_extra(*last_entry->subtree); + TSSymbol alias_symbol = is_extra ? 0 : self->root_alias_symbol; + if (self->stack.size > 1 && !is_extra) { + TreeCursorEntry *parent_entry = array_get(&self->stack, self->stack.size - 2); + alias_symbol = ts_language_alias_at( + self->tree->language, + parent_entry->subtree->ptr->production_id, + last_entry->structural_child_index + ); + } + return ts_node_new( + self->tree, + last_entry->subtree, + last_entry->position, + alias_symbol + ); +} + +// Private - Get various facts about the current node that are needed +// when executing tree queries. +void ts_tree_cursor_current_status( + const TSTreeCursor *_self, + TSFieldId *field_id, + bool *has_later_siblings, + bool *has_later_named_siblings, + bool *can_have_later_siblings_with_this_field, + TSSymbol *supertypes, + unsigned *supertype_count +) { + const TreeCursor *self = (const TreeCursor *)_self; + unsigned max_supertypes = *supertype_count; + *field_id = 0; + *supertype_count = 0; + *has_later_siblings = false; + *has_later_named_siblings = false; + *can_have_later_siblings_with_this_field = false; + + // Walk up the tree, visiting the current node and its invisible ancestors, + // because fields can refer to nodes through invisible *wrapper* nodes, + for (unsigned i = self->stack.size - 1; i > 0; i--) { + TreeCursorEntry *entry = array_get(&self->stack, i); + TreeCursorEntry *parent_entry = array_get(&self->stack, i - 1); + + const TSSymbol *alias_sequence = ts_language_alias_sequence( + self->tree->language, + parent_entry->subtree->ptr->production_id + ); + + #define subtree_symbol(subtree, structural_child_index) \ + (( \ + !ts_subtree_extra(subtree) && \ + alias_sequence && \ + alias_sequence[structural_child_index] \ + ) ? \ + alias_sequence[structural_child_index] : \ + ts_subtree_symbol(subtree)) + + // Stop walking up when a visible ancestor is found. + TSSymbol entry_symbol = subtree_symbol( + *entry->subtree, + entry->structural_child_index + ); + TSSymbolMetadata entry_metadata = ts_language_symbol_metadata( + self->tree->language, + entry_symbol + ); + if (i != self->stack.size - 1 && entry_metadata.visible) break; + + // Record any supertypes + if (entry_metadata.supertype && *supertype_count < max_supertypes) { + supertypes[*supertype_count] = entry_symbol; + (*supertype_count)++; + } + + // Determine if the current node has later siblings. + if (!*has_later_siblings) { + unsigned sibling_count = parent_entry->subtree->ptr->child_count; + unsigned structural_child_index = entry->structural_child_index; + if (!ts_subtree_extra(*entry->subtree)) structural_child_index++; + for (unsigned j = entry->child_index + 1; j < sibling_count; j++) { + Subtree sibling = ts_subtree_children(*parent_entry->subtree)[j]; + TSSymbolMetadata sibling_metadata = ts_language_symbol_metadata( + self->tree->language, + subtree_symbol(sibling, structural_child_index) + ); + if (sibling_metadata.visible) { + *has_later_siblings = true; + if (*has_later_named_siblings) break; + if (sibling_metadata.named) { + *has_later_named_siblings = true; + break; + } + } else if (ts_subtree_visible_child_count(sibling) > 0) { + *has_later_siblings = true; + if (*has_later_named_siblings) break; + if (sibling.ptr->named_child_count > 0) { + *has_later_named_siblings = true; + break; + } + } + if (!ts_subtree_extra(sibling)) structural_child_index++; + } + } + + #undef subtree_symbol + + if (!ts_subtree_extra(*entry->subtree)) { + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map( + self->tree->language, + parent_entry->subtree->ptr->production_id, + &field_map, &field_map_end + ); + + // Look for a field name associated with the current node. + if (!*field_id) { + for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) { + if (!map->inherited && map->child_index == entry->structural_child_index) { + *field_id = map->field_id; + break; + } + } + } + + // Determine if the current node can have later siblings with the same field name. + if (*field_id) { + for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) { + if ( + map->field_id == *field_id && + map->child_index > entry->structural_child_index + ) { + *can_have_later_siblings_with_this_field = true; + break; + } + } + } + } + } +} + +uint32_t ts_tree_cursor_current_depth(const TSTreeCursor *_self) { + const TreeCursor *self = (const TreeCursor *)_self; + uint32_t depth = 0; + for (unsigned i = 1; i < self->stack.size; i++) { + if (ts_tree_cursor_is_entry_visible(self, i)) { + depth++; + } + } + return depth; +} + +TSNode ts_tree_cursor_parent_node(const TSTreeCursor *_self) { + const TreeCursor *self = (const TreeCursor *)_self; + for (int i = (int)self->stack.size - 2; i >= 0; i--) { + TreeCursorEntry *entry = array_get(&self->stack, i); + bool is_visible = true; + TSSymbol alias_symbol = 0; + if (i > 0) { + TreeCursorEntry *parent_entry = array_get(&self->stack, i - 1); + alias_symbol = ts_language_alias_at( + self->tree->language, + parent_entry->subtree->ptr->production_id, + entry->structural_child_index + ); + is_visible = (alias_symbol != 0) || ts_subtree_visible(*entry->subtree); + } + if (is_visible) { + return ts_node_new( + self->tree, + entry->subtree, + entry->position, + alias_symbol + ); + } + } + return ts_node_new(NULL, NULL, length_zero(), 0); +} + +TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *_self) { + const TreeCursor *self = (const TreeCursor *)_self; + + // Walk up the tree, visiting the current node and its invisible ancestors. + for (unsigned i = self->stack.size - 1; i > 0; i--) { + TreeCursorEntry *entry = array_get(&self->stack, i); + TreeCursorEntry *parent_entry = array_get(&self->stack, i - 1); + + // Stop walking up when another visible node is found. + if ( + i != self->stack.size - 1 && + ts_tree_cursor_is_entry_visible(self, i) + ) break; + + if (ts_subtree_extra(*entry->subtree)) break; + + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map( + self->tree->language, + parent_entry->subtree->ptr->production_id, + &field_map, &field_map_end + ); + for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) { + if (!map->inherited && map->child_index == entry->structural_child_index) { + return map->field_id; + } + } + } + return 0; +} + +const char *ts_tree_cursor_current_field_name(const TSTreeCursor *_self) { + TSFieldId id = ts_tree_cursor_current_field_id(_self); + if (id) { + const TreeCursor *self = (const TreeCursor *)_self; + return self->tree->language->field_names[id]; + } else { + return NULL; + } +} + +TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *_cursor) { + const TreeCursor *cursor = (const TreeCursor *)_cursor; + TSTreeCursor res = {NULL, NULL, {0, 0}}; + TreeCursor *copy = (TreeCursor *)&res; + copy->tree = cursor->tree; + copy->root_alias_symbol = cursor->root_alias_symbol; + array_init(©->stack); + array_push_all(©->stack, &cursor->stack); + return res; +} + +void ts_tree_cursor_reset_to(TSTreeCursor *_dst, const TSTreeCursor *_src) { + const TreeCursor *cursor = (const TreeCursor *)_src; + TreeCursor *copy = (TreeCursor *)_dst; + copy->tree = cursor->tree; + copy->root_alias_symbol = cursor->root_alias_symbol; + array_clear(©->stack); + array_push_all(©->stack, &cursor->stack); +} diff --git a/codegraph-kernel/vendor/tree-sitter/src/tree_cursor.h b/codegraph-kernel/vendor/tree-sitter/src/tree_cursor.h new file mode 100644 index 0000000000..7d4e7ef0a6 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/tree_cursor.h @@ -0,0 +1,48 @@ +#ifndef TREE_SITTER_TREE_CURSOR_H_ +#define TREE_SITTER_TREE_CURSOR_H_ + +#include "./subtree.h" + +typedef struct { + const Subtree *subtree; + Length position; + uint32_t child_index; + uint32_t structural_child_index; + uint32_t descendant_index; +} TreeCursorEntry; + +typedef struct { + const TSTree *tree; + Array(TreeCursorEntry) stack; + TSSymbol root_alias_symbol; +} TreeCursor; + +typedef enum { + TreeCursorStepNone, + TreeCursorStepHidden, + TreeCursorStepVisible, +} TreeCursorStep; + +void ts_tree_cursor_init(TreeCursor *self, TSNode node); +void ts_tree_cursor_current_status( + const TSTreeCursor *_self, + TSFieldId *field_id, + bool *has_later_siblings, + bool *has_later_named_siblings, + bool *can_have_later_siblings_with_this_field, + TSSymbol *supertypes, + unsigned *supertype_count +); + +TreeCursorStep ts_tree_cursor_goto_first_child_internal(TSTreeCursor *_self); +TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self); + +static inline Subtree ts_tree_cursor_current_subtree(const TSTreeCursor *_self) { + const TreeCursor *self = (const TreeCursor *)_self; + TreeCursorEntry *last_entry = array_back(&self->stack); + return *last_entry->subtree; +} + +TSNode ts_tree_cursor_parent_node(const TSTreeCursor *_self); + +#endif // TREE_SITTER_TREE_CURSOR_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/ts_assert.h b/codegraph-kernel/vendor/tree-sitter/src/ts_assert.h new file mode 100644 index 0000000000..4cb8f36a12 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/ts_assert.h @@ -0,0 +1,11 @@ +#ifndef TREE_SITTER_ASSERT_H_ +#define TREE_SITTER_ASSERT_H_ + +#ifdef NDEBUG +#define ts_assert(e) ((void)(e)) +#else +#include +#define ts_assert(e) assert(e) +#endif + +#endif // TREE_SITTER_ASSERT_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode.h b/codegraph-kernel/vendor/tree-sitter/src/unicode.h new file mode 100644 index 0000000000..0fba3f2961 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode.h @@ -0,0 +1,75 @@ +#ifndef TREE_SITTER_UNICODE_H_ +#define TREE_SITTER_UNICODE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define U_EXPORT +#define U_EXPORT2 +#include "unicode/utf8.h" +#include "unicode/utf16.h" +#include "portable/endian.h" + +#define U16_NEXT_LE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ + (c)=le16toh((s)[(i)++]); \ + if(U16_IS_LEAD(c)) { \ + uint16_t __c2; \ + if((i)!=(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \ + ++(i); \ + (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +#define U16_NEXT_BE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \ + (c)=be16toh((s)[(i)++]); \ + if(U16_IS_LEAD(c)) { \ + uint16_t __c2; \ + if((i)!=(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \ + ++(i); \ + (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +static const int32_t TS_DECODE_ERROR = U_SENTINEL; + +static inline uint32_t ts_decode_utf8( + const uint8_t *string, + uint32_t length, + int32_t *code_point +) { + uint32_t i = 0; + U8_NEXT(string, i, length, *code_point); + return i; +} + +static inline uint32_t ts_decode_utf16_le( + const uint8_t *string, + uint32_t length, + int32_t *code_point +) { + uint32_t i = 0; + U16_NEXT_LE(((uint16_t *)string), i, length, *code_point); + return i * 2; +} + +static inline uint32_t ts_decode_utf16_be( + const uint8_t *string, + uint32_t length, + int32_t *code_point +) { + uint32_t i = 0; + U16_NEXT_BE(((uint16_t *)string), i, length, *code_point); + return i * 2; +} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_UNICODE_H_ diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/ICU_SHA b/codegraph-kernel/vendor/tree-sitter/src/unicode/ICU_SHA new file mode 100644 index 0000000000..3622283ba3 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/ICU_SHA @@ -0,0 +1 @@ +552b01f61127d30d6589aa4bf99468224979b661 diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/LICENSE b/codegraph-kernel/vendor/tree-sitter/src/unicode/LICENSE new file mode 100644 index 0000000000..2e01e36876 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/LICENSE @@ -0,0 +1,414 @@ +COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) + +Copyright © 1991-2019 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +--------------------- + +Third-Party Software Licenses + +This section contains third-party software notices and/or additional +terms for licensed third-party software components included within ICU +libraries. + +1. ICU License - ICU 1.8.1 to ICU 57.1 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2016 International Business Machines Corporation and others +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY +SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +All trademarks and registered trademarks mentioned herein are the +property of their respective owners. + +2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) + + # The Google Chrome software developed by Google is licensed under + # the BSD license. Other software included in this distribution is + # provided under other licenses, as set forth below. + # + # The BSD License + # http://opensource.org/licenses/bsd-license.php + # Copyright (C) 2006-2008, Google Inc. + # + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are met: + # + # Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided with + # the distribution. + # Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # + # + # The word list in cjdict.txt are generated by combining three word lists + # listed below with further processing for compound word breaking. The + # frequency is generated with an iterative training against Google web + # corpora. + # + # * Libtabe (Chinese) + # - https://sourceforge.net/project/?group_id=1519 + # - Its license terms and conditions are shown below. + # + # * IPADIC (Japanese) + # - http://chasen.aist-nara.ac.jp/chasen/distribution.html + # - Its license terms and conditions are shown below. + # + # ---------COPYING.libtabe ---- BEGIN-------------------- + # + # /* + # * Copyright (c) 1999 TaBE Project. + # * Copyright (c) 1999 Pai-Hsiang Hsiao. + # * All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the TaBE Project nor the names of its + # * contributors may be used to endorse or promote products derived + # * from this software without specific prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # /* + # * Copyright (c) 1999 Computer Systems and Communication Lab, + # * Institute of Information Science, Academia + # * Sinica. All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the Computer Systems and Communication Lab + # * nor the names of its contributors may be used to endorse or + # * promote products derived from this software without specific + # * prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, + # University of Illinois + # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 + # + # ---------------COPYING.libtabe-----END-------------------------------- + # + # + # ---------------COPYING.ipadic-----BEGIN------------------------------- + # + # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science + # and Technology. All Rights Reserved. + # + # Use, reproduction, and distribution of this software is permitted. + # Any copy of this software, whether in its original form or modified, + # must include both the above copyright notice and the following + # paragraphs. + # + # Nara Institute of Science and Technology (NAIST), + # the copyright holders, disclaims all warranties with regard to this + # software, including all implied warranties of merchantability and + # fitness, in no event shall NAIST be liable for + # any special, indirect or consequential damages or any damages + # whatsoever resulting from loss of use, data or profits, whether in an + # action of contract, negligence or other tortuous action, arising out + # of or in connection with the use or performance of this software. + # + # A large portion of the dictionary entries + # originate from ICOT Free Software. The following conditions for ICOT + # Free Software applies to the current dictionary as well. + # + # Each User may also freely distribute the Program, whether in its + # original form or modified, to any third party or parties, PROVIDED + # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear + # on, or be attached to, the Program, which is distributed substantially + # in the same form as set out herein and that such intended + # distribution, if actually made, will neither violate or otherwise + # contravene any of the laws and regulations of the countries having + # jurisdiction over the User or the intended distribution itself. + # + # NO WARRANTY + # + # The program was produced on an experimental basis in the course of the + # research and development conducted during the project and is provided + # to users as so produced on an experimental basis. Accordingly, the + # program is provided without any warranty whatsoever, whether express, + # implied, statutory or otherwise. The term "warranty" used herein + # includes, but is not limited to, any warranty of the quality, + # performance, merchantability and fitness for a particular purpose of + # the program and the nonexistence of any infringement or violation of + # any right of any third party. + # + # Each user of the program will agree and understand, and be deemed to + # have agreed and understood, that there is no warranty whatsoever for + # the program and, accordingly, the entire risk arising from or + # otherwise connected with the program is assumed by the user. + # + # Therefore, neither ICOT, the copyright holder, or any other + # organization that participated in or was otherwise related to the + # development of the program and their respective officials, directors, + # officers and other employees shall be held liable for any and all + # damages, including, without limitation, general, special, incidental + # and consequential damages, arising out of or otherwise in connection + # with the use or inability to use the program or any product, material + # or result produced or otherwise obtained by using the program, + # regardless of whether they have been advised of, or otherwise had + # knowledge of, the possibility of such damages at any time during the + # project or thereafter. Each user will be deemed to have agreed to the + # foregoing by his or her commencement of use of the program. The term + # "use" as used herein includes, but is not limited to, the use, + # modification, copying and distribution of the program and the + # production of secondary products from the program. + # + # In the case where the program, whether in its original form or + # modified, was distributed or delivered to or received by a user from + # any person, organization or entity other than ICOT, unless it makes or + # grants independently of ICOT any specific warranty to the user in + # writing, such person, organization or entity, will also be exempted + # from and not be held liable to the user for any such damages as noted + # above as far as the program is concerned. + # + # ---------------COPYING.ipadic-----END---------------------------------- + +3. Lao Word Break Dictionary Data (laodict.txt) + + # Copyright (c) 2013 International Business Machines Corporation + # and others. All Rights Reserved. + # + # Project: http://code.google.com/p/lao-dictionary/ + # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt + # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt + # (copied below) + # + # This file is derived from the above dictionary, with slight + # modifications. + # ---------------------------------------------------------------------- + # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, + # are permitted provided that the following conditions are met: + # + # + # Redistributions of source code must retain the above copyright notice, this + # list of conditions and the following disclaimer. Redistributions in + # binary form must reproduce the above copyright notice, this list of + # conditions and the following disclaimer in the documentation and/or + # other materials provided with the distribution. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # OF THE POSSIBILITY OF SUCH DAMAGE. + # -------------------------------------------------------------------------- + +4. Burmese Word Break Dictionary Data (burmesedict.txt) + + # Copyright (c) 2014 International Business Machines Corporation + # and others. All Rights Reserved. + # + # This list is part of a project hosted at: + # github.com/kanyawtech/myanmar-karen-word-lists + # + # -------------------------------------------------------------------------- + # Copyright (c) 2013, LeRoy Benjamin Sharon + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions + # are met: Redistributions of source code must retain the above + # copyright notice, this list of conditions and the following + # disclaimer. Redistributions in binary form must reproduce the + # above copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided + # with the distribution. + # + # Neither the name Myanmar Karen Word Lists, nor the names of its + # contributors may be used to endorse or promote products derived + # from this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + # SUCH DAMAGE. + # -------------------------------------------------------------------------- + +5. Time Zone Database + + ICU uses the public domain data and code derived from Time Zone +Database for its time zone support. The ownership of the TZ database +is explained in BCP 175: Procedure for Maintaining the Time Zone +Database section 7. + + # 7. Database Ownership + # + # The TZ database itself is not an IETF Contribution or an IETF + # document. Rather it is a pre-existing and regularly updated work + # that is in the public domain, and is intended to remain in the + # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do + # not apply to the TZ Database or contributions that individuals make + # to it. Should any claims be made and substantiated against the TZ + # Database, the organization that is providing the IANA + # Considerations defined in this RFC, under the memorandum of + # understanding with the IETF, currently ICANN, may act in accordance + # with all competent court orders. No ownership claims will be made + # by ICANN or the IETF Trust on the database or the code. Any person + # making a contribution to the database or code waives all rights to + # future claims in that contribution or in the TZ Database. + +6. Google double-conversion + +Copyright 2006-2011, the V8 project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/README.md b/codegraph-kernel/vendor/tree-sitter/src/unicode/README.md new file mode 100644 index 0000000000..623b8e3843 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/README.md @@ -0,0 +1,29 @@ +# ICU Parts + +This directory contains a small subset of files from the Unicode organization's [ICU repository](https://github.com/unicode-org/icu). + +### License + +The license for these files is contained in the `LICENSE` file within this directory. + +### Contents + +* Source files taken from the [`icu4c/source/common/unicode`](https://github.com/unicode-org/icu/tree/552b01f61127d30d6589aa4bf99468224979b661/icu4c/source/common/unicode) directory: + * `utf8.h` + * `utf16.h` + * `umachine.h` +* Empty source files that are referenced by the above source files, but whose original contents in `libicu` are not needed: + * `ptypes.h` + * `urename.h` + * `utf.h` +* `ICU_SHA` - File containing the Git SHA of the commit in the `icu` repository from which the files were obtained. +* `LICENSE` - The license file from the [`icu4c`](https://github.com/unicode-org/icu/tree/552b01f61127d30d6589aa4bf99468224979b661/icu4c) directory of the `icu` repository. +* `README.md` - This text file. + +### Updating ICU + +To incorporate changes from the upstream `icu` repository: + +* Update `ICU_SHA` with the new Git SHA. +* Update `LICENSE` with the license text from the directory mentioned above. +* Update `utf8.h`, `utf16.h`, and `umachine.h` with their new contents in the `icu` repository. diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/ptypes.h b/codegraph-kernel/vendor/tree-sitter/src/unicode/ptypes.h new file mode 100644 index 0000000000..ac79ad0f98 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/ptypes.h @@ -0,0 +1 @@ +// This file must exist in order for `utf8.h` and `utf16.h` to be used. diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/umachine.h b/codegraph-kernel/vendor/tree-sitter/src/unicode/umachine.h new file mode 100644 index 0000000000..9195824d5b --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/umachine.h @@ -0,0 +1,448 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +****************************************************************************** +* +* Copyright (C) 1999-2015, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +* file name: umachine.h +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 1999sep13 +* created by: Markus W. Scherer +* +* This file defines basic types and constants for ICU to be +* platform-independent. umachine.h and utf.h are included into +* utypes.h to provide all the general definitions for ICU. +* All of these definitions used to be in utypes.h before +* the UTF-handling macros made this unmaintainable. +*/ + +#ifndef __UMACHINE_H__ +#define __UMACHINE_H__ + + +/** + * \file + * \brief Basic types and constants for UTF + * + *

Basic types and constants for UTF

+ * This file defines basic types and constants for utf.h to be + * platform-independent. umachine.h and utf.h are included into + * utypes.h to provide all the general definitions for ICU. + * All of these definitions used to be in utypes.h before + * the UTF-handling macros made this unmaintainable. + * + */ +/*==========================================================================*/ +/* Include platform-dependent definitions */ +/* which are contained in the platform-specific file platform.h */ +/*==========================================================================*/ + +#include "unicode/ptypes.h" /* platform.h is included in ptypes.h */ + +/* + * ANSI C headers: + * stddef.h defines wchar_t + */ +#include + +/*==========================================================================*/ +/* For C wrappers, we use the symbol U_STABLE. */ +/* This works properly if the includer is C or C++. */ +/* Functions are declared U_STABLE return-type U_EXPORT2 function-name()... */ +/*==========================================================================*/ + +/** + * \def U_CFUNC + * This is used in a declaration of a library private ICU C function. + * @stable ICU 2.4 + */ + +/** + * \def U_CDECL_BEGIN + * This is used to begin a declaration of a library private ICU C API. + * @stable ICU 2.4 + */ + +/** + * \def U_CDECL_END + * This is used to end a declaration of a library private ICU C API + * @stable ICU 2.4 + */ + +#ifdef __cplusplus +# define U_CFUNC extern "C" +# define U_CDECL_BEGIN extern "C" { +# define U_CDECL_END } +#else +# define U_CFUNC extern +# define U_CDECL_BEGIN +# define U_CDECL_END +#endif + +#ifndef U_ATTRIBUTE_DEPRECATED +/** + * \def U_ATTRIBUTE_DEPRECATED + * This is used for GCC specific attributes + * @internal + */ +#if U_GCC_MAJOR_MINOR >= 302 +# define U_ATTRIBUTE_DEPRECATED __attribute__ ((deprecated)) +/** + * \def U_ATTRIBUTE_DEPRECATED + * This is used for Visual C++ specific attributes + * @internal + */ +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +# define U_ATTRIBUTE_DEPRECATED __declspec(deprecated) +#else +# define U_ATTRIBUTE_DEPRECATED +#endif +#endif + +/** This is used to declare a function as a public ICU C API @stable ICU 2.0*/ +#define U_CAPI U_CFUNC U_EXPORT +/** This is used to declare a function as a stable public ICU C API*/ +#define U_STABLE U_CAPI +/** This is used to declare a function as a draft public ICU C API */ +#define U_DRAFT U_CAPI +/** This is used to declare a function as a deprecated public ICU C API */ +#define U_DEPRECATED U_CAPI U_ATTRIBUTE_DEPRECATED +/** This is used to declare a function as an obsolete public ICU C API */ +#define U_OBSOLETE U_CAPI +/** This is used to declare a function as an internal ICU C API */ +#define U_INTERNAL U_CAPI + +/** + * \def U_OVERRIDE + * Defined to the C++11 "override" keyword if available. + * Denotes a class or member which is an override of the base class. + * May result in an error if it applied to something not an override. + * @internal + */ +#ifndef U_OVERRIDE +#define U_OVERRIDE override +#endif + +/** + * \def U_FINAL + * Defined to the C++11 "final" keyword if available. + * Denotes a class or member which may not be overridden in subclasses. + * May result in an error if subclasses attempt to override. + * @internal + */ +#if !defined(U_FINAL) || defined(U_IN_DOXYGEN) +#define U_FINAL final +#endif + +// Before ICU 65, function-like, multi-statement ICU macros were just defined as +// series of statements wrapped in { } blocks and the caller could choose to +// either treat them as if they were actual functions and end the invocation +// with a trailing ; creating an empty statement after the block or else omit +// this trailing ; using the knowledge that the macro would expand to { }. +// +// But doing so doesn't work well with macros that look like functions and +// compiler warnings about empty statements (ICU-20601) and ICU 65 therefore +// switches to the standard solution of wrapping such macros in do { } while. +// +// This will however break existing code that depends on being able to invoke +// these macros without a trailing ; so to be able to remain compatible with +// such code the wrapper is itself defined as macros so that it's possible to +// build ICU 65 and later with the old macro behaviour, like this: +// +// CPPFLAGS='-DUPRV_BLOCK_MACRO_BEGIN="" -DUPRV_BLOCK_MACRO_END=""' +// runConfigureICU ... + +/** + * \def UPRV_BLOCK_MACRO_BEGIN + * Defined as the "do" keyword by default. + * @internal + */ +#ifndef UPRV_BLOCK_MACRO_BEGIN +#define UPRV_BLOCK_MACRO_BEGIN do +#endif + +/** + * \def UPRV_BLOCK_MACRO_END + * Defined as "while (FALSE)" by default. + * @internal + */ +#ifndef UPRV_BLOCK_MACRO_END +#define UPRV_BLOCK_MACRO_END while (FALSE) +#endif + +/*==========================================================================*/ +/* limits for int32_t etc., like in POSIX inttypes.h */ +/*==========================================================================*/ + +#ifndef INT8_MIN +/** The smallest value an 8 bit signed integer can hold @stable ICU 2.0 */ +# define INT8_MIN ((int8_t)(-128)) +#endif +#ifndef INT16_MIN +/** The smallest value a 16 bit signed integer can hold @stable ICU 2.0 */ +# define INT16_MIN ((int16_t)(-32767-1)) +#endif +#ifndef INT32_MIN +/** The smallest value a 32 bit signed integer can hold @stable ICU 2.0 */ +# define INT32_MIN ((int32_t)(-2147483647-1)) +#endif + +#ifndef INT8_MAX +/** The largest value an 8 bit signed integer can hold @stable ICU 2.0 */ +# define INT8_MAX ((int8_t)(127)) +#endif +#ifndef INT16_MAX +/** The largest value a 16 bit signed integer can hold @stable ICU 2.0 */ +# define INT16_MAX ((int16_t)(32767)) +#endif +#ifndef INT32_MAX +/** The largest value a 32 bit signed integer can hold @stable ICU 2.0 */ +# define INT32_MAX ((int32_t)(2147483647)) +#endif + +#ifndef UINT8_MAX +/** The largest value an 8 bit unsigned integer can hold @stable ICU 2.0 */ +# define UINT8_MAX ((uint8_t)(255U)) +#endif +#ifndef UINT16_MAX +/** The largest value a 16 bit unsigned integer can hold @stable ICU 2.0 */ +# define UINT16_MAX ((uint16_t)(65535U)) +#endif +#ifndef UINT32_MAX +/** The largest value a 32 bit unsigned integer can hold @stable ICU 2.0 */ +# define UINT32_MAX ((uint32_t)(4294967295U)) +#endif + +#if defined(U_INT64_T_UNAVAILABLE) +# error int64_t is required for decimal format and rule-based number format. +#else +# ifndef INT64_C +/** + * Provides a platform independent way to specify a signed 64-bit integer constant. + * note: may be wrong for some 64 bit platforms - ensure your compiler provides INT64_C + * @stable ICU 2.8 + */ +# define INT64_C(c) c ## LL +# endif +# ifndef UINT64_C +/** + * Provides a platform independent way to specify an unsigned 64-bit integer constant. + * note: may be wrong for some 64 bit platforms - ensure your compiler provides UINT64_C + * @stable ICU 2.8 + */ +# define UINT64_C(c) c ## ULL +# endif +# ifndef U_INT64_MIN +/** The smallest value a 64 bit signed integer can hold @stable ICU 2.8 */ +# define U_INT64_MIN ((int64_t)(INT64_C(-9223372036854775807)-1)) +# endif +# ifndef U_INT64_MAX +/** The largest value a 64 bit signed integer can hold @stable ICU 2.8 */ +# define U_INT64_MAX ((int64_t)(INT64_C(9223372036854775807))) +# endif +# ifndef U_UINT64_MAX +/** The largest value a 64 bit unsigned integer can hold @stable ICU 2.8 */ +# define U_UINT64_MAX ((uint64_t)(UINT64_C(18446744073709551615))) +# endif +#endif + +/*==========================================================================*/ +/* Boolean data type */ +/*==========================================================================*/ + +/** The ICU boolean type @stable ICU 2.0 */ +typedef int8_t UBool; + +#ifndef TRUE +/** The TRUE value of a UBool @stable ICU 2.0 */ +# define TRUE 1 +#endif +#ifndef FALSE +/** The FALSE value of a UBool @stable ICU 2.0 */ +# define FALSE 0 +#endif + + +/*==========================================================================*/ +/* Unicode data types */ +/*==========================================================================*/ + +/* wchar_t-related definitions -------------------------------------------- */ + +/* + * \def U_WCHAR_IS_UTF16 + * Defined if wchar_t uses UTF-16. + * + * @stable ICU 2.0 + */ +/* + * \def U_WCHAR_IS_UTF32 + * Defined if wchar_t uses UTF-32. + * + * @stable ICU 2.0 + */ +#if !defined(U_WCHAR_IS_UTF16) && !defined(U_WCHAR_IS_UTF32) +# ifdef __STDC_ISO_10646__ +# if (U_SIZEOF_WCHAR_T==2) +# define U_WCHAR_IS_UTF16 +# elif (U_SIZEOF_WCHAR_T==4) +# define U_WCHAR_IS_UTF32 +# endif +# elif defined __UCS2__ +# if (U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400) && (U_SIZEOF_WCHAR_T==2) +# define U_WCHAR_IS_UTF16 +# endif +# elif defined(__UCS4__) || (U_PLATFORM == U_PF_OS400 && defined(__UTF32__)) +# if (U_SIZEOF_WCHAR_T==4) +# define U_WCHAR_IS_UTF32 +# endif +# elif U_PLATFORM_IS_DARWIN_BASED || (U_SIZEOF_WCHAR_T==4 && U_PLATFORM_IS_LINUX_BASED) +# define U_WCHAR_IS_UTF32 +# elif U_PLATFORM_HAS_WIN32_API +# define U_WCHAR_IS_UTF16 +# endif +#endif + +/* UChar and UChar32 definitions -------------------------------------------- */ + +/** Number of bytes in a UChar. @stable ICU 2.0 */ +#define U_SIZEOF_UCHAR 2 + +/** + * \def U_CHAR16_IS_TYPEDEF + * If 1, then char16_t is a typedef and not a real type (yet) + * @internal + */ +#if (U_PLATFORM == U_PF_AIX) && defined(__cplusplus) &&(U_CPLUSPLUS_VERSION < 11) +// for AIX, uchar.h needs to be included +# include +# define U_CHAR16_IS_TYPEDEF 1 +#elif defined(_MSC_VER) && (_MSC_VER < 1900) +// Versions of Visual Studio/MSVC below 2015 do not support char16_t as a real type, +// and instead use a typedef. https://msdn.microsoft.com/library/bb531344.aspx +# define U_CHAR16_IS_TYPEDEF 1 +#else +# define U_CHAR16_IS_TYPEDEF 0 +#endif + + +/** + * \var UChar + * + * The base type for UTF-16 code units and pointers. + * Unsigned 16-bit integer. + * Starting with ICU 59, C++ API uses char16_t directly, while C API continues to use UChar. + * + * UChar is configurable by defining the macro UCHAR_TYPE + * on the preprocessor or compiler command line: + * -DUCHAR_TYPE=uint16_t or -DUCHAR_TYPE=wchar_t (if U_SIZEOF_WCHAR_T==2) etc. + * (The UCHAR_TYPE can also be \#defined earlier in this file, for outside the ICU library code.) + * This is for transitional use from application code that uses uint16_t or wchar_t for UTF-16. + * + * The default is UChar=char16_t. + * + * C++11 defines char16_t as bit-compatible with uint16_t, but as a distinct type. + * + * In C, char16_t is a simple typedef of uint_least16_t. + * ICU requires uint_least16_t=uint16_t for data memory mapping. + * On macOS, char16_t is not available because the uchar.h standard header is missing. + * + * @stable ICU 4.4 + */ + +#if 1 + // #if 1 is normal. UChar defaults to char16_t in C++. + // For configuration testing of UChar=uint16_t temporarily change this to #if 0. + // The intltest Makefile #defines UCHAR_TYPE=char16_t, + // so we only #define it to uint16_t if it is undefined so far. +#elif !defined(UCHAR_TYPE) +# define UCHAR_TYPE uint16_t +#endif + +#if defined(U_COMBINED_IMPLEMENTATION) || defined(U_COMMON_IMPLEMENTATION) || \ + defined(U_I18N_IMPLEMENTATION) || defined(U_IO_IMPLEMENTATION) + // Inside the ICU library code, never configurable. + typedef char16_t UChar; +#elif defined(UCHAR_TYPE) + typedef UCHAR_TYPE UChar; +#elif defined(__cplusplus) + typedef char16_t UChar; +#else + typedef uint16_t UChar; +#endif + +/** + * \var OldUChar + * Default ICU 58 definition of UChar. + * A base type for UTF-16 code units and pointers. + * Unsigned 16-bit integer. + * + * Define OldUChar to be wchar_t if that is 16 bits wide. + * If wchar_t is not 16 bits wide, then define UChar to be uint16_t. + * + * This makes the definition of OldUChar platform-dependent + * but allows direct string type compatibility with platforms with + * 16-bit wchar_t types. + * + * This is how UChar was defined in ICU 58, for transition convenience. + * Exception: ICU 58 UChar was defined to UCHAR_TYPE if that macro was defined. + * The current UChar responds to UCHAR_TYPE but OldUChar does not. + * + * @stable ICU 59 + */ +#if U_SIZEOF_WCHAR_T==2 + typedef wchar_t OldUChar; +#elif defined(__CHAR16_TYPE__) + typedef __CHAR16_TYPE__ OldUChar; +#else + typedef uint16_t OldUChar; +#endif + +/** + * Define UChar32 as a type for single Unicode code points. + * UChar32 is a signed 32-bit integer (same as int32_t). + * + * The Unicode code point range is 0..0x10ffff. + * All other values (negative or >=0x110000) are illegal as Unicode code points. + * They may be used as sentinel values to indicate "done", "error" + * or similar non-code point conditions. + * + * Before ICU 2.4 (Jitterbug 2146), UChar32 was defined + * to be wchar_t if that is 32 bits wide (wchar_t may be signed or unsigned) + * or else to be uint32_t. + * That is, the definition of UChar32 was platform-dependent. + * + * @see U_SENTINEL + * @stable ICU 2.4 + */ +typedef int32_t UChar32; + +/** + * This value is intended for sentinel values for APIs that + * (take or) return single code points (UChar32). + * It is outside of the Unicode code point range 0..0x10ffff. + * + * For example, a "done" or "error" value in a new API + * could be indicated with U_SENTINEL. + * + * ICU APIs designed before ICU 2.4 usually define service-specific "done" + * values, mostly 0xffff. + * Those may need to be distinguished from + * actual U+ffff text contents by calling functions like + * CharacterIterator::hasNext() or UnicodeString::length(). + * + * @return -1 + * @see UChar32 + * @stable ICU 2.4 + */ +#define U_SENTINEL (-1) + +#include "unicode/urename.h" + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/urename.h b/codegraph-kernel/vendor/tree-sitter/src/unicode/urename.h new file mode 100644 index 0000000000..ac79ad0f98 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/urename.h @@ -0,0 +1 @@ +// This file must exist in order for `utf8.h` and `utf16.h` to be used. diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/utf.h b/codegraph-kernel/vendor/tree-sitter/src/unicode/utf.h new file mode 100644 index 0000000000..ac79ad0f98 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/utf.h @@ -0,0 +1 @@ +// This file must exist in order for `utf8.h` and `utf16.h` to be used. diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/utf16.h b/codegraph-kernel/vendor/tree-sitter/src/unicode/utf16.h new file mode 100644 index 0000000000..9fd7d5c8a7 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/utf16.h @@ -0,0 +1,733 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +******************************************************************************* +* +* Copyright (C) 1999-2012, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: utf16.h +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 1999sep09 +* created by: Markus W. Scherer +*/ + +/** + * \file + * \brief C API: 16-bit Unicode handling macros + * + * This file defines macros to deal with 16-bit Unicode (UTF-16) code units and strings. + * + * For more information see utf.h and the ICU User Guide Strings chapter + * (http://userguide.icu-project.org/strings). + * + * Usage: + * ICU coding guidelines for if() statements should be followed when using these macros. + * Compound statements (curly braces {}) must be used for if-else-while... + * bodies and all macro statements should be terminated with semicolon. + */ + +#ifndef __UTF16_H__ +#define __UTF16_H__ + +#include "unicode/umachine.h" +#ifndef __UTF_H__ +# include "unicode/utf.h" +#endif + +/* single-code point definitions -------------------------------------------- */ + +/** + * Does this code unit alone encode a code point (BMP, not a surrogate)? + * @param c 16-bit code unit + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) + +/** + * Is this code unit a lead surrogate (U+d800..U+dbff)? + * @param c 16-bit code unit + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) + +/** + * Is this code unit a trail surrogate (U+dc00..U+dfff)? + * @param c 16-bit code unit + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) + +/** + * Is this code unit a surrogate (U+d800..U+dfff)? + * @param c 16-bit code unit + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c) + +/** + * Assuming c is a surrogate code point (U16_IS_SURROGATE(c)), + * is it a lead surrogate? + * @param c 16-bit code unit + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) + +/** + * Assuming c is a surrogate code point (U16_IS_SURROGATE(c)), + * is it a trail surrogate? + * @param c 16-bit code unit + * @return TRUE or FALSE + * @stable ICU 4.2 + */ +#define U16_IS_SURROGATE_TRAIL(c) (((c)&0x400)!=0) + +/** + * Helper constant for U16_GET_SUPPLEMENTARY. + * @internal + */ +#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) + +/** + * Get a supplementary code point value (U+10000..U+10ffff) + * from its lead and trail surrogates. + * The result is undefined if the input values are not + * lead and trail surrogates. + * + * @param lead lead surrogate (U+d800..U+dbff) + * @param trail trail surrogate (U+dc00..U+dfff) + * @return supplementary code point (U+10000..U+10ffff) + * @stable ICU 2.4 + */ +#define U16_GET_SUPPLEMENTARY(lead, trail) \ + (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET) + + +/** + * Get the lead surrogate (0xd800..0xdbff) for a + * supplementary code point (0x10000..0x10ffff). + * @param supplementary 32-bit code point (U+10000..U+10ffff) + * @return lead surrogate (U+d800..U+dbff) for supplementary + * @stable ICU 2.4 + */ +#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) + +/** + * Get the trail surrogate (0xdc00..0xdfff) for a + * supplementary code point (0x10000..0x10ffff). + * @param supplementary 32-bit code point (U+10000..U+10ffff) + * @return trail surrogate (U+dc00..U+dfff) for supplementary + * @stable ICU 2.4 + */ +#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) + +/** + * How many 16-bit code units are used to encode this Unicode code point? (1 or 2) + * The result is not defined if c is not a Unicode code point (U+0000..U+10ffff). + * @param c 32-bit code point + * @return 1 or 2 + * @stable ICU 2.4 + */ +#define U16_LENGTH(c) ((uint32_t)(c)<=0xffff ? 1 : 2) + +/** + * The maximum number of 16-bit code units per Unicode code point (U+0000..U+10ffff). + * @return 2 + * @stable ICU 2.4 + */ +#define U16_MAX_LENGTH 2 + +/** + * Get a code point from a string at a random-access offset, + * without changing the offset. + * "Unsafe" macro, assumes well-formed UTF-16. + * + * The offset may point to either the lead or trail surrogate unit + * for a supplementary code point, in which case the macro will read + * the adjacent matching surrogate as well. + * The result is undefined if the offset points to a single, unpaired surrogate. + * Iteration through a string is more efficient with U16_NEXT_UNSAFE or U16_NEXT. + * + * @param s const UChar * string + * @param i string offset + * @param c output UChar32 variable + * @see U16_GET + * @stable ICU 2.4 + */ +#define U16_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ + (c)=(s)[i]; \ + if(U16_IS_SURROGATE(c)) { \ + if(U16_IS_SURROGATE_LEAD(c)) { \ + (c)=U16_GET_SUPPLEMENTARY((c), (s)[(i)+1]); \ + } else { \ + (c)=U16_GET_SUPPLEMENTARY((s)[(i)-1], (c)); \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Get a code point from a string at a random-access offset, + * without changing the offset. + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The offset may point to either the lead or trail surrogate unit + * for a supplementary code point, in which case the macro will read + * the adjacent matching surrogate as well. + * + * The length can be negative for a NUL-terminated string. + * + * If the offset points to a single, unpaired surrogate, then + * c is set to that unpaired surrogate. + * Iteration through a string is more efficient with U16_NEXT_UNSAFE or U16_NEXT. + * + * @param s const UChar * string + * @param start starting string offset (usually 0) + * @param i string offset, must be start<=i(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Get a code point from a string at a random-access offset, + * without changing the offset. + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The offset may point to either the lead or trail surrogate unit + * for a supplementary code point, in which case the macro will read + * the adjacent matching surrogate as well. + * + * The length can be negative for a NUL-terminated string. + * + * If the offset points to a single, unpaired surrogate, then + * c is set to U+FFFD. + * Iteration through a string is more efficient with U16_NEXT_UNSAFE or U16_NEXT_OR_FFFD. + * + * @param s const UChar * string + * @param start starting string offset (usually 0) + * @param i string offset, must be start<=i(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } else { \ + (c)=0xfffd; \ + } \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/* definitions with forward iteration --------------------------------------- */ + +/** + * Get a code point from a string at a code point boundary offset, + * and advance the offset to the next code point boundary. + * (Post-incrementing forward iteration.) + * "Unsafe" macro, assumes well-formed UTF-16. + * + * The offset may point to the lead surrogate unit + * for a supplementary code point, in which case the macro will read + * the following trail surrogate as well. + * If the offset points to a trail surrogate, then that itself + * will be returned as the code point. + * The result is undefined if the offset points to a single, unpaired lead surrogate. + * + * @param s const UChar * string + * @param i string offset + * @param c output UChar32 variable + * @see U16_NEXT + * @stable ICU 2.4 + */ +#define U16_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ + (c)=(s)[(i)++]; \ + if(U16_IS_LEAD(c)) { \ + (c)=U16_GET_SUPPLEMENTARY((c), (s)[(i)++]); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Get a code point from a string at a code point boundary offset, + * and advance the offset to the next code point boundary. + * (Post-incrementing forward iteration.) + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * The offset may point to the lead surrogate unit + * for a supplementary code point, in which case the macro will read + * the following trail surrogate as well. + * If the offset points to a trail surrogate or + * to a single, unpaired lead surrogate, then c is set to that unpaired surrogate. + * + * @param s const UChar * string + * @param i string offset, must be i>10)+0xd7c0); \ + (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Append a code point to a string, overwriting 1 or 2 code units. + * The offset points to the current end of the string contents + * and is advanced (post-increment). + * "Safe" macro, checks for a valid code point. + * If a surrogate pair is written, checks for sufficient space in the string. + * If the code point is not valid or a trail surrogate does not fit, + * then isError is set to TRUE. + * + * @param s const UChar * string buffer + * @param i string offset, must be i>10)+0xd7c0); \ + (s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \ + } else /* c>0x10ffff or not enough space */ { \ + (isError)=TRUE; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the next. + * (Post-incrementing iteration.) + * "Unsafe" macro, assumes well-formed UTF-16. + * + * @param s const UChar * string + * @param i string offset + * @see U16_FWD_1 + * @stable ICU 2.4 + */ +#define U16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + if(U16_IS_LEAD((s)[(i)++])) { \ + ++(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the next. + * (Post-incrementing iteration.) + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * @param s const UChar * string + * @param i string offset, must be i0) { \ + U16_FWD_1_UNSAFE(s, i); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the n-th next one, + * i.e., move forward by n code points. + * (Post-incrementing iteration.) + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * @param s const UChar * string + * @param i int32_t string offset, must be i0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \ + U16_FWD_1(s, i, length); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary + * at the start of a code point. + * If the offset points to the trail surrogate of a surrogate pair, + * then the offset is decremented. + * Otherwise, it is not modified. + * "Unsafe" macro, assumes well-formed UTF-16. + * + * @param s const UChar * string + * @param i string offset + * @see U16_SET_CP_START + * @stable ICU 2.4 + */ +#define U16_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + if(U16_IS_TRAIL((s)[i])) { \ + --(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary + * at the start of a code point. + * If the offset points to the trail surrogate of a surrogate pair, + * then the offset is decremented. + * Otherwise, it is not modified. + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * @param s const UChar * string + * @param start starting string offset (usually 0) + * @param i string offset, must be start<=i + * @see U16_SET_CP_START_UNSAFE + * @stable ICU 2.4 + */ +#define U16_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ + if(U16_IS_TRAIL((s)[i]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \ + --(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +/* definitions with backward iteration -------------------------------------- */ + +/** + * Move the string offset from one code point boundary to the previous one + * and get the code point between them. + * (Pre-decrementing backward iteration.) + * "Unsafe" macro, assumes well-formed UTF-16. + * + * The input offset may be the same as the string length. + * If the offset is behind a trail surrogate unit + * for a supplementary code point, then the macro will read + * the preceding lead surrogate as well. + * If the offset is behind a lead surrogate, then that itself + * will be returned as the code point. + * The result is undefined if the offset is behind a single, unpaired trail surrogate. + * + * @param s const UChar * string + * @param i string offset + * @param c output UChar32 variable + * @see U16_PREV + * @stable ICU 2.4 + */ +#define U16_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ + (c)=(s)[--(i)]; \ + if(U16_IS_TRAIL(c)) { \ + (c)=U16_GET_SUPPLEMENTARY((s)[--(i)], (c)); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the previous one + * and get the code point between them. + * (Pre-decrementing backward iteration.) + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The input offset may be the same as the string length. + * If the offset is behind a trail surrogate unit + * for a supplementary code point, then the macro will read + * the preceding lead surrogate as well. + * If the offset is behind a lead surrogate or behind a single, unpaired + * trail surrogate, then c is set to that unpaired surrogate. + * + * @param s const UChar * string + * @param start starting string offset (usually 0) + * @param i string offset, must be start(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + --(i); \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the previous one + * and get the code point between them. + * (Pre-decrementing backward iteration.) + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The input offset may be the same as the string length. + * If the offset is behind a trail surrogate unit + * for a supplementary code point, then the macro will read + * the preceding lead surrogate as well. + * If the offset is behind a lead surrogate or behind a single, unpaired + * trail surrogate, then c is set to U+FFFD. + * + * @param s const UChar * string + * @param start starting string offset (usually 0) + * @param i string offset, must be start(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + --(i); \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } else { \ + (c)=0xfffd; \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the previous one. + * (Pre-decrementing backward iteration.) + * The input offset may be the same as the string length. + * "Unsafe" macro, assumes well-formed UTF-16. + * + * @param s const UChar * string + * @param i string offset + * @see U16_BACK_1 + * @stable ICU 2.4 + */ +#define U16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + if(U16_IS_TRAIL((s)[--(i)])) { \ + --(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the previous one. + * (Pre-decrementing backward iteration.) + * The input offset may be the same as the string length. + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * @param s const UChar * string + * @param start starting string offset (usually 0) + * @param i string offset, must be start(start) && U16_IS_LEAD((s)[(i)-1])) { \ + --(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the n-th one before it, + * i.e., move backward by n code points. + * (Pre-decrementing backward iteration.) + * The input offset may be the same as the string length. + * "Unsafe" macro, assumes well-formed UTF-16. + * + * @param s const UChar * string + * @param i string offset + * @param n number of code points to skip + * @see U16_BACK_N + * @stable ICU 2.4 + */ +#define U16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ + int32_t __N=(n); \ + while(__N>0) { \ + U16_BACK_1_UNSAFE(s, i); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the n-th one before it, + * i.e., move backward by n code points. + * (Pre-decrementing backward iteration.) + * The input offset may be the same as the string length. + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * @param s const UChar * string + * @param start start of string + * @param i string offset, must be start0 && (i)>(start)) { \ + U16_BACK_1(s, start, i); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary after a code point. + * If the offset is behind the lead surrogate of a surrogate pair, + * then the offset is incremented. + * Otherwise, it is not modified. + * The input offset may be the same as the string length. + * "Unsafe" macro, assumes well-formed UTF-16. + * + * @param s const UChar * string + * @param i string offset + * @see U16_SET_CP_LIMIT + * @stable ICU 2.4 + */ +#define U16_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + if(U16_IS_LEAD((s)[(i)-1])) { \ + ++(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary after a code point. + * If the offset is behind the lead surrogate of a surrogate pair, + * then the offset is incremented. + * Otherwise, it is not modified. + * The input offset may be the same as the string length. + * "Safe" macro, handles unpaired surrogates and checks for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * @param s const UChar * string + * @param start int32_t starting string offset (usually 0) + * @param i int32_t string offset, start<=i<=length + * @param length int32_t string length + * @see U16_SET_CP_LIMIT_UNSAFE + * @stable ICU 2.4 + */ +#define U16_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \ + if((start)<(i) && ((i)<(length) || (length)<0) && U16_IS_LEAD((s)[(i)-1]) && U16_IS_TRAIL((s)[i])) { \ + ++(i); \ + } \ +} UPRV_BLOCK_MACRO_END + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/unicode/utf8.h b/codegraph-kernel/vendor/tree-sitter/src/unicode/utf8.h new file mode 100644 index 0000000000..bb00130374 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/unicode/utf8.h @@ -0,0 +1,881 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +******************************************************************************* +* +* Copyright (C) 1999-2015, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: utf8.h +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +* +* created on: 1999sep13 +* created by: Markus W. Scherer +*/ + +/** + * \file + * \brief C API: 8-bit Unicode handling macros + * + * This file defines macros to deal with 8-bit Unicode (UTF-8) code units (bytes) and strings. + * + * For more information see utf.h and the ICU User Guide Strings chapter + * (http://userguide.icu-project.org/strings). + * + * Usage: + * ICU coding guidelines for if() statements should be followed when using these macros. + * Compound statements (curly braces {}) must be used for if-else-while... + * bodies and all macro statements should be terminated with semicolon. + */ + +#ifndef __UTF8_H__ +#define __UTF8_H__ + +#include "unicode/umachine.h" +#ifndef __UTF_H__ +# include "unicode/utf.h" +#endif + +/* internal definitions ----------------------------------------------------- */ + +/** + * Counts the trail bytes for a UTF-8 lead byte. + * Returns 0 for 0..0xc1 as well as for 0xf5..0xff. + * leadByte might be evaluated multiple times. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is called by public macros in this file and thus must remain stable. + * + * @param leadByte The first byte of a UTF-8 sequence. Must be 0..0xff. + * @internal + */ +#define U8_COUNT_TRAIL_BYTES(leadByte) \ + (U8_IS_LEAD(leadByte) ? \ + ((uint8_t)(leadByte)>=0xe0)+((uint8_t)(leadByte)>=0xf0)+1 : 0) + +/** + * Counts the trail bytes for a UTF-8 lead byte of a valid UTF-8 sequence. + * Returns 0 for 0..0xc1. Undefined for 0xf5..0xff. + * leadByte might be evaluated multiple times. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is called by public macros in this file and thus must remain stable. + * + * @param leadByte The first byte of a UTF-8 sequence. Must be 0..0xff. + * @internal + */ +#define U8_COUNT_TRAIL_BYTES_UNSAFE(leadByte) \ + (((uint8_t)(leadByte)>=0xc2)+((uint8_t)(leadByte)>=0xe0)+((uint8_t)(leadByte)>=0xf0)) + +/** + * Mask a UTF-8 lead byte, leave only the lower bits that form part of the code point value. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is called by public macros in this file and thus must remain stable. + * @internal + */ +#define U8_MASK_LEAD_BYTE(leadByte, countTrailBytes) ((leadByte)&=(1<<(6-(countTrailBytes)))-1) + +/** + * Internal bit vector for 3-byte UTF-8 validity check, for use in U8_IS_VALID_LEAD3_AND_T1. + * Each bit indicates whether one lead byte + first trail byte pair starts a valid sequence. + * Lead byte E0..EF bits 3..0 are used as byte index, + * first trail byte bits 7..5 are used as bit index into that byte. + * @see U8_IS_VALID_LEAD3_AND_T1 + * @internal + */ +#define U8_LEAD3_T1_BITS "\x20\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x10\x30\x30" + +/** + * Internal 3-byte UTF-8 validity check. + * Non-zero if lead byte E0..EF and first trail byte 00..FF start a valid sequence. + * @internal + */ +#define U8_IS_VALID_LEAD3_AND_T1(lead, t1) (U8_LEAD3_T1_BITS[(lead)&0xf]&(1<<((uint8_t)(t1)>>5))) + +/** + * Internal bit vector for 4-byte UTF-8 validity check, for use in U8_IS_VALID_LEAD4_AND_T1. + * Each bit indicates whether one lead byte + first trail byte pair starts a valid sequence. + * First trail byte bits 7..4 are used as byte index, + * lead byte F0..F4 bits 2..0 are used as bit index into that byte. + * @see U8_IS_VALID_LEAD4_AND_T1 + * @internal + */ +#define U8_LEAD4_T1_BITS "\x00\x00\x00\x00\x00\x00\x00\x00\x1E\x0F\x0F\x0F\x00\x00\x00\x00" + +/** + * Internal 4-byte UTF-8 validity check. + * Non-zero if lead byte F0..F4 and first trail byte 00..FF start a valid sequence. + * @internal + */ +#define U8_IS_VALID_LEAD4_AND_T1(lead, t1) (U8_LEAD4_T1_BITS[(uint8_t)(t1)>>4]&(1<<((lead)&7))) + +/** + * Function for handling "next code point" with error-checking. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is U_STABLE (not U_INTERNAL) since it is called by public macros in this + * file and thus must remain stable, and should not be hidden when other internal + * functions are hidden (otherwise public macros would fail to compile). + * @internal + */ +U_STABLE UChar32 U_EXPORT2 +utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c, UBool strict); + +/** + * Function for handling "append code point" with error-checking. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is U_STABLE (not U_INTERNAL) since it is called by public macros in this + * file and thus must remain stable, and should not be hidden when other internal + * functions are hidden (otherwise public macros would fail to compile). + * @internal + */ +U_STABLE int32_t U_EXPORT2 +utf8_appendCharSafeBody(uint8_t *s, int32_t i, int32_t length, UChar32 c, UBool *pIsError); + +/** + * Function for handling "previous code point" with error-checking. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is U_STABLE (not U_INTERNAL) since it is called by public macros in this + * file and thus must remain stable, and should not be hidden when other internal + * functions are hidden (otherwise public macros would fail to compile). + * @internal + */ +U_STABLE UChar32 U_EXPORT2 +utf8_prevCharSafeBody(const uint8_t *s, int32_t start, int32_t *pi, UChar32 c, UBool strict); + +/** + * Function for handling "skip backward one code point" with error-checking. + * + * This is internal since it is not meant to be called directly by external clients; + * however it is U_STABLE (not U_INTERNAL) since it is called by public macros in this + * file and thus must remain stable, and should not be hidden when other internal + * functions are hidden (otherwise public macros would fail to compile). + * @internal + */ +U_STABLE int32_t U_EXPORT2 +utf8_back1SafeBody(const uint8_t *s, int32_t start, int32_t i); + +/* single-code point definitions -------------------------------------------- */ + +/** + * Does this code unit (byte) encode a code point by itself (US-ASCII 0..0x7f)? + * @param c 8-bit code unit (byte) + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U8_IS_SINGLE(c) (((c)&0x80)==0) + +/** + * Is this code unit (byte) a UTF-8 lead byte? (0xC2..0xF4) + * @param c 8-bit code unit (byte) + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U8_IS_LEAD(c) ((uint8_t)((c)-0xc2)<=0x32) +// 0x32=0xf4-0xc2 + +/** + * Is this code unit (byte) a UTF-8 trail byte? (0x80..0xBF) + * @param c 8-bit code unit (byte) + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U8_IS_TRAIL(c) ((int8_t)(c)<-0x40) + +/** + * How many code units (bytes) are used for the UTF-8 encoding + * of this Unicode code point? + * @param c 32-bit code point + * @return 1..4, or 0 if c is a surrogate or not a Unicode code point + * @stable ICU 2.4 + */ +#define U8_LENGTH(c) \ + ((uint32_t)(c)<=0x7f ? 1 : \ + ((uint32_t)(c)<=0x7ff ? 2 : \ + ((uint32_t)(c)<=0xd7ff ? 3 : \ + ((uint32_t)(c)<=0xdfff || (uint32_t)(c)>0x10ffff ? 0 : \ + ((uint32_t)(c)<=0xffff ? 3 : 4)\ + ) \ + ) \ + ) \ + ) + +/** + * The maximum number of UTF-8 code units (bytes) per Unicode code point (U+0000..U+10ffff). + * @return 4 + * @stable ICU 2.4 + */ +#define U8_MAX_LENGTH 4 + +/** + * Get a code point from a string at a random-access offset, + * without changing the offset. + * The offset may point to either the lead byte or one of the trail bytes + * for a code point, in which case the macro will read all of the bytes + * for the code point. + * The result is undefined if the offset points to an illegal UTF-8 + * byte sequence. + * Iteration through a string is more efficient with U8_NEXT_UNSAFE or U8_NEXT. + * + * @param s const uint8_t * string + * @param i string offset + * @param c output UChar32 variable + * @see U8_GET + * @stable ICU 2.4 + */ +#define U8_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ + int32_t _u8_get_unsafe_index=(int32_t)(i); \ + U8_SET_CP_START_UNSAFE(s, _u8_get_unsafe_index); \ + U8_NEXT_UNSAFE(s, _u8_get_unsafe_index, c); \ +} UPRV_BLOCK_MACRO_END + +/** + * Get a code point from a string at a random-access offset, + * without changing the offset. + * The offset may point to either the lead byte or one of the trail bytes + * for a code point, in which case the macro will read all of the bytes + * for the code point. + * + * The length can be negative for a NUL-terminated string. + * + * If the offset points to an illegal UTF-8 byte sequence, then + * c is set to a negative value. + * Iteration through a string is more efficient with U8_NEXT_UNSAFE or U8_NEXT. + * + * @param s const uint8_t * string + * @param start int32_t starting string offset + * @param i int32_t string offset, must be start<=i=0xe0 ? \ + ((c)<0xf0 ? /* U+0800..U+FFFF except surrogates */ \ + U8_LEAD3_T1_BITS[(c)&=0xf]&(1<<((__t=(s)[i])>>5)) && \ + (__t&=0x3f, 1) \ + : /* U+10000..U+10FFFF */ \ + ((c)-=0xf0)<=4 && \ + U8_LEAD4_T1_BITS[(__t=(s)[i])>>4]&(1<<(c)) && \ + ((c)=((c)<<6)|(__t&0x3f), ++(i)!=(length)) && \ + (__t=(s)[i]-0x80)<=0x3f) && \ + /* valid second-to-last trail byte */ \ + ((c)=((c)<<6)|__t, ++(i)!=(length)) \ + : /* U+0080..U+07FF */ \ + (c)>=0xc2 && ((c)&=0x1f, 1)) && \ + /* last trail byte */ \ + (__t=(s)[i]-0x80)<=0x3f && \ + ((c)=((c)<<6)|__t, ++(i), 1)) { \ + } else { \ + (c)=(sub); /* ill-formed*/ \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Append a code point to a string, overwriting 1 to 4 bytes. + * The offset points to the current end of the string contents + * and is advanced (post-increment). + * "Unsafe" macro, assumes a valid code point and sufficient space in the string. + * Otherwise, the result is undefined. + * + * @param s const uint8_t * string buffer + * @param i string offset + * @param c code point to append + * @see U8_APPEND + * @stable ICU 2.4 + */ +#define U8_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ + uint32_t __uc=(c); \ + if(__uc<=0x7f) { \ + (s)[(i)++]=(uint8_t)__uc; \ + } else { \ + if(__uc<=0x7ff) { \ + (s)[(i)++]=(uint8_t)((__uc>>6)|0xc0); \ + } else { \ + if(__uc<=0xffff) { \ + (s)[(i)++]=(uint8_t)((__uc>>12)|0xe0); \ + } else { \ + (s)[(i)++]=(uint8_t)((__uc>>18)|0xf0); \ + (s)[(i)++]=(uint8_t)(((__uc>>12)&0x3f)|0x80); \ + } \ + (s)[(i)++]=(uint8_t)(((__uc>>6)&0x3f)|0x80); \ + } \ + (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Append a code point to a string, overwriting 1 to 4 bytes. + * The offset points to the current end of the string contents + * and is advanced (post-increment). + * "Safe" macro, checks for a valid code point. + * If a non-ASCII code point is written, checks for sufficient space in the string. + * If the code point is not valid or trail bytes do not fit, + * then isError is set to TRUE. + * + * @param s const uint8_t * string buffer + * @param i int32_t string offset, must be i>6)|0xc0); \ + (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ + } else if((__uc<=0xd7ff || (0xe000<=__uc && __uc<=0xffff)) && (i)+2<(capacity)) { \ + (s)[(i)++]=(uint8_t)((__uc>>12)|0xe0); \ + (s)[(i)++]=(uint8_t)(((__uc>>6)&0x3f)|0x80); \ + (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ + } else if(0xffff<__uc && __uc<=0x10ffff && (i)+3<(capacity)) { \ + (s)[(i)++]=(uint8_t)((__uc>>18)|0xf0); \ + (s)[(i)++]=(uint8_t)(((__uc>>12)&0x3f)|0x80); \ + (s)[(i)++]=(uint8_t)(((__uc>>6)&0x3f)|0x80); \ + (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ + } else { \ + (isError)=TRUE; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the next. + * (Post-incrementing iteration.) + * "Unsafe" macro, assumes well-formed UTF-8. + * + * @param s const uint8_t * string + * @param i string offset + * @see U8_FWD_1 + * @stable ICU 2.4 + */ +#define U8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + (i)+=1+U8_COUNT_TRAIL_BYTES_UNSAFE((s)[i]); \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the next. + * (Post-incrementing iteration.) + * "Safe" macro, checks for illegal sequences and for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * @param s const uint8_t * string + * @param i int32_t string offset, must be i=0xf0 */ { \ + if(U8_IS_VALID_LEAD4_AND_T1(__b, __t1) && \ + ++(i)!=(length) && U8_IS_TRAIL((s)[i]) && \ + ++(i)!=(length) && U8_IS_TRAIL((s)[i])) { \ + ++(i); \ + } \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the n-th next one, + * i.e., move forward by n code points. + * (Post-incrementing iteration.) + * "Unsafe" macro, assumes well-formed UTF-8. + * + * @param s const uint8_t * string + * @param i string offset + * @param n number of code points to skip + * @see U8_FWD_N + * @stable ICU 2.4 + */ +#define U8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \ + int32_t __N=(n); \ + while(__N>0) { \ + U8_FWD_1_UNSAFE(s, i); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Advance the string offset from one code point boundary to the n-th next one, + * i.e., move forward by n code points. + * (Post-incrementing iteration.) + * "Safe" macro, checks for illegal sequences and for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * @param s const uint8_t * string + * @param i int32_t string offset, must be i0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \ + U8_FWD_1(s, i, length); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary + * at the start of a code point. + * If the offset points to a UTF-8 trail byte, + * then the offset is moved backward to the corresponding lead byte. + * Otherwise, it is not modified. + * "Unsafe" macro, assumes well-formed UTF-8. + * + * @param s const uint8_t * string + * @param i string offset + * @see U8_SET_CP_START + * @stable ICU 2.4 + */ +#define U8_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + while(U8_IS_TRAIL((s)[i])) { --(i); } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary + * at the start of a code point. + * If the offset points to a UTF-8 trail byte, + * then the offset is moved backward to the corresponding lead byte. + * Otherwise, it is not modified. + * + * "Safe" macro, checks for illegal sequences and for string boundaries. + * Unlike U8_TRUNCATE_IF_INCOMPLETE(), this macro always reads s[i]. + * + * @param s const uint8_t * string + * @param start int32_t starting string offset (usually 0) + * @param i int32_t string offset, must be start<=i + * @see U8_SET_CP_START_UNSAFE + * @see U8_TRUNCATE_IF_INCOMPLETE + * @stable ICU 2.4 + */ +#define U8_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \ + if(U8_IS_TRAIL((s)[(i)])) { \ + (i)=utf8_back1SafeBody(s, start, (i)); \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * If the string ends with a UTF-8 byte sequence that is valid so far + * but incomplete, then reduce the length of the string to end before + * the lead byte of that incomplete sequence. + * For example, if the string ends with E1 80, the length is reduced by 2. + * + * In all other cases (the string ends with a complete sequence, or it is not + * possible for any further trail byte to extend the trailing sequence) + * the length remains unchanged. + * + * Useful for processing text split across multiple buffers + * (save the incomplete sequence for later) + * and for optimizing iteration + * (check for string length only once per character). + * + * "Safe" macro, checks for illegal sequences and for string boundaries. + * Unlike U8_SET_CP_START(), this macro never reads s[length]. + * + * (In UTF-16, simply check for U16_IS_LEAD(last code unit).) + * + * @param s const uint8_t * string + * @param start int32_t starting string offset (usually 0) + * @param length int32_t string length (usually start<=length) + * @see U8_SET_CP_START + * @stable ICU 61 + */ +#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) UPRV_BLOCK_MACRO_BEGIN { \ + if((length)>(start)) { \ + uint8_t __b1=s[(length)-1]; \ + if(U8_IS_SINGLE(__b1)) { \ + /* common ASCII character */ \ + } else if(U8_IS_LEAD(__b1)) { \ + --(length); \ + } else if(U8_IS_TRAIL(__b1) && ((length)-2)>=(start)) { \ + uint8_t __b2=s[(length)-2]; \ + if(0xe0<=__b2 && __b2<=0xf4) { \ + if(__b2<0xf0 ? U8_IS_VALID_LEAD3_AND_T1(__b2, __b1) : \ + U8_IS_VALID_LEAD4_AND_T1(__b2, __b1)) { \ + (length)-=2; \ + } \ + } else if(U8_IS_TRAIL(__b2) && ((length)-3)>=(start)) { \ + uint8_t __b3=s[(length)-3]; \ + if(0xf0<=__b3 && __b3<=0xf4 && U8_IS_VALID_LEAD4_AND_T1(__b3, __b2)) { \ + (length)-=3; \ + } \ + } \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/* definitions with backward iteration -------------------------------------- */ + +/** + * Move the string offset from one code point boundary to the previous one + * and get the code point between them. + * (Pre-decrementing backward iteration.) + * "Unsafe" macro, assumes well-formed UTF-8. + * + * The input offset may be the same as the string length. + * If the offset is behind a multi-byte sequence, then the macro will read + * the whole sequence. + * If the offset is behind a lead byte, then that itself + * will be returned as the code point. + * The result is undefined if the offset is behind an illegal UTF-8 sequence. + * + * @param s const uint8_t * string + * @param i string offset + * @param c output UChar32 variable + * @see U8_PREV + * @stable ICU 2.4 + */ +#define U8_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \ + (c)=(uint8_t)(s)[--(i)]; \ + if(U8_IS_TRAIL(c)) { \ + uint8_t __b, __count=1, __shift=6; \ +\ + /* c is a trail byte */ \ + (c)&=0x3f; \ + for(;;) { \ + __b=(s)[--(i)]; \ + if(__b>=0xc0) { \ + U8_MASK_LEAD_BYTE(__b, __count); \ + (c)|=(UChar32)__b<<__shift; \ + break; \ + } else { \ + (c)|=(UChar32)(__b&0x3f)<<__shift; \ + ++__count; \ + __shift+=6; \ + } \ + } \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the previous one + * and get the code point between them. + * (Pre-decrementing backward iteration.) + * "Safe" macro, checks for illegal sequences and for string boundaries. + * + * The input offset may be the same as the string length. + * If the offset is behind a multi-byte sequence, then the macro will read + * the whole sequence. + * If the offset is behind a lead byte, then that itself + * will be returned as the code point. + * If the offset is behind an illegal UTF-8 sequence, then c is set to a negative value. + * + * @param s const uint8_t * string + * @param start int32_t starting string offset (usually 0) + * @param i int32_t string offset, must be start0) { \ + U8_BACK_1_UNSAFE(s, i); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Move the string offset from one code point boundary to the n-th one before it, + * i.e., move backward by n code points. + * (Pre-decrementing backward iteration.) + * The input offset may be the same as the string length. + * "Safe" macro, checks for illegal sequences and for string boundaries. + * + * @param s const uint8_t * string + * @param start int32_t index of the start of the string + * @param i int32_t string offset, must be start0 && (i)>(start)) { \ + U8_BACK_1(s, start, i); \ + --__N; \ + } \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary after a code point. + * If the offset is behind a partial multi-byte sequence, + * then the offset is incremented to behind the whole sequence. + * Otherwise, it is not modified. + * The input offset may be the same as the string length. + * "Unsafe" macro, assumes well-formed UTF-8. + * + * @param s const uint8_t * string + * @param i string offset + * @see U8_SET_CP_LIMIT + * @stable ICU 2.4 + */ +#define U8_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \ + U8_BACK_1_UNSAFE(s, i); \ + U8_FWD_1_UNSAFE(s, i); \ +} UPRV_BLOCK_MACRO_END + +/** + * Adjust a random-access offset to a code point boundary after a code point. + * If the offset is behind a partial multi-byte sequence, + * then the offset is incremented to behind the whole sequence. + * Otherwise, it is not modified. + * The input offset may be the same as the string length. + * "Safe" macro, checks for illegal sequences and for string boundaries. + * + * The length can be negative for a NUL-terminated string. + * + * @param s const uint8_t * string + * @param start int32_t starting string offset (usually 0) + * @param i int32_t string offset, must be start<=i<=length + * @param length int32_t string length + * @see U8_SET_CP_LIMIT_UNSAFE + * @stable ICU 2.4 + */ +#define U8_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \ + if((start)<(i) && ((i)<(length) || (length)<0)) { \ + U8_BACK_1(s, start, i); \ + U8_FWD_1(s, i, length); \ + } \ +} UPRV_BLOCK_MACRO_END + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib-symbols.txt b/codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib-symbols.txt new file mode 100644 index 0000000000..1b6d789ee5 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib-symbols.txt @@ -0,0 +1,24 @@ +"calloc", +"free", +"iswalnum", +"iswalpha", +"iswblank", +"iswdigit", +"iswlower", +"iswspace", +"iswupper", +"iswxdigit", +"malloc", +"memchr", +"memcmp", +"memcpy", +"memmove", +"memset", +"realloc", +"strcmp", +"strlen", +"strncat", +"strncmp", +"strncpy", +"towlower", +"towupper", diff --git a/codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib.c b/codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib.c new file mode 100644 index 0000000000..af8936f445 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/wasm/stdlib.c @@ -0,0 +1,137 @@ +// This file implements a very simple allocator for external scanners running +// in WASM. Allocation is just bumping a static pointer and growing the heap +// as needed, and freeing is just adding the freed region to a free list. +// When additional memory is allocated, the free list is searched first. +// If there is not a suitable region in the free list, the heap is +// grown as necessary, and the allocation is made at the end of the heap. +// When the heap is reset, all allocated memory is considered freed. + +#ifdef TREE_SITTER_FEATURE_WASM + +#include +#include +#include +#include + +extern void tree_sitter_debug_message(const char *, size_t); + +#define PAGESIZE 0x10000 +#define MAX_HEAP_SIZE (4 * 1024 * 1024) + +typedef struct { + size_t size; + struct Region *next; + char data[0]; +} Region; + +static Region *heap_end = NULL; +static Region *heap_start = NULL; +static Region *next = NULL; +static Region *free_list = NULL; + +// Get the region metadata for the given heap pointer. +static inline Region *region_for_ptr(void *ptr) { + return ((Region *)ptr) - 1; +} + +// Get the location of the next region after the given region, +// if the given region had the given size. +static inline Region *region_after(Region *self, size_t len) { + char *address = self->data + len; + char *aligned = (char *)((uintptr_t)(address + 3) & ~0x3); + return (Region *)aligned; +} + +static void *get_heap_end() { + return (void *)(__builtin_wasm_memory_size(0) * PAGESIZE); +} + +static int grow_heap(size_t size) { + size_t new_page_count = ((size - 1) / PAGESIZE) + 1; + return __builtin_wasm_memory_grow(0, new_page_count) != SIZE_MAX; +} + +// Clear out the heap, and move it to the given address. +void reset_heap(void *new_heap_start) { + heap_start = new_heap_start; + next = new_heap_start; + heap_end = get_heap_end(); + free_list = NULL; +} + +void *malloc(size_t size) { + Region *prev = NULL; + Region *curr = free_list; + while (curr != NULL) { + if (curr->size >= size) { + if (prev == NULL) { + free_list = curr->next; + } else { + prev->next = curr->next; + } + return &curr->data; + } + prev = curr; + curr = curr->next; + } + + Region *region_end = region_after(next, size); + + if (region_end > heap_end) { + if ((char *)region_end - (char *)heap_start > MAX_HEAP_SIZE) { + return NULL; + } + if (!grow_heap(size)) return NULL; + heap_end = get_heap_end(); + } + + void *result = &next->data; + next->size = size; + next = region_end; + + return result; +} + +void free(void *ptr) { + if (ptr == NULL) return; + + Region *region = region_for_ptr(ptr); + Region *region_end = region_after(region, region->size); + + // When freeing the last allocated pointer, re-use that + // pointer for the next allocation. + if (region_end == next) { + next = region; + } else { + region->next = free_list; + free_list = region; + } +} + +void *calloc(size_t count, size_t size) { + void *result = malloc(count * size); + memset(result, 0, count * size); + return result; +} + +void *realloc(void *ptr, size_t new_size) { + if (ptr == NULL) { + return malloc(new_size); + } + + Region *region = region_for_ptr(ptr); + Region *region_end = region_after(region, region->size); + + // When reallocating the last allocated region, return + // the same pointer, and skip copying the data. + if (region_end == next) { + next = region; + return malloc(new_size); + } + + void *result = malloc(new_size); + memcpy(result, ®ion->data, region->size); + return result; +} + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/wasm/wasm-stdlib.h b/codegraph-kernel/vendor/tree-sitter/src/wasm/wasm-stdlib.h new file mode 100644 index 0000000000..a9d241d7e1 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/wasm/wasm-stdlib.h @@ -0,0 +1,1314 @@ +#ifdef TREE_SITTER_FEATURE_WASM + +unsigned char STDLIB_WASM[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1e, 0x06, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x7f, 0x60, 0x03, 0x7f, + 0x7f, 0x7f, 0x01, 0x7f, 0x02, 0x9e, 0x01, 0x05, 0x03, 0x65, 0x6e, 0x76, + 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x02, 0x03, 0x65, + 0x6e, 0x76, 0x19, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x01, 0x70, 0x00, 0x01, 0x16, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x08, 0x61, 0x72, 0x67, 0x73, + 0x5f, 0x67, 0x65, 0x74, 0x00, 0x00, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, + 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x31, 0x0e, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x73, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x00, 0x16, 0x77, + 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x09, 0x70, 0x72, + 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x00, 0x01, 0x03, 0x2a, 0x29, + 0x02, 0x00, 0x02, 0x02, 0x01, 0x03, 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, + 0x00, 0x01, 0x02, 0x02, 0x05, 0x05, 0x03, 0x03, 0x05, 0x05, 0x00, 0x03, + 0x00, 0x03, 0x05, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x05, + 0x03, 0x03, 0x00, 0x03, 0x03, 0x06, 0x0d, 0x02, 0x7f, 0x01, 0x41, 0x80, + 0x80, 0x04, 0x0b, 0x7f, 0x00, 0x41, 0x00, 0x0b, 0x07, 0xad, 0x02, 0x1c, + 0x11, 0x5f, 0x5f, 0x77, 0x61, 0x73, 0x6d, 0x5f, 0x63, 0x61, 0x6c, 0x6c, + 0x5f, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x00, 0x03, 0x0f, 0x5f, 0x5f, 0x73, + 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x03, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x06, 0x0a, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x00, 0x07, + 0x06, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x00, 0x08, 0x04, 0x66, 0x72, + 0x65, 0x65, 0x00, 0x09, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x00, + 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x73, 0x65, 0x74, 0x00, 0x14, 0x07, 0x72, + 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x00, 0x0b, 0x06, 0x6d, 0x65, 0x6d, + 0x63, 0x70, 0x79, 0x00, 0x13, 0x06, 0x73, 0x74, 0x72, 0x6c, 0x65, 0x6e, + 0x00, 0x15, 0x08, 0x69, 0x73, 0x77, 0x61, 0x6c, 0x6e, 0x75, 0x6d, 0x00, + 0x2b, 0x08, 0x69, 0x73, 0x77, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x00, 0x16, + 0x08, 0x69, 0x73, 0x77, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x00, 0x22, 0x08, + 0x69, 0x73, 0x77, 0x64, 0x69, 0x67, 0x69, 0x74, 0x00, 0x23, 0x08, 0x69, + 0x73, 0x77, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x20, 0x08, 0x69, 0x73, + 0x77, 0x73, 0x70, 0x61, 0x63, 0x65, 0x00, 0x2a, 0x08, 0x69, 0x73, 0x77, + 0x75, 0x70, 0x70, 0x65, 0x72, 0x00, 0x1e, 0x09, 0x69, 0x73, 0x77, 0x78, + 0x64, 0x69, 0x67, 0x69, 0x74, 0x00, 0x27, 0x08, 0x74, 0x6f, 0x77, 0x6c, + 0x6f, 0x77, 0x65, 0x72, 0x00, 0x1a, 0x08, 0x74, 0x6f, 0x77, 0x75, 0x70, + 0x70, 0x65, 0x72, 0x00, 0x1c, 0x06, 0x6d, 0x65, 0x6d, 0x63, 0x68, 0x72, + 0x00, 0x18, 0x06, 0x6d, 0x65, 0x6d, 0x63, 0x6d, 0x70, 0x00, 0x17, 0x07, + 0x6d, 0x65, 0x6d, 0x6d, 0x6f, 0x76, 0x65, 0x00, 0x1f, 0x06, 0x73, 0x74, + 0x72, 0x63, 0x6d, 0x70, 0x00, 0x19, 0x07, 0x73, 0x74, 0x72, 0x6e, 0x63, + 0x61, 0x74, 0x00, 0x24, 0x07, 0x73, 0x74, 0x72, 0x6e, 0x63, 0x6d, 0x70, + 0x00, 0x1d, 0x07, 0x73, 0x74, 0x72, 0x6e, 0x63, 0x70, 0x79, 0x00, 0x26, + 0x08, 0x01, 0x05, 0x0a, 0xff, 0x2b, 0x29, 0x02, 0x00, 0x0b, 0x03, 0x00, + 0x00, 0x0b, 0x0d, 0x00, 0x41, 0xe8, 0xc2, 0x04, 0x41, 0x00, 0x41, 0x10, + 0xfc, 0x0b, 0x00, 0x0b, 0x51, 0x01, 0x01, 0x7f, 0x02, 0x40, 0x02, 0x40, + 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xe8, 0xc2, 0x84, 0x80, 0x00, + 0x6a, 0x28, 0x02, 0x00, 0x0d, 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, + 0x41, 0xe8, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x41, 0x01, 0x36, 0x02, 0x00, + 0x10, 0x83, 0x80, 0x80, 0x80, 0x00, 0x10, 0x8d, 0x80, 0x80, 0x80, 0x00, + 0x21, 0x00, 0x10, 0x92, 0x80, 0x80, 0x80, 0x00, 0x20, 0x00, 0x0d, 0x01, + 0x0f, 0x0b, 0x00, 0x0b, 0x20, 0x00, 0x10, 0x90, 0x80, 0x80, 0x80, 0x00, + 0x00, 0x0b, 0x37, 0x01, 0x01, 0x7f, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, + 0x22, 0x01, 0x41, 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x20, 0x00, 0x36, + 0x02, 0x00, 0x20, 0x01, 0x41, 0xec, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0xf4, 0xc2, 0x84, 0x80, 0x00, + 0x6a, 0x3f, 0x00, 0x41, 0x10, 0x74, 0x36, 0x02, 0x00, 0x0b, 0xb4, 0x01, + 0x01, 0x03, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x23, 0x81, 0x80, 0x80, 0x80, + 0x00, 0x22, 0x01, 0x41, 0xf4, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x28, 0x02, + 0x00, 0x20, 0x01, 0x41, 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x28, 0x02, + 0x00, 0x22, 0x01, 0x20, 0x00, 0x6a, 0x41, 0x07, 0x6a, 0x41, 0x7c, 0x71, + 0x22, 0x02, 0x4f, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x20, 0x02, 0x23, + 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xec, 0xc2, 0x84, 0x80, 0x00, 0x6a, + 0x28, 0x02, 0x00, 0x6b, 0x41, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x0d, 0x01, + 0x20, 0x00, 0x41, 0x7f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x01, 0x6a, 0x40, + 0x00, 0x41, 0x7f, 0x46, 0x0d, 0x01, 0x3f, 0x00, 0x21, 0x01, 0x23, 0x81, + 0x80, 0x80, 0x80, 0x00, 0x22, 0x03, 0x41, 0xf4, 0xc2, 0x84, 0x80, 0x00, + 0x6a, 0x20, 0x01, 0x41, 0x10, 0x74, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, + 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x21, 0x01, 0x0b, + 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, + 0x00, 0x41, 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x20, 0x02, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x01, 0x0b, + 0x48, 0x01, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x20, + 0x00, 0x41, 0x7c, 0x6a, 0x22, 0x01, 0x28, 0x02, 0x00, 0x21, 0x02, 0x23, + 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, + 0x28, 0x02, 0x00, 0x20, 0x00, 0x20, 0x02, 0x6a, 0x41, 0x03, 0x6a, 0x41, + 0x7c, 0x71, 0x47, 0x0d, 0x00, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, + 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x0b, + 0x0b, 0x19, 0x00, 0x20, 0x01, 0x20, 0x00, 0x6c, 0x22, 0x00, 0x10, 0x88, + 0x80, 0x80, 0x80, 0x00, 0x41, 0x00, 0x20, 0x00, 0x10, 0x94, 0x80, 0x80, + 0x80, 0x00, 0x0b, 0x6b, 0x01, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x45, + 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7c, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, + 0x21, 0x03, 0x02, 0x40, 0x23, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xf0, + 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x00, 0x20, 0x03, + 0x6a, 0x41, 0x03, 0x6a, 0x41, 0x7c, 0x71, 0x47, 0x0d, 0x00, 0x23, 0x81, + 0x80, 0x80, 0x80, 0x00, 0x41, 0xf0, 0xc2, 0x84, 0x80, 0x00, 0x6a, 0x20, + 0x02, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x10, 0x88, 0x80, + 0x80, 0x80, 0x00, 0x20, 0x00, 0x20, 0x02, 0x28, 0x02, 0x00, 0x10, 0x93, + 0x80, 0x80, 0x80, 0x00, 0x0f, 0x0b, 0x20, 0x01, 0x10, 0x88, 0x80, 0x80, + 0x80, 0x00, 0x0b, 0x0b, 0x00, 0x20, 0x00, 0x10, 0x90, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x0b, 0xd5, 0x01, 0x01, 0x03, 0x7f, 0x23, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x00, 0x24, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, + 0x00, 0x41, 0x08, 0x6a, 0x20, 0x00, 0x41, 0x0c, 0x6a, 0x10, 0x8f, 0x80, + 0x80, 0x80, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x08, 0x41, 0x01, + 0x6a, 0x22, 0x01, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x28, 0x02, 0x0c, 0x10, + 0x88, 0x80, 0x80, 0x80, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x02, 0x20, 0x01, + 0x41, 0x04, 0x10, 0x8a, 0x80, 0x80, 0x80, 0x00, 0x22, 0x01, 0x45, 0x0d, + 0x03, 0x20, 0x01, 0x20, 0x02, 0x10, 0x8e, 0x80, 0x80, 0x80, 0x00, 0x0d, + 0x04, 0x20, 0x00, 0x28, 0x02, 0x08, 0x20, 0x01, 0x10, 0x84, 0x80, 0x80, + 0x80, 0x00, 0x21, 0x01, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x24, 0x80, 0x80, + 0x80, 0x80, 0x00, 0x20, 0x01, 0x0f, 0x0b, 0x41, 0xc7, 0x00, 0x10, 0x8c, + 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x41, 0xc6, 0x00, 0x10, 0x8c, 0x80, + 0x80, 0x80, 0x00, 0x00, 0x0b, 0x41, 0xc6, 0x00, 0x10, 0x8c, 0x80, 0x80, + 0x80, 0x00, 0x00, 0x0b, 0x20, 0x02, 0x10, 0x89, 0x80, 0x80, 0x80, 0x00, + 0x41, 0xc6, 0x00, 0x10, 0x8c, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x20, + 0x02, 0x10, 0x89, 0x80, 0x80, 0x80, 0x00, 0x20, 0x01, 0x10, 0x89, 0x80, + 0x80, 0x80, 0x00, 0x41, 0xc7, 0x00, 0x10, 0x8c, 0x80, 0x80, 0x80, 0x00, + 0x00, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0b, 0x11, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x41, 0xff, 0xff, 0x03, + 0x71, 0x0b, 0x0b, 0x00, 0x20, 0x00, 0x10, 0x82, 0x80, 0x80, 0x80, 0x00, + 0x00, 0x0b, 0x02, 0x00, 0x0b, 0x0e, 0x00, 0x10, 0x91, 0x80, 0x80, 0x80, + 0x00, 0x10, 0x91, 0x80, 0x80, 0x80, 0x00, 0x0b, 0xee, 0x07, 0x01, 0x04, + 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x20, 0x4b, + 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x01, 0x20, 0x02, + 0x45, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x01, + 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x05, 0x41, 0x03, + 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, + 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x02, 0x41, 0x7e, 0x6a, + 0x21, 0x03, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, + 0x02, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, + 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, + 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x03, + 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x22, 0x05, 0x41, 0x03, + 0x71, 0x45, 0x0d, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x02, 0x20, 0x00, 0x20, + 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x02, 0x41, 0x7c, 0x6a, + 0x21, 0x03, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, + 0x04, 0x6a, 0x21, 0x05, 0x0c, 0x02, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, + 0x02, 0xfc, 0x0a, 0x00, 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x21, + 0x03, 0x20, 0x00, 0x21, 0x04, 0x20, 0x01, 0x21, 0x05, 0x0b, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, 0x22, 0x02, 0x0d, 0x00, 0x02, + 0x40, 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, 0x0d, 0x00, 0x20, 0x03, + 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x70, 0x6a, + 0x22, 0x02, 0x41, 0x10, 0x71, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, + 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x08, + 0x37, 0x02, 0x08, 0x20, 0x04, 0x41, 0x10, 0x6a, 0x21, 0x04, 0x20, 0x05, + 0x41, 0x10, 0x6a, 0x21, 0x05, 0x20, 0x02, 0x21, 0x03, 0x0b, 0x20, 0x02, + 0x41, 0x10, 0x49, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, 0x03, 0x40, 0x20, + 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x04, 0x20, + 0x05, 0x29, 0x02, 0x08, 0x37, 0x02, 0x08, 0x20, 0x04, 0x20, 0x05, 0x29, + 0x02, 0x10, 0x37, 0x02, 0x10, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x18, + 0x37, 0x02, 0x18, 0x20, 0x04, 0x41, 0x20, 0x6a, 0x21, 0x04, 0x20, 0x05, + 0x41, 0x20, 0x6a, 0x21, 0x05, 0x20, 0x02, 0x41, 0x60, 0x6a, 0x22, 0x02, + 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, + 0x08, 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x29, 0x02, 0x00, 0x37, + 0x02, 0x00, 0x20, 0x05, 0x41, 0x08, 0x6a, 0x21, 0x05, 0x20, 0x04, 0x41, + 0x08, 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x04, 0x71, + 0x45, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x20, 0x04, 0x41, 0x04, + 0x6a, 0x21, 0x04, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x02, 0x71, 0x45, + 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, + 0x20, 0x04, 0x41, 0x02, 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x02, 0x6a, + 0x21, 0x05, 0x0b, 0x20, 0x02, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x01, 0x20, + 0x04, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x0f, + 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, + 0x03, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x3a, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, + 0x41, 0x7f, 0x6a, 0x0e, 0x03, 0x03, 0x00, 0x01, 0x03, 0x0b, 0x20, 0x04, + 0x20, 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, 0x20, 0x04, 0x20, 0x05, + 0x41, 0x06, 0x6a, 0x29, 0x01, 0x00, 0x37, 0x02, 0x06, 0x20, 0x04, 0x20, + 0x05, 0x28, 0x02, 0x04, 0x41, 0x10, 0x74, 0x20, 0x03, 0x41, 0x10, 0x76, + 0x72, 0x36, 0x02, 0x02, 0x20, 0x04, 0x41, 0x12, 0x6a, 0x21, 0x02, 0x20, + 0x05, 0x41, 0x12, 0x6a, 0x21, 0x01, 0x41, 0x0e, 0x21, 0x06, 0x20, 0x05, + 0x41, 0x0e, 0x6a, 0x28, 0x01, 0x00, 0x21, 0x05, 0x41, 0x0e, 0x21, 0x03, + 0x0c, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x05, 0x41, 0x05, 0x6a, 0x29, 0x00, + 0x00, 0x37, 0x02, 0x05, 0x20, 0x04, 0x20, 0x05, 0x28, 0x02, 0x04, 0x41, + 0x18, 0x74, 0x20, 0x03, 0x41, 0x08, 0x76, 0x72, 0x36, 0x02, 0x01, 0x20, + 0x04, 0x41, 0x11, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x11, 0x6a, 0x21, + 0x01, 0x41, 0x0d, 0x21, 0x06, 0x20, 0x05, 0x41, 0x0d, 0x6a, 0x28, 0x00, + 0x00, 0x21, 0x05, 0x41, 0x0f, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x41, 0x10, 0x4f, 0x0d, 0x00, 0x20, 0x04, 0x21, + 0x02, 0x20, 0x05, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x20, 0x05, + 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x04, 0x20, 0x05, 0x28, 0x00, + 0x01, 0x36, 0x00, 0x01, 0x20, 0x04, 0x20, 0x05, 0x29, 0x00, 0x05, 0x37, + 0x00, 0x05, 0x20, 0x04, 0x20, 0x05, 0x2f, 0x00, 0x0d, 0x3b, 0x00, 0x0d, + 0x20, 0x04, 0x20, 0x05, 0x2d, 0x00, 0x0f, 0x3a, 0x00, 0x0f, 0x20, 0x04, + 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x01, + 0x0b, 0x20, 0x03, 0x41, 0x08, 0x71, 0x0d, 0x02, 0x0c, 0x03, 0x0b, 0x20, + 0x04, 0x20, 0x03, 0x41, 0x10, 0x76, 0x3a, 0x00, 0x02, 0x20, 0x04, 0x20, + 0x03, 0x41, 0x08, 0x76, 0x3a, 0x00, 0x01, 0x20, 0x04, 0x20, 0x05, 0x41, + 0x07, 0x6a, 0x29, 0x00, 0x00, 0x37, 0x02, 0x07, 0x20, 0x04, 0x20, 0x05, + 0x28, 0x02, 0x04, 0x41, 0x08, 0x74, 0x20, 0x03, 0x41, 0x18, 0x76, 0x72, + 0x36, 0x02, 0x03, 0x20, 0x04, 0x41, 0x13, 0x6a, 0x21, 0x02, 0x20, 0x05, + 0x41, 0x13, 0x6a, 0x21, 0x01, 0x41, 0x0f, 0x21, 0x06, 0x20, 0x05, 0x41, + 0x0f, 0x6a, 0x28, 0x00, 0x00, 0x21, 0x05, 0x41, 0x0d, 0x21, 0x03, 0x0b, + 0x20, 0x04, 0x20, 0x06, 0x6a, 0x20, 0x05, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x02, 0x20, 0x01, 0x29, 0x00, 0x00, 0x37, 0x00, 0x00, 0x20, 0x02, 0x41, + 0x08, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x21, 0x01, 0x0b, + 0x02, 0x40, 0x20, 0x03, 0x41, 0x04, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, + 0x20, 0x01, 0x28, 0x00, 0x00, 0x36, 0x00, 0x00, 0x20, 0x02, 0x41, 0x04, + 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x0b, 0x02, + 0x40, 0x20, 0x03, 0x41, 0x02, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, + 0x01, 0x2f, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x20, 0x02, 0x41, 0x02, 0x6a, + 0x21, 0x02, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x03, + 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x0b, 0x88, 0x03, 0x02, 0x03, + 0x7f, 0x01, 0x7e, 0x02, 0x40, 0x20, 0x02, 0x41, 0x21, 0x49, 0x0d, 0x00, + 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0xfc, 0x0b, 0x00, 0x20, 0x00, 0x0f, + 0x0b, 0x02, 0x40, 0x20, 0x02, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, 0x02, 0x6a, 0x22, 0x03, 0x41, 0x7f, + 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x03, 0x49, 0x0d, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, + 0x3a, 0x00, 0x01, 0x20, 0x03, 0x41, 0x7d, 0x6a, 0x20, 0x01, 0x3a, 0x00, + 0x00, 0x20, 0x03, 0x41, 0x7e, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, + 0x02, 0x41, 0x07, 0x49, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, + 0x03, 0x20, 0x03, 0x41, 0x7c, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, + 0x02, 0x41, 0x09, 0x49, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x20, 0x00, + 0x6b, 0x41, 0x03, 0x71, 0x22, 0x04, 0x6a, 0x22, 0x05, 0x20, 0x01, 0x41, + 0xff, 0x01, 0x71, 0x41, 0x81, 0x82, 0x84, 0x08, 0x6c, 0x22, 0x03, 0x36, + 0x02, 0x00, 0x20, 0x05, 0x20, 0x02, 0x20, 0x04, 0x6b, 0x41, 0x3c, 0x71, + 0x22, 0x01, 0x6a, 0x22, 0x02, 0x41, 0x7c, 0x6a, 0x20, 0x03, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x41, 0x09, 0x49, 0x0d, 0x00, 0x20, 0x05, 0x20, 0x03, + 0x36, 0x02, 0x08, 0x20, 0x05, 0x20, 0x03, 0x36, 0x02, 0x04, 0x20, 0x02, + 0x41, 0x78, 0x6a, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x74, + 0x6a, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x19, 0x49, 0x0d, + 0x00, 0x20, 0x05, 0x20, 0x03, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, 0x03, + 0x36, 0x02, 0x14, 0x20, 0x05, 0x20, 0x03, 0x36, 0x02, 0x10, 0x20, 0x05, + 0x20, 0x03, 0x36, 0x02, 0x0c, 0x20, 0x02, 0x41, 0x70, 0x6a, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x6c, 0x6a, 0x20, 0x03, 0x36, 0x02, + 0x00, 0x20, 0x02, 0x41, 0x68, 0x6a, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, + 0x02, 0x41, 0x64, 0x6a, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x01, 0x20, + 0x05, 0x41, 0x04, 0x71, 0x41, 0x18, 0x72, 0x22, 0x02, 0x6b, 0x22, 0x01, + 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, 0x03, 0xad, 0x42, 0x81, 0x80, 0x80, + 0x80, 0x10, 0x7e, 0x21, 0x06, 0x20, 0x05, 0x20, 0x02, 0x6a, 0x21, 0x02, + 0x03, 0x40, 0x20, 0x02, 0x20, 0x06, 0x37, 0x03, 0x18, 0x20, 0x02, 0x20, + 0x06, 0x37, 0x03, 0x10, 0x20, 0x02, 0x20, 0x06, 0x37, 0x03, 0x08, 0x20, + 0x02, 0x20, 0x06, 0x37, 0x03, 0x00, 0x20, 0x02, 0x41, 0x20, 0x6a, 0x21, + 0x02, 0x20, 0x01, 0x41, 0x60, 0x6a, 0x22, 0x01, 0x41, 0x1f, 0x4b, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x0b, 0xcf, 0x01, 0x01, 0x03, 0x7f, 0x20, + 0x00, 0x21, 0x01, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x0d, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x6b, 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, + 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x22, 0x01, 0x41, + 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, + 0x01, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, + 0x0d, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x0d, 0x01, 0x20, 0x00, + 0x41, 0x04, 0x6a, 0x22, 0x01, 0x41, 0x03, 0x71, 0x0d, 0x01, 0x0b, 0x20, + 0x01, 0x41, 0x7c, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x41, 0x7b, 0x6a, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x41, 0x80, + 0x82, 0x84, 0x08, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x22, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x6b, 0x20, 0x03, 0x72, 0x41, 0x80, 0x81, 0x82, 0x84, + 0x78, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x46, 0x0d, 0x00, 0x0b, + 0x03, 0x40, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x2d, + 0x00, 0x00, 0x21, 0x03, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x20, + 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0b, 0x44, + 0x00, 0x02, 0x40, 0x20, 0x00, 0x41, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, + 0x20, 0x00, 0x41, 0x08, 0x76, 0x41, 0x80, 0x80, 0x84, 0x80, 0x00, 0x6a, + 0x2d, 0x00, 0x00, 0x41, 0x05, 0x74, 0x20, 0x00, 0x41, 0x03, 0x76, 0x41, + 0x1f, 0x71, 0x72, 0x41, 0x80, 0x80, 0x84, 0x80, 0x00, 0x6a, 0x2d, 0x00, + 0x00, 0x20, 0x00, 0x41, 0x07, 0x71, 0x76, 0x41, 0x01, 0x71, 0x0f, 0x0b, + 0x20, 0x00, 0x41, 0xfe, 0xff, 0x0b, 0x49, 0x0b, 0x49, 0x01, 0x03, 0x7f, + 0x41, 0x00, 0x21, 0x03, 0x02, 0x40, 0x20, 0x02, 0x45, 0x0d, 0x00, 0x02, + 0x40, 0x03, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x22, 0x04, 0x20, 0x01, + 0x2d, 0x00, 0x00, 0x22, 0x05, 0x47, 0x0d, 0x01, 0x20, 0x01, 0x41, 0x01, + 0x6a, 0x21, 0x01, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x00, 0x20, 0x02, + 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0c, 0x02, 0x0b, 0x0b, 0x20, + 0x04, 0x20, 0x05, 0x6b, 0x21, 0x03, 0x0b, 0x20, 0x03, 0x0b, 0xf6, 0x02, + 0x01, 0x03, 0x7f, 0x20, 0x02, 0x41, 0x00, 0x47, 0x21, 0x03, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x71, 0x45, + 0x0d, 0x00, 0x20, 0x02, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x2d, + 0x00, 0x00, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x47, 0x0d, 0x00, 0x20, + 0x00, 0x21, 0x04, 0x20, 0x02, 0x21, 0x05, 0x0c, 0x03, 0x0b, 0x20, 0x02, + 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x41, 0x00, 0x47, 0x21, 0x03, 0x20, 0x00, + 0x41, 0x01, 0x6a, 0x22, 0x04, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x01, 0x20, + 0x05, 0x45, 0x0d, 0x01, 0x20, 0x04, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, + 0xff, 0x01, 0x71, 0x46, 0x0d, 0x02, 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x22, + 0x05, 0x41, 0x00, 0x47, 0x21, 0x03, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x22, + 0x04, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x01, 0x20, 0x05, 0x45, 0x0d, 0x01, + 0x20, 0x04, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x46, + 0x0d, 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x22, 0x05, 0x41, 0x00, 0x47, + 0x21, 0x03, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x22, 0x04, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x01, 0x20, 0x05, 0x45, 0x0d, 0x01, 0x20, 0x04, 0x2d, 0x00, + 0x00, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x46, 0x0d, 0x02, 0x20, 0x00, + 0x41, 0x04, 0x6a, 0x21, 0x04, 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x22, 0x05, + 0x41, 0x00, 0x47, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x21, 0x05, + 0x20, 0x00, 0x21, 0x04, 0x0b, 0x20, 0x03, 0x45, 0x0d, 0x01, 0x02, 0x40, + 0x20, 0x04, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x46, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x04, 0x49, 0x0d, 0x00, 0x20, 0x01, 0x41, + 0xff, 0x01, 0x71, 0x41, 0x81, 0x82, 0x84, 0x08, 0x6c, 0x21, 0x00, 0x03, + 0x40, 0x41, 0x80, 0x82, 0x84, 0x08, 0x20, 0x04, 0x28, 0x02, 0x00, 0x20, + 0x00, 0x73, 0x22, 0x02, 0x6b, 0x20, 0x02, 0x72, 0x41, 0x80, 0x81, 0x82, + 0x84, 0x78, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x47, 0x0d, 0x02, + 0x20, 0x04, 0x41, 0x04, 0x6a, 0x21, 0x04, 0x20, 0x05, 0x41, 0x7c, 0x6a, + 0x22, 0x05, 0x41, 0x03, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x05, 0x45, + 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x21, 0x02, 0x03, + 0x40, 0x02, 0x40, 0x20, 0x04, 0x2d, 0x00, 0x00, 0x20, 0x02, 0x47, 0x0d, + 0x00, 0x20, 0x04, 0x0f, 0x0b, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x21, 0x04, + 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x0d, 0x00, 0x0b, 0x0b, 0x41, + 0x00, 0x0b, 0x67, 0x01, 0x02, 0x7f, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x21, + 0x02, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x22, 0x03, 0x45, 0x0d, + 0x00, 0x20, 0x03, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, 0x47, 0x0d, 0x00, + 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a, + 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x21, 0x02, 0x20, + 0x00, 0x2d, 0x00, 0x00, 0x22, 0x03, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, + 0x01, 0x6a, 0x21, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, + 0x03, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, 0x46, 0x0d, 0x00, 0x0b, 0x0b, + 0x20, 0x03, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, 0x6b, 0x0b, 0x0c, 0x00, + 0x20, 0x00, 0x41, 0x00, 0x10, 0x9b, 0x80, 0x80, 0x80, 0x00, 0x0b, 0xb4, + 0x02, 0x01, 0x07, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x41, 0xff, 0xff, 0x07, + 0x4b, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x41, 0xff, 0x01, 0x71, 0x22, + 0x02, 0x41, 0x03, 0x6e, 0x22, 0x03, 0x41, 0x03, 0x6c, 0x6b, 0x41, 0xff, + 0x01, 0x71, 0x41, 0x02, 0x74, 0x41, 0xc0, 0x9e, 0x84, 0x80, 0x00, 0x6a, + 0x28, 0x02, 0x00, 0x20, 0x00, 0x41, 0x08, 0x76, 0x22, 0x04, 0x41, 0xa0, + 0xa9, 0x84, 0x80, 0x00, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0xd6, 0x00, 0x6c, + 0x20, 0x03, 0x6a, 0x41, 0xa0, 0xa9, 0x84, 0x80, 0x00, 0x6a, 0x2d, 0x00, + 0x00, 0x6c, 0x41, 0x0b, 0x76, 0x41, 0x06, 0x70, 0x20, 0x04, 0x41, 0x90, + 0xbe, 0x84, 0x80, 0x00, 0x6a, 0x2d, 0x00, 0x00, 0x6a, 0x41, 0x02, 0x74, + 0x41, 0xd0, 0x9e, 0x84, 0x80, 0x00, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x03, + 0x41, 0x08, 0x75, 0x21, 0x04, 0x02, 0x40, 0x20, 0x03, 0x41, 0xff, 0x01, + 0x71, 0x22, 0x03, 0x41, 0x01, 0x4b, 0x0d, 0x00, 0x20, 0x04, 0x41, 0x00, + 0x20, 0x03, 0x20, 0x01, 0x73, 0x6b, 0x71, 0x20, 0x00, 0x6a, 0x0f, 0x0b, + 0x20, 0x04, 0x41, 0xff, 0x01, 0x71, 0x22, 0x03, 0x45, 0x0d, 0x00, 0x20, + 0x04, 0x41, 0x08, 0x76, 0x21, 0x04, 0x03, 0x40, 0x02, 0x40, 0x20, 0x02, + 0x20, 0x03, 0x41, 0x01, 0x76, 0x22, 0x05, 0x20, 0x04, 0x6a, 0x22, 0x06, + 0x41, 0x01, 0x74, 0x41, 0x90, 0xa6, 0x84, 0x80, 0x00, 0x6a, 0x22, 0x07, + 0x2d, 0x00, 0x00, 0x22, 0x08, 0x47, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x07, + 0x2d, 0x00, 0x01, 0x41, 0x02, 0x74, 0x41, 0xd0, 0x9e, 0x84, 0x80, 0x00, + 0x6a, 0x28, 0x02, 0x00, 0x22, 0x03, 0x41, 0xff, 0x01, 0x71, 0x22, 0x04, + 0x41, 0x01, 0x4b, 0x0d, 0x00, 0x20, 0x03, 0x41, 0x08, 0x75, 0x41, 0x00, + 0x20, 0x04, 0x20, 0x01, 0x73, 0x6b, 0x71, 0x20, 0x00, 0x6a, 0x0f, 0x0b, + 0x41, 0x7f, 0x41, 0x01, 0x20, 0x01, 0x1b, 0x20, 0x00, 0x6a, 0x0f, 0x0b, + 0x20, 0x04, 0x20, 0x06, 0x20, 0x02, 0x20, 0x08, 0x49, 0x22, 0x08, 0x1b, + 0x21, 0x04, 0x20, 0x05, 0x20, 0x03, 0x20, 0x05, 0x6b, 0x20, 0x08, 0x1b, + 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x0b, 0x0c, 0x00, 0x20, + 0x00, 0x41, 0x01, 0x10, 0x9b, 0x80, 0x80, 0x80, 0x00, 0x0b, 0x87, 0x01, + 0x01, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x02, 0x0d, 0x00, 0x41, 0x00, 0x0f, + 0x0b, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x22, 0x03, + 0x0d, 0x00, 0x41, 0x00, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x41, + 0x01, 0x6a, 0x21, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, 0x02, 0x02, + 0x40, 0x03, 0x40, 0x20, 0x03, 0x41, 0xff, 0x01, 0x71, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x22, 0x04, 0x47, 0x0d, 0x01, 0x20, 0x04, 0x45, 0x0d, 0x01, + 0x20, 0x02, 0x41, 0x00, 0x46, 0x0d, 0x01, 0x20, 0x02, 0x41, 0x7f, 0x6a, + 0x21, 0x02, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x00, 0x2d, + 0x00, 0x00, 0x21, 0x03, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x00, 0x20, + 0x03, 0x0d, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x03, 0x0b, 0x20, 0x03, 0x41, + 0xff, 0x01, 0x71, 0x21, 0x03, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x6b, 0x0b, 0x0d, 0x00, 0x20, 0x00, 0x10, 0x9a, 0x80, 0x80, 0x80, + 0x00, 0x20, 0x00, 0x47, 0x0b, 0xbf, 0x09, 0x01, 0x04, 0x7f, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x21, 0x4f, 0x0d, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x46, 0x0d, 0x02, 0x20, 0x01, 0x20, 0x00, 0x20, 0x02, + 0x6a, 0x22, 0x03, 0x6b, 0x41, 0x00, 0x20, 0x02, 0x41, 0x01, 0x74, 0x6b, + 0x4b, 0x0d, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0xfc, 0x0a, + 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x73, 0x41, 0x03, + 0x71, 0x21, 0x04, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x20, + 0x01, 0x4f, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x04, 0x45, 0x0d, 0x00, 0x20, + 0x02, 0x21, 0x05, 0x20, 0x00, 0x21, 0x03, 0x0c, 0x03, 0x0b, 0x02, 0x40, + 0x20, 0x00, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x20, 0x02, 0x21, 0x05, 0x20, + 0x00, 0x21, 0x03, 0x0c, 0x02, 0x0b, 0x20, 0x02, 0x45, 0x0d, 0x03, 0x20, + 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, + 0x7f, 0x6a, 0x21, 0x05, 0x02, 0x40, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, + 0x03, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, + 0x01, 0x0c, 0x02, 0x0b, 0x20, 0x05, 0x45, 0x0d, 0x03, 0x20, 0x00, 0x20, + 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x02, 0x41, 0x7e, 0x6a, + 0x21, 0x05, 0x02, 0x40, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x22, 0x03, 0x41, + 0x03, 0x71, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x0c, + 0x02, 0x0b, 0x20, 0x05, 0x45, 0x0d, 0x03, 0x20, 0x00, 0x20, 0x01, 0x2d, + 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x21, 0x05, + 0x02, 0x40, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x22, 0x03, 0x41, 0x03, 0x71, + 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x21, 0x01, 0x0c, 0x02, 0x0b, + 0x20, 0x05, 0x45, 0x0d, 0x03, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x03, + 0x3a, 0x00, 0x03, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x01, + 0x41, 0x04, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x21, 0x05, + 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x04, 0x0d, 0x00, 0x02, 0x40, 0x20, + 0x03, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x02, 0x45, 0x0d, 0x04, + 0x20, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x03, 0x6a, 0x22, 0x04, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x02, + 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, + 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x45, 0x0d, 0x04, 0x20, 0x00, 0x20, 0x02, + 0x41, 0x7e, 0x6a, 0x22, 0x03, 0x6a, 0x22, 0x04, 0x20, 0x01, 0x20, 0x03, + 0x6a, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x40, 0x20, 0x04, 0x41, + 0x03, 0x71, 0x0d, 0x00, 0x20, 0x03, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, + 0x03, 0x45, 0x0d, 0x04, 0x20, 0x00, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x22, + 0x03, 0x6a, 0x22, 0x04, 0x20, 0x01, 0x20, 0x03, 0x6a, 0x2d, 0x00, 0x00, + 0x3a, 0x00, 0x00, 0x02, 0x40, 0x20, 0x04, 0x41, 0x03, 0x71, 0x0d, 0x00, + 0x20, 0x03, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x45, 0x0d, 0x04, + 0x20, 0x00, 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x22, 0x02, 0x6a, 0x20, 0x01, + 0x20, 0x02, 0x6a, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x02, + 0x41, 0x04, 0x49, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x02, 0x41, 0x7c, 0x6a, + 0x22, 0x06, 0x41, 0x02, 0x76, 0x41, 0x01, 0x6a, 0x41, 0x03, 0x71, 0x22, + 0x03, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, 0x04, 0x20, + 0x00, 0x41, 0x7c, 0x6a, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x20, 0x02, + 0x6a, 0x20, 0x04, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x21, 0x02, 0x20, 0x03, 0x41, 0x7f, 0x6a, + 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x41, 0x0c, 0x49, 0x0d, + 0x00, 0x20, 0x01, 0x41, 0x70, 0x6a, 0x21, 0x05, 0x20, 0x00, 0x41, 0x70, + 0x6a, 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x02, 0x6a, 0x22, 0x03, + 0x41, 0x0c, 0x6a, 0x20, 0x05, 0x20, 0x02, 0x6a, 0x22, 0x04, 0x41, 0x0c, + 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x08, 0x6a, + 0x20, 0x04, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x41, 0x04, 0x6a, 0x20, 0x04, 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x04, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x02, 0x41, 0x70, 0x6a, 0x22, 0x02, 0x41, 0x03, 0x4b, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x45, 0x0d, 0x02, 0x20, 0x02, 0x21, 0x03, + 0x02, 0x40, 0x20, 0x02, 0x41, 0x03, 0x71, 0x22, 0x04, 0x45, 0x0d, 0x00, + 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, 0x05, 0x20, 0x00, 0x41, 0x7f, 0x6a, + 0x21, 0x06, 0x20, 0x02, 0x21, 0x03, 0x03, 0x40, 0x20, 0x06, 0x20, 0x03, + 0x6a, 0x20, 0x05, 0x20, 0x03, 0x6a, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, + 0x20, 0x03, 0x41, 0x7f, 0x6a, 0x21, 0x03, 0x20, 0x04, 0x41, 0x7f, 0x6a, + 0x22, 0x04, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x41, 0x04, 0x49, 0x0d, + 0x02, 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, 0x04, 0x20, 0x00, 0x41, 0x7c, + 0x6a, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x20, 0x03, 0x6a, 0x22, 0x01, + 0x41, 0x03, 0x6a, 0x20, 0x04, 0x20, 0x03, 0x6a, 0x22, 0x02, 0x41, 0x03, + 0x6a, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x01, 0x41, 0x02, 0x6a, + 0x20, 0x02, 0x41, 0x02, 0x6a, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, + 0x01, 0x41, 0x01, 0x6a, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x2d, 0x00, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x01, 0x20, 0x02, 0x2d, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x20, 0x03, 0x41, 0x7c, 0x6a, 0x22, 0x03, 0x0d, 0x00, 0x0c, 0x03, + 0x0b, 0x0b, 0x20, 0x05, 0x41, 0x04, 0x49, 0x0d, 0x00, 0x02, 0x40, 0x20, + 0x05, 0x41, 0x7c, 0x6a, 0x22, 0x04, 0x41, 0x02, 0x76, 0x41, 0x01, 0x6a, + 0x41, 0x07, 0x71, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x20, 0x02, + 0x41, 0x02, 0x74, 0x6b, 0x21, 0x05, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, + 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, + 0x01, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x02, 0x41, 0x7f, + 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x04, 0x41, 0x1c, 0x49, + 0x0d, 0x00, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x04, 0x36, 0x02, 0x04, + 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x08, 0x36, 0x02, 0x08, 0x20, 0x03, + 0x20, 0x01, 0x28, 0x02, 0x0c, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x01, + 0x28, 0x02, 0x10, 0x36, 0x02, 0x10, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, + 0x14, 0x36, 0x02, 0x14, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x18, 0x36, + 0x02, 0x18, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x1c, 0x36, 0x02, 0x1c, + 0x20, 0x01, 0x41, 0x20, 0x6a, 0x21, 0x01, 0x20, 0x03, 0x41, 0x20, 0x6a, + 0x21, 0x03, 0x20, 0x05, 0x41, 0x60, 0x6a, 0x22, 0x05, 0x41, 0x03, 0x4b, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x05, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x02, + 0x40, 0x20, 0x05, 0x41, 0x07, 0x71, 0x22, 0x02, 0x0d, 0x00, 0x20, 0x05, + 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x41, 0x78, 0x71, 0x21, 0x04, + 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, + 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x01, 0x6a, + 0x21, 0x01, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0b, + 0x0b, 0x20, 0x05, 0x41, 0x08, 0x49, 0x0d, 0x00, 0x03, 0x40, 0x20, 0x03, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, + 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, + 0x02, 0x3a, 0x00, 0x02, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, + 0x00, 0x03, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x04, 0x3a, 0x00, 0x04, + 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x05, 0x3a, 0x00, 0x05, 0x20, 0x03, + 0x20, 0x01, 0x2d, 0x00, 0x06, 0x3a, 0x00, 0x06, 0x20, 0x03, 0x20, 0x01, + 0x2d, 0x00, 0x07, 0x3a, 0x00, 0x07, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x21, + 0x03, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x41, 0x78, + 0x6a, 0x22, 0x04, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x0b, 0x0d, 0x00, + 0x20, 0x00, 0x10, 0x9c, 0x80, 0x80, 0x80, 0x00, 0x20, 0x00, 0x47, 0x0b, + 0x0d, 0x00, 0x20, 0x00, 0x41, 0x20, 0x46, 0x20, 0x00, 0x41, 0x09, 0x46, + 0x72, 0x0b, 0x0a, 0x00, 0x20, 0x00, 0x10, 0xa1, 0x80, 0x80, 0x80, 0x00, + 0x0b, 0x0a, 0x00, 0x20, 0x00, 0x41, 0x50, 0x6a, 0x41, 0x0a, 0x49, 0x0b, + 0x4d, 0x01, 0x02, 0x7f, 0x20, 0x00, 0x20, 0x00, 0x10, 0x95, 0x80, 0x80, + 0x80, 0x00, 0x6a, 0x21, 0x03, 0x02, 0x40, 0x20, 0x02, 0x45, 0x0d, 0x00, + 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x22, 0x04, 0x45, 0x0d, 0x01, + 0x20, 0x03, 0x20, 0x04, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x41, 0x01, 0x6a, + 0x21, 0x03, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, + 0x7f, 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x41, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x00, 0x0b, 0xf3, 0x03, 0x01, 0x04, 0x7f, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x20, + 0x00, 0x73, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x21, 0x03, + 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x41, 0x00, 0x47, 0x21, 0x04, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x01, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x20, 0x00, 0x21, + 0x03, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x0d, 0x00, 0x20, 0x00, + 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x2d, 0x00, 0x00, + 0x22, 0x03, 0x3a, 0x00, 0x00, 0x02, 0x40, 0x20, 0x03, 0x0d, 0x00, 0x20, + 0x00, 0x21, 0x03, 0x20, 0x02, 0x21, 0x05, 0x0c, 0x05, 0x0b, 0x20, 0x00, + 0x41, 0x01, 0x6a, 0x21, 0x03, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x05, + 0x41, 0x00, 0x47, 0x21, 0x04, 0x02, 0x40, 0x20, 0x01, 0x41, 0x01, 0x6a, + 0x22, 0x06, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x45, 0x0d, + 0x00, 0x20, 0x03, 0x20, 0x06, 0x2d, 0x00, 0x00, 0x22, 0x04, 0x3a, 0x00, + 0x00, 0x20, 0x04, 0x45, 0x0d, 0x05, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x21, + 0x03, 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x22, 0x05, 0x41, 0x00, 0x47, 0x21, + 0x04, 0x02, 0x40, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x22, 0x06, 0x41, 0x03, + 0x71, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x45, 0x0d, 0x00, 0x20, 0x03, 0x20, + 0x06, 0x2d, 0x00, 0x00, 0x22, 0x04, 0x3a, 0x00, 0x00, 0x20, 0x04, 0x45, + 0x0d, 0x06, 0x20, 0x00, 0x41, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x02, 0x41, + 0x7d, 0x6a, 0x22, 0x05, 0x41, 0x00, 0x47, 0x21, 0x04, 0x02, 0x40, 0x20, + 0x01, 0x41, 0x03, 0x6a, 0x22, 0x06, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, + 0x20, 0x05, 0x45, 0x0d, 0x00, 0x20, 0x03, 0x20, 0x06, 0x2d, 0x00, 0x00, + 0x22, 0x04, 0x3a, 0x00, 0x00, 0x20, 0x04, 0x45, 0x0d, 0x07, 0x20, 0x00, + 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, + 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x22, 0x02, 0x41, 0x00, 0x47, 0x21, 0x04, + 0x0c, 0x03, 0x0b, 0x20, 0x06, 0x21, 0x01, 0x20, 0x05, 0x21, 0x02, 0x0c, + 0x02, 0x0b, 0x20, 0x06, 0x21, 0x01, 0x20, 0x05, 0x21, 0x02, 0x0c, 0x01, + 0x0b, 0x20, 0x06, 0x21, 0x01, 0x20, 0x05, 0x21, 0x02, 0x0b, 0x20, 0x04, + 0x45, 0x0d, 0x02, 0x02, 0x40, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x0d, 0x00, + 0x20, 0x02, 0x21, 0x05, 0x0c, 0x04, 0x0b, 0x20, 0x02, 0x41, 0x04, 0x49, + 0x0d, 0x00, 0x03, 0x40, 0x41, 0x80, 0x82, 0x84, 0x08, 0x20, 0x01, 0x28, + 0x02, 0x00, 0x22, 0x00, 0x6b, 0x20, 0x00, 0x72, 0x41, 0x80, 0x81, 0x82, + 0x84, 0x78, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, 0x47, 0x0d, 0x02, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, 0x6a, + 0x21, 0x03, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, + 0x7c, 0x6a, 0x22, 0x02, 0x41, 0x03, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, + 0x02, 0x45, 0x0d, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x22, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x40, 0x20, 0x00, 0x0d, + 0x00, 0x20, 0x02, 0x21, 0x05, 0x0c, 0x03, 0x0b, 0x20, 0x03, 0x41, 0x01, + 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, + 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, 0x21, + 0x05, 0x0b, 0x20, 0x03, 0x41, 0x00, 0x20, 0x05, 0x10, 0x94, 0x80, 0x80, + 0x80, 0x00, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0xa5, 0x80, 0x80, 0x80, 0x00, 0x1a, 0x20, 0x00, 0x0b, 0x17, 0x00, 0x20, + 0x00, 0x41, 0x50, 0x6a, 0x41, 0x0a, 0x49, 0x20, 0x00, 0x41, 0x20, 0x72, + 0x41, 0x9f, 0x7f, 0x6a, 0x41, 0x06, 0x49, 0x72, 0x0b, 0x2a, 0x01, 0x03, + 0x7f, 0x41, 0x00, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x6a, + 0x21, 0x02, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x22, 0x03, 0x21, 0x01, 0x20, + 0x02, 0x28, 0x02, 0x00, 0x0d, 0x00, 0x0b, 0x20, 0x03, 0x41, 0x7c, 0x6a, + 0x41, 0x02, 0x75, 0x0b, 0x45, 0x01, 0x01, 0x7f, 0x02, 0x40, 0x20, 0x01, + 0x45, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7c, 0x6a, 0x21, 0x00, 0x02, 0x40, + 0x03, 0x40, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x22, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x02, 0x20, 0x01, 0x47, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x00, 0x41, 0x00, 0x20, 0x02, 0x1b, 0x0f, 0x0b, 0x20, + 0x00, 0x20, 0x00, 0x10, 0xa8, 0x80, 0x80, 0x80, 0x00, 0x41, 0x02, 0x74, + 0x6a, 0x0b, 0x1d, 0x00, 0x02, 0x40, 0x20, 0x00, 0x0d, 0x00, 0x41, 0x00, + 0x0f, 0x0b, 0x41, 0x90, 0xc2, 0x84, 0x80, 0x00, 0x20, 0x00, 0x10, 0xa9, + 0x80, 0x80, 0x80, 0x00, 0x41, 0x00, 0x47, 0x0b, 0x24, 0x01, 0x01, 0x7f, + 0x41, 0x01, 0x21, 0x01, 0x02, 0x40, 0x20, 0x00, 0x41, 0x50, 0x6a, 0x41, + 0x0a, 0x49, 0x0d, 0x00, 0x20, 0x00, 0x10, 0x96, 0x80, 0x80, 0x80, 0x00, + 0x41, 0x00, 0x47, 0x21, 0x01, 0x0b, 0x20, 0x01, 0x0b, 0x0b, 0xf1, 0x42, + 0x01, 0x00, 0x41, 0x80, 0x80, 0x04, 0x0b, 0xe8, 0x42, 0x12, 0x11, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x11, 0x22, 0x23, 0x24, 0x11, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x11, 0x2d, 0x2e, 0x2f, 0x10, 0x10, 0x30, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x31, 0x32, 0x33, 0x10, 0x34, 0x35, 0x10, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x36, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x37, 0x11, 0x11, 0x11, 0x11, 0x38, 0x11, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x3f, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x40, 0x41, 0x11, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x11, 0x4b, 0x4c, 0x4d, 0x4e, + 0x4f, 0x50, 0x51, 0x10, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x5b, 0x5c, 0x5d, 0x10, 0x5e, 0x5f, 0x60, 0x10, 0x11, 0x11, 0x11, + 0x61, 0x62, 0x63, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x11, 0x11, 0x11, 0x11, 0x64, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x65, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x66, + 0x67, 0x10, 0x10, 0x68, 0x69, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x6a, 0x11, 0x11, 0x6b, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x6c, 0x6d, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6e, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x6f, 0x70, 0x71, + 0x72, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x73, 0x74, 0x75, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x76, 0x77, 0x10, 0x10, 0x10, 0x10, 0x78, + 0x10, 0x10, 0x79, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0xfe, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x04, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0x03, 0x00, 0x1f, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xdf, 0xbc, 0x40, 0xd7, 0xff, 0xff, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0x7f, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xbf, 0xb6, 0x00, 0xff, 0xff, 0xff, 0x87, 0x07, + 0x00, 0x00, 0x00, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0x1f, 0xfe, 0xe1, 0xff, 0x9f, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x30, 0x04, 0xff, 0xff, 0xff, 0xfc, 0xff, 0x1f, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x01, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xdf, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xf8, 0x03, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xdf, 0xe1, + 0xff, 0xcf, 0xff, 0xfe, 0xff, 0xef, 0x9f, 0xf9, 0xff, 0xff, 0xfd, 0xc5, + 0xe3, 0x9f, 0x59, 0x80, 0xb0, 0xcf, 0xff, 0x03, 0x10, 0xee, 0x87, 0xf9, + 0xff, 0xff, 0xfd, 0x6d, 0xc3, 0x87, 0x19, 0x02, 0x5e, 0xc0, 0xff, 0x3f, + 0x00, 0xee, 0xbf, 0xfb, 0xff, 0xff, 0xfd, 0xed, 0xe3, 0xbf, 0x1b, 0x01, + 0x00, 0xcf, 0xff, 0x00, 0x1e, 0xee, 0x9f, 0xf9, 0xff, 0xff, 0xfd, 0xed, + 0xe3, 0x9f, 0x19, 0xc0, 0xb0, 0xcf, 0xff, 0x02, 0x00, 0xec, 0xc7, 0x3d, + 0xd6, 0x18, 0xc7, 0xff, 0xc3, 0xc7, 0x1d, 0x81, 0x00, 0xc0, 0xff, 0x00, + 0x00, 0xef, 0xdf, 0xfd, 0xff, 0xff, 0xfd, 0xff, 0xe3, 0xdf, 0x1d, 0x60, + 0x07, 0xcf, 0xff, 0x00, 0x00, 0xef, 0xdf, 0xfd, 0xff, 0xff, 0xfd, 0xef, + 0xe3, 0xdf, 0x1d, 0x60, 0x40, 0xcf, 0xff, 0x06, 0x00, 0xef, 0xdf, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xe7, 0xdf, 0x5d, 0xf0, 0x80, 0xcf, 0xff, 0x00, + 0xfc, 0xec, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xfb, 0x2f, 0x7f, 0x80, 0x5f, + 0xff, 0xc0, 0xff, 0x0c, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0x07, 0x3f, 0x20, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf7, 0xff, + 0xff, 0xaf, 0xff, 0xff, 0x3b, 0x5f, 0x20, 0xff, 0xf3, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0x1f, 0xfe, 0xff, 0x03, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xf9, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x20, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3d, 0x7f, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xff, + 0xff, 0xff, 0xff, 0x3d, 0x7f, 0x3d, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfe, 0xff, 0xff, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, + 0x01, 0xff, 0xdf, 0x0f, 0x00, 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x0f, + 0x00, 0xff, 0xdf, 0x0d, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, + 0xff, 0xff, 0x01, 0x80, 0x10, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x0f, 0xff, + 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x1f, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x03, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0xff, 0x03, 0xff, 0x03, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0x0f, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x6f, + 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x3f, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0xff, 0xaa, 0xff, 0xff, 0xff, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x5f, 0xdc, 0x1f, 0xcf, + 0x0f, 0xff, 0x1f, 0xdc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x84, 0xfc, 0x2f, 0x3e, 0x50, 0xbd, 0xff, 0xf3, 0xe0, 0x43, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x78, 0x0c, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x80, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x3e, + 0x1f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x1f, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf0, + 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x2f, 0x00, 0xff, 0x03, 0x00, 0x00, 0xfc, 0xe8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0xff, + 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0x00, 0x80, 0xff, + 0x03, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0xff, 0x3f, 0xff, 0x03, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x05, 0x00, 0x00, 0x38, 0xff, 0xff, 0x3c, + 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x7f, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0x00, 0xf8, 0xe0, 0xff, 0xfd, 0x7f, 0x5f, 0xdb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0xff, 0x03, 0xfe, 0xff, 0xff, 0x07, 0xfe, 0xff, 0xff, + 0x07, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfc, 0xfc, 0xfc, 0x1c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xef, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xb7, 0xff, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x3f, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0x91, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x37, + 0x00, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xf0, 0xef, + 0xfe, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x80, 0x00, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc7, 0xff, 0x70, 0x00, 0xff, 0xff, 0xff, 0xff, 0x47, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0xff, + 0x17, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0x9f, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xbd, 0xff, + 0xbf, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, + 0x03, 0xef, 0x9f, 0xf9, 0xff, 0xff, 0xfd, 0xed, 0xe3, 0x9f, 0x19, 0x81, + 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x07, 0xff, 0x83, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb3, 0x00, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x7f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x11, 0x00, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x01, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xe7, 0xff, 0x07, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1a, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe7, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x7f, 0x01, 0x00, 0xff, 0x03, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xb4, 0xcb, 0x00, 0xff, + 0x03, 0xbf, 0xfd, 0xff, 0xff, 0xff, 0x7f, 0x7b, 0x01, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x0f, 0x00, 0xff, 0x03, 0xf8, 0xff, 0xff, 0xe0, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xf0, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0xff, 0x1f, 0xff, 0x01, 0xff, 0x43, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdf, 0x64, 0xde, 0xff, 0xeb, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xe7, 0xdf, 0xdf, 0xff, 0xff, 0xff, + 0x7b, 0x5f, 0xfc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, + 0xff, 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xdf, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xf7, 0xcf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xf9, 0xdb, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x80, 0x3f, 0xff, 0x43, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0x08, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xff, + 0xff, 0x96, 0xfe, 0xf7, 0x0a, 0x84, 0xea, 0x96, 0xaa, 0x96, 0xf7, 0xf7, + 0x5e, 0xff, 0xfb, 0xff, 0x0f, 0xee, 0xfb, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x39, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0x00, 0xbf, 0x1d, 0x00, 0x00, 0xe7, 0x02, + 0x00, 0x00, 0x79, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x39, 0xff, 0xff, 0x00, 0x18, 0xff, + 0xff, 0x01, 0x87, 0xff, 0xff, 0x00, 0xd4, 0xfe, 0xff, 0x00, 0xc3, 0x00, + 0x00, 0x01, 0xd2, 0x00, 0x00, 0x01, 0xce, 0x00, 0x00, 0x01, 0xcd, 0x00, + 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, 0xca, 0x00, 0x00, 0x01, 0xcb, 0x00, + 0x00, 0x01, 0xcf, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x01, 0xd3, 0x00, + 0x00, 0x01, 0xd1, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x01, 0xd5, 0x00, + 0x00, 0x00, 0x82, 0x00, 0x00, 0x01, 0xd6, 0x00, 0x00, 0x01, 0xda, 0x00, + 0x00, 0x01, 0xd9, 0x00, 0x00, 0x01, 0xdb, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xff, 0xff, 0x01, 0x9f, 0xff, + 0xff, 0x01, 0xc8, 0xff, 0xff, 0x02, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x33, 0xff, + 0xff, 0x00, 0x26, 0xff, 0xff, 0x01, 0x7e, 0xff, 0xff, 0x01, 0x2b, 0x2a, + 0x00, 0x01, 0x5d, 0xff, 0xff, 0x01, 0x28, 0x2a, 0x00, 0x00, 0x3f, 0x2a, + 0x00, 0x01, 0x3d, 0xff, 0xff, 0x01, 0x45, 0x00, 0x00, 0x01, 0x47, 0x00, + 0x00, 0x00, 0x1f, 0x2a, 0x00, 0x00, 0x1c, 0x2a, 0x00, 0x00, 0x1e, 0x2a, + 0x00, 0x00, 0x2e, 0xff, 0xff, 0x00, 0x32, 0xff, 0xff, 0x00, 0x36, 0xff, + 0xff, 0x00, 0x35, 0xff, 0xff, 0x00, 0x4f, 0xa5, 0x00, 0x00, 0x4b, 0xa5, + 0x00, 0x00, 0x31, 0xff, 0xff, 0x00, 0x28, 0xa5, 0x00, 0x00, 0x44, 0xa5, + 0x00, 0x00, 0x2f, 0xff, 0xff, 0x00, 0x2d, 0xff, 0xff, 0x00, 0xf7, 0x29, + 0x00, 0x00, 0x41, 0xa5, 0x00, 0x00, 0xfd, 0x29, 0x00, 0x00, 0x2b, 0xff, + 0xff, 0x00, 0x2a, 0xff, 0xff, 0x00, 0xe7, 0x29, 0x00, 0x00, 0x43, 0xa5, + 0x00, 0x00, 0x2a, 0xa5, 0x00, 0x00, 0xbb, 0xff, 0xff, 0x00, 0x27, 0xff, + 0xff, 0x00, 0xb9, 0xff, 0xff, 0x00, 0x25, 0xff, 0xff, 0x00, 0x15, 0xa5, + 0x00, 0x00, 0x12, 0xa5, 0x00, 0x02, 0x24, 0x4c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x01, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x54, 0x00, 0x00, 0x01, 0x74, 0x00, + 0x00, 0x01, 0x26, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x01, 0x40, 0x00, + 0x00, 0x01, 0x3f, 0x00, 0x00, 0x00, 0xda, 0xff, 0xff, 0x00, 0xdb, 0xff, + 0xff, 0x00, 0xe1, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x00, 0xc1, 0xff, + 0xff, 0x01, 0x08, 0x00, 0x00, 0x00, 0xc2, 0xff, 0xff, 0x00, 0xc7, 0xff, + 0xff, 0x00, 0xd1, 0xff, 0xff, 0x00, 0xca, 0xff, 0xff, 0x00, 0xf8, 0xff, + 0xff, 0x00, 0xaa, 0xff, 0xff, 0x00, 0xb0, 0xff, 0xff, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x8c, 0xff, 0xff, 0x01, 0xc4, 0xff, 0xff, 0x00, 0xa0, 0xff, + 0xff, 0x01, 0xf9, 0xff, 0xff, 0x02, 0x1a, 0x70, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x01, 0x20, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0x01, 0x50, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x00, 0xf1, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0xd0, 0xff, + 0xff, 0x01, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x0b, 0x00, 0x01, 0x60, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xd0, 0x97, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0x02, 0x05, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0xf4, + 0xff, 0x00, 0x9e, 0xe7, 0xff, 0x00, 0xc2, 0x89, 0x00, 0x00, 0xdb, 0xe7, + 0xff, 0x00, 0x92, 0xe7, 0xff, 0x00, 0x93, 0xe7, 0xff, 0x00, 0x9c, 0xe7, + 0xff, 0x00, 0x9d, 0xe7, 0xff, 0x00, 0xa4, 0xe7, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x8a, 0x00, 0x00, 0x04, 0x8a, 0x00, 0x00, 0xe6, 0x0e, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc5, 0xff, 0xff, 0x01, 0x41, 0xe2, 0xff, 0x02, 0x1d, 0x8f, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x56, 0x00, 0x00, 0x01, 0xaa, 0xff, 0xff, 0x00, 0x4a, 0x00, + 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0xb6, 0xff, + 0xff, 0x01, 0xf7, 0xff, 0xff, 0x00, 0xdb, 0xe3, 0xff, 0x01, 0x9c, 0xff, + 0xff, 0x01, 0x90, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0x01, 0x82, 0xff, + 0xff, 0x02, 0x05, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, + 0x00, 0x00, 0xf0, 0xff, 0xff, 0x01, 0x1c, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x01, 0xa3, 0xe2, 0xff, 0x01, 0x41, 0xdf, 0xff, 0x01, 0xba, 0xdf, + 0xff, 0x00, 0xe4, 0xff, 0xff, 0x02, 0x0b, 0xb1, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x01, 0x30, 0x00, 0x00, 0x00, 0xd0, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0xd6, 0xff, 0x01, 0x1a, 0xf1, + 0xff, 0x01, 0x19, 0xd6, 0xff, 0x00, 0xd5, 0xd5, 0xff, 0x00, 0xd8, 0xd5, + 0xff, 0x01, 0xe4, 0xd5, 0xff, 0x01, 0x03, 0xd6, 0xff, 0x01, 0xe1, 0xd5, + 0xff, 0x01, 0xe2, 0xd5, 0xff, 0x01, 0xc1, 0xd5, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x02, 0x0c, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x01, 0xbc, 0x5a, + 0xff, 0x01, 0xa0, 0x03, 0x00, 0x01, 0xfc, 0x75, 0xff, 0x01, 0xd8, 0x5a, + 0xff, 0x00, 0x30, 0x00, 0x00, 0x01, 0xb1, 0x5a, 0xff, 0x01, 0xb5, 0x5a, + 0xff, 0x01, 0xbf, 0x5a, 0xff, 0x01, 0xee, 0x5a, 0xff, 0x01, 0xd6, 0x5a, + 0xff, 0x01, 0xeb, 0x5a, 0xff, 0x01, 0xd0, 0xff, 0xff, 0x01, 0xbd, 0x5a, + 0xff, 0x01, 0xc8, 0x75, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x68, + 0xff, 0x00, 0x60, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x00, + 0x00, 0x00, 0xd8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x00, + 0x00, 0x00, 0xde, 0xff, 0xff, 0x30, 0x0c, 0x31, 0x0d, 0x78, 0x0e, 0x7f, + 0x0f, 0x80, 0x10, 0x81, 0x11, 0x86, 0x12, 0x89, 0x13, 0x8a, 0x13, 0x8e, + 0x14, 0x8f, 0x15, 0x90, 0x16, 0x93, 0x13, 0x94, 0x17, 0x95, 0x18, 0x96, + 0x19, 0x97, 0x1a, 0x9a, 0x1b, 0x9c, 0x19, 0x9d, 0x1c, 0x9e, 0x1d, 0x9f, + 0x1e, 0xa6, 0x1f, 0xa9, 0x1f, 0xae, 0x1f, 0xb1, 0x20, 0xb2, 0x20, 0xb7, + 0x21, 0xbf, 0x22, 0xc5, 0x23, 0xc8, 0x23, 0xcb, 0x23, 0xdd, 0x24, 0xf2, + 0x23, 0xf6, 0x25, 0xf7, 0x26, 0x20, 0x2d, 0x3a, 0x2e, 0x3d, 0x2f, 0x3e, + 0x30, 0x3f, 0x31, 0x40, 0x31, 0x43, 0x32, 0x44, 0x33, 0x45, 0x34, 0x50, + 0x35, 0x51, 0x36, 0x52, 0x37, 0x53, 0x38, 0x54, 0x39, 0x59, 0x3a, 0x5b, + 0x3b, 0x5c, 0x3c, 0x61, 0x3d, 0x63, 0x3e, 0x65, 0x3f, 0x66, 0x40, 0x68, + 0x41, 0x69, 0x42, 0x6a, 0x40, 0x6b, 0x43, 0x6c, 0x44, 0x6f, 0x42, 0x71, + 0x45, 0x72, 0x46, 0x75, 0x47, 0x7d, 0x48, 0x82, 0x49, 0x87, 0x4a, 0x89, + 0x4b, 0x8a, 0x4c, 0x8b, 0x4c, 0x8c, 0x4d, 0x92, 0x4e, 0x9d, 0x4f, 0x9e, + 0x50, 0x45, 0x57, 0x7b, 0x1d, 0x7c, 0x1d, 0x7d, 0x1d, 0x7f, 0x58, 0x86, + 0x59, 0x88, 0x5a, 0x89, 0x5a, 0x8a, 0x5a, 0x8c, 0x5b, 0x8e, 0x5c, 0x8f, + 0x5c, 0xac, 0x5d, 0xad, 0x5e, 0xae, 0x5e, 0xaf, 0x5e, 0xc2, 0x5f, 0xcc, + 0x60, 0xcd, 0x61, 0xce, 0x61, 0xcf, 0x62, 0xd0, 0x63, 0xd1, 0x64, 0xd5, + 0x65, 0xd6, 0x66, 0xd7, 0x67, 0xf0, 0x68, 0xf1, 0x69, 0xf2, 0x6a, 0xf3, + 0x6b, 0xf4, 0x6c, 0xf5, 0x6d, 0xf9, 0x6e, 0xfd, 0x2d, 0xfe, 0x2d, 0xff, + 0x2d, 0x50, 0x69, 0x51, 0x69, 0x52, 0x69, 0x53, 0x69, 0x54, 0x69, 0x55, + 0x69, 0x56, 0x69, 0x57, 0x69, 0x58, 0x69, 0x59, 0x69, 0x5a, 0x69, 0x5b, + 0x69, 0x5c, 0x69, 0x5d, 0x69, 0x5e, 0x69, 0x5f, 0x69, 0x82, 0x00, 0x83, + 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x00, 0x89, + 0x00, 0xc0, 0x75, 0xcf, 0x76, 0x80, 0x89, 0x81, 0x8a, 0x82, 0x8b, 0x85, + 0x8c, 0x86, 0x8d, 0x70, 0x9d, 0x71, 0x9d, 0x76, 0x9e, 0x77, 0x9e, 0x78, + 0x9f, 0x79, 0x9f, 0x7a, 0xa0, 0x7b, 0xa0, 0x7c, 0xa1, 0x7d, 0xa1, 0xb3, + 0xa2, 0xba, 0xa3, 0xbb, 0xa3, 0xbc, 0xa4, 0xbe, 0xa5, 0xc3, 0xa2, 0xcc, + 0xa4, 0xda, 0xa6, 0xdb, 0xa6, 0xe5, 0x6a, 0xea, 0xa7, 0xeb, 0xa7, 0xec, + 0x6e, 0xf3, 0xa2, 0xf8, 0xa8, 0xf9, 0xa8, 0xfa, 0xa9, 0xfb, 0xa9, 0xfc, + 0xa4, 0x26, 0xb0, 0x2a, 0xb1, 0x2b, 0xb2, 0x4e, 0xb3, 0x84, 0x08, 0x62, + 0xba, 0x63, 0xbb, 0x64, 0xbc, 0x65, 0xbd, 0x66, 0xbe, 0x6d, 0xbf, 0x6e, + 0xc0, 0x6f, 0xc1, 0x70, 0xc2, 0x7e, 0xc3, 0x7f, 0xc3, 0x7d, 0xcf, 0x8d, + 0xd0, 0x94, 0xd1, 0xab, 0xd2, 0xac, 0xd3, 0xad, 0xd4, 0xb0, 0xd5, 0xb1, + 0xd6, 0xb2, 0xd7, 0xc4, 0xd8, 0xc5, 0xd9, 0xc6, 0xda, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x0d, 0x06, 0x06, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x0f, 0x10, 0x11, 0x12, 0x06, 0x13, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x14, 0x15, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x16, 0x17, 0x06, 0x06, 0x06, + 0x18, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x19, 0x06, 0x06, 0x06, 0x06, 0x1a, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x1b, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x1c, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x1d, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1e, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x01, 0x00, 0x54, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x07, 0x2b, + 0x2b, 0x5b, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x4a, 0x56, 0x56, + 0x05, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x24, 0x50, 0x79, 0x31, 0x50, 0x31, 0x50, + 0x31, 0x38, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x4e, 0x31, 0x02, 0x4e, 0x0d, 0x0d, 0x4e, + 0x03, 0x4e, 0x00, 0x24, 0x6e, 0x00, 0x4e, 0x31, 0x26, 0x6e, 0x51, 0x4e, + 0x24, 0x50, 0x4e, 0x39, 0x14, 0x81, 0x1b, 0x1d, 0x1d, 0x53, 0x31, 0x50, + 0x31, 0x50, 0x0d, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x1b, 0x53, 0x24, + 0x50, 0x31, 0x02, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, + 0x7b, 0x14, 0x79, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x2d, 0x2b, 0x49, 0x03, + 0x48, 0x03, 0x78, 0x5c, 0x7b, 0x14, 0x00, 0x96, 0x0a, 0x01, 0x2b, 0x28, + 0x06, 0x06, 0x00, 0x2a, 0x06, 0x2a, 0x2a, 0x2b, 0x07, 0xbb, 0xb5, 0x2b, + 0x1e, 0x00, 0x2b, 0x07, 0x2b, 0x2b, 0x2b, 0x01, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x01, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0xcd, 0x46, 0xcd, 0x2b, 0x00, 0x25, + 0x2b, 0x07, 0x01, 0x06, 0x01, 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x55, + 0x56, 0x56, 0x02, 0x24, 0x81, 0x81, 0x81, 0x81, 0x81, 0x15, 0x81, 0x81, + 0x81, 0x00, 0x00, 0x2b, 0x00, 0xb2, 0xd1, 0xb2, 0xd1, 0xb2, 0xd1, 0xb2, + 0xd1, 0x00, 0x00, 0xcd, 0xcc, 0x01, 0x00, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, + 0x83, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x02, 0x00, 0x00, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x4e, + 0x31, 0x50, 0x31, 0x50, 0x4e, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x02, 0x87, 0xa6, 0x87, + 0xa6, 0x87, 0xa6, 0x87, 0xa6, 0x87, 0xa6, 0x87, 0xa6, 0x87, 0xa6, 0x87, + 0xa6, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x00, 0x00, 0x00, 0x54, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x0c, 0x00, 0x0c, 0x2a, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x07, 0x2a, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x56, 0x56, 0x6c, + 0x81, 0x15, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x07, 0x6c, 0x03, + 0x41, 0x2b, 0x2b, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x2c, 0x56, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x6c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x25, 0x06, 0x25, 0x06, + 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, + 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, + 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, + 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x56, 0x7a, 0x9e, + 0x26, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, + 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, + 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x25, 0x06, 0x01, 0x2b, 0x2b, 0x4f, + 0x56, 0x56, 0x2c, 0x2b, 0x7f, 0x56, 0x56, 0x39, 0x2b, 0x2b, 0x55, 0x56, + 0x56, 0x2b, 0x2b, 0x4f, 0x56, 0x56, 0x2c, 0x2b, 0x7f, 0x56, 0x56, 0x81, + 0x37, 0x75, 0x5b, 0x7b, 0x5c, 0x2b, 0x2b, 0x4f, 0x56, 0x56, 0x02, 0xac, + 0x04, 0x00, 0x00, 0x39, 0x2b, 0x2b, 0x55, 0x56, 0x56, 0x2b, 0x2b, 0x4f, + 0x56, 0x56, 0x2c, 0x2b, 0x2b, 0x56, 0x56, 0x32, 0x13, 0x81, 0x57, 0x00, + 0x6f, 0x81, 0x7e, 0xc9, 0xd7, 0x7e, 0x2d, 0x81, 0x81, 0x0e, 0x7e, 0x39, + 0x7f, 0x6f, 0x57, 0x00, 0x81, 0x81, 0x7e, 0x15, 0x00, 0x7e, 0x03, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x07, + 0x2b, 0x24, 0x2b, 0x97, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x80, 0x81, 0x81, 0x81, 0x81, 0x39, 0xbb, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x01, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0xc9, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xd0, 0x0d, 0x00, 0x4e, + 0x31, 0x02, 0xb4, 0xc1, 0xc1, 0xd7, 0xd7, 0x24, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0xd7, 0xd7, 0x53, 0xc1, 0x47, 0xd4, 0xd7, + 0xd7, 0xd7, 0x05, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x07, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4e, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, + 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x31, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x79, 0x5c, 0x7b, 0x5c, 0x7b, 0x4f, + 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, + 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x7b, 0x5c, 0x2d, 0x2b, 0x2b, 0x79, + 0x14, 0x5c, 0x7b, 0x5c, 0x2d, 0x79, 0x2a, 0x5c, 0x27, 0x5c, 0x7b, 0x5c, + 0x7b, 0x5c, 0x7b, 0xa4, 0x00, 0x0a, 0xb4, 0x5c, 0x7b, 0x5c, 0x7b, 0x4f, + 0x03, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x07, 0x00, 0x48, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x07, + 0x00, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x07, 0x00, 0x00, 0x00, 0x00, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x55, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x27, 0x51, 0x6f, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x8e, 0x92, + 0x97, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xb4, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc6, 0xc9, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, + 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, + 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, + 0x00, 0x05, 0x20, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, + 0x00, 0x09, 0x20, 0x00, 0x00, 0x0a, 0x20, 0x00, 0x00, 0x28, 0x20, 0x00, + 0x00, 0x29, 0x20, 0x00, 0x00, 0x5f, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x05, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x00, 0x0c, 0x0b, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x2e, 0x77, + 0x61, 0x73, 0x6d, 0x01, 0xc9, 0x04, 0x2c, 0x00, 0x2a, 0x5f, 0x5f, 0x69, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x77, 0x61, 0x73, 0x69, + 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, + 0x67, 0x65, 0x74, 0x01, 0x30, 0x5f, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x5f, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x31, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x73, 0x5f, 0x67, 0x65, 0x74, 0x02, 0x2b, 0x5f, 0x5f, 0x69, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x31, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, + 0x69, 0x74, 0x03, 0x11, 0x5f, 0x5f, 0x77, 0x61, 0x73, 0x6d, 0x5f, 0x63, + 0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x04, 0x13, 0x75, + 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x77, 0x65, 0x61, + 0x6b, 0x3a, 0x6d, 0x61, 0x69, 0x6e, 0x05, 0x12, 0x5f, 0x5f, 0x77, 0x61, + 0x73, 0x6d, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x06, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x07, 0x0a, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x08, 0x06, + 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x09, 0x04, 0x66, 0x72, 0x65, 0x65, + 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x0b, 0x07, 0x72, 0x65, + 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x0c, 0x05, 0x5f, 0x45, 0x78, 0x69, 0x74, + 0x0d, 0x0b, 0x5f, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x76, 0x6f, 0x69, + 0x64, 0x0e, 0x0f, 0x5f, 0x5f, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x61, 0x72, + 0x67, 0x73, 0x5f, 0x67, 0x65, 0x74, 0x0f, 0x15, 0x5f, 0x5f, 0x77, 0x61, + 0x73, 0x69, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x73, 0x5f, 0x67, 0x65, 0x74, 0x10, 0x10, 0x5f, 0x5f, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x11, + 0x05, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x12, 0x11, 0x5f, 0x5f, 0x77, 0x61, + 0x73, 0x6d, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x64, 0x74, 0x6f, 0x72, + 0x73, 0x13, 0x06, 0x6d, 0x65, 0x6d, 0x63, 0x70, 0x79, 0x14, 0x06, 0x6d, + 0x65, 0x6d, 0x73, 0x65, 0x74, 0x15, 0x06, 0x73, 0x74, 0x72, 0x6c, 0x65, + 0x6e, 0x16, 0x08, 0x69, 0x73, 0x77, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x17, + 0x06, 0x6d, 0x65, 0x6d, 0x63, 0x6d, 0x70, 0x18, 0x06, 0x6d, 0x65, 0x6d, + 0x63, 0x68, 0x72, 0x19, 0x06, 0x73, 0x74, 0x72, 0x63, 0x6d, 0x70, 0x1a, + 0x08, 0x74, 0x6f, 0x77, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x1b, 0x07, 0x63, + 0x61, 0x73, 0x65, 0x6d, 0x61, 0x70, 0x1c, 0x08, 0x74, 0x6f, 0x77, 0x75, + 0x70, 0x70, 0x65, 0x72, 0x1d, 0x07, 0x73, 0x74, 0x72, 0x6e, 0x63, 0x6d, + 0x70, 0x1e, 0x08, 0x69, 0x73, 0x77, 0x75, 0x70, 0x70, 0x65, 0x72, 0x1f, + 0x07, 0x6d, 0x65, 0x6d, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x08, 0x69, 0x73, + 0x77, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x21, 0x07, 0x69, 0x73, 0x62, 0x6c, + 0x61, 0x6e, 0x6b, 0x22, 0x08, 0x69, 0x73, 0x77, 0x62, 0x6c, 0x61, 0x6e, + 0x6b, 0x23, 0x08, 0x69, 0x73, 0x77, 0x64, 0x69, 0x67, 0x69, 0x74, 0x24, + 0x07, 0x73, 0x74, 0x72, 0x6e, 0x63, 0x61, 0x74, 0x25, 0x09, 0x5f, 0x5f, + 0x73, 0x74, 0x70, 0x6e, 0x63, 0x70, 0x79, 0x26, 0x07, 0x73, 0x74, 0x72, + 0x6e, 0x63, 0x70, 0x79, 0x27, 0x09, 0x69, 0x73, 0x77, 0x78, 0x64, 0x69, + 0x67, 0x69, 0x74, 0x28, 0x06, 0x77, 0x63, 0x73, 0x6c, 0x65, 0x6e, 0x29, + 0x06, 0x77, 0x63, 0x73, 0x63, 0x68, 0x72, 0x2a, 0x08, 0x69, 0x73, 0x77, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x2b, 0x08, 0x69, 0x73, 0x77, 0x61, 0x6c, + 0x6e, 0x75, 0x6d, 0x07, 0x33, 0x02, 0x00, 0x0f, 0x5f, 0x5f, 0x73, 0x74, + 0x61, 0x63, 0x6b, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x01, + 0x1f, 0x47, 0x4f, 0x54, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x5f, 0x5f, 0x6d, 0x65, 0x6d, + 0x6f, 0x72, 0x79, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x09, 0x0a, 0x01, 0x00, + 0x07, 0x2e, 0x72, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x00, 0x8e, 0x01, 0x09, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x02, 0x08, 0x6c, + 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x01, 0x03, 0x43, 0x31, 0x31, + 0x00, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2d, + 0x62, 0x79, 0x01, 0x05, 0x63, 0x6c, 0x61, 0x6e, 0x67, 0x5f, 0x31, 0x39, + 0x2e, 0x31, 0x2e, 0x35, 0x2d, 0x77, 0x61, 0x73, 0x69, 0x2d, 0x73, 0x64, + 0x6b, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x6c, + 0x76, 0x6d, 0x2f, 0x6c, 0x6c, 0x76, 0x6d, 0x2d, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x20, 0x61, 0x62, 0x34, 0x62, 0x35, 0x61, 0x32, 0x64, + 0x62, 0x35, 0x38, 0x32, 0x39, 0x35, 0x38, 0x61, 0x66, 0x31, 0x65, 0x65, + 0x33, 0x30, 0x38, 0x61, 0x37, 0x39, 0x30, 0x63, 0x66, 0x64, 0x62, 0x34, + 0x32, 0x62, 0x64, 0x32, 0x34, 0x37, 0x32, 0x30, 0x29, 0x00, 0x56, 0x0f, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x05, 0x2b, 0x0b, 0x62, 0x75, 0x6c, 0x6b, 0x2d, 0x6d, + 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2b, 0x0a, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2b, 0x0f, 0x6d, 0x75, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x2d, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x2b, 0x0f, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2b, 0x08, 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x65, 0x78, + 0x74 +}; +unsigned int STDLIB_WASM_LEN = 15673; + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/wasm_store.c b/codegraph-kernel/vendor/tree-sitter/src/wasm_store.c new file mode 100644 index 0000000000..e844c2a0d2 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/wasm_store.c @@ -0,0 +1,1937 @@ +#include "tree_sitter/api.h" +#include "./parser.h" +#include + +#ifdef TREE_SITTER_FEATURE_WASM + +#include "./alloc.h" +#include "./array.h" +#include "./atomic.h" +#include "./language.h" +#include "./lexer.h" +#include "./wasm/wasm-stdlib.h" +#include "./wasm_store.h" + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define array_len(a) (sizeof(a) / sizeof(a[0])) + +// The following symbols from the C and C++ standard libraries are available +// for external scanners to use. +const char *STDLIB_SYMBOLS[] = { + #include "./stdlib-symbols.txt" +}; + +// The contents of the `dylink.0` custom section of a wasm module, +// as specified by the current WebAssembly dynamic linking ABI proposal. +typedef struct { + uint32_t memory_size; + uint32_t memory_align; + uint32_t table_size; + uint32_t table_align; +} WasmDylinkInfo; + +// WasmLanguageId - A pointer used to identify a language. This language id is +// reference-counted, so that its ownership can be shared between the language +// itself and the instances of the language that are held in wasm stores. +typedef struct { + volatile uint32_t ref_count; + volatile uint32_t is_language_deleted; +} WasmLanguageId; + +// LanguageWasmModule - Additional data associated with a wasm-backed +// `TSLanguage`. This data is read-only and does not reference a particular +// wasm store, so it can be shared by all users of a `TSLanguage`. A pointer to +// this is stored on the language itself. +typedef struct { + volatile uint32_t ref_count; + WasmLanguageId *language_id; + wasmtime_module_t *module; + const char *name; + char *symbol_name_buffer; + char *field_name_buffer; + WasmDylinkInfo dylink_info; +} LanguageWasmModule; + +// LanguageWasmInstance - Additional data associated with an instantiation of +// a `TSLanguage` in a particular wasm store. The wasm store holds one of +// these structs for each language that it has instantiated. +typedef struct { + WasmLanguageId *language_id; + wasmtime_instance_t instance; + int32_t external_states_address; + int32_t lex_main_fn_index; + int32_t lex_keyword_fn_index; + int32_t scanner_create_fn_index; + int32_t scanner_destroy_fn_index; + int32_t scanner_serialize_fn_index; + int32_t scanner_deserialize_fn_index; + int32_t scanner_scan_fn_index; +} LanguageWasmInstance; + +typedef struct { + uint32_t reset_heap; + uint32_t proc_exit; + uint32_t abort; + uint32_t assert_fail; + uint32_t notify_memory_growth; + uint32_t debug_message; + uint32_t at_exit; + uint32_t args_get; + uint32_t args_sizes_get; +} BuiltinFunctionIndices; + +// TSWasmStore - A struct that allows a given `Parser` to use wasm-backed +// languages. This struct is mutable, and can only be used by one parser at a +// time. +struct TSWasmStore { + wasm_engine_t *engine; + wasmtime_store_t *store; + wasmtime_table_t function_table; + wasmtime_memory_t memory; + TSLexer *current_lexer; + LanguageWasmInstance *current_instance; + Array(LanguageWasmInstance) language_instances; + uint32_t current_memory_offset; + uint32_t current_function_table_offset; + uint32_t *stdlib_fn_indices; + BuiltinFunctionIndices builtin_fn_indices; + wasmtime_global_t stack_pointer_global; + wasm_globaltype_t *const_i32_type; + bool has_error; + uint32_t lexer_address; +}; + +typedef Array(char) StringData; + +// LanguageInWasmMemory - The memory layout of a `TSLanguage` when compiled to +// wasm32. This is used to copy static language data out of the wasm memory. +typedef struct { + uint32_t abi_version; + uint32_t symbol_count; + uint32_t alias_count; + uint32_t token_count; + uint32_t external_token_count; + uint32_t state_count; + uint32_t large_state_count; + uint32_t production_id_count; + uint32_t field_count; + uint16_t max_alias_sequence_length; + int32_t parse_table; + int32_t small_parse_table; + int32_t small_parse_table_map; + int32_t parse_actions; + int32_t symbol_names; + int32_t field_names; + int32_t field_map_slices; + int32_t field_map_entries; + int32_t symbol_metadata; + int32_t public_symbol_map; + int32_t alias_map; + int32_t alias_sequences; + int32_t lex_modes; + int32_t lex_fn; + int32_t keyword_lex_fn; + TSSymbol keyword_capture_token; + struct { + int32_t states; + int32_t symbol_map; + int32_t create; + int32_t destroy; + int32_t scan; + int32_t serialize; + int32_t deserialize; + } external_scanner; + int32_t primary_state_ids; + int32_t name; + int32_t reserved_words; + uint16_t max_reserved_word_set_size; + uint32_t supertype_count; + int32_t supertype_symbols; + int32_t supertype_map_slices; + int32_t supertype_map_entries; + TSLanguageMetadata metadata; +} LanguageInWasmMemory; + +// LexerInWasmMemory - The memory layout of a `TSLexer` when compiled to wasm32. +// This is used to copy mutable lexing state in and out of the wasm memory. +typedef struct { + int32_t lookahead; + TSSymbol result_symbol; + int32_t advance; + int32_t mark_end; + int32_t get_column; + int32_t is_at_included_range_start; + int32_t eof; +} LexerInWasmMemory; + +// Linear memory layout: +// [ <-- stack | stdlib statics | lexer | language statics --> | serialization_buffer | heap --> ] +#define MAX_MEMORY_SIZE (128 * 1024 * 1024 / MEMORY_PAGE_SIZE) + +/************************ + * WasmDylinkMemoryInfo + ***********************/ + +static uint8_t read_u8(const uint8_t **p) { + return *(*p)++; +} + +static inline uint64_t read_uleb128(const uint8_t **p, const uint8_t *end) { + uint64_t value = 0; + unsigned shift = 0; + do { + if (*p == end) return UINT64_MAX; + value += (uint64_t)(**p & 0x7f) << shift; + shift += 7; + } while (*((*p)++) >= 128); + return value; +} + +static bool wasm_dylink_info__parse( + const uint8_t *bytes, + size_t length, + WasmDylinkInfo *info +) { + const uint8_t WASM_MAGIC_NUMBER[4] = {0, 'a', 's', 'm'}; + const uint8_t WASM_VERSION[4] = {1, 0, 0, 0}; + const uint8_t WASM_CUSTOM_SECTION = 0x0; + const uint8_t WASM_DYLINK_MEM_INFO = 0x1; + + const uint8_t *p = bytes; + const uint8_t *end = bytes + length; + + if (length < 8) return false; + if (memcmp(p, WASM_MAGIC_NUMBER, 4) != 0) return false; + p += 4; + if (memcmp(p, WASM_VERSION, 4) != 0) return false; + p += 4; + + while (p < end) { + uint8_t section_id = read_u8(&p); + uint32_t section_length = read_uleb128(&p, end); + const uint8_t *section_end = p + section_length; + if (section_end > end) return false; + + if (section_id == WASM_CUSTOM_SECTION) { + uint32_t name_length = read_uleb128(&p, section_end); + const uint8_t *name_end = p + name_length; + if (name_end > section_end) return false; + + if (name_length == 8 && memcmp(p, "dylink.0", 8) == 0) { + p = name_end; + while (p < section_end) { + uint8_t subsection_type = read_u8(&p); + uint32_t subsection_size = read_uleb128(&p, section_end); + const uint8_t *subsection_end = p + subsection_size; + if (subsection_end > section_end) return false; + if (subsection_type == WASM_DYLINK_MEM_INFO) { + info->memory_size = read_uleb128(&p, subsection_end); + info->memory_align = read_uleb128(&p, subsection_end); + info->table_size = read_uleb128(&p, subsection_end); + info->table_align = read_uleb128(&p, subsection_end); + return true; + } + p = subsection_end; + } + } + } + p = section_end; + } + return false; +} + +/******************************************* + * Native callbacks exposed to wasm modules + *******************************************/ + + static wasm_trap_t *callback__abort( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + return wasmtime_trap_new("wasm module called abort", 24); +} + +static wasm_trap_t *callback__debug_message( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + wasmtime_context_t *context = wasmtime_caller_context(caller); + TSWasmStore *store = env; + ts_assert(args_and_results_len == 2); + uint32_t string_address = args_and_results[0].i32; + uint32_t value = args_and_results[1].i32; + uint8_t *memory = wasmtime_memory_data(context, &store->memory); + printf("DEBUG: %s %u\n", &memory[string_address], value); + return NULL; +} + +static wasm_trap_t *callback__noop( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + return NULL; +} + +static wasm_trap_t *callback__lexer_advance( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + wasmtime_context_t *context = wasmtime_caller_context(caller); + ts_assert(args_and_results_len == 2); + + TSWasmStore *store = env; + TSLexer *lexer = store->current_lexer; + bool skip = args_and_results[1].i32; + lexer->advance(lexer, skip); + + uint8_t *memory = wasmtime_memory_data(context, &store->memory); + memcpy(&memory[store->lexer_address], &lexer->lookahead, sizeof(lexer->lookahead)); + return NULL; +} + +static wasm_trap_t *callback__lexer_mark_end( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + TSWasmStore *store = env; + TSLexer *lexer = store->current_lexer; + lexer->mark_end(lexer); + return NULL; +} + +static wasm_trap_t *callback__lexer_get_column( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + TSWasmStore *store = env; + TSLexer *lexer = store->current_lexer; + uint32_t result = lexer->get_column(lexer); + args_and_results[0].i32 = result; + return NULL; +} + +static wasm_trap_t *callback__lexer_is_at_included_range_start( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + TSWasmStore *store = env; + TSLexer *lexer = store->current_lexer; + bool result = lexer->is_at_included_range_start(lexer); + args_and_results[0].i32 = result; + return NULL; +} + +static wasm_trap_t *callback__lexer_eof( + void *env, + wasmtime_caller_t* caller, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + TSWasmStore *store = env; + TSLexer *lexer = store->current_lexer; + bool result = lexer->eof(lexer); + args_and_results[0].i32 = result; + return NULL; +} + +typedef struct { + uint32_t *storage_location; + wasmtime_func_unchecked_callback_t callback; + wasm_functype_t *type; +} FunctionDefinition; + +static void *copy(const void *data, size_t size) { + void *result = ts_malloc(size); + memcpy(result, data, size); + return result; +} + +static void *copy_unsized_static_array( + const uint8_t *data, + int32_t start_address, + const int32_t all_addresses[], + size_t address_count +) { + int32_t end_address = 0; + for (unsigned i = 0; i < address_count; i++) { + if (all_addresses[i] > start_address) { + if (!end_address || all_addresses[i] < end_address) { + end_address = all_addresses[i]; + } + } + } + + if (!end_address) return NULL; + size_t size = end_address - start_address; + void *result = ts_malloc(size); + memcpy(result, &data[start_address], size); + return result; +} + +static void *copy_strings( + const uint8_t *data, + int32_t array_address, + size_t count, + StringData *string_data +) { + const char **result = ts_malloc(count * sizeof(char *)); + for (unsigned i = 0; i < count; i++) { + int32_t address; + memcpy(&address, &data[array_address + i * sizeof(address)], sizeof(address)); + if (address == 0) { + result[i] = (const char *)-1; + } else { + const uint8_t *string = &data[address]; + uint32_t len = strlen((const char *)string); + result[i] = (const char *)(uintptr_t)string_data->size; + array_extend(string_data, len + 1, string); + } + } + for (unsigned i = 0; i < count; i++) { + if (result[i] == (const char *)-1) { + result[i] = NULL; + } else { + result[i] = string_data->contents + (uintptr_t)result[i]; + } + } + return result; +} + +static void *copy_string( + const uint8_t *data, + int32_t address +) { + const char *string = (const char *)&data[address]; + size_t len = strlen(string); + char *result = ts_malloc(len + 1); + memcpy(result, string, len + 1); + return result; +} + +static bool name_eq(const wasm_name_t *name, const char *string) { + return strncmp(string, name->data, name->size) == 0; +} + +static inline wasm_functype_t* wasm_functype_new_4_0( + wasm_valtype_t* p1, + wasm_valtype_t* p2, + wasm_valtype_t* p3, + wasm_valtype_t* p4 +) { + wasm_valtype_t* ps[4] = {p1, p2, p3, p4}; + wasm_valtype_vec_t params, results; + wasm_valtype_vec_new(¶ms, 4, ps); + wasm_valtype_vec_new_empty(&results); + return wasm_functype_new(¶ms, &results); +} + +#define format(output, ...) \ + do { \ + size_t message_length = snprintf((char *)NULL, 0, __VA_ARGS__); \ + *output = ts_malloc(message_length + 1); \ + snprintf(*output, message_length + 1, __VA_ARGS__); \ + } while (0) + +WasmLanguageId *language_id_new(void) { + WasmLanguageId *self = ts_malloc(sizeof(WasmLanguageId)); + self->is_language_deleted = false; + self->ref_count = 1; + return self; +} + +WasmLanguageId *language_id_clone(WasmLanguageId *self) { + atomic_inc(&self->ref_count); + return self; +} + +void language_id_delete(WasmLanguageId *self) { + if (atomic_dec(&self->ref_count) == 0) { + ts_free(self); + } +} + +static wasmtime_extern_t get_builtin_extern( + wasmtime_table_t *table, + unsigned index +) { + return (wasmtime_extern_t) { + .kind = WASMTIME_EXTERN_FUNC, + .of.func = (wasmtime_func_t) { + .store_id = table->store_id, + .__private = index + } + }; +} + +static bool ts_wasm_store__provide_builtin_import( + TSWasmStore *self, + const wasm_name_t *import_name, + wasmtime_extern_t *import +) { + wasmtime_error_t *error = NULL; + wasmtime_context_t *context = wasmtime_store_context(self->store); + + // Dynamic linking parameters + if (name_eq(import_name, "__memory_base")) { + wasmtime_val_t value = WASM_I32_VAL(self->current_memory_offset); + wasmtime_global_t global; + error = wasmtime_global_new(context, self->const_i32_type, &value, &global); + ts_assert(!error); + *import = (wasmtime_extern_t) {.kind = WASMTIME_EXTERN_GLOBAL, .of.global = global}; + } else if (name_eq(import_name, "__table_base")) { + wasmtime_val_t value = WASM_I32_VAL(self->current_function_table_offset); + wasmtime_global_t global; + error = wasmtime_global_new(context, self->const_i32_type, &value, &global); + ts_assert(!error); + *import = (wasmtime_extern_t) {.kind = WASMTIME_EXTERN_GLOBAL, .of.global = global}; + } else if (name_eq(import_name, "__stack_pointer")) { + *import = (wasmtime_extern_t) {.kind = WASMTIME_EXTERN_GLOBAL, .of.global = self->stack_pointer_global}; + } else if (name_eq(import_name, "__indirect_function_table")) { + *import = (wasmtime_extern_t) {.kind = WASMTIME_EXTERN_TABLE, .of.table = self->function_table}; + } else if (name_eq(import_name, "memory")) { + *import = (wasmtime_extern_t) {.kind = WASMTIME_EXTERN_MEMORY, .of.memory = self->memory}; + } + + // Builtin functions + else if (name_eq(import_name, "__assert_fail")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.assert_fail); + } else if (name_eq(import_name, "__cxa_atexit")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.at_exit); + } else if (name_eq(import_name, "args_get")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.args_get); + } else if (name_eq(import_name, "args_sizes_get")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.args_sizes_get); + } else if (name_eq(import_name, "abort")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.abort); + } else if (name_eq(import_name, "proc_exit")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.proc_exit); + } else if (name_eq(import_name, "emscripten_notify_memory_growth")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.notify_memory_growth); + } else if (name_eq(import_name, "tree_sitter_debug_message")) { + *import = get_builtin_extern(&self->function_table, self->builtin_fn_indices.debug_message); + } else { + return false; + } + + return true; +} + +static bool ts_wasm_store__call_module_initializer( + TSWasmStore *self, + const wasm_name_t *export_name, + wasmtime_extern_t *export, + wasm_trap_t **trap +) { + if ( + name_eq(export_name, "_initialize") || + name_eq(export_name, "__wasm_apply_data_relocs") || + name_eq(export_name, "__wasm_call_ctors") + ) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + wasmtime_func_t initialization_func = export->of.func; + wasmtime_error_t *error = wasmtime_func_call(context, &initialization_func, NULL, 0, NULL, 0, trap); + ts_assert(!error); + return true; + } else { + return false; + } +} + +TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine, TSWasmError *wasm_error) { + TSWasmStore *self = ts_calloc(1, sizeof(TSWasmStore)); + wasmtime_store_t *store = wasmtime_store_new(engine, self, NULL); + wasmtime_context_t *context = wasmtime_store_context(store); + wasmtime_error_t *error = NULL; + wasm_trap_t *trap = NULL; + wasm_message_t message = WASM_EMPTY_VEC; + wasm_exporttype_vec_t export_types = WASM_EMPTY_VEC; + wasm_importtype_vec_t import_types = WASM_EMPTY_VEC; + wasmtime_extern_t *imports = NULL; + wasmtime_module_t *stdlib_module = NULL; + wasm_memorytype_t *memory_type = NULL; + wasm_tabletype_t *table_type = NULL; + + // Define functions called by scanners via function pointers on the lexer. + LexerInWasmMemory lexer = { + .lookahead = 0, + .result_symbol = 0, + }; + FunctionDefinition lexer_definitions[] = { + { + (uint32_t *)&lexer.advance, + callback__lexer_advance, + wasm_functype_new_2_0(wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + (uint32_t *)&lexer.mark_end, + callback__lexer_mark_end, + wasm_functype_new_1_0(wasm_valtype_new_i32()) + }, + { + (uint32_t *)&lexer.get_column, + callback__lexer_get_column, + wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + (uint32_t *)&lexer.is_at_included_range_start, + callback__lexer_is_at_included_range_start, + wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + (uint32_t *)&lexer.eof, + callback__lexer_eof, + wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + }; + + // Define builtin functions that can be imported by scanners. + BuiltinFunctionIndices builtin_fn_indices; + FunctionDefinition builtin_definitions[] = { + { + &builtin_fn_indices.proc_exit, + callback__abort, + wasm_functype_new_1_0(wasm_valtype_new_i32()) + }, + { + &builtin_fn_indices.abort, + callback__abort, + wasm_functype_new_0_0() + }, + { + &builtin_fn_indices.assert_fail, + callback__abort, + wasm_functype_new_4_0(wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + &builtin_fn_indices.notify_memory_growth, + callback__noop, + wasm_functype_new_1_0(wasm_valtype_new_i32()) + }, + { + &builtin_fn_indices.debug_message, + callback__debug_message, + wasm_functype_new_2_0(wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + &builtin_fn_indices.at_exit, + callback__noop, + wasm_functype_new_3_1(wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + &builtin_fn_indices.args_get, + callback__noop, + wasm_functype_new_2_1(wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + { + &builtin_fn_indices.args_sizes_get, + callback__noop, + wasm_functype_new_2_1(wasm_valtype_new_i32(), wasm_valtype_new_i32(), wasm_valtype_new_i32()) + }, + }; + + // Create all of the wasm functions. + unsigned builtin_definitions_len = array_len(builtin_definitions); + unsigned lexer_definitions_len = array_len(lexer_definitions); + for (unsigned i = 0; i < builtin_definitions_len; i++) { + FunctionDefinition *definition = &builtin_definitions[i]; + wasmtime_func_t func; + wasmtime_func_new_unchecked(context, definition->type, definition->callback, self, NULL, &func); + *definition->storage_location = func.__private; + wasm_functype_delete(definition->type); + } + for (unsigned i = 0; i < lexer_definitions_len; i++) { + FunctionDefinition *definition = &lexer_definitions[i]; + wasmtime_func_t func; + wasmtime_func_new_unchecked(context, definition->type, definition->callback, self, NULL, &func); + *definition->storage_location = func.__private; + wasm_functype_delete(definition->type); + } + + // Compile the stdlib module. + error = wasmtime_module_new(engine, STDLIB_WASM, STDLIB_WASM_LEN, &stdlib_module); + if (error) { + wasmtime_error_message(error, &message); + wasm_error->kind = TSWasmErrorKindCompile; + format( + &wasm_error->message, + "failed to compile wasm stdlib: %.*s", + (int)message.size, message.data + ); + goto error; + } + + // Retrieve the stdlib module's imports. + wasmtime_module_imports(stdlib_module, &import_types); + + // Find the initial number of memory pages needed by the stdlib. + const wasm_memorytype_t *stdlib_memory_type = NULL; + for (unsigned i = 0; i < import_types.size; i++) { + wasm_importtype_t *import_type = import_types.data[i]; + const wasm_name_t *import_name = wasm_importtype_name(import_type); + if (name_eq(import_name, "memory")) { + const wasm_externtype_t *type = wasm_importtype_type(import_type); + stdlib_memory_type = wasm_externtype_as_memorytype_const(type); + } + } + if (!stdlib_memory_type) { + wasm_error->kind = TSWasmErrorKindCompile; + format( + &wasm_error->message, + "wasm stdlib is missing the 'memory' import" + ); + goto error; + } + + // Initialize store's memory + uint64_t initial_memory_pages = wasmtime_memorytype_minimum(stdlib_memory_type); + wasm_limits_t memory_limits = {.min = initial_memory_pages, .max = MAX_MEMORY_SIZE}; + memory_type = wasm_memorytype_new(&memory_limits); + wasmtime_memory_t memory; + error = wasmtime_memory_new(context, memory_type, &memory); + if (error) { + wasmtime_error_message(error, &message); + wasm_error->kind = TSWasmErrorKindAllocate; + format( + &wasm_error->message, + "failed to allocate wasm memory: %.*s", + (int)message.size, message.data + ); + goto error; + } + wasm_memorytype_delete(memory_type); + memory_type = NULL; + + // Initialize store's function table + wasm_limits_t table_limits = {.min = 1, .max = wasm_limits_max_default}; + table_type = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), &table_limits); + wasmtime_val_t initializer = {.kind = WASMTIME_FUNCREF}; + wasmtime_table_t function_table; + error = wasmtime_table_new(context, table_type, &initializer, &function_table); + if (error) { + wasmtime_error_message(error, &message); + wasm_error->kind = TSWasmErrorKindAllocate; + format( + &wasm_error->message, + "failed to allocate wasm table: %.*s", + (int)message.size, message.data + ); + goto error; + } + wasm_tabletype_delete(table_type); + table_type = NULL; + + unsigned stdlib_symbols_len = array_len(STDLIB_SYMBOLS); + + // Define globals for the stack and heap start addresses. + wasm_globaltype_t *const_i32_type = wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST); + wasm_globaltype_t *var_i32_type = wasm_globaltype_new(wasm_valtype_new_i32(), WASM_VAR); + + wasmtime_val_t stack_pointer_value = WASM_I32_VAL(0); + wasmtime_global_t stack_pointer_global; + error = wasmtime_global_new(context, var_i32_type, &stack_pointer_value, &stack_pointer_global); + wasm_globaltype_delete(var_i32_type); + ts_assert(!error); + + *self = (TSWasmStore) { + .engine = wasmtime_engine_clone(engine), + .store = store, + .memory = memory, + .function_table = function_table, + .language_instances = array_new(), + .stdlib_fn_indices = ts_calloc(stdlib_symbols_len, sizeof(uint32_t)), + .builtin_fn_indices = builtin_fn_indices, + .stack_pointer_global = stack_pointer_global, + .current_memory_offset = 0, + .current_function_table_offset = 0, + .const_i32_type = const_i32_type, + }; + + // Set up the imports for the stdlib module. + imports = ts_calloc(import_types.size, sizeof(wasmtime_extern_t)); + for (unsigned i = 0; i < import_types.size; i++) { + wasm_importtype_t *type = import_types.data[i]; + const wasm_name_t *import_name = wasm_importtype_name(type); + if (!ts_wasm_store__provide_builtin_import(self, import_name, &imports[i])) { + wasm_error->kind = TSWasmErrorKindInstantiate; + format( + &wasm_error->message, + "unexpected import in wasm stdlib: %.*s\n", + (int)import_name->size, import_name->data + ); + goto error; + } + } + + // Instantiate the stdlib module. + wasmtime_instance_t instance; + error = wasmtime_instance_new(context, stdlib_module, imports, import_types.size, &instance, &trap); + ts_free(imports); + imports = NULL; + if (error) { + wasmtime_error_message(error, &message); + wasm_error->kind = TSWasmErrorKindInstantiate; + format( + &wasm_error->message, + "failed to instantiate wasm stdlib module: %.*s", + (int)message.size, message.data + ); + goto error; + } + if (trap) { + wasm_trap_message(trap, &message); + wasm_error->kind = TSWasmErrorKindInstantiate; + format( + &wasm_error->message, + "trapped when instantiating wasm stdlib module: %.*s", + (int)message.size, message.data + ); + goto error; + } + wasm_importtype_vec_delete(&import_types); + + // Process the stdlib module's exports. + for (unsigned i = 0; i < stdlib_symbols_len; i++) { + self->stdlib_fn_indices[i] = UINT32_MAX; + } + wasmtime_module_exports(stdlib_module, &export_types); + for (unsigned i = 0; i < export_types.size; i++) { + wasm_exporttype_t *export_type = export_types.data[i]; + const wasm_name_t *name = wasm_exporttype_name(export_type); + + char *export_name; + size_t name_len; + wasmtime_extern_t export = {.kind = WASM_EXTERN_GLOBAL}; + bool exists = wasmtime_instance_export_nth(context, &instance, i, &export_name, &name_len, &export); + ts_assert(exists); + + if (export.kind == WASMTIME_EXTERN_GLOBAL) { + if (name_eq(name, "__stack_pointer")) { + self->stack_pointer_global = export.of.global; + } + } + + if (export.kind == WASMTIME_EXTERN_FUNC) { + if (ts_wasm_store__call_module_initializer(self, name, &export, &trap)) { + if (trap) { + wasm_trap_message(trap, &message); + wasm_error->kind = TSWasmErrorKindInstantiate; + format( + &wasm_error->message, + "trap when calling stdlib relocation function: %.*s\n", + (int)message.size, message.data + ); + goto error; + } + continue; + } + + if (name_eq(name, "reset_heap")) { + self->builtin_fn_indices.reset_heap = export.of.func.__private; + continue; + } + + for (unsigned j = 0; j < stdlib_symbols_len; j++) { + if (name_eq(name, STDLIB_SYMBOLS[j])) { + self->stdlib_fn_indices[j] = export.of.func.__private; + break; + } + } + } + } + + if (self->builtin_fn_indices.reset_heap == UINT32_MAX) { + wasm_error->kind = TSWasmErrorKindInstantiate; + format( + &wasm_error->message, + "missing malloc reset function in wasm stdlib" + ); + goto error; + } + + for (unsigned i = 0; i < stdlib_symbols_len; i++) { + if (self->stdlib_fn_indices[i] == UINT32_MAX) { + wasm_error->kind = TSWasmErrorKindInstantiate; + format( + &wasm_error->message, + "missing exported symbol in wasm stdlib: %s", + STDLIB_SYMBOLS[i] + ); + goto error; + } + } + + wasm_exporttype_vec_delete(&export_types); + wasmtime_module_delete(stdlib_module); + + // Add all of the lexer callback functions to the function table. Store their function table + // indices on the in-memory lexer. + uint64_t table_index; + error = wasmtime_table_grow(context, &function_table, lexer_definitions_len, &initializer, &table_index); + if (error) { + wasmtime_error_message(error, &message); + wasm_error->kind = TSWasmErrorKindAllocate; + format( + &wasm_error->message, + "failed to grow wasm table to initial size: %.*s", + (int)message.size, message.data + ); + goto error; + } + for (unsigned i = 0; i < lexer_definitions_len; i++) { + FunctionDefinition *definition = &lexer_definitions[i]; + wasmtime_func_t func = {function_table.store_id, *definition->storage_location}; + wasmtime_val_t func_val = {.kind = WASMTIME_FUNCREF, .of.funcref = func}; + error = wasmtime_table_set(context, &function_table, table_index, &func_val); + ts_assert(!error); + *(int32_t *)(definition->storage_location) = table_index; + table_index++; + } + + self->current_function_table_offset = table_index; + self->lexer_address = initial_memory_pages * MEMORY_PAGE_SIZE; + self->current_memory_offset = self->lexer_address + sizeof(LexerInWasmMemory); + + // Grow the memory enough to hold the builtin lexer and serialization buffer. + uint32_t new_pages_needed = (self->current_memory_offset - self->lexer_address - 1) / MEMORY_PAGE_SIZE + 1; + uint64_t prev_memory_size; + wasmtime_memory_grow(context, &memory, new_pages_needed, &prev_memory_size); + + uint8_t *memory_data = wasmtime_memory_data(context, &memory); + memcpy(&memory_data[self->lexer_address], &lexer, sizeof(lexer)); + return self; + +error: + ts_free(self); + if (stdlib_module) wasmtime_module_delete(stdlib_module); + if (store) wasmtime_store_delete(store); + if (import_types.size) wasm_importtype_vec_delete(&import_types); + if (memory_type) wasm_memorytype_delete(memory_type); + if (table_type) wasm_tabletype_delete(table_type); + if (trap) wasm_trap_delete(trap); + if (error) wasmtime_error_delete(error); + if (message.size) wasm_byte_vec_delete(&message); + if (export_types.size) wasm_exporttype_vec_delete(&export_types); + if (imports) ts_free(imports); + return NULL; +} + +void ts_wasm_store_delete(TSWasmStore *self) { + if (!self) return; + ts_free(self->stdlib_fn_indices); + wasm_globaltype_delete(self->const_i32_type); + wasmtime_store_delete(self->store); + wasm_engine_delete(self->engine); + for (unsigned i = 0; i < self->language_instances.size; i++) { + LanguageWasmInstance *instance = array_get(&self->language_instances, i); + language_id_delete(instance->language_id); + } + array_delete(&self->language_instances); + ts_free(self); +} + +size_t ts_wasm_store_language_count(const TSWasmStore *self) { + size_t result = 0; + for (unsigned i = 0; i < self->language_instances.size; i++) { + const WasmLanguageId *id = array_get(&self->language_instances, i)->language_id; + if (!id->is_language_deleted) { + result++; + } + } + return result; +} + +static uint32_t ts_wasm_store__heap_address(TSWasmStore *self) { + return self->current_memory_offset + TREE_SITTER_SERIALIZATION_BUFFER_SIZE; +} + +static uint32_t ts_wasm_store__serialization_buffer_address(TSWasmStore *self) { + return self->current_memory_offset; +} + +static bool ts_wasm_store__instantiate( + TSWasmStore *self, + wasmtime_module_t *module, + const char *language_name, + const WasmDylinkInfo *dylink_info, + wasmtime_instance_t *result, + int32_t *language_address, + char **error_message +) { + wasmtime_error_t *error = NULL; + wasm_trap_t *trap = NULL; + wasm_message_t message = WASM_EMPTY_VEC; + char *language_function_name = NULL; + wasmtime_extern_t *imports = NULL; + wasmtime_context_t *context = wasmtime_store_context(self->store); + + // Grow the function table to make room for the new functions. + wasmtime_val_t initializer = {.kind = WASMTIME_FUNCREF}; + uint64_t prev_table_size; + error = wasmtime_table_grow(context, &self->function_table, dylink_info->table_size, &initializer, &prev_table_size); + if (error) { + format(error_message, "invalid function table size %u", dylink_info->table_size); + goto error; + } + + // Grow the memory to make room for the new data. + uint32_t needed_memory_size = ts_wasm_store__heap_address(self) + dylink_info->memory_size; + uint32_t current_memory_size = wasmtime_memory_data_size(context, &self->memory); + if (needed_memory_size > current_memory_size) { + uint32_t pages_to_grow = ( + needed_memory_size - current_memory_size + MEMORY_PAGE_SIZE - 1) / + MEMORY_PAGE_SIZE; + uint64_t prev_memory_size; + error = wasmtime_memory_grow(context, &self->memory, pages_to_grow, &prev_memory_size); + if (error) { + format(error_message, "invalid memory size %u", dylink_info->memory_size); + goto error; + } + } + + // Construct the language function name as string. + format(&language_function_name, "tree_sitter_%s", language_name); + + const uint64_t store_id = self->function_table.store_id; + + // Build the imports list for the module. + wasm_importtype_vec_t import_types = WASM_EMPTY_VEC; + wasmtime_module_imports(module, &import_types); + imports = ts_calloc(import_types.size, sizeof(wasmtime_extern_t)); + + for (unsigned i = 0; i < import_types.size; i++) { + const wasm_importtype_t *import_type = import_types.data[i]; + const wasm_name_t *import_name = wasm_importtype_name(import_type); + if (import_name->size == 0) { + format(error_message, "empty import name"); + goto error; + } + + if (ts_wasm_store__provide_builtin_import(self, import_name, &imports[i])) { + continue; + } + + bool defined_in_stdlib = false; + for (unsigned j = 0; j < array_len(STDLIB_SYMBOLS); j++) { + if (name_eq(import_name, STDLIB_SYMBOLS[j])) { + uint16_t address = self->stdlib_fn_indices[j]; + imports[i] = (wasmtime_extern_t) {.kind = WASMTIME_EXTERN_FUNC, .of.func = {store_id, address}}; + defined_in_stdlib = true; + break; + } + } + + if (!defined_in_stdlib) { + format( + error_message, + "invalid import '%.*s'\n", + (int)import_name->size, import_name->data + ); + goto error; + } + } + + wasmtime_instance_t instance; + error = wasmtime_instance_new(context, module, imports, import_types.size, &instance, &trap); + wasm_importtype_vec_delete(&import_types); + ts_free(imports); + imports = NULL; + if (error) { + wasmtime_error_message(error, &message); + format( + error_message, + "error instantiating wasm module: %.*s\n", + (int)message.size, message.data + ); + goto error; + } + if (trap) { + wasm_trap_message(trap, &message); + format( + error_message, + "trap when instantiating wasm module: %.*s\n", + (int)message.size, message.data + ); + goto error; + } + + self->current_memory_offset += dylink_info->memory_size; + self->current_function_table_offset += dylink_info->table_size; + + // Process the module's exports. + bool found_language = false; + wasmtime_extern_t language_extern; + wasm_exporttype_vec_t export_types = WASM_EMPTY_VEC; + wasmtime_module_exports(module, &export_types); + for (unsigned i = 0; i < export_types.size; i++) { + wasm_exporttype_t *export_type = export_types.data[i]; + const wasm_name_t *name = wasm_exporttype_name(export_type); + + size_t name_len; + char *export_name; + wasmtime_extern_t export = {.kind = WASM_EXTERN_GLOBAL}; + bool exists = wasmtime_instance_export_nth(context, &instance, i, &export_name, &name_len, &export); + ts_assert(exists); + + // If the module exports an initialization or data-relocation function, call it. + if (ts_wasm_store__call_module_initializer(self, name, &export, &trap)) { + if (trap) { + wasm_trap_message(trap, &message); + format( + error_message, + "trap when calling data relocation function: %.*s\n", + (int)message.size, message.data + ); + goto error; + } + } + + // Find the main language function for the module. + else if (name_eq(name, language_function_name)) { + language_extern = export; + found_language = true; + } + } + wasm_exporttype_vec_delete(&export_types); + + if (!found_language) { + format( + error_message, + "module did not contain language function: %s", + language_function_name + ); + goto error; + } + + // Invoke the language function to get the static address of the language object. + wasmtime_func_t language_func = language_extern.of.func; + wasmtime_val_t language_address_val; + error = wasmtime_func_call(context, &language_func, NULL, 0, &language_address_val, 1, &trap); + ts_assert(!error); + if (trap) { + wasm_trap_message(trap, &message); + format( + error_message, + "trapped when calling language function: %s: %.*s\n", + language_function_name, (int)message.size, message.data + ); + goto error; + } + + if (language_address_val.kind != WASMTIME_I32) { + format( + error_message, + "language function did not return an integer: %s\n", + language_function_name + ); + goto error; + } + + ts_free(language_function_name); + *result = instance; + *language_address = language_address_val.of.i32; + return true; + +error: + if (language_function_name) ts_free(language_function_name); + if (message.size) wasm_byte_vec_delete(&message); + if (error) wasmtime_error_delete(error); + if (trap) wasm_trap_delete(trap); + if (imports) ts_free(imports); + return false; +} + +static bool ts_wasm_store__sentinel_lex_fn(TSLexer *_lexer, TSStateId state) { + return false; +} + +const TSLanguage *ts_wasm_store_load_language( + TSWasmStore *self, + const char *language_name, + const char *wasm, + uint32_t wasm_len, + TSWasmError *wasm_error +) { + WasmDylinkInfo dylink_info; + wasmtime_module_t *module = NULL; + wasmtime_error_t *error = NULL; + wasm_error->kind = TSWasmErrorKindNone; + + if (!wasm_dylink_info__parse((const unsigned char *)wasm, wasm_len, &dylink_info)) { + wasm_error->kind = TSWasmErrorKindParse; + format(&wasm_error->message, "failed to parse dylink section of wasm module"); + goto error; + } + + // Compile the wasm code. + error = wasmtime_module_new(self->engine, (const uint8_t *)wasm, wasm_len, &module); + if (error) { + wasm_message_t message; + wasmtime_error_message(error, &message); + wasm_error->kind = TSWasmErrorKindCompile; + format(&wasm_error->message, "error compiling wasm module: %.*s", (int)message.size, message.data); + wasm_byte_vec_delete(&message); + goto error; + } + + // Instantiate the module in this store. + wasmtime_instance_t instance; + int32_t language_address; + if (!ts_wasm_store__instantiate( + self, + module, + language_name, + &dylink_info, + &instance, + &language_address, + &wasm_error->message + )) { + wasm_error->kind = TSWasmErrorKindInstantiate; + goto error; + } + + // Copy all of the static data out of the language object in wasm memory, + // constructing a native language object. + LanguageInWasmMemory wasm_language; + wasmtime_context_t *context = wasmtime_store_context(self->store); + const uint8_t *memory = wasmtime_memory_data(context, &self->memory); + memcpy(&wasm_language, &memory[language_address], sizeof(LanguageInWasmMemory)); + + bool has_supertypes = + wasm_language.abi_version > LANGUAGE_VERSION_WITH_RESERVED_WORDS && + wasm_language.supertype_count > 0; + + int32_t addresses[] = { + wasm_language.parse_table, + wasm_language.small_parse_table, + wasm_language.small_parse_table_map, + wasm_language.parse_actions, + wasm_language.symbol_names, + wasm_language.field_names, + wasm_language.field_map_slices, + wasm_language.field_map_entries, + wasm_language.symbol_metadata, + wasm_language.public_symbol_map, + wasm_language.alias_map, + wasm_language.alias_sequences, + wasm_language.lex_modes, + wasm_language.lex_fn, + wasm_language.keyword_lex_fn, + wasm_language.primary_state_ids, + wasm_language.name, + wasm_language.reserved_words, + has_supertypes ? wasm_language.supertype_symbols : 0, + has_supertypes ? wasm_language.supertype_map_entries : 0, + has_supertypes ? wasm_language.supertype_map_slices : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.states : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.symbol_map : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.create : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.destroy : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.scan : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.serialize : 0, + wasm_language.external_token_count > 0 ? wasm_language.external_scanner.deserialize : 0, + language_address, + self->current_memory_offset, + }; + uint32_t address_count = array_len(addresses); + + TSLanguage *language = ts_calloc(1, sizeof(TSLanguage)); + StringData symbol_name_buffer = array_new(); + StringData field_name_buffer = array_new(); + + *language = (TSLanguage) { + .abi_version = wasm_language.abi_version, + .symbol_count = wasm_language.symbol_count, + .alias_count = wasm_language.alias_count, + .token_count = wasm_language.token_count, + .external_token_count = wasm_language.external_token_count, + .state_count = wasm_language.state_count, + .large_state_count = wasm_language.large_state_count, + .production_id_count = wasm_language.production_id_count, + .field_count = wasm_language.field_count, + .supertype_count = wasm_language.supertype_count, + .max_alias_sequence_length = wasm_language.max_alias_sequence_length, + .keyword_capture_token = wasm_language.keyword_capture_token, + .metadata = wasm_language.metadata, + .parse_table = copy( + &memory[wasm_language.parse_table], + wasm_language.large_state_count * wasm_language.symbol_count * sizeof(uint16_t) + ), + .parse_actions = copy_unsized_static_array( + memory, + wasm_language.parse_actions, + addresses, + address_count + ), + .symbol_names = copy_strings( + memory, + wasm_language.symbol_names, + wasm_language.symbol_count + wasm_language.alias_count, + &symbol_name_buffer + ), + .symbol_metadata = copy( + &memory[wasm_language.symbol_metadata], + (wasm_language.symbol_count + wasm_language.alias_count) * sizeof(TSSymbolMetadata) + ), + .public_symbol_map = copy( + &memory[wasm_language.public_symbol_map], + (wasm_language.symbol_count + wasm_language.alias_count) * sizeof(TSSymbol) + ), + .lex_modes = copy( + &memory[wasm_language.lex_modes], + wasm_language.state_count * sizeof(TSLexerMode) + ), + }; + + if (language->field_count > 0 && language->production_id_count > 0) { + language->field_map_slices = copy( + &memory[wasm_language.field_map_slices], + wasm_language.production_id_count * sizeof(TSMapSlice) + ); + + // Determine the number of field map entries by finding the greatest index + // in any of the slices. + uint32_t field_map_entry_count = 0; + for (uint32_t i = 0; i < wasm_language.production_id_count; i++) { + TSMapSlice slice = language->field_map_slices[i]; + uint32_t slice_end = slice.index + slice.length; + if (slice_end > field_map_entry_count) { + field_map_entry_count = slice_end; + } + } + + language->field_map_entries = copy( + &memory[wasm_language.field_map_entries], + field_map_entry_count * sizeof(TSFieldMapEntry) + ); + language->field_names = copy_strings( + memory, + wasm_language.field_names, + wasm_language.field_count + 1, + &field_name_buffer + ); + } + + if (has_supertypes) { + language->supertype_symbols = copy( + &memory[wasm_language.supertype_symbols], + wasm_language.supertype_count * sizeof(TSSymbol) + ); + + // Determine the number of supertype map slices by finding the greatest + // supertype ID. + int largest_supertype = 0; + for (unsigned i = 0; i < language->supertype_count; i++) { + TSSymbol supertype = language->supertype_symbols[i]; + if (supertype > largest_supertype) { + largest_supertype = supertype; + } + } + + language->supertype_map_slices = copy( + &memory[wasm_language.supertype_map_slices], + (largest_supertype + 1) * sizeof(TSMapSlice) + ); + + TSSymbol last_supertype = language->supertype_symbols[language->supertype_count - 1]; + TSMapSlice last_slice = language->supertype_map_slices[last_supertype]; + uint32_t supertype_map_entry_count = last_slice.index + last_slice.length; + + language->supertype_map_entries = copy( + &memory[wasm_language.supertype_map_entries], + supertype_map_entry_count * sizeof(char *) + ); + } + + if (language->max_alias_sequence_length > 0 && language->production_id_count > 0) { + // The alias map contains symbols, alias counts, and aliases, terminated by a null symbol. + int32_t alias_map_size = 0; + for (;;) { + TSSymbol symbol; + memcpy(&symbol, &memory[wasm_language.alias_map + alias_map_size], sizeof(symbol)); + alias_map_size += sizeof(TSSymbol); + if (symbol == 0) break; + uint16_t value_count; + memcpy(&value_count, &memory[wasm_language.alias_map + alias_map_size], sizeof(value_count)); + alias_map_size += sizeof(uint16_t); + alias_map_size += value_count * sizeof(TSSymbol); + } + language->alias_map = copy( + &memory[wasm_language.alias_map], + alias_map_size + ); + language->alias_sequences = copy( + &memory[wasm_language.alias_sequences], + wasm_language.production_id_count * wasm_language.max_alias_sequence_length * sizeof(TSSymbol) + ); + } + + if (language->state_count > language->large_state_count) { + uint32_t small_state_count = wasm_language.state_count - wasm_language.large_state_count; + language->small_parse_table_map = copy( + &memory[wasm_language.small_parse_table_map], + small_state_count * sizeof(uint32_t) + ); + language->small_parse_table = copy_unsized_static_array( + memory, + wasm_language.small_parse_table, + addresses, + address_count + ); + } + + if (language->abi_version >= LANGUAGE_VERSION_WITH_PRIMARY_STATES) { + language->primary_state_ids = copy( + &memory[wasm_language.primary_state_ids], + wasm_language.state_count * sizeof(TSStateId) + ); + } + + if (language->abi_version >= LANGUAGE_VERSION_WITH_RESERVED_WORDS) { + language->name = copy_string(memory, wasm_language.name); + language->reserved_words = copy( + &memory[wasm_language.reserved_words], + wasm_language.max_reserved_word_set_size * sizeof(TSSymbol) + ); + language->max_reserved_word_set_size = wasm_language.max_reserved_word_set_size; + } + + if (language->external_token_count > 0) { + language->external_scanner.symbol_map = copy( + &memory[wasm_language.external_scanner.symbol_map], + wasm_language.external_token_count * sizeof(TSSymbol) + ); + language->external_scanner.states = (void *)(uintptr_t)wasm_language.external_scanner.states; + } + + unsigned name_len = strlen(language_name); + char *name = ts_malloc(name_len + 1); + memcpy(name, language_name, name_len); + name[name_len] = '\0'; + + LanguageWasmModule *language_module = ts_malloc(sizeof(LanguageWasmModule)); + *language_module = (LanguageWasmModule) { + .language_id = language_id_new(), + .module = module, + .name = name, + .symbol_name_buffer = symbol_name_buffer.contents, + .field_name_buffer = field_name_buffer.contents, + .dylink_info = dylink_info, + .ref_count = 1, + }; + + // The lex functions are not used for wasm languages. Use those two fields + // to mark this language as WASM-based and to store the language's + // WASM-specific data. + language->lex_fn = ts_wasm_store__sentinel_lex_fn; + language->keyword_lex_fn = (bool (*)(TSLexer *, TSStateId))language_module; + + // Clear out any instances of languages that have been deleted. + for (unsigned i = 0; i < self->language_instances.size; i++) { + WasmLanguageId *id = array_get(&self->language_instances, i)->language_id; + if (id->is_language_deleted) { + language_id_delete(id); + array_erase(&self->language_instances, i); + i--; + } + } + + // Store this store's instance of this language module. + array_push(&self->language_instances, ((LanguageWasmInstance) { + .language_id = language_id_clone(language_module->language_id), + .instance = instance, + .external_states_address = wasm_language.external_scanner.states, + .lex_main_fn_index = wasm_language.lex_fn, + .lex_keyword_fn_index = wasm_language.keyword_lex_fn, + .scanner_create_fn_index = wasm_language.external_scanner.create, + .scanner_destroy_fn_index = wasm_language.external_scanner.destroy, + .scanner_serialize_fn_index = wasm_language.external_scanner.serialize, + .scanner_deserialize_fn_index = wasm_language.external_scanner.deserialize, + .scanner_scan_fn_index = wasm_language.external_scanner.scan, + })); + + return language; + +error: + if (module) wasmtime_module_delete(module); + return NULL; +} + +bool ts_wasm_store_add_language( + TSWasmStore *self, + const TSLanguage *language, + uint32_t *index +) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + const LanguageWasmModule *language_module = (void *)language->keyword_lex_fn; + + // Search for this store's instance of the language module. Also clear out any + // instances of languages that have been deleted. + bool exists = false; + for (unsigned i = 0; i < self->language_instances.size; i++) { + WasmLanguageId *id = array_get(&self->language_instances, i)->language_id; + if (id->is_language_deleted) { + language_id_delete(id); + array_erase(&self->language_instances, i); + i--; + } else if (id == language_module->language_id) { + exists = true; + *index = i; + } + } + + // If the language module has not been instantiated in this store, then add + // it to this store. + if (!exists) { + *index = self->language_instances.size; + char *message; + wasmtime_instance_t instance; + int32_t language_address; + if (!ts_wasm_store__instantiate( + self, + language_module->module, + language_module->name, + &language_module->dylink_info, + &instance, + &language_address, + &message + )) { + ts_free(message); + return false; + } + + LanguageInWasmMemory wasm_language; + const uint8_t *memory = wasmtime_memory_data(context, &self->memory); + memcpy(&wasm_language, &memory[language_address], sizeof(LanguageInWasmMemory)); + array_push(&self->language_instances, ((LanguageWasmInstance) { + .language_id = language_id_clone(language_module->language_id), + .instance = instance, + .external_states_address = wasm_language.external_scanner.states, + .lex_main_fn_index = wasm_language.lex_fn, + .lex_keyword_fn_index = wasm_language.keyword_lex_fn, + .scanner_create_fn_index = wasm_language.external_scanner.create, + .scanner_destroy_fn_index = wasm_language.external_scanner.destroy, + .scanner_serialize_fn_index = wasm_language.external_scanner.serialize, + .scanner_deserialize_fn_index = wasm_language.external_scanner.deserialize, + .scanner_scan_fn_index = wasm_language.external_scanner.scan, + })); + } + + return true; +} + +void ts_wasm_store_reset_heap(TSWasmStore *self) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + wasmtime_func_t func = { + self->function_table.store_id, + self->builtin_fn_indices.reset_heap + }; + wasm_trap_t *trap = NULL; + wasmtime_val_t args[1] = { + {.of.i32 = ts_wasm_store__heap_address(self), .kind = WASMTIME_I32}, + }; + + wasmtime_error_t *error = wasmtime_func_call(context, &func, args, 1, NULL, 0, &trap); + ts_assert(!error); + ts_assert(!trap); +} + +bool ts_wasm_store_start(TSWasmStore *self, TSLexer *lexer, const TSLanguage *language) { + uint32_t instance_index; + if (!ts_wasm_store_add_language(self, language, &instance_index)) return false; + self->current_lexer = lexer; + self->current_instance = array_get(&self->language_instances, instance_index); + self->has_error = false; + ts_wasm_store_reset_heap(self); + return true; +} + +void ts_wasm_store_reset(TSWasmStore *self) { + self->current_lexer = NULL; + self->current_instance = NULL; + self->has_error = false; + ts_wasm_store_reset_heap(self); +} + +static void ts_wasm_store__call( + TSWasmStore *self, + int32_t function_index, + wasmtime_val_raw_t *args_and_results, + size_t args_and_results_len +) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + wasmtime_val_t value; + bool succeeded = wasmtime_table_get(context, &self->function_table, function_index, &value); + ts_assert(succeeded); + ts_assert(value.kind == WASMTIME_FUNCREF); + wasmtime_func_t func = value.of.funcref; + + wasm_trap_t *trap = NULL; + wasmtime_error_t *error = wasmtime_func_call_unchecked(context, &func, args_and_results, args_and_results_len, &trap); + if (error) { + // wasm_message_t message; + // wasmtime_error_message(error, &message); + // fprintf( + // stderr, + // "error in wasm module: %.*s\n", + // (int)message.size, message.data + // ); + wasmtime_error_delete(error); + self->has_error = true; + } else if (trap) { + // wasm_message_t message; + // wasm_trap_message(trap, &message); + // fprintf( + // stderr, + // "trap in wasm module: %.*s\n", + // (int)message.size, message.data + // ); + wasm_trap_delete(trap); + self->has_error = true; + } +} + +// The data fields of TSLexer, without the function pointers. +// +// This portion of the struct needs to be copied in and out +// of wasm memory before and after calling a scan function. +typedef struct { + int32_t lookahead; + TSSymbol result_symbol; +} TSLexerDataPrefix; + +static bool ts_wasm_store__call_lex_function(TSWasmStore *self, unsigned function_index, TSStateId state) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + uint8_t *memory_data = wasmtime_memory_data(context, &self->memory); + memcpy( + &memory_data[self->lexer_address], + self->current_lexer, + sizeof(TSLexerDataPrefix) + ); + + wasmtime_val_raw_t args[2] = { + {.i32 = self->lexer_address}, + {.i32 = state}, + }; + ts_wasm_store__call(self, function_index, args, 2); + if (self->has_error) return false; + bool result = args[0].i32; + + memcpy( + self->current_lexer, + &memory_data[self->lexer_address], + sizeof(TSLexerDataPrefix) + ); + return result; +} + +bool ts_wasm_store_call_lex_main(TSWasmStore *self, TSStateId state) { + return ts_wasm_store__call_lex_function( + self, + self->current_instance->lex_main_fn_index, + state + ); +} + +bool ts_wasm_store_call_lex_keyword(TSWasmStore *self, TSStateId state) { + return ts_wasm_store__call_lex_function( + self, + self->current_instance->lex_keyword_fn_index, + state + ); +} + +uint32_t ts_wasm_store_call_scanner_create(TSWasmStore *self) { + wasmtime_val_raw_t args[1] = {{.i32 = 0}}; + ts_wasm_store__call(self, self->current_instance->scanner_create_fn_index, args, 1); + if (self->has_error) return 0; + return args[0].i32; +} + +void ts_wasm_store_call_scanner_destroy(TSWasmStore *self, uint32_t scanner_address) { + if (self->current_instance) { + wasmtime_val_raw_t args[1] = {{.i32 = scanner_address}}; + ts_wasm_store__call(self, self->current_instance->scanner_destroy_fn_index, args, 1); + } +} + +bool ts_wasm_store_call_scanner_scan( + TSWasmStore *self, + uint32_t scanner_address, + uint32_t valid_tokens_ix +) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + uint8_t *memory_data = wasmtime_memory_data(context, &self->memory); + + memcpy( + &memory_data[self->lexer_address], + self->current_lexer, + sizeof(TSLexerDataPrefix) + ); + + uint32_t valid_tokens_address = + self->current_instance->external_states_address + + (valid_tokens_ix * sizeof(bool)); + wasmtime_val_raw_t args[3] = { + {.i32 = scanner_address}, + {.i32 = self->lexer_address}, + {.i32 = valid_tokens_address} + }; + ts_wasm_store__call(self, self->current_instance->scanner_scan_fn_index, args, 3); + if (self->has_error) return false; + + memcpy( + self->current_lexer, + &memory_data[self->lexer_address], + sizeof(TSLexerDataPrefix) + ); + return args[0].i32; +} + +uint32_t ts_wasm_store_call_scanner_serialize( + TSWasmStore *self, + uint32_t scanner_address, + char *buffer +) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + uint8_t *memory_data = wasmtime_memory_data(context, &self->memory); + uint32_t serialization_buffer_address = ts_wasm_store__serialization_buffer_address(self); + + wasmtime_val_raw_t args[2] = { + {.i32 = scanner_address}, + {.i32 = serialization_buffer_address}, + }; + ts_wasm_store__call(self, self->current_instance->scanner_serialize_fn_index, args, 2); + if (self->has_error) return 0; + + uint32_t length = args[0].i32; + if (length > TREE_SITTER_SERIALIZATION_BUFFER_SIZE) { + self->has_error = true; + return 0; + } + + if (length > 0) { + memcpy( + ((Lexer *)self->current_lexer)->debug_buffer, + &memory_data[serialization_buffer_address], + length + ); + } + return length; +} + +void ts_wasm_store_call_scanner_deserialize( + TSWasmStore *self, + uint32_t scanner_address, + const char *buffer, + unsigned length +) { + wasmtime_context_t *context = wasmtime_store_context(self->store); + uint8_t *memory_data = wasmtime_memory_data(context, &self->memory); + uint32_t serialization_buffer_address = ts_wasm_store__serialization_buffer_address(self); + + if (length > 0) { + memcpy( + &memory_data[serialization_buffer_address], + buffer, + length + ); + } + + wasmtime_val_raw_t args[3] = { + {.i32 = scanner_address}, + {.i32 = serialization_buffer_address}, + {.i32 = length}, + }; + ts_wasm_store__call(self, self->current_instance->scanner_deserialize_fn_index, args, 3); +} + +bool ts_wasm_store_has_error(const TSWasmStore *self) { + return self->has_error; +} + +bool ts_language_is_wasm(const TSLanguage *self) { + return self->lex_fn == ts_wasm_store__sentinel_lex_fn; +} + +static inline LanguageWasmModule *ts_language__wasm_module(const TSLanguage *self) { + return (LanguageWasmModule *)self->keyword_lex_fn; +} + +void ts_wasm_language_retain(const TSLanguage *self) { + LanguageWasmModule *module = ts_language__wasm_module(self); + ts_assert(module->ref_count > 0); + atomic_inc(&module->ref_count); +} + +void ts_wasm_language_release(const TSLanguage *self) { + LanguageWasmModule *module = ts_language__wasm_module(self); + ts_assert(module->ref_count > 0); + if (atomic_dec(&module->ref_count) == 0) { + // Update the language id to reflect that the language is deleted. This allows any wasm stores + // that hold wasm instances for this language to delete those instances. + atomic_inc(&module->language_id->is_language_deleted); + language_id_delete(module->language_id); + + ts_free((void *)module->field_name_buffer); + ts_free((void *)module->symbol_name_buffer); + ts_free((void *)module->name); + wasmtime_module_delete(module->module); + ts_free(module); + + ts_free((void *)self->alias_map); + ts_free((void *)self->alias_sequences); + ts_free((void *)self->external_scanner.symbol_map); + ts_free((void *)self->field_map_entries); + ts_free((void *)self->field_map_slices); + ts_free((void *)self->supertype_symbols); + ts_free((void *)self->supertype_map_entries); + ts_free((void *)self->supertype_map_slices); + ts_free((void *)self->field_names); + ts_free((void *)self->lex_modes); + ts_free((void *)self->name); + ts_free((void *)self->reserved_words); + ts_free((void *)self->parse_actions); + ts_free((void *)self->parse_table); + ts_free((void *)self->primary_state_ids); + ts_free((void *)self->public_symbol_map); + ts_free((void *)self->small_parse_table); + ts_free((void *)self->small_parse_table_map); + ts_free((void *)self->symbol_metadata); + ts_free((void *)self->symbol_names); + ts_free((void *)self); + } +} + +#ifdef _MSC_VER +#pragma warning(pop) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#else + +// If the WASM feature is not enabled, define dummy versions of all of the +// wasm-related functions. + +void ts_wasm_store_delete(TSWasmStore *self) { + (void)self; +} + +bool ts_wasm_store_start( + TSWasmStore *self, + TSLexer *lexer, + const TSLanguage *language +) { + (void)self; + (void)lexer; + (void)language; + return false; +} + +void ts_wasm_store_reset(TSWasmStore *self) { + (void)self; +} + +bool ts_wasm_store_call_lex_main(TSWasmStore *self, TSStateId state) { + (void)self; + (void)state; + return false; +} + +bool ts_wasm_store_call_lex_keyword(TSWasmStore *self, TSStateId state) { + (void)self; + (void)state; + return false; +} + +uint32_t ts_wasm_store_call_scanner_create(TSWasmStore *self) { + (void)self; + return 0; +} + +void ts_wasm_store_call_scanner_destroy( + TSWasmStore *self, + uint32_t scanner_address +) { + (void)self; + (void)scanner_address; +} + +bool ts_wasm_store_call_scanner_scan( + TSWasmStore *self, + uint32_t scanner_address, + uint32_t valid_tokens_ix +) { + (void)self; + (void)scanner_address; + (void)valid_tokens_ix; + return false; +} + +uint32_t ts_wasm_store_call_scanner_serialize( + TSWasmStore *self, + uint32_t scanner_address, + char *buffer +) { + (void)self; + (void)scanner_address; + (void)buffer; + return 0; +} + +void ts_wasm_store_call_scanner_deserialize( + TSWasmStore *self, + uint32_t scanner_address, + const char *buffer, + unsigned length +) { + (void)self; + (void)scanner_address; + (void)buffer; + (void)length; +} + +bool ts_wasm_store_has_error(const TSWasmStore *self) { + (void)self; + return false; +} + +bool ts_language_is_wasm(const TSLanguage *self) { + (void)self; + return false; +} + +void ts_wasm_language_retain(const TSLanguage *self) { + (void)self; +} + +void ts_wasm_language_release(const TSLanguage *self) { + (void)self; +} + +#endif diff --git a/codegraph-kernel/vendor/tree-sitter/src/wasm_store.h b/codegraph-kernel/vendor/tree-sitter/src/wasm_store.h new file mode 100644 index 0000000000..0fd17e0d17 --- /dev/null +++ b/codegraph-kernel/vendor/tree-sitter/src/wasm_store.h @@ -0,0 +1,31 @@ +#ifndef TREE_SITTER_WASM_H_ +#define TREE_SITTER_WASM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tree_sitter/api.h" +#include "./parser.h" + +bool ts_wasm_store_start(TSWasmStore *self, TSLexer *lexer, const TSLanguage *language); +void ts_wasm_store_reset(TSWasmStore *self); +bool ts_wasm_store_has_error(const TSWasmStore *self); + +bool ts_wasm_store_call_lex_main(TSWasmStore *self, TSStateId state); +bool ts_wasm_store_call_lex_keyword(TSWasmStore *self, TSStateId state); + +uint32_t ts_wasm_store_call_scanner_create(TSWasmStore *self); +void ts_wasm_store_call_scanner_destroy(TSWasmStore *self, uint32_t scanner_address); +bool ts_wasm_store_call_scanner_scan(TSWasmStore *self, uint32_t scanner_address, uint32_t valid_tokens_ix); +uint32_t ts_wasm_store_call_scanner_serialize(TSWasmStore *self, uint32_t scanner_address, char *buffer); +void ts_wasm_store_call_scanner_deserialize(TSWasmStore *self, uint32_t scanner, const char *buffer, unsigned length); + +void ts_wasm_language_retain(const TSLanguage *self); +void ts_wasm_language_release(const TSLanguage *self); + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_WASM_H_ diff --git a/docs/grammars/web-tree-sitter-runtime.md b/docs/grammars/web-tree-sitter-runtime.md index 79608cd622..98f50454e5 100644 --- a/docs/grammars/web-tree-sitter-runtime.md +++ b/docs/grammars/web-tree-sitter-runtime.md @@ -1,7 +1,8 @@ # Vendored tree-sitter runtime (web-tree-sitter 0.25.10 + #5997) `src/extraction/runtime/tree-sitter.wasm` replaces the `tree-sitter.wasm` that ships in the -web-tree-sitter npm package. `initGrammars()` loads it through `Parser.init({ locateFile })` +web-tree-sitter npm package, and `codegraph-kernel/vendor/tree-sitter` replaces the crates.io +`tree-sitter` crate for the native kernel. `initGrammars()` loads the wasm through `Parser.init({ locateFile })` and throws if it is missing. `copy-assets` copies it into `dist/extraction/runtime/`, and `scripts/check-ui-build.mjs` fails a build without it. @@ -47,7 +48,17 @@ cp lib/binding_web/lib/tree-sitter.wasm /src/extraction/runtime/tree- - web-tree-sitter is pinned exactly (`0.25.10`). `__tests__/tsx-error-recovery-hang.test.ts` fails if the installed version moves, because new glue with this wasm is untested. - The same test fails under the unpatched npm runtime (`did not finish within 2000ms`). +- Dev scripts (ts-differential, add-lang/dump-ast, add-lang/check-grammar, gen-go-stdlib-methods) + init through `scripts/tree-sitter-runtime.mjs`; `check-ui-build` checks the dist copy's sha256. - Exit: once the legacy-`dylink` grammars are rebuilt (or tree-sitter-wasms is replaced), move to web-tree-sitter 0.27.1+ and delete this runtime, the patch and this file. -- The native kernel (`codegraph-kernel`, Rust `tree-sitter` 0.25) carries the same bug and is - not patched here. +- The native kernel builds against the same patched runtime C: + `codegraph-kernel/vendor/tree-sitter` is the crates.io `tree-sitter` 0.25.10 crate (its + `src/parser.c` is identical to the git tag's) with the same patch applied, wired in through + `[patch.crates-io]` in `codegraph-kernel/Cargo.toml`. TypeScript and TSX are kernel-routed by + default whenever the kernel is present (release bundles ship it). The kernel half of the hang + test runs `extractFile` in a child with a 10s timeout; with the unpatched crate the tsx case + times out. +- Bumping the kernel's `tree-sitter` crate means re-vendoring: copy the new crate source into + `codegraph-kernel/vendor/tree-sitter` and re-apply the patch, or drop the `[patch]` entry + once the crate is 0.27.1+. diff --git a/scripts/add-lang/check-grammar.mjs b/scripts/add-lang/check-grammar.mjs index 9aff935474..5616b0c976 100755 --- a/scripts/add-lang/check-grammar.mjs +++ b/scripts/add-lang/check-grammar.mjs @@ -150,8 +150,8 @@ function describeEnd(run) { async function runGrammar(wasmPath, samplePath, itersArg) { const iters = Number(itersArg); const { Parser, Language } = await import('web-tree-sitter'); - try { await Parser.init(); } - catch { await Parser.init({ locateFile: () => require.resolve('web-tree-sitter/tree-sitter.wasm') }); } + const { initVendoredRuntime } = await import('../tree-sitter-runtime.mjs'); + await initVendoredRuntime(Parser); // The other grammars an index loads beside this one: the corruption surfaces // under the multi-grammar runtime that real indexing uses, not a single diff --git a/scripts/add-lang/dump-ast.mjs b/scripts/add-lang/dump-ast.mjs index 26406b09c6..cc63adf934 100755 --- a/scripts/add-lang/dump-ast.mjs +++ b/scripts/add-lang/dump-ast.mjs @@ -16,6 +16,7 @@ import { readFileSync, existsSync } from 'node:fs'; import { createRequire } from 'node:module'; import { Parser, Language } from 'web-tree-sitter'; +import { initVendoredRuntime } from '../tree-sitter-runtime.mjs'; const require = createRequire(import.meta.url); const fail = (msg) => { console.error(`[dump-ast] ${msg}`); process.exit(1); }; @@ -57,11 +58,7 @@ function resolveWasm(token) { const wasmPath = resolveWasm(langOrWasm); const source = readFileSync(sampleFile, 'utf8'); -try { - await Parser.init(); -} catch { - await Parser.init({ locateFile: () => require.resolve('web-tree-sitter/tree-sitter.wasm') }); -} +await initVendoredRuntime(Parser); let language; try { diff --git a/scripts/check-ui-build.mjs b/scripts/check-ui-build.mjs index 62b0912d50..ff43279f6e 100644 --- a/scripts/check-ui-build.mjs +++ b/scripts/check-ui-build.mjs @@ -26,6 +26,7 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'; import { dirname, join, resolve, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { createHash } from 'node:crypto'; const argv = process.argv.slice(2); const rootFlag = argv.indexOf('--root'); @@ -160,6 +161,16 @@ if (!existsSync(runtimeWasm)) { : 'run `npm run copy-assets` (it copies src/extraction/runtime/tree-sitter.wasm into dist/)' ); } +// Identity, not just presence: npm's unpatched tree-sitter.wasm at this path would ship the +// error-recovery livelock (docs/grammars/web-tree-sitter-runtime.md lists the sha256). +const RUNTIME_SHA256 = 'd48b82be2c17998ef4b2b9ab0cadbbd5ae838ef6ff0eca37b9c12ab887988d78'; +const runtimeSha = createHash('sha256').update(readFileSync(runtimeWasm)).digest('hex'); +if (runtimeSha !== RUNTIME_SHA256) { + fail( + `${runtimeWasm} is not the vendored runtime (sha256 ${runtimeSha.slice(0, 16)}…, want ${RUNTIME_SHA256.slice(0, 16)}…)`, + 'copy src/extraction/runtime/tree-sitter.wasm again (npm run copy-assets); if the runtime was rebuilt on purpose, update RUNTIME_SHA256 and the doc' + ); +} const grammarCount = readdirSync(wasmDir).filter((n) => n.endsWith('.wasm')).length; diff --git a/scripts/gen-go-stdlib-methods.mjs b/scripts/gen-go-stdlib-methods.mjs index 88f672b7a6..d208b43986 100644 --- a/scripts/gen-go-stdlib-methods.mjs +++ b/scripts/gen-go-stdlib-methods.mjs @@ -28,6 +28,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import { createRequire } from 'node:module'; import { fileURLToPath, pathToFileURL } from 'node:url'; +import { initVendoredRuntime } from './tree-sitter-runtime.mjs'; const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const MODULE = path.join(ROOT, 'src', 'resolution', 'go-stdlib-methods.ts'); @@ -52,7 +53,7 @@ const open = moduleText.indexOf('{', moduleText.indexOf('const GO_STDLIB_METHODS const close = moduleText.indexOf('\n};', open); const listed = new Function(`return ${moduleText.slice(open, close + 2)}`)(); -await Parser.init(); +await initVendoredRuntime(Parser); const parser = new Parser(); parser.setLanguage(await Language.load(wasm)); diff --git a/scripts/tree-sitter-runtime.mjs b/scripts/tree-sitter-runtime.mjs new file mode 100644 index 0000000000..768cdc11a4 --- /dev/null +++ b/scripts/tree-sitter-runtime.mjs @@ -0,0 +1,25 @@ +/** + * Initialize web-tree-sitter on CodeGraph's vendored runtime, the way + * src/extraction/grammars.ts initGrammars() does, for scripts that cannot import it. + * + * npm's tree-sitter.wasm (0.25.10) loops forever in error recovery on some broken + * input (tree-sitter/tree-sitter#5997); src/extraction/runtime/tree-sitter.wasm is the + * same build with the fix. See docs/grammars/web-tree-sitter-runtime.md. + */ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); + +export const RUNTIME_WASM_PATH = path.join(ROOT, 'src', 'extraction', 'runtime', 'tree-sitter.wasm'); + +/** `await Parser.init()` on the vendored runtime; throws if it is missing. */ +export async function initVendoredRuntime(Parser) { + if (!fs.existsSync(RUNTIME_WASM_PATH)) { + throw new Error(`tree-sitter runtime missing: ${RUNTIME_WASM_PATH}`); + } + await Parser.init({ + locateFile: (file, scriptDirectory) => (file === 'tree-sitter.wasm' ? RUNTIME_WASM_PATH : scriptDirectory + file), + }); +} diff --git a/scripts/ts-differential.mjs b/scripts/ts-differential.mjs index 7aaa0fdbdf..0bc0311ec9 100644 --- a/scripts/ts-differential.mjs +++ b/scripts/ts-differential.mjs @@ -68,6 +68,7 @@ import * as crypto from 'node:crypto'; import { createRequire } from 'node:module'; import { execFileSync, spawnSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; +import { initVendoredRuntime } from './tree-sitter-runtime.mjs'; const SELF = fileURLToPath(import.meta.url); const ROOT = path.resolve(path.dirname(SELF), '..'); @@ -377,7 +378,7 @@ async function main() { } } - await Parser.init(); + await initVendoredRuntime(Parser); const langs = { typescript: await Language.load(WASM.typescript), tsx: await Language.load(WASM.tsx), From 872fd58ae52c6914afe4b72322a6614d3fd0f479 Mon Sep 17 00:00:00 2001 From: Eric Minish Date: Fri, 6 Nov 2026 17:19:35 -0500 Subject: [PATCH 3/3] fix(kernel): guard the patched runtime in CI (PR #18 review round 2) - release gate runs tsx-error-recovery-hang.test.ts with CODEGRAPH_KERNEL_EXPECT=1; the test fails when EXPECT is set and no kernel is staged - sha256 pin on the vendored parser.c (runs without a kernel build; fails with the patch reverted) - kernel child asserts `defer` (the parse went through error recovery), not just done - tree-sitter = "=0.25.10" (the [patch] replaces exactly this version) - codegraph-kernel/vendor/** linguist-vendored; CHANGELOG entry trimmed to one sentence Release gate set (kernel built): 19 files, 319 passed. --- .gitattributes | 2 ++ .github/workflows/release.yml | 2 +- CHANGELOG.md | 2 +- __tests__/tsx-error-recovery-hang.test.ts | 31 ++++++++++++++++++----- codegraph-kernel/Cargo.toml | 3 ++- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/.gitattributes b/.gitattributes index a63fc54f57..e318b6b00f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,3 +7,5 @@ # reach the files inside it. codegraph-kernel/grammars/** linguist-vendored codegraph-kernel/grammars/**/parser.c linguist-generated +# The kernel's patched copy of the tree-sitter runtime crate (docs/grammars/web-tree-sitter-runtime.md). +codegraph-kernel/vendor/** linguist-vendored diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38b097e17a..6fafa24a3d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -188,7 +188,7 @@ jobs: if [ -f release/kernel/linux-x64/codegraph-kernel.node ]; then mkdir -p codegraph-kernel/prebuilds/linux-x64 cp release/kernel/linux-x64/codegraph-kernel.node codegraph-kernel/prebuilds/linux-x64/ - CODEGRAPH_KERNEL_EXPECT=1 npx vitest run __tests__/kernel-*.test.ts + CODEGRAPH_KERNEL_EXPECT=1 npx vitest run __tests__/kernel-*.test.ts __tests__/tsx-error-recovery-hang.test.ts else echo "::error::linux-x64 kernel prebuild missing despite required matrix" exit 1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 36616009f8..a8a2081894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixes -- A TSX file holding a broken JSX attribute such as `
c:d(e f)` no longer costs each index run three 30-second worker kills and then gets dropped. It now parses in milliseconds and is indexed like any other file with a syntax error. The hang was in tree-sitter's error recovery. CodeGraph now ships web-tree-sitter 0.25.10's runtime with the upstream fix (tree-sitter/tree-sitter#5997) applied, because 0.27.1, the first release that has it, cannot load most of the grammars CodeGraph uses. The native kernel builds against the same patched runtime. +- A TSX file with a broken JSX attribute such as `c:d(e f)` no longer stalls indexing for about 90 seconds and then drops out of the index; it is indexed like any other file with a syntax error. - TypeScript variance annotations like `interface Stream` or `` now parse. Before, each one was a parse error, and in a large file enough of them could make the whole file fail to parse and show up with almost no symbols. Re-index TypeScript projects after upgrading. - In TypeScript, an awaited call with type arguments like `await fetchApi("/me")` or `await api.get(url)` now links to the function it calls. Before, the call was dropped, so typed fetch wrappers looked like they had no callers. (#2586) - In JavaScript and TypeScript, a call or `new` in a parameter's default value, like `function renderWithNote(note = buildNote())`, a destructured `{ size = defaultSize() }` or `constructor(private svc = new Service())`, now counts as the function's own call. Before, it was dropped, so `buildNote` was missing that caller and impact on it came back incomplete. Re-index JavaScript and TypeScript projects after upgrading. Thanks @inth3shadows for the report and the pull request. (#2588) diff --git a/__tests__/tsx-error-recovery-hang.test.ts b/__tests__/tsx-error-recovery-hang.test.ts index 95cb68b856..866b6eeb6b 100644 --- a/__tests__/tsx-error-recovery-hang.test.ts +++ b/__tests__/tsx-error-recovery-hang.test.ts @@ -12,6 +12,7 @@ import { describe, it, expect, beforeAll } from 'vitest'; import * as fs from 'fs'; import * as path from 'path'; import { spawnSync } from 'child_process'; +import { createHash } from 'crypto'; import { initGrammars, loadGrammarsForLanguages, getParser, RUNTIME_WASM_PATH } from '../src/extraction/grammars'; import { parseWithinBudget } from '../src/extraction/parse-budget'; @@ -42,17 +43,35 @@ describe('vendored tree-sitter runtime', () => { // The native kernel links the same runtime C (codegraph-kernel/vendor/tree-sitter, patched). // A native parse cannot be cancelled from JS, so it runs in a child with a hard timeout. // The kernel throws `defer: parse tree contains errors` for an erroring tree (the file then -// goes to wasm): that is a finished parse, so it counts as done. +// goes to wasm): a finished parse that went through error recovery, which is what this pins. +// Only tsx + the first input hangs an unpatched kernel; the rest pin that recovery still errors. const KERNEL_PATH = path.join(__dirname, '..', 'codegraph-kernel', 'prebuilds', `${process.platform}-${process.arch}`, 'codegraph-kernel.node'); +const kernelBuilt = fs.existsSync(KERNEL_PATH); +const expectKernel = process.env.CODEGRAPH_KERNEL_EXPECT === '1'; const KERNEL_CHILD = ` const k = require(process.argv[1]); const [src, lang] = [process.argv[2], process.argv[3]]; -try { k.extractFile(lang === 'tsx' ? 'poc.tsx' : 'poc.ts', src, lang); } -catch (e) { if (!String(e && e.message).startsWith('defer:')) throw e; } -console.log('done'); +try { k.extractFile(lang === 'tsx' ? 'poc.tsx' : 'poc.ts', src, lang); console.log('clean'); } +catch (e) { if (!String(e && e.message).startsWith('defer:')) throw e; console.log('defer'); } `; -describe.skipIf(!fs.existsSync(KERNEL_PATH))('kernel: error recovery finishes on the same input', () => { +// The kernel's copy of the runtime C: crates.io tree-sitter 0.25.10 src/parser.c + the #5997 +// patch. Re-vendoring without the patch changes this hash; CI catches it without a kernel build. +const VENDORED_PARSER_C = path.join(__dirname, '..', 'codegraph-kernel', 'vendor', 'tree-sitter', 'src', 'parser.c'); +const VENDORED_PARSER_C_SHA256 = '612383a469d79c61f8b5b749714d60a6a85ca2b49c708e10ad0901be5b3987d0'; + +describe('kernel runtime', () => { + it('vendored parser.c carries the #5997 patch', () => { + const sha = createHash('sha256').update(fs.readFileSync(VENDORED_PARSER_C)).digest('hex'); + expect(sha, 'codegraph-kernel/vendor/tree-sitter/src/parser.c changed: re-apply docs/grammars/web-tree-sitter-runtime.patch, then update this hash').toBe(VENDORED_PARSER_C_SHA256); + }); + + it.runIf(expectKernel)('kernel binary must exist when CODEGRAPH_KERNEL_EXPECT=1', () => { + expect(kernelBuilt, `expected kernel at ${KERNEL_PATH} — run scripts/build-kernel.sh`).toBe(true); + }); +}); + +describe.skipIf(!kernelBuilt)('kernel: error recovery finishes on the same input', () => { it.each(['tsx', 'typescript'] as const)('%s', (language) => { for (const src of HANG_INPUTS) { const child = spawnSync(process.execPath, ['-e', KERNEL_CHILD, KERNEL_PATH, src, language], { @@ -60,7 +79,7 @@ describe.skipIf(!fs.existsSync(KERNEL_PATH))('kernel: error recovery finishes on timeout: 10_000, }); expect(child.error?.message, `${language}: ${JSON.stringify(src)} — kernel parse did not finish within 10s`).toBeUndefined(); - expect(child.stdout.trim(), child.stderr).toBe('done'); + expect(child.stdout.trim(), child.stderr).toBe('defer'); } }); }); diff --git a/codegraph-kernel/Cargo.toml b/codegraph-kernel/Cargo.toml index 65fbc4659a..708956520f 100644 --- a/codegraph-kernel/Cargo.toml +++ b/codegraph-kernel/Cargo.toml @@ -12,7 +12,8 @@ crate-type = ["cdylib"] [dependencies] napi = { version = "3", default-features = false, features = ["napi8"] } napi-derive = "3" -tree-sitter = "0.25" +# Exact: the [patch.crates-io] entry below replaces exactly this version. +tree-sitter = "=0.25.10" sha2 = "0.10" regex = "1"