@sanbus/galley-bun 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 +8 -0
- package/build.mjs +85 -0
- package/dist/dispatch.d.ts +15 -0
- package/dist/dispatch.js +135 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/ffi.d.ts +255 -0
- package/dist/ffi.js +794 -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 +23 -0
- package/dist/session.js.map +1 -0
- package/package.json +49 -0
- package/src/dispatch.ts +146 -0
- package/src/ffi.ts +1036 -0
- package/src/index.ts +79 -0
- package/src/session.ts +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# JavaScript Bindings for Bun
|
|
2
|
+
|
|
3
|
+
`@sanbus/galley-core` over `bun:ffi` and `bindings/c/galley.h`. No native
|
|
4
|
+
dependencies beyond the built parser library.
|
|
5
|
+
|
|
6
|
+
See `docs/bindings_js_bun.md` and `examples/js/bun` for the consumer flow.
|
|
7
|
+
|
|
8
|
+
One shared library embeds one parser; sessions are not thread-safe.
|
package/build.mjs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Builds a Galley parser and its shared library for a JavaScript consumer
|
|
4
|
+
* on Bun.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx galley-js-bun <language-dir>
|
|
8
|
+
*
|
|
9
|
+
* Thin wrapper over the shared gate (`@sanbus/galley-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/galley`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import * as fs from "node:fs";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
18
|
+
import { buildParserArtifact } from "@sanbus/galley-core/build/builder.mjs";
|
|
19
|
+
|
|
20
|
+
const LIBRARY_NAME = "galley-js-bun";
|
|
21
|
+
|
|
22
|
+
function fatal(message) {
|
|
23
|
+
console.error(`galley-bindings: ${message}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function main() {
|
|
28
|
+
if (process.argv.length !== 3) fatal("usage: npx galley-js-bun <language-dir>");
|
|
29
|
+
const bindingsDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const languageDirectory = path.resolve(process.argv[2]);
|
|
31
|
+
await buildParserArtifact({
|
|
32
|
+
languageDirectory,
|
|
33
|
+
libraryName: LIBRARY_NAME,
|
|
34
|
+
bindingsDirectory,
|
|
35
|
+
dependencyName: "@sanbus/galley-core",
|
|
36
|
+
installCommand: "bun install",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Bun snapshots `file:` dependencies into node_modules at install time,
|
|
40
|
+
// so a consumer's copy can predate the build outputs (dist/ and the
|
|
41
|
+
// nested @sanbus/galley-core, materialized above, after install) and fail
|
|
42
|
+
// resolution with "Cannot find package". Refresh every snapshot copy
|
|
43
|
+
// reachable from this build: the language dir's own and the invoking
|
|
44
|
+
// directory's (the benchmark flow builds benchmark/ while resolving
|
|
45
|
+
// through the parent example dir). The npm-based adapters symlink
|
|
46
|
+
// `file:` dirs and never need this. This stays in the wrapper: it is a
|
|
47
|
+
// Bun install-layout quirk, not build semantics.
|
|
48
|
+
const refreshed = new Set();
|
|
49
|
+
for (const rootDirectory of [languageDirectory, process.cwd()]) {
|
|
50
|
+
const resolved = path.resolve(rootDirectory);
|
|
51
|
+
if (refreshed.has(resolved)) continue;
|
|
52
|
+
refreshed.add(resolved);
|
|
53
|
+
refreshSnapshot(resolved, bindingsDirectory);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function refreshSnapshot(rootDirectory, bindingsDirectory) {
|
|
58
|
+
const snapshotDirectory = path.join(rootDirectory, "node_modules", "@sanbus/galley-bun");
|
|
59
|
+
const snapshotPackage = path.join(snapshotDirectory, "package.json");
|
|
60
|
+
if (!fs.existsSync(snapshotPackage)) return;
|
|
61
|
+
// Only touch our own snapshot copy, never an unrelated registry install.
|
|
62
|
+
const bindingsPackage = JSON.parse(fs.readFileSync(path.join(bindingsDirectory, "package.json"), "utf-8"));
|
|
63
|
+
const snapshotManifest = JSON.parse(fs.readFileSync(snapshotPackage, "utf-8"));
|
|
64
|
+
if (
|
|
65
|
+
snapshotManifest.name !== bindingsPackage.name ||
|
|
66
|
+
snapshotManifest.version !== bindingsPackage.version
|
|
67
|
+
)
|
|
68
|
+
return;
|
|
69
|
+
const snapshotDist = path.join(snapshotDirectory, "dist");
|
|
70
|
+
fs.rmSync(snapshotDist, { recursive: true, force: true });
|
|
71
|
+
fs.cpSync(path.join(bindingsDirectory, "dist"), snapshotDist, { recursive: true });
|
|
72
|
+
console.log(`galley-bindings: refreshed ${snapshotDist}`);
|
|
73
|
+
const snapshotCore = path.join(snapshotDirectory, "node_modules", "@sanbus/galley-core");
|
|
74
|
+
fs.rmSync(snapshotCore, { recursive: true, force: true });
|
|
75
|
+
fs.mkdirSync(path.join(snapshotDirectory, "node_modules"), { recursive: true });
|
|
76
|
+
// Dereference: the source entry is usually a symlink into the checkout,
|
|
77
|
+
// which would dangle from inside the snapshot.
|
|
78
|
+
fs.cpSync(path.join(bindingsDirectory, "node_modules", "@sanbus/galley-core"), snapshotCore, {
|
|
79
|
+
recursive: true,
|
|
80
|
+
dereference: true,
|
|
81
|
+
});
|
|
82
|
+
console.log(`galley-bindings: refreshed ${snapshotCore}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
main().catch((error) => fatal(error?.message ?? String(error)));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun procedure-dispatch installer.
|
|
3
|
+
*
|
|
4
|
+
* Owns the `JSCallback` that the shared JS shim
|
|
5
|
+
* (`galley_install_js_dispatch_id`, generated by `@sanbus/galley-core/build/shim.mjs`)
|
|
6
|
+
* forwards every parser hook through, plus the `require()`-based auto-scan
|
|
7
|
+
* of `procedures.*` in the language directory (Bun loads TypeScript
|
|
8
|
+
* synchronously, like Node). The registry and the ID-to-name dispatcher
|
|
9
|
+
* live in the core; this module only bridges the native boundary.
|
|
10
|
+
* Libraries that predate integer hook IDs still export the name-carrying
|
|
11
|
+
* `galley_install_js_dispatch`, used as a fallback.
|
|
12
|
+
*/
|
|
13
|
+
import type { FfiPort } from "@sanbus/galley-core";
|
|
14
|
+
import type { BunPort } from "./ffi.ts";
|
|
15
|
+
export declare function ensureDispatchFor(port: BunPort & FfiPort): void;
|
package/dist/dispatch.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun procedure-dispatch installer.
|
|
3
|
+
*
|
|
4
|
+
* Owns the `JSCallback` that the shared JS shim
|
|
5
|
+
* (`galley_install_js_dispatch_id`, generated by `@sanbus/galley-core/build/shim.mjs`)
|
|
6
|
+
* forwards every parser hook through, plus the `require()`-based auto-scan
|
|
7
|
+
* of `procedures.*` in the language directory (Bun loads TypeScript
|
|
8
|
+
* synchronously, like Node). The registry and the ID-to-name dispatcher
|
|
9
|
+
* live in the core; this module only bridges the native boundary.
|
|
10
|
+
* Libraries that predate integer hook IDs still export the name-carrying
|
|
11
|
+
* `galley_install_js_dispatch`, used as a fallback.
|
|
12
|
+
*/
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { JSCallback, FFIType, toArrayBuffer } from "bun:ffi";
|
|
16
|
+
import { dispatchProcedure, installProcedures, listProcedures } from "@sanbus/galley-core";
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const textDecoder = new TextDecoder();
|
|
19
|
+
// Held to prevent GC of the callbacks; installed per library path.
|
|
20
|
+
// ID and name paths keep separate slots: their signatures differ.
|
|
21
|
+
let dispatchIdCallback = null;
|
|
22
|
+
let dispatchIdPointer = null;
|
|
23
|
+
let dispatchCallback = null;
|
|
24
|
+
let dispatchPointer = null;
|
|
25
|
+
const installedFor = new Set();
|
|
26
|
+
let autoAttempted = false;
|
|
27
|
+
function isProcedureName(name) {
|
|
28
|
+
return name === "reduction" || name.startsWith("reduction_") || name.startsWith("hook_");
|
|
29
|
+
}
|
|
30
|
+
function tryAutoRegister(libPath) {
|
|
31
|
+
if (listProcedures().length > 0 || autoAttempted)
|
|
32
|
+
return;
|
|
33
|
+
autoAttempted = true;
|
|
34
|
+
const tryLoadModule = (modulePath) => {
|
|
35
|
+
try {
|
|
36
|
+
const loadedModule = require(modulePath);
|
|
37
|
+
let hasHook = false;
|
|
38
|
+
for (const [name, value] of Object.entries(loadedModule)) {
|
|
39
|
+
if (typeof value !== "function" || !isProcedureName(name))
|
|
40
|
+
continue;
|
|
41
|
+
hasHook = true;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (hasHook)
|
|
45
|
+
return installProcedures(loadedModule) > 0;
|
|
46
|
+
const defaultExport = loadedModule.default;
|
|
47
|
+
if (defaultExport && typeof defaultExport === "object") {
|
|
48
|
+
return installProcedures(defaultExport) > 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
return false;
|
|
53
|
+
};
|
|
54
|
+
// One place: the directory holding the loaded library. Anything found
|
|
55
|
+
// there belongs to this grammar; nothing else is even looked at.
|
|
56
|
+
const baseDirectory = path.dirname(libPath);
|
|
57
|
+
const extensions = ["", ".js", ".ts"];
|
|
58
|
+
for (const extension of extensions) {
|
|
59
|
+
if (tryLoadModule(path.join(baseDirectory, `procedures${extension}`)))
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function ensureDispatchFor(port) {
|
|
64
|
+
if (!port.supportsDispatch) {
|
|
65
|
+
// Library was built for C procedures (no shim); installs will be no-ops.
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
tryAutoRegister(port.libraryPath);
|
|
69
|
+
if (installedFor.has(port.libraryPath))
|
|
70
|
+
return;
|
|
71
|
+
if (typeof port.native.galley_install_js_dispatch_id === "function" &&
|
|
72
|
+
port.procedureNames().length > 0) {
|
|
73
|
+
installIdDispatch(port);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
installNameDispatch(port);
|
|
77
|
+
}
|
|
78
|
+
installedFor.add(port.libraryPath);
|
|
79
|
+
}
|
|
80
|
+
function installIdDispatch(port) {
|
|
81
|
+
if (dispatchIdCallback === null) {
|
|
82
|
+
// Integer hook IDs: no string copy or decode on the hot path. The table
|
|
83
|
+
// is fixed per library build; unknown IDs are silent no-ops.
|
|
84
|
+
const table = port.procedureNames();
|
|
85
|
+
const cb = new JSCallback((id, argsPtr) => {
|
|
86
|
+
const name = table[id];
|
|
87
|
+
if (name === undefined)
|
|
88
|
+
return;
|
|
89
|
+
dispatchProcedure(name, argsPtr, port);
|
|
90
|
+
}, { args: [FFIType.u32, FFIType.ptr], returns: FFIType.void });
|
|
91
|
+
// Prevent GC — the trampoline must stay reachable for the process lifetime.
|
|
92
|
+
globalThis.__galley_js_dispatchIdCallback = cb;
|
|
93
|
+
dispatchIdCallback = cb;
|
|
94
|
+
dispatchIdPointer = cb.ptr;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
port.native.galley_install_js_dispatch_id(dispatchIdPointer);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Installer resolution is lazy on some runtimes; a missing installer
|
|
101
|
+
// means a C-procedures library — installs stay no-ops.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function installNameDispatch(port) {
|
|
105
|
+
if (dispatchCallback === null) {
|
|
106
|
+
// Signature mirrors Zig: fn([*]const u8, usize, ?*anyopaque) callconv(.c) void.
|
|
107
|
+
// Note: usize arrives as bigint in callbacks.
|
|
108
|
+
const cb = new JSCallback((namePtr, nameLen, argsPtr) => {
|
|
109
|
+
if (!namePtr)
|
|
110
|
+
return;
|
|
111
|
+
let name;
|
|
112
|
+
try {
|
|
113
|
+
const bytes = toArrayBuffer(namePtr, 0, Number(nameLen));
|
|
114
|
+
name = textDecoder.decode(bytes);
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
console.error("galley procedure dispatch: failed to decode name", e);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
dispatchProcedure(name, argsPtr, port);
|
|
121
|
+
}, { args: [FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.void });
|
|
122
|
+
// Prevent GC — the trampoline must stay reachable for the process lifetime.
|
|
123
|
+
globalThis.__galley_js_dispatchCallback = cb;
|
|
124
|
+
dispatchCallback = cb;
|
|
125
|
+
dispatchPointer = cb.ptr;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
port.native.galley_install_js_dispatch(dispatchPointer);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Installer resolution is lazy on some runtimes; a missing installer
|
|
132
|
+
// means a C-procedures library — installs stay no-ops.
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# 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,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun adapter for the Galley JavaScript bindings: `bun:ffi` bindings over
|
|
3
|
+
* `bindings/c/galley.h`, implementing the core `FfiPort`.
|
|
4
|
+
*
|
|
5
|
+
* Zero npm dependencies: `bun:ffi` is built into the runtime. The core
|
|
6
|
+
* (`@sanbus/galley-core`) owns all session logic; memory copying and integer
|
|
7
|
+
* normalization live here. Library discovery mirrors the Node adapter.
|
|
8
|
+
*/
|
|
9
|
+
import type { FfiPort, Handle, SessionCOptions, TreeSnapshot, WalkedStep } from "@sanbus/galley-core";
|
|
10
|
+
/** Native handles are addresses; 0 is null. */
|
|
11
|
+
type NativeHandle = number;
|
|
12
|
+
/** Callable view of the native symbols (see `BASE_SYMBOLS` below). */
|
|
13
|
+
interface GalleySymbols {
|
|
14
|
+
galley_version(): string;
|
|
15
|
+
galley_parser_type(): bigint;
|
|
16
|
+
galley_error_recovery_mode(): bigint;
|
|
17
|
+
galley_has_ast(): number;
|
|
18
|
+
galley_has_procedures(): number;
|
|
19
|
+
galley_allows_no_ast_tree_procedures(): number;
|
|
20
|
+
galley_source_retention_enabled(): number;
|
|
21
|
+
galley_has_position_tracking(): number;
|
|
22
|
+
galley_has_input_streaming(): number;
|
|
23
|
+
galley_uses_verbatim(): number;
|
|
24
|
+
galley_stack_overflow_recovery_available(): number;
|
|
25
|
+
galley_symbol_count(): bigint;
|
|
26
|
+
galley_variable_count(): bigint;
|
|
27
|
+
galley_status_string(status: bigint): string;
|
|
28
|
+
galley_symbol_name(session: NativeHandle, index: bigint, outData: number, outLen: number): bigint;
|
|
29
|
+
galley_symbol_is_terminal(session: NativeHandle, index: bigint): number;
|
|
30
|
+
galley_variable_name(session: NativeHandle, index: bigint, outData: number, outLen: number): bigint;
|
|
31
|
+
galley_session_create(): NativeHandle;
|
|
32
|
+
galley_session_create_ex(options: number): NativeHandle;
|
|
33
|
+
galley_session_destroy(session: NativeHandle): void;
|
|
34
|
+
galley_session_set_message_override(session: NativeHandle, name: number, nameLen: bigint, message: number, messageLen: bigint): bigint;
|
|
35
|
+
galley_parse(session: NativeHandle, data: number, len: bigint): bigint;
|
|
36
|
+
galley_parse_file(session: NativeHandle, path: number): bigint;
|
|
37
|
+
galley_last_position(session: NativeHandle, outLine: number, outCol: number): bigint;
|
|
38
|
+
galley_node_count(session: NativeHandle): bigint;
|
|
39
|
+
galley_reserve_nodes(session: NativeHandle, capacity: bigint): bigint;
|
|
40
|
+
galley_node_capacity(session: NativeHandle): bigint;
|
|
41
|
+
galley_root_node(session: NativeHandle): bigint;
|
|
42
|
+
galley_node_is_valid(session: NativeHandle, node: bigint): number;
|
|
43
|
+
galley_node_child_count(session: NativeHandle, node: bigint): number;
|
|
44
|
+
galley_node_first_child(session: NativeHandle, node: bigint): bigint;
|
|
45
|
+
galley_node_last_child(session: NativeHandle, node: bigint): bigint;
|
|
46
|
+
galley_node_next_sibling(session: NativeHandle, node: bigint): bigint;
|
|
47
|
+
galley_node_prior_sibling(session: NativeHandle, node: bigint): bigint;
|
|
48
|
+
galley_node_parent(session: NativeHandle, node: bigint): bigint;
|
|
49
|
+
galley_tree_snapshot(session: NativeHandle, outParent: number, outFirstChild: number, outNext: number, outChildCount: number, outVariable: number, outSpanStart: number, outSpanLen: number, capacity: bigint): bigint;
|
|
50
|
+
galley_walker_create(session: NativeHandle, node: bigint, skipSemanticErrors: number): NativeHandle;
|
|
51
|
+
galley_walker_next(walker: NativeHandle, outNode: number, outDepth: number, outFlag: number): number;
|
|
52
|
+
galley_walker_skip_children(walker: NativeHandle): void;
|
|
53
|
+
galley_walker_destroy(walker: NativeHandle): void;
|
|
54
|
+
galley_node_span(session: NativeHandle, node: bigint, outStart: number, outLen: number): bigint;
|
|
55
|
+
galley_node_symbol_name(session: NativeHandle, node: bigint, outData: number, outLen: number): bigint;
|
|
56
|
+
galley_node_variable_index(session: NativeHandle, node: bigint): bigint;
|
|
57
|
+
galley_node_text(session: NativeHandle, node: bigint, outData: number, outLen: number): bigint;
|
|
58
|
+
galley_node_line_column(session: NativeHandle, node: bigint, outLine: number, outCol: number): bigint;
|
|
59
|
+
galley_has_diagnostic(session: NativeHandle): number;
|
|
60
|
+
galley_diagnostic_kind(session: NativeHandle): bigint;
|
|
61
|
+
galley_diagnostic_message(session: NativeHandle, out: number): bigint;
|
|
62
|
+
galley_diagnostic_message_ansi(session: NativeHandle, out: number): bigint;
|
|
63
|
+
galley_diagnostic_position(session: NativeHandle, outLine: number, outCol: number): bigint;
|
|
64
|
+
galley_diagnostic_unexpected_token(session: NativeHandle, outData: number, outLen: number): bigint;
|
|
65
|
+
galley_diagnostic_expected_count(session: NativeHandle): bigint;
|
|
66
|
+
galley_diagnostic_expected_at(session: NativeHandle, index: bigint, outData: number, outLen: number): bigint;
|
|
67
|
+
galley_diagnostic_context_count(session: NativeHandle): bigint;
|
|
68
|
+
galley_diagnostic_context_at(session: NativeHandle, index: bigint, outData: number, outLen: number): bigint;
|
|
69
|
+
galley_diagnostic_indentation(session: NativeHandle, outSpaces: number, outWidth: number): bigint;
|
|
70
|
+
galley_syntax_error_count(session: NativeHandle): bigint;
|
|
71
|
+
galley_semantic_error_count(session: NativeHandle): bigint;
|
|
72
|
+
galley_diagnostic_semantic(session: NativeHandle, outVariable: number, outVariableLen: number, outMessage: number, outMessageLen: number): bigint;
|
|
73
|
+
galley_diagnostic_recovery_kind(session: NativeHandle): bigint;
|
|
74
|
+
galley_diagnostic_recovery_terminal(session: NativeHandle, outData: number, outLen: number): bigint;
|
|
75
|
+
galley_diagnostic_recovery_resume(session: NativeHandle, out: number): bigint;
|
|
76
|
+
galley_diagnostic_recovery_lhs_variable(session: NativeHandle, outData: number, outLen: number): bigint;
|
|
77
|
+
galley_diagnostic_recovery_production(session: NativeHandle, outVar: number, outLen: number, outIdx: number): bigint;
|
|
78
|
+
galley_diagnostic_recovery_occurrence(session: NativeHandle, outParent: number, outParentLen: number, outRhs: number, outSym: number, outVar: number, outVarLen: number): bigint;
|
|
79
|
+
galley_recorded_diagnostic_count(session: NativeHandle): bigint;
|
|
80
|
+
galley_recorded_diagnostic_kind(session: NativeHandle, diagIndex: bigint): bigint;
|
|
81
|
+
galley_recorded_diagnostic_position(session: NativeHandle, diagIndex: bigint, outLine: number, outCol: number): bigint;
|
|
82
|
+
galley_recorded_unexpected_token(session: NativeHandle, diagIndex: bigint, outData: number, outLen: number): bigint;
|
|
83
|
+
galley_recorded_diagnostic_message(session: NativeHandle, diagIndex: bigint, out: number): bigint;
|
|
84
|
+
galley_recorded_indentation(session: NativeHandle, diagIndex: bigint, outSpaces: number, outWidth: number): bigint;
|
|
85
|
+
galley_recorded_semantic(session: NativeHandle, diagIndex: bigint, outVariable: number, outVariableLen: number, outMessage: number, outMessageLen: number): bigint;
|
|
86
|
+
galley_recorded_expected_count(session: NativeHandle, diagIndex: bigint): bigint;
|
|
87
|
+
galley_recorded_expected_token(session: NativeHandle, diagIndex: bigint, tokenIndex: bigint, outData: number, outLen: number): bigint;
|
|
88
|
+
galley_recorded_context_count(session: NativeHandle, diagIndex: bigint): bigint;
|
|
89
|
+
galley_recorded_context_name(session: NativeHandle, diagIndex: bigint, ctxIndex: bigint, outData: number, outLen: number): bigint;
|
|
90
|
+
galley_recorded_diagnostic_recovery_kind(session: NativeHandle, diagIndex: bigint): bigint;
|
|
91
|
+
galley_recorded_recovery_terminal(session: NativeHandle, diagIndex: bigint, outData: number, outLen: number): bigint;
|
|
92
|
+
galley_recorded_recovery_resume(session: NativeHandle, diagIndex: bigint, out: number): bigint;
|
|
93
|
+
galley_recorded_recovery_lhs_variable(session: NativeHandle, diagIndex: bigint, outData: number, outLen: number): bigint;
|
|
94
|
+
galley_recorded_recovery_production(session: NativeHandle, diagIndex: bigint, outVar: number, outLen: number, outIdx: number): bigint;
|
|
95
|
+
galley_recorded_recovery_occurrence(session: NativeHandle, diagIndex: bigint, outParent: number, outParentLen: number, outRhs: number, outSym: number, outVar: number, outVarLen: number): bigint;
|
|
96
|
+
galley_tree_append_children(session: NativeHandle, parent: bigint, first: bigint): bigint;
|
|
97
|
+
galley_tree_insert_before(session: NativeHandle, target: bigint, first: bigint): bigint;
|
|
98
|
+
galley_tree_insert_after(session: NativeHandle, target: bigint, first: bigint): bigint;
|
|
99
|
+
galley_tree_remove_siblings(session: NativeHandle, node: bigint, count: bigint, outHead: number): bigint;
|
|
100
|
+
galley_tree_remove_self(session: NativeHandle, node: bigint, outHead: number): bigint;
|
|
101
|
+
galley_tree_promote_children_over_wrapper(session: NativeHandle, wrapper: bigint, outHead: number): bigint;
|
|
102
|
+
galley_tree_clean_children(session: NativeHandle, node: bigint, outHead: number): bigint;
|
|
103
|
+
galley_tree_unlink_wrapper(session: NativeHandle, wrapper: bigint): bigint;
|
|
104
|
+
galley_tree_insert_children_at(session: NativeHandle, parent: bigint, index: bigint, first: bigint): bigint;
|
|
105
|
+
galley_tree_remove_children_at(session: NativeHandle, parent: bigint, index: bigint, count: bigint, outHead: number): bigint;
|
|
106
|
+
galley_procedure_session(args: NativeHandle): NativeHandle;
|
|
107
|
+
galley_procedure_current_node(args: NativeHandle): bigint;
|
|
108
|
+
galley_procedure_set_current_node(args: NativeHandle, node: bigint): void;
|
|
109
|
+
galley_procedure_drop_self(args: NativeHandle): bigint;
|
|
110
|
+
galley_procedure_drop_children(args: NativeHandle): bigint;
|
|
111
|
+
galley_procedure_drop_if_empty(args: NativeHandle): bigint;
|
|
112
|
+
galley_procedure_replace_with_children(args: NativeHandle): bigint;
|
|
113
|
+
galley_procedure_context_line(args: NativeHandle): number;
|
|
114
|
+
galley_procedure_context_column(args: NativeHandle): number;
|
|
115
|
+
galley_procedure_report_semantic_error(args: NativeHandle, message: number, messageLen: bigint): bigint;
|
|
116
|
+
galley_install_js_dispatch(callback: NativeHandle): void;
|
|
117
|
+
galley_install_js_dispatch_id?(callback: NativeHandle): void;
|
|
118
|
+
galley_js_procedure_count?(): number;
|
|
119
|
+
galley_js_procedure_name_ptr?(index: number): bigint;
|
|
120
|
+
galley_js_procedure_name_len?(index: number): bigint;
|
|
121
|
+
galley_js_procedure_enable?(name: number, nameLen: bigint): number;
|
|
122
|
+
galley_js_procedure_clear?(): void;
|
|
123
|
+
}
|
|
124
|
+
export declare function libFileName(base?: string): string;
|
|
125
|
+
export declare function findLibrary(explicit?: string): string;
|
|
126
|
+
/** Copy (addr,len) into a Uint8Array owning its bytes. */
|
|
127
|
+
export declare function readBytes(addr: bigint, len: bigint): Uint8Array;
|
|
128
|
+
export declare function readCString(addr: bigint): string;
|
|
129
|
+
export declare class BunPort implements FfiPort {
|
|
130
|
+
#private;
|
|
131
|
+
readonly native: GalleySymbols;
|
|
132
|
+
readonly libraryPath: string;
|
|
133
|
+
readonly supportsDispatch: boolean;
|
|
134
|
+
constructor(native: GalleySymbols, libraryPath: string, supportsDispatch: boolean);
|
|
135
|
+
syncProcedures(names: string[]): void;
|
|
136
|
+
procedureNames(): string[];
|
|
137
|
+
version(): string;
|
|
138
|
+
parserType(): number;
|
|
139
|
+
errorRecoveryMode(): number;
|
|
140
|
+
hasAst(): boolean;
|
|
141
|
+
hasProcedures(): boolean;
|
|
142
|
+
allowsNoAstTreeProcedures(): boolean;
|
|
143
|
+
sourceRetentionEnabled(): boolean;
|
|
144
|
+
hasPositionTracking(): boolean;
|
|
145
|
+
hasInputStreaming(): boolean;
|
|
146
|
+
usesVerbatim(): boolean;
|
|
147
|
+
stackOverflowRecoveryAvailable(): boolean;
|
|
148
|
+
symbolCount(): number;
|
|
149
|
+
variableCount(): number;
|
|
150
|
+
statusString(status: number): string | null;
|
|
151
|
+
createSession(options: SessionCOptions | null): Handle;
|
|
152
|
+
destroySession(handle: Handle): void;
|
|
153
|
+
setMessageOverride(handle: Handle, name: Uint8Array, message: Uint8Array): number;
|
|
154
|
+
parse(handle: Handle, data: Uint8Array): number;
|
|
155
|
+
parseFile(handle: Handle, filePath: string): number;
|
|
156
|
+
lastPosition(handle: Handle): [number, number] | null;
|
|
157
|
+
nodeCount(handle: Handle): number;
|
|
158
|
+
reserveNodes(handle: Handle, capacity: bigint): number;
|
|
159
|
+
nodeCapacity(handle: Handle): number;
|
|
160
|
+
rootNode(handle: Handle): bigint;
|
|
161
|
+
nodeValid(handle: Handle, node: bigint): boolean;
|
|
162
|
+
childCount(handle: Handle, node: bigint): number;
|
|
163
|
+
firstChild(handle: Handle, node: bigint): bigint;
|
|
164
|
+
lastChild(handle: Handle, node: bigint): bigint;
|
|
165
|
+
nextSibling(handle: Handle, node: bigint): bigint;
|
|
166
|
+
priorSibling(handle: Handle, node: bigint): bigint;
|
|
167
|
+
parent(handle: Handle, node: bigint): bigint;
|
|
168
|
+
treeSnapshot(handle: Handle): TreeSnapshot;
|
|
169
|
+
walkerCreate(handle: Handle, node: bigint, skipSemanticErrors: boolean): Handle | null;
|
|
170
|
+
walkerNext(walker: Handle): WalkedStep | null;
|
|
171
|
+
walkerSkipChildren(walker: Handle): void;
|
|
172
|
+
walkerDestroy(walker: Handle): void;
|
|
173
|
+
nodeSymbolName(handle: Handle, node: bigint): Uint8Array | null;
|
|
174
|
+
nodeText(handle: Handle, node: bigint): Uint8Array | null;
|
|
175
|
+
nodeSpan(handle: Handle, node: bigint): [bigint, bigint] | null;
|
|
176
|
+
nodeLineColumn(handle: Handle, node: bigint): [number, number] | null;
|
|
177
|
+
nodeVariableIndex(handle: Handle, node: bigint): number;
|
|
178
|
+
symbolNameAt(handle: Handle, index: number): Uint8Array | null;
|
|
179
|
+
symbolIsTerminal(handle: Handle, index: number): boolean;
|
|
180
|
+
variableNameAt(handle: Handle, index: number): Uint8Array | null;
|
|
181
|
+
hasDiagnostic(handle: Handle): boolean;
|
|
182
|
+
diagnosticKind(handle: Handle): number;
|
|
183
|
+
diagnosticMessage(handle: Handle): string | null;
|
|
184
|
+
diagnosticMessageAnsi(handle: Handle): string | null;
|
|
185
|
+
diagnosticPosition(handle: Handle): [number, number] | null;
|
|
186
|
+
diagnosticUnexpectedToken(handle: Handle): Uint8Array | null;
|
|
187
|
+
diagnosticExpectedCount(handle: Handle): number;
|
|
188
|
+
diagnosticExpectedAt(handle: Handle, index: number): Uint8Array | null;
|
|
189
|
+
diagnosticContextCount(handle: Handle): number;
|
|
190
|
+
diagnosticContextAt(handle: Handle, index: number): Uint8Array | null;
|
|
191
|
+
syntaxErrorCount(handle: Handle): number;
|
|
192
|
+
semanticErrorCount(handle: Handle): number;
|
|
193
|
+
diagnosticSemantic(handle: Handle): [string, string] | null;
|
|
194
|
+
diagnosticIndentation(handle: Handle): [number, number] | null;
|
|
195
|
+
diagnosticRecoveryKind(handle: Handle): number;
|
|
196
|
+
diagnosticRecoveryTerminal(handle: Handle): Uint8Array | null;
|
|
197
|
+
diagnosticRecoveryResume(handle: Handle): number | null;
|
|
198
|
+
diagnosticRecoveryLhsVariable(handle: Handle): string | null;
|
|
199
|
+
diagnosticRecoveryProduction(handle: Handle): [string, number] | null;
|
|
200
|
+
diagnosticRecoveryOccurrence(handle: Handle): [string, number, number, string] | null;
|
|
201
|
+
recordedDiagnosticCount(handle: Handle): number;
|
|
202
|
+
recordedDiagnosticKind(handle: Handle, diagIndex: number): number;
|
|
203
|
+
recordedDiagnosticPosition(handle: Handle, diagIndex: number): [number, number] | null;
|
|
204
|
+
recordedUnexpectedToken(handle: Handle, diagIndex: number): Uint8Array | null;
|
|
205
|
+
recordedDiagnosticMessage(handle: Handle, diagIndex: number): string | null;
|
|
206
|
+
recordedIndentation(handle: Handle, diagIndex: number): [number, number] | null;
|
|
207
|
+
recordedSemantic(handle: Handle, diagIndex: number): [string, string] | null;
|
|
208
|
+
recordedExpectedCount(handle: Handle, diagIndex: number): number;
|
|
209
|
+
recordedExpectedToken(handle: Handle, diagIndex: number, tokenIndex: number): Uint8Array | null;
|
|
210
|
+
recordedContextCount(handle: Handle, diagIndex: number): number;
|
|
211
|
+
recordedContextName(handle: Handle, diagIndex: number, contextIndex: number): Uint8Array | null;
|
|
212
|
+
recordedRecoveryKind(handle: Handle, diagIndex: number): number;
|
|
213
|
+
recordedRecoveryTerminal(handle: Handle, diagIndex: number): Uint8Array | null;
|
|
214
|
+
recordedRecoveryResume(handle: Handle, diagIndex: number): number | null;
|
|
215
|
+
recordedRecoveryLhsVariable(handle: Handle, diagIndex: number): string | null;
|
|
216
|
+
recordedRecoveryProduction(handle: Handle, diagIndex: number): [string, number] | null;
|
|
217
|
+
recordedRecoveryOccurrence(handle: Handle, diagIndex: number): [string, number, number, string] | null;
|
|
218
|
+
treeAppendChildren(handle: Handle, parent: bigint, first: bigint): number;
|
|
219
|
+
treeInsertBefore(handle: Handle, target: bigint, first: bigint): number;
|
|
220
|
+
treeInsertAfter(handle: Handle, target: bigint, first: bigint): number;
|
|
221
|
+
treeRemoveSiblings(handle: Handle, node: bigint, count: number): {
|
|
222
|
+
status: number;
|
|
223
|
+
head: bigint;
|
|
224
|
+
};
|
|
225
|
+
treeRemoveSelf(handle: Handle, node: bigint): {
|
|
226
|
+
status: number;
|
|
227
|
+
head: bigint;
|
|
228
|
+
};
|
|
229
|
+
treePromoteChildrenOverWrapper(handle: Handle, wrapper: bigint): {
|
|
230
|
+
status: number;
|
|
231
|
+
head: bigint;
|
|
232
|
+
};
|
|
233
|
+
treeCleanChildren(handle: Handle, node: bigint): {
|
|
234
|
+
status: number;
|
|
235
|
+
head: bigint;
|
|
236
|
+
};
|
|
237
|
+
treeUnlinkWrapper(handle: Handle, wrapper: bigint): number;
|
|
238
|
+
treeInsertChildrenAt(handle: Handle, parent: bigint, index: number, first: bigint): number;
|
|
239
|
+
treeRemoveChildrenAt(handle: Handle, parent: bigint, index: number, count: number): {
|
|
240
|
+
status: number;
|
|
241
|
+
head: bigint;
|
|
242
|
+
};
|
|
243
|
+
procCurrentNode(args: Handle): bigint;
|
|
244
|
+
procSetCurrentNode(args: Handle, node: bigint): void;
|
|
245
|
+
procDropSelf(args: Handle): number;
|
|
246
|
+
procDropChildren(args: Handle): number;
|
|
247
|
+
procDropIfEmpty(args: Handle): number;
|
|
248
|
+
procReplaceWithChildren(args: Handle): number;
|
|
249
|
+
procContextLine(args: Handle): number;
|
|
250
|
+
procContextColumn(args: Handle): number;
|
|
251
|
+
procReportSemanticError(args: Handle, message: Uint8Array): number;
|
|
252
|
+
}
|
|
253
|
+
/** Port for the library at `explicitPath` (or default discovery), cached per path. */
|
|
254
|
+
export declare function getBunPort(explicitPath?: string): BunPort;
|
|
255
|
+
export {};
|