galley-js-node 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # JavaScript Bindings for Node
2
+
3
+ `galley-js-core` over koffi FFI and `bindings/c/galley.h`.
4
+
5
+ See `docs/bindings_typescript.md` and `examples/js/node` for the consumer flow.
6
+
7
+ One shared library embeds one parser; sessions are not thread-safe.
package/build.mjs ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Builds a Galley parser and its shared library for a JavaScript consumer
4
+ * on Node.
5
+ *
6
+ * Usage:
7
+ * npx galley-js-node <language-dir>
8
+ *
9
+ * Thin wrapper over the shared gate (`galley-js-core/build/builder.mjs`),
10
+ * which documents the accepted grammar files and owns the build. For both
11
+ * legs at once, use the single entry instead: `galley build <language-dir>`
12
+ * from `@sanbus-org/galley`.
13
+ */
14
+
15
+ import * as path from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ import { buildParserArtifact } from "galley-js-core/build/builder.mjs";
18
+
19
+ const LIBRARY_NAME = "galley-js-node";
20
+
21
+ function fatal(message) {
22
+ console.error(`galley-bindings: ${message}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ async function main() {
27
+ if (process.argv.length !== 3) fatal("usage: npx galley-js-node <language-dir>");
28
+ await buildParserArtifact({
29
+ languageDirectory: process.argv[2],
30
+ libraryName: LIBRARY_NAME,
31
+ bindingsDirectory: path.dirname(fileURLToPath(import.meta.url)),
32
+ dependencyName: "koffi",
33
+ });
34
+ }
35
+
36
+ main().catch((error) => fatal(error?.message ?? String(error)));
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Node procedure-dispatch installer.
3
+ *
4
+ * Owns the koffi callback that the shared JS shim
5
+ * (`galley_install_js_dispatch_id`, generated by `galley-js-core/build/shim.mjs`)
6
+ * forwards every parser hook through, plus the `require()`-based auto-scan
7
+ * of `procedures.*` in the language directory. The registry and the
8
+ * ID-to-name dispatcher live in the core; this module only bridges the
9
+ * native boundary. Libraries that predate integer hook IDs still export
10
+ * the name-carrying `galley_install_js_dispatch`, used as a fallback.
11
+ */
12
+ import type { FfiPort } from "galley-js-core";
13
+ import { type GalleyFFI } from "./ffi.ts";
14
+ export declare function ensureDispatchFor(foreignInterface: GalleyFFI, port: FfiPort): void;
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Node procedure-dispatch installer.
3
+ *
4
+ * Owns the koffi callback that the shared JS shim
5
+ * (`galley_install_js_dispatch_id`, generated by `galley-js-core/build/shim.mjs`)
6
+ * forwards every parser hook through, plus the `require()`-based auto-scan
7
+ * of `procedures.*` in the language directory. The registry and the
8
+ * ID-to-name dispatcher live in the core; this module only bridges the
9
+ * native boundary. Libraries that predate integer hook IDs still export
10
+ * the name-carrying `galley_install_js_dispatch`, used as a fallback.
11
+ */
12
+ import { createRequire } from "node:module";
13
+ import * as path from "node:path";
14
+ const require = createRequire(import.meta.url);
15
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
16
+ const koffi = require("koffi");
17
+ import { dispatchProcedure, installProcedures, listProcedures } from "galley-js-core";
18
+ import { copyStringBytes } from "./ffi.js";
19
+ // Held to prevent GC of the koffi callbacks; installed per library path.
20
+ // ID and name paths keep separate slots: their signatures differ.
21
+ let dispatchIdCallback = null;
22
+ let dispatchCallback = null;
23
+ const installedFor = new Set();
24
+ let autoAttempted = false;
25
+ function isProcedureName(name) {
26
+ return name === "reduction" || name.startsWith("reduction_") || name.startsWith("hook_");
27
+ }
28
+ function tryAutoRegister(foreignInterface) {
29
+ if (listProcedures().length > 0 || autoAttempted)
30
+ return;
31
+ autoAttempted = true;
32
+ const tryLoadModule = (modulePath) => {
33
+ try {
34
+ const loadedModule = require(modulePath);
35
+ let hasHook = false;
36
+ for (const [name, value] of Object.entries(loadedModule)) {
37
+ if (typeof value !== "function" || !isProcedureName(name))
38
+ continue;
39
+ hasHook = true;
40
+ break;
41
+ }
42
+ if (hasHook)
43
+ return installProcedures(loadedModule) > 0;
44
+ const defaultExport = loadedModule.default;
45
+ if (defaultExport && typeof defaultExport === "object") {
46
+ return installProcedures(defaultExport) > 0;
47
+ }
48
+ }
49
+ catch { }
50
+ return false;
51
+ };
52
+ // One place: the directory holding the loaded library. Anything found
53
+ // there belongs to this grammar; nothing else is even looked at.
54
+ const baseDirectory = path.dirname(foreignInterface.libPath);
55
+ const extensions = ["", ".js", ".ts"];
56
+ for (const extension of extensions) {
57
+ if (tryLoadModule(path.join(baseDirectory, `procedures${extension}`)))
58
+ return;
59
+ }
60
+ }
61
+ export function ensureDispatchFor(foreignInterface, port) {
62
+ // Option B: auto — if no explicit hooks yet, try to auto-discover procedures.* in language dir
63
+ tryAutoRegister(foreignInterface);
64
+ const useIds = foreignInterface.galley_install_js_dispatch_id !== null &&
65
+ typeof port.procedureNames === "function" &&
66
+ port.procedureNames().length > 0;
67
+ if (!useIds && foreignInterface.galley_install_js_dispatch === null) {
68
+ // Library was built for C procedures (no shim); installs will be no-ops.
69
+ return;
70
+ }
71
+ if (installedFor.has(foreignInterface.libPath))
72
+ return;
73
+ if (useIds) {
74
+ installIdDispatch(foreignInterface, port);
75
+ }
76
+ else {
77
+ installNameDispatch(foreignInterface, port);
78
+ }
79
+ installedFor.add(foreignInterface.libPath);
80
+ }
81
+ function installIdDispatch(foreignInterface, port) {
82
+ if (dispatchIdCallback === null) {
83
+ // Integer hook IDs: no string copy or decode on the hot path. The table
84
+ // is fixed per library build; unknown IDs are silent no-ops.
85
+ const table = port.procedureNames();
86
+ const proto = koffi.proto("void DispatchId(uint32_t id, void *args)");
87
+ const cb = koffi.register((id, argsPtr) => {
88
+ const name = table[typeof id === "bigint" ? Number(id) : id];
89
+ if (name === undefined)
90
+ return;
91
+ let argsAddr = 0n;
92
+ if (argsPtr !== null && argsPtr !== undefined) {
93
+ try {
94
+ argsAddr = typeof argsPtr === "bigint" ? argsPtr : BigInt(argsPtr);
95
+ }
96
+ catch {
97
+ argsAddr = 0n;
98
+ }
99
+ }
100
+ dispatchProcedure(name, argsAddr, port);
101
+ }, koffi.pointer(proto));
102
+ // Prevent GC — registered callbacks must stay reachable; koffi holds the
103
+ // trampoline, but we keep the address alive as well.
104
+ globalThis.__galley_js_dispatchIdCallback = cb;
105
+ dispatchIdCallback = cb;
106
+ }
107
+ foreignInterface.galley_install_js_dispatch_id(dispatchIdCallback);
108
+ }
109
+ function installNameDispatch(foreignInterface, port) {
110
+ if (dispatchCallback === null) {
111
+ // Create single global dispatcher. Uses registered callback (must persist
112
+ // beyond the installer call, unlike transient callbacks). Signature mirrors
113
+ // Zig: fn([*]const u8, usize, ?*anyopaque) callconv(.c) void — void* for
114
+ // the name pointer keeps it as a raw address with length.
115
+ const proto = koffi.proto("void Dispatch(void *name_ptr, size_t name_len, void *args)");
116
+ const cb = koffi.register((namePtr, nameLen, argsPtr) => {
117
+ let name;
118
+ try {
119
+ // Registered callbacks receive pointer values as BigInt (or null).
120
+ const ptrVal = typeof namePtr === "bigint" ? namePtr : BigInt(namePtr);
121
+ const lenVal = typeof nameLen === "bigint" ? nameLen : nameLen;
122
+ name = copyStringBytes(ptrVal, lenVal);
123
+ }
124
+ catch (e) {
125
+ console.error("galley procedure dispatch: failed to decode name", e);
126
+ return;
127
+ }
128
+ let argsAddr = 0n;
129
+ if (argsPtr !== null && argsPtr !== undefined) {
130
+ try {
131
+ argsAddr = typeof argsPtr === "bigint" ? argsPtr : BigInt(argsPtr);
132
+ }
133
+ catch {
134
+ argsAddr = 0n;
135
+ }
136
+ }
137
+ dispatchProcedure(name, argsAddr, port);
138
+ }, koffi.pointer(proto));
139
+ // Prevent GC — registered callbacks must stay reachable; koffi holds the
140
+ // trampoline, but we keep the address alive as well.
141
+ globalThis.__galley_js_dispatchCallback = cb;
142
+ dispatchCallback = cb;
143
+ }
144
+ foreignInterface.galley_install_js_dispatch(dispatchCallback);
145
+ }
146
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"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"}
package/dist/ffi.d.ts ADDED
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Node adapter for the Galley JavaScript bindings: low-level koffi bindings
3
+ * over `bindings/c/galley.h`, implementing the core `FfiPort`.
4
+ *
5
+ * This is the single FFI boundary for the Node runtime (mirroring
6
+ * `bindings/python/_galley.c` and `bindings/go/assets/wrapper.go.tmpl`).
7
+ * Library discovery, memory copying, and integer normalization live here;
8
+ * all session logic lives in `galley-js-core`. No caller touches koffi
9
+ * directly outside this module and `dispatch.ts`.
10
+ */
11
+ import type { FfiPort, Handle, SessionCOptions, TreeSnapshot, WalkedStep } from "galley-js-core";
12
+ declare const koffi: typeof import("koffi");
13
+ export type LibraryHandle = ReturnType<typeof koffi.load>;
14
+ export interface GalleyFFI {
15
+ libPath: string;
16
+ lib: LibraryHandle;
17
+ galley_version: () => string;
18
+ galley_parser_type: () => bigint | number;
19
+ galley_error_recovery_mode: () => bigint | number;
20
+ galley_has_ast: () => number;
21
+ galley_has_procedures: () => number;
22
+ galley_allows_no_ast_tree_procedures: () => number;
23
+ galley_source_retention_enabled: () => number;
24
+ galley_has_position_tracking: () => number;
25
+ galley_has_input_streaming: () => number;
26
+ galley_uses_verbatim: () => number;
27
+ galley_stack_overflow_recovery_available: () => number;
28
+ galley_symbol_count: () => bigint | number;
29
+ galley_variable_count: () => bigint | number;
30
+ galley_status_string: (status: bigint | number) => string | null;
31
+ galley_symbol_name: (session: bigint, index: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
32
+ galley_symbol_is_terminal: (session: bigint, index: bigint | number) => number;
33
+ galley_variable_name: (session: bigint, index: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
34
+ galley_session_create: () => bigint;
35
+ galley_session_create_ex: (options: unknown) => bigint;
36
+ galley_session_destroy: (session: bigint) => void;
37
+ galley_session_set_message_override: (session: bigint, name: string, nameLen: number | bigint, message: string, messageLen: number | bigint) => bigint | number;
38
+ galley_parse_sentinel: (session: bigint, input: string) => bigint | number;
39
+ galley_parse: (session: bigint, data: unknown, len: number | bigint) => bigint | number;
40
+ galley_parse_file: (session: bigint, p: string) => bigint | number;
41
+ galley_last_position: (session: bigint, outLine: unknown[], outCol: unknown[]) => bigint | number;
42
+ galley_node_count: (session: bigint) => bigint | number;
43
+ galley_reserve_nodes: (session: bigint, cap: bigint | number) => bigint | number;
44
+ galley_node_capacity: (session: bigint) => bigint | number;
45
+ galley_root_node: (session: bigint) => bigint | number;
46
+ galley_node_is_valid: (session: bigint, node: bigint | number) => number;
47
+ galley_node_child_count: (session: bigint, node: bigint | number) => number;
48
+ galley_node_first_child: (session: bigint, node: bigint | number) => bigint | number;
49
+ galley_node_last_child: (session: bigint, node: bigint | number) => bigint | number;
50
+ galley_node_next_sibling: (session: bigint, node: bigint | number) => bigint | number;
51
+ galley_node_prior_sibling: (session: bigint, node: bigint | number) => bigint | number;
52
+ galley_node_parent: (session: bigint, node: bigint | number) => bigint | number;
53
+ galley_walker_create: (session: bigint, node: bigint | number, skipSemanticErrors: number) => bigint;
54
+ galley_walker_next: (walker: bigint, outNode: unknown[], outDepth: unknown[], outIsSemanticError: unknown[]) => number;
55
+ galley_walker_skip_children: (walker: bigint) => void;
56
+ galley_walker_destroy: (walker: bigint) => void;
57
+ galley_node_symbol_name: (session: bigint, node: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
58
+ galley_node_text: (session: bigint, node: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
59
+ galley_node_span: (session: bigint, node: bigint | number, outStart: unknown[], outLen: unknown[]) => bigint | number;
60
+ galley_node_line_column: (session: bigint, node: bigint | number, outLine: unknown[], outCol: unknown[]) => bigint | number;
61
+ galley_node_variable_index: (session: bigint, node: bigint | number) => bigint | number;
62
+ galley_tree_snapshot: (session: bigint, outParent: BigUint64Array, outFirstChild: BigUint64Array, outNext: BigUint64Array, outChildCount: Uint32Array, outVariable: BigInt64Array, outSpanStart: BigUint64Array, outSpanLen: BigUint64Array, capacity: bigint | number) => bigint | number;
63
+ galley_has_diagnostic: (session: bigint) => number;
64
+ galley_diagnostic_kind: (session: bigint) => bigint | number;
65
+ galley_diagnostic_message: (session: bigint, out: unknown[]) => bigint | number;
66
+ galley_diagnostic_message_ansi: (session: bigint, out: unknown[]) => bigint | number;
67
+ galley_diagnostic_position: (session: bigint, outLine: unknown[], outCol: unknown[]) => bigint | number;
68
+ galley_diagnostic_unexpected_token: (session: bigint, outData: unknown[], outLen: unknown[]) => bigint | number;
69
+ galley_diagnostic_expected_count: (session: bigint) => bigint | number;
70
+ galley_diagnostic_expected_at: (session: bigint, index: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
71
+ galley_diagnostic_context_count: (session: bigint) => bigint | number;
72
+ galley_diagnostic_context_at: (session: bigint, index: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
73
+ galley_diagnostic_indentation: (session: bigint, outSpaces: unknown[], outWidth: unknown[]) => bigint | number;
74
+ galley_syntax_error_count: (session: bigint) => bigint | number;
75
+ galley_semantic_error_count: (session: bigint) => bigint | number;
76
+ galley_diagnostic_semantic: (session: bigint, outVariable: unknown[], outVariableLen: unknown[], outMessage: unknown[], outMessageLen: unknown[]) => bigint | number;
77
+ galley_recorded_semantic: (session: bigint, diagIndex: bigint | number, outVariable: unknown[], outVariableLen: unknown[], outMessage: unknown[], outMessageLen: unknown[]) => bigint | number;
78
+ galley_diagnostic_recovery_kind: (session: bigint) => bigint | number;
79
+ galley_diagnostic_recovery_terminal: (session: bigint, outData: unknown[], outLen: unknown[]) => bigint | number;
80
+ galley_diagnostic_recovery_resume: (session: bigint, out: unknown[]) => bigint | number;
81
+ galley_diagnostic_recovery_lhs_variable: (session: bigint, outData: unknown[], outLen: unknown[]) => bigint | number;
82
+ galley_diagnostic_recovery_production: (session: bigint, outVar: unknown[], outLen: unknown[], outIndex: unknown[]) => bigint | number;
83
+ galley_diagnostic_recovery_occurrence: (session: bigint, outParent: unknown[], outParentLen: unknown[], outRhs: unknown[], outSym: unknown[], outVar: unknown[], outVarLen: unknown[]) => bigint | number;
84
+ galley_recorded_diagnostic_count: (session: bigint) => bigint | number;
85
+ galley_recorded_diagnostic_kind: (session: bigint, idx: bigint | number) => bigint | number;
86
+ galley_recorded_diagnostic_position: (session: bigint, idx: bigint | number, outLine: unknown[], outCol: unknown[]) => bigint | number;
87
+ galley_recorded_unexpected_token: (session: bigint, idx: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
88
+ galley_recorded_diagnostic_message: (session: bigint, idx: bigint | number, out: unknown[]) => bigint | number;
89
+ galley_recorded_indentation: (session: bigint, idx: bigint | number, outSpaces: unknown[], outWidth: unknown[]) => bigint | number;
90
+ galley_recorded_expected_count: (session: bigint, idx: bigint | number) => bigint | number;
91
+ galley_recorded_expected_token: (session: bigint, idx: bigint | number, tokenIdx: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
92
+ galley_recorded_context_count: (session: bigint, idx: bigint | number) => bigint | number;
93
+ galley_recorded_context_name: (session: bigint, idx: bigint | number, ctxIdx: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
94
+ galley_recorded_recovery_kind: (session: bigint, idx: bigint | number) => bigint | number;
95
+ galley_recorded_recovery_terminal: (session: bigint, idx: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
96
+ galley_recorded_recovery_resume: (session: bigint, idx: bigint | number, out: unknown[]) => bigint | number;
97
+ galley_recorded_recovery_lhs_variable: (session: bigint, idx: bigint | number, outData: unknown[], outLen: unknown[]) => bigint | number;
98
+ galley_recorded_recovery_production: (session: bigint, idx: bigint | number, outVar: unknown[], outLen: unknown[], outIdx: unknown[]) => bigint | number;
99
+ galley_recorded_recovery_occurrence: (session: bigint, idx: bigint | number, outParent: unknown[], outParentLen: unknown[], outRhs: unknown[], outSym: unknown[], outVar: unknown[], outVarLen: unknown[]) => bigint | number;
100
+ galley_tree_append_children: (session: bigint, parent: bigint | number, first: bigint | number) => bigint | number;
101
+ galley_tree_insert_before: (session: bigint, target: bigint | number, first: bigint | number) => bigint | number;
102
+ galley_tree_insert_after: (session: bigint, target: bigint | number, first: bigint | number) => bigint | number;
103
+ galley_tree_remove_siblings: (session: bigint, node: bigint | number, count: number | bigint, outHead: unknown[]) => bigint | number;
104
+ galley_tree_remove_self: (session: bigint, node: bigint | number, outHead: unknown[]) => bigint | number;
105
+ galley_tree_promote_children_over_wrapper: (session: bigint, wrapper: bigint | number, outHead: unknown[]) => bigint | number;
106
+ galley_tree_clean_children: (session: bigint, node: bigint | number, outHead: unknown[]) => bigint | number;
107
+ galley_tree_unlink_wrapper: (session: bigint, wrapper: bigint | number) => bigint | number;
108
+ galley_tree_insert_children_at: (session: bigint, parent: bigint | number, index: number | bigint, first: bigint | number) => bigint | number;
109
+ galley_tree_remove_children_at: (session: bigint, parent: bigint | number, index: number | bigint, count: number | bigint, outHead: unknown[]) => bigint | number;
110
+ galley_install_js_dispatch_id: ((target: unknown) => void) | null;
111
+ galley_install_js_dispatch: ((target: unknown) => void) | null;
112
+ galley_js_procedure_count: (() => number | bigint) | null;
113
+ galley_js_procedure_name_ptr: ((index: number) => bigint) | null;
114
+ galley_js_procedure_name_len: ((index: number) => number | bigint) | null;
115
+ galley_js_procedure_enable: ((name: string, nameLen: number | bigint) => number | bigint) | null;
116
+ galley_js_procedure_clear: (() => void) | null;
117
+ galley_procedure_session: (args: bigint) => bigint;
118
+ galley_procedure_current_node: (args: bigint) => bigint;
119
+ galley_procedure_set_current_node: (args: bigint, node: bigint | number) => void;
120
+ galley_procedure_drop_self: (args: bigint) => bigint | number;
121
+ galley_procedure_drop_children: (args: bigint) => bigint | number;
122
+ galley_procedure_drop_if_empty: (args: bigint) => bigint | number;
123
+ galley_procedure_replace_with_children: (args: bigint) => bigint | number;
124
+ galley_procedure_context_line: (args: bigint) => number;
125
+ galley_procedure_context_column: (args: bigint) => number;
126
+ galley_procedure_report_semantic_error: (args: bigint, message: string, messageLen: number | bigint) => bigint | number;
127
+ GalleyCOptions: ReturnType<typeof koffi.struct>;
128
+ }
129
+ export declare function libFileName(base?: string): string;
130
+ export declare function findLibrary(explicit?: string): string;
131
+ export declare function loadLibrary(explicitPath?: string): GalleyFFI;
132
+ export declare function toBigInt(v: bigint | number): bigint;
133
+ export declare function isOk(status: bigint | number): boolean;
134
+ export declare function toNumber(v: bigint | number): number;
135
+ /** Copy (ptr,len) into Uint8Array owning its bytes. */
136
+ export declare function copyBytes(ptr: bigint, len: bigint | number): Uint8Array;
137
+ export declare function copyStringBytes(ptr: bigint, len: bigint | number): string;
138
+ /**
139
+ * Node's {@link FfiPort}: normalizes koffi's `bigint | number` unions and
140
+ * `_Out_` arrays into the structured values the core expects. All memory
141
+ * copying happens here; the core only sees owned bytes.
142
+ */
143
+ export declare class NodePort implements FfiPort {
144
+ #private;
145
+ readonly ffi: GalleyFFI;
146
+ readonly libraryPath: string;
147
+ constructor(ffi: GalleyFFI);
148
+ version(): string;
149
+ parserType(): number;
150
+ errorRecoveryMode(): number;
151
+ hasAst(): boolean;
152
+ hasProcedures(): boolean;
153
+ allowsNoAstTreeProcedures(): boolean;
154
+ sourceRetentionEnabled(): boolean;
155
+ hasPositionTracking(): boolean;
156
+ hasInputStreaming(): boolean;
157
+ usesVerbatim(): boolean;
158
+ stackOverflowRecoveryAvailable(): boolean;
159
+ symbolCount(): number;
160
+ variableCount(): number;
161
+ statusString(status: number): string | null;
162
+ createSession(options: SessionCOptions | null): Handle;
163
+ destroySession(handle: Handle): void;
164
+ setMessageOverride(handle: Handle, name: Uint8Array, message: Uint8Array): number;
165
+ parse(handle: Handle, data: Uint8Array): number;
166
+ parseFile(handle: Handle, filePath: string): number;
167
+ lastPosition(handle: Handle): [number, number] | null;
168
+ nodeCount(handle: Handle): number;
169
+ reserveNodes(handle: Handle, capacity: bigint): number;
170
+ nodeCapacity(handle: Handle): number;
171
+ rootNode(handle: Handle): bigint;
172
+ nodeValid(handle: Handle, node: bigint): boolean;
173
+ childCount(handle: Handle, node: bigint): number;
174
+ firstChild(handle: Handle, node: bigint): bigint;
175
+ lastChild(handle: Handle, node: bigint): bigint;
176
+ nextSibling(handle: Handle, node: bigint): bigint;
177
+ priorSibling(handle: Handle, node: bigint): bigint;
178
+ parent(handle: Handle, node: bigint): bigint;
179
+ treeSnapshot(handle: Handle): TreeSnapshot;
180
+ walkerCreate(handle: Handle, node: bigint, skipSemanticErrors: boolean): Handle | null;
181
+ walkerNext(walker: Handle): WalkedStep | null;
182
+ walkerSkipChildren(walker: Handle): void;
183
+ walkerDestroy(walker: Handle): void;
184
+ nodeSymbolName(handle: Handle, node: bigint): Uint8Array | null;
185
+ nodeText(handle: Handle, node: bigint): Uint8Array | null;
186
+ nodeSpan(handle: Handle, node: bigint): [bigint, bigint] | null;
187
+ nodeLineColumn(handle: Handle, node: bigint): [number, number] | null;
188
+ nodeVariableIndex(handle: Handle, node: bigint): number;
189
+ symbolNameAt(handle: Handle, index: number): Uint8Array | null;
190
+ symbolIsTerminal(handle: Handle, index: number): boolean;
191
+ variableNameAt(handle: Handle, index: number): Uint8Array | null;
192
+ hasDiagnostic(handle: Handle): boolean;
193
+ diagnosticKind(handle: Handle): number;
194
+ diagnosticMessage(handle: Handle): string | null;
195
+ diagnosticMessageAnsi(handle: Handle): string | null;
196
+ diagnosticPosition(handle: Handle): [number, number] | null;
197
+ diagnosticUnexpectedToken(handle: Handle): Uint8Array | null;
198
+ diagnosticExpectedCount(handle: Handle): number;
199
+ diagnosticExpectedAt(handle: Handle, index: number): Uint8Array | null;
200
+ diagnosticContextCount(handle: Handle): number;
201
+ diagnosticContextAt(handle: Handle, index: number): Uint8Array | null;
202
+ syntaxErrorCount(handle: Handle): number;
203
+ semanticErrorCount(handle: Handle): number;
204
+ diagnosticSemantic(handle: Handle): [string, string] | null;
205
+ diagnosticIndentation(handle: Handle): [number, number] | null;
206
+ diagnosticRecoveryKind(handle: Handle): number;
207
+ diagnosticRecoveryTerminal(handle: Handle): Uint8Array | null;
208
+ diagnosticRecoveryResume(handle: Handle): number | null;
209
+ diagnosticRecoveryLhsVariable(handle: Handle): string | null;
210
+ diagnosticRecoveryProduction(handle: Handle): [string, number] | null;
211
+ diagnosticRecoveryOccurrence(handle: Handle): [string, number, number, string] | null;
212
+ recordedDiagnosticCount(handle: Handle): number;
213
+ recordedDiagnosticKind(handle: Handle, diagIndex: number): number;
214
+ recordedDiagnosticPosition(handle: Handle, diagIndex: number): [number, number] | null;
215
+ recordedUnexpectedToken(handle: Handle, diagIndex: number): Uint8Array | null;
216
+ recordedDiagnosticMessage(handle: Handle, diagIndex: number): string | null;
217
+ recordedIndentation(handle: Handle, diagIndex: number): [number, number] | null;
218
+ recordedSemantic(handle: Handle, diagIndex: number): [string, string] | null;
219
+ recordedExpectedCount(handle: Handle, diagIndex: number): number;
220
+ recordedExpectedToken(handle: Handle, diagIndex: number, tokenIndex: number): Uint8Array | null;
221
+ recordedContextCount(handle: Handle, diagIndex: number): number;
222
+ recordedContextName(handle: Handle, diagIndex: number, contextIndex: number): Uint8Array | null;
223
+ recordedRecoveryKind(handle: Handle, diagIndex: number): number;
224
+ recordedRecoveryTerminal(handle: Handle, diagIndex: number): Uint8Array | null;
225
+ recordedRecoveryResume(handle: Handle, diagIndex: number): number | null;
226
+ recordedRecoveryLhsVariable(handle: Handle, diagIndex: number): string | null;
227
+ recordedRecoveryProduction(handle: Handle, diagIndex: number): [string, number] | null;
228
+ recordedRecoveryOccurrence(handle: Handle, diagIndex: number): [string, number, number, string] | null;
229
+ treeAppendChildren(handle: Handle, parent: bigint, first: bigint): number;
230
+ treeInsertBefore(handle: Handle, target: bigint, first: bigint): number;
231
+ treeInsertAfter(handle: Handle, target: bigint, first: bigint): number;
232
+ treeRemoveSiblings(handle: Handle, node: bigint, count: number): {
233
+ status: number;
234
+ head: bigint;
235
+ };
236
+ treeRemoveSelf(handle: Handle, node: bigint): {
237
+ status: number;
238
+ head: bigint;
239
+ };
240
+ treePromoteChildrenOverWrapper(handle: Handle, wrapper: bigint): {
241
+ status: number;
242
+ head: bigint;
243
+ };
244
+ treeCleanChildren(handle: Handle, node: bigint): {
245
+ status: number;
246
+ head: bigint;
247
+ };
248
+ treeUnlinkWrapper(handle: Handle, wrapper: bigint): number;
249
+ treeInsertChildrenAt(handle: Handle, parent: bigint, index: number, first: bigint): number;
250
+ treeRemoveChildrenAt(handle: Handle, parent: bigint, index: number, count: number): {
251
+ status: number;
252
+ head: bigint;
253
+ };
254
+ procCurrentNode(args: Handle): bigint;
255
+ procSetCurrentNode(args: Handle, node: bigint): void;
256
+ procDropSelf(args: Handle): number;
257
+ procDropChildren(args: Handle): number;
258
+ procDropIfEmpty(args: Handle): number;
259
+ procReplaceWithChildren(args: Handle): number;
260
+ procContextLine(args: Handle): number;
261
+ procContextColumn(args: Handle): number;
262
+ procReportSemanticError(args: Handle, message: Uint8Array): number;
263
+ syncProcedures(names: string[]): void;
264
+ procedureNames(): string[];
265
+ }
266
+ /** Port for the library at `explicitPath` (or default discovery), cached per path. */
267
+ export declare function getNodePort(explicitPath?: string): NodePort;
268
+ export {};