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 +7 -0
- package/build.mjs +36 -0
- package/dist/dispatch.d.ts +14 -0
- package/dist/dispatch.js +146 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/ffi.d.ts +268 -0
- package/dist/ffi.js +842 -0
- package/dist/ffi.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/session.d.ts +13 -0
- package/dist/session.js +25 -0
- package/dist/session.js.map +1 -0
- package/package.json +49 -0
- package/src/dispatch.ts +147 -0
- package/src/ffi.ts +1498 -0
- package/src/index.ts +79 -0
- package/src/session.ts +28 -0
package/README.md
ADDED
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;
|
package/dist/dispatch.js
ADDED
|
@@ -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 {};
|