@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/dist/ffi.js ADDED
@@ -0,0 +1,794 @@
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 { Buffer } from "node:buffer";
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+ import process from "node:process";
13
+ import { dlopen, FFIType, ptr, toArrayBuffer, CString } from "bun:ffi";
14
+ import { GalleyError, resolveArtifact, artifactFileName } from "@sanbus/galley-core";
15
+ // --- library discovery -------------------------------------------------
16
+ // One place, named up front: an explicit path or GALLEY_LIBRARY_PATH.
17
+ // Anything else is a loud error, never a search.
18
+ const BUILD_HINT = `Build it first: bunx galley-js-bun <language-dir>\n` +
19
+ `or set GALLEY_LIBRARY_PATH=/path/to/${libFileName()}`;
20
+ export function libFileName(base = "galley-js-bun") {
21
+ return artifactFileName(base, process.platform);
22
+ }
23
+ function exists(candidate) {
24
+ try {
25
+ fs.accessSync(candidate);
26
+ return true;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ export function findLibrary(explicit) {
33
+ return resolveArtifact(explicit, {
34
+ getEnv: (name) => process.env[name],
35
+ resolvePath: (candidate) => path.resolve(candidate),
36
+ existsSync: exists,
37
+ buildHint: BUILD_HINT,
38
+ });
39
+ }
40
+ // --- loader ------------------------------------------------------------
41
+ const BASE_SYMBOLS = {
42
+ galley_version: { args: [], returns: FFIType.cstring },
43
+ galley_parser_type: { args: [], returns: FFIType.i64 },
44
+ galley_error_recovery_mode: { args: [], returns: FFIType.i64 },
45
+ galley_has_ast: { args: [], returns: FFIType.i32 },
46
+ galley_has_procedures: { args: [], returns: FFIType.i32 },
47
+ galley_allows_no_ast_tree_procedures: { args: [], returns: FFIType.i32 },
48
+ galley_source_retention_enabled: { args: [], returns: FFIType.i32 },
49
+ galley_has_position_tracking: { args: [], returns: FFIType.i32 },
50
+ galley_has_input_streaming: { args: [], returns: FFIType.i32 },
51
+ galley_uses_verbatim: { args: [], returns: FFIType.i32 },
52
+ galley_stack_overflow_recovery_available: { args: [], returns: FFIType.i32 },
53
+ galley_symbol_count: { args: [], returns: FFIType.u64 },
54
+ galley_variable_count: { args: [], returns: FFIType.u64 },
55
+ galley_status_string: { args: [FFIType.i64], returns: FFIType.cstring },
56
+ galley_symbol_name: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
57
+ galley_symbol_is_terminal: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i32 },
58
+ galley_variable_name: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
59
+ galley_session_create: { args: [], returns: FFIType.ptr },
60
+ galley_session_create_ex: { args: [FFIType.ptr], returns: FFIType.ptr },
61
+ galley_session_destroy: { args: [FFIType.ptr], returns: FFIType.void },
62
+ galley_session_set_message_override: { args: [FFIType.ptr, FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
63
+ galley_parse: { args: [FFIType.ptr, FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
64
+ galley_parse_file: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
65
+ galley_last_position: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
66
+ galley_node_count: { args: [FFIType.ptr], returns: FFIType.u64 },
67
+ galley_reserve_nodes: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
68
+ galley_node_capacity: { args: [FFIType.ptr], returns: FFIType.u64 },
69
+ galley_root_node: { args: [FFIType.ptr], returns: FFIType.u64 },
70
+ galley_node_is_valid: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i32 },
71
+ galley_node_child_count: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.u32 },
72
+ galley_node_first_child: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.u64 },
73
+ galley_node_last_child: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.u64 },
74
+ galley_node_next_sibling: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.u64 },
75
+ galley_node_prior_sibling: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.u64 },
76
+ galley_node_parent: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.u64 },
77
+ galley_tree_snapshot: {
78
+ args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.u64],
79
+ returns: FFIType.i64,
80
+ },
81
+ galley_walker_create: { args: [FFIType.ptr, FFIType.u64, FFIType.i32], returns: FFIType.ptr },
82
+ galley_walker_next: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
83
+ galley_walker_skip_children: { args: [FFIType.ptr], returns: FFIType.void },
84
+ galley_walker_destroy: { args: [FFIType.ptr], returns: FFIType.void },
85
+ galley_node_span: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
86
+ galley_node_symbol_name: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
87
+ galley_node_variable_index: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
88
+ galley_node_text: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
89
+ galley_node_line_column: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
90
+ galley_has_diagnostic: { args: [FFIType.ptr], returns: FFIType.i32 },
91
+ galley_diagnostic_kind: { args: [FFIType.ptr], returns: FFIType.i64 },
92
+ galley_diagnostic_message: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
93
+ galley_diagnostic_message_ansi: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
94
+ galley_diagnostic_position: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
95
+ galley_diagnostic_unexpected_token: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
96
+ galley_diagnostic_expected_count: { args: [FFIType.ptr], returns: FFIType.i64 },
97
+ galley_diagnostic_expected_at: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
98
+ galley_diagnostic_context_count: { args: [FFIType.ptr], returns: FFIType.i64 },
99
+ galley_diagnostic_context_at: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
100
+ galley_diagnostic_indentation: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
101
+ galley_syntax_error_count: { args: [FFIType.ptr], returns: FFIType.i64 },
102
+ galley_semantic_error_count: { args: [FFIType.ptr], returns: FFIType.i64 },
103
+ galley_diagnostic_semantic: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
104
+ galley_diagnostic_recovery_kind: { args: [FFIType.ptr], returns: FFIType.i64 },
105
+ galley_diagnostic_recovery_terminal: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
106
+ galley_diagnostic_recovery_resume: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
107
+ galley_diagnostic_recovery_lhs_variable: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
108
+ galley_diagnostic_recovery_production: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
109
+ galley_diagnostic_recovery_occurrence: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
110
+ galley_recorded_diagnostic_count: { args: [FFIType.ptr], returns: FFIType.i64 },
111
+ galley_recorded_diagnostic_kind: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
112
+ galley_recorded_diagnostic_position: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
113
+ galley_recorded_unexpected_token: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
114
+ galley_recorded_diagnostic_message: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
115
+ galley_recorded_indentation: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
116
+ galley_recorded_semantic: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
117
+ galley_recorded_expected_count: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
118
+ galley_recorded_expected_token: { args: [FFIType.ptr, FFIType.u64, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
119
+ galley_recorded_context_count: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
120
+ galley_recorded_context_name: { args: [FFIType.ptr, FFIType.u64, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
121
+ galley_recorded_diagnostic_recovery_kind: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
122
+ galley_recorded_recovery_terminal: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
123
+ galley_recorded_recovery_resume: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
124
+ galley_recorded_recovery_lhs_variable: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
125
+ galley_recorded_recovery_production: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
126
+ galley_recorded_recovery_occurrence: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i64 },
127
+ galley_tree_append_children: { args: [FFIType.ptr, FFIType.u64, FFIType.u64], returns: FFIType.i64 },
128
+ galley_tree_insert_before: { args: [FFIType.ptr, FFIType.u64, FFIType.u64], returns: FFIType.i64 },
129
+ galley_tree_insert_after: { args: [FFIType.ptr, FFIType.u64, FFIType.u64], returns: FFIType.i64 },
130
+ galley_tree_remove_siblings: { args: [FFIType.ptr, FFIType.u64, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
131
+ galley_tree_remove_self: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
132
+ galley_tree_promote_children_over_wrapper: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
133
+ galley_tree_clean_children: { args: [FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
134
+ galley_tree_unlink_wrapper: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
135
+ galley_tree_insert_children_at: { args: [FFIType.ptr, FFIType.u64, FFIType.u64, FFIType.u64], returns: FFIType.i64 },
136
+ galley_tree_remove_children_at: { args: [FFIType.ptr, FFIType.u64, FFIType.u64, FFIType.u64, FFIType.ptr], returns: FFIType.i64 },
137
+ galley_procedure_session: { args: [FFIType.ptr], returns: FFIType.ptr },
138
+ galley_procedure_current_node: { args: [FFIType.ptr], returns: FFIType.u64 },
139
+ galley_procedure_set_current_node: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.void },
140
+ galley_procedure_drop_self: { args: [FFIType.ptr], returns: FFIType.i64 },
141
+ galley_procedure_drop_children: { args: [FFIType.ptr], returns: FFIType.i64 },
142
+ galley_procedure_drop_if_empty: { args: [FFIType.ptr], returns: FFIType.i64 },
143
+ galley_procedure_replace_with_children: { args: [FFIType.ptr], returns: FFIType.i64 },
144
+ galley_procedure_context_line: { args: [FFIType.ptr], returns: FFIType.u32 },
145
+ galley_procedure_context_column: { args: [FFIType.ptr], returns: FFIType.u32 },
146
+ galley_procedure_report_semantic_error: { args: [FFIType.ptr, FFIType.ptr, FFIType.u64], returns: FFIType.i64 },
147
+ };
148
+ const DISPATCH_SYMBOL = {
149
+ galley_install_js_dispatch: { args: [FFIType.function], returns: FFIType.void },
150
+ };
151
+ const ID_DISPATCH_SYMBOL = {
152
+ galley_install_js_dispatch_id: { args: [FFIType.function], returns: FFIType.void },
153
+ galley_js_procedure_count: { args: [], returns: FFIType.u32 },
154
+ galley_js_procedure_name_ptr: { args: [FFIType.u32], returns: FFIType.ptr },
155
+ galley_js_procedure_name_len: { args: [FFIType.u32], returns: FFIType.u64 },
156
+ };
157
+ const SELECTIVE_SYMBOL = {
158
+ galley_js_procedure_enable: { args: [FFIType.ptr, FFIType.u64], returns: FFIType.i32 },
159
+ galley_js_procedure_clear: { args: [], returns: FFIType.void },
160
+ };
161
+ function openNative(libPath, level) {
162
+ const table = level >= 3
163
+ ? { ...BASE_SYMBOLS, ...ID_DISPATCH_SYMBOL, ...SELECTIVE_SYMBOL }
164
+ : level >= 2
165
+ ? { ...BASE_SYMBOLS, ...DISPATCH_SYMBOL, ...SELECTIVE_SYMBOL }
166
+ : level >= 1
167
+ ? { ...BASE_SYMBOLS, ...DISPATCH_SYMBOL }
168
+ : BASE_SYMBOLS;
169
+ return dlopen(libPath, table);
170
+ }
171
+ // --- read helpers ----------------------------------------------------------
172
+ /** Copy (addr,len) into a Uint8Array owning its bytes. */
173
+ export function readBytes(addr, len) {
174
+ if (addr === 0n || len === 0n)
175
+ return new Uint8Array(0);
176
+ const view = toArrayBuffer(Number(addr), 0, Number(len));
177
+ return new Uint8Array(view.slice(0));
178
+ }
179
+ export function readCString(addr) {
180
+ return String(new CString(Number(addr)));
181
+ }
182
+ function ptrOut64() {
183
+ return new BigUint64Array(1);
184
+ }
185
+ function u32Out() {
186
+ return new Uint32Array(1);
187
+ }
188
+ function i64Out() {
189
+ return new BigInt64Array(1);
190
+ }
191
+ // --- FfiPort implementation ----------------------------------------------
192
+ export class BunPort {
193
+ native;
194
+ libraryPath;
195
+ supportsDispatch;
196
+ constructor(native, libraryPath, supportsDispatch) {
197
+ this.native = native;
198
+ this.libraryPath = libraryPath;
199
+ this.supportsDispatch = supportsDispatch;
200
+ }
201
+ syncProcedures(names) {
202
+ if (typeof this.native.galley_js_procedure_clear !== "function")
203
+ return;
204
+ if (typeof this.native.galley_js_procedure_enable !== "function")
205
+ return;
206
+ this.native.galley_js_procedure_clear();
207
+ const encoder = new TextEncoder();
208
+ for (const name of names) {
209
+ const bytes = encoder.encode(name);
210
+ this.native.galley_js_procedure_enable(ptr(bytes), BigInt(bytes.length));
211
+ }
212
+ // Warm the ID table outside any parse so the hot path never queries.
213
+ this.procedureNames();
214
+ }
215
+ #procedureNameTable = null;
216
+ procedureNames() {
217
+ if (this.#procedureNameTable !== null)
218
+ return this.#procedureNameTable;
219
+ const table = [];
220
+ if (typeof this.native.galley_js_procedure_count === "function" &&
221
+ typeof this.native.galley_js_procedure_name_ptr === "function" &&
222
+ typeof this.native.galley_js_procedure_name_len === "function") {
223
+ const decoder = new TextDecoder();
224
+ const n = this.native.galley_js_procedure_count();
225
+ for (let i = 0; i < n; i++) {
226
+ const ptrValue = this.native.galley_js_procedure_name_ptr(i);
227
+ if (ptrValue === 0n)
228
+ break;
229
+ const len = this.native.galley_js_procedure_name_len(i);
230
+ table.push(decoder.decode(readBytes(ptrValue, len)));
231
+ }
232
+ }
233
+ this.#procedureNameTable = table;
234
+ return table;
235
+ }
236
+ // -- module-level queries --------------------------------------------
237
+ version() {
238
+ return String(this.native.galley_version());
239
+ }
240
+ parserType() {
241
+ return Number(this.native.galley_parser_type());
242
+ }
243
+ errorRecoveryMode() {
244
+ return Number(this.native.galley_error_recovery_mode());
245
+ }
246
+ hasAst() {
247
+ return this.native.galley_has_ast() !== 0;
248
+ }
249
+ hasProcedures() {
250
+ return this.native.galley_has_procedures() !== 0;
251
+ }
252
+ allowsNoAstTreeProcedures() {
253
+ return this.native.galley_allows_no_ast_tree_procedures() !== 0;
254
+ }
255
+ sourceRetentionEnabled() {
256
+ return this.native.galley_source_retention_enabled() !== 0;
257
+ }
258
+ hasPositionTracking() {
259
+ return this.native.galley_has_position_tracking() !== 0;
260
+ }
261
+ hasInputStreaming() {
262
+ return this.native.galley_has_input_streaming() !== 0;
263
+ }
264
+ usesVerbatim() {
265
+ return this.native.galley_uses_verbatim() !== 0;
266
+ }
267
+ stackOverflowRecoveryAvailable() {
268
+ return this.native.galley_stack_overflow_recovery_available() !== 0;
269
+ }
270
+ symbolCount() {
271
+ return Number(this.native.galley_symbol_count());
272
+ }
273
+ variableCount() {
274
+ return Number(this.native.galley_variable_count());
275
+ }
276
+ statusString(status) {
277
+ // Native returns NULL for unknown codes; bun:ffi coerces that to "".
278
+ const rendered = String(this.native.galley_status_string(BigInt(status)));
279
+ return rendered === "" ? null : rendered;
280
+ }
281
+ // -- sessions ---------------------------------------------------------
282
+ createSession(options) {
283
+ let handle;
284
+ if (options === null) {
285
+ handle = this.native.galley_session_create();
286
+ }
287
+ else {
288
+ // GalleyCOptions layout: int32 x5, double, uint64 (40 bytes, LE).
289
+ const buf = new ArrayBuffer(40);
290
+ const view = new DataView(buf);
291
+ view.setInt32(0, options.maxErrors, true);
292
+ view.setInt32(4, options.recoveryWindow, true);
293
+ view.setInt32(8, options.stackOverflowRecovery, true);
294
+ view.setUint32(12, options.syntaxErrorStackDepth, true);
295
+ view.setInt32(16, options.verbosity, true);
296
+ view.setFloat64(24, options.astPreallocationRatio, true);
297
+ view.setBigUint64(32, options.astPreallocationCap, true);
298
+ handle = this.native.galley_session_create_ex(ptr(new Uint8Array(buf)));
299
+ }
300
+ if (handle === 0 || handle === null || handle === undefined)
301
+ return null;
302
+ return handle;
303
+ }
304
+ destroySession(handle) {
305
+ this.native.galley_session_destroy(handle);
306
+ }
307
+ setMessageOverride(handle, name, message) {
308
+ return Number(this.native.galley_session_set_message_override(handle, ptr(name), BigInt(name.length), ptr(message), BigInt(message.length)));
309
+ }
310
+ // -- parsing ----------------------------------------------------------
311
+ parse(handle, data) {
312
+ return Number(this.native.galley_parse(handle, ptr(data), BigInt(data.length)));
313
+ }
314
+ parseFile(handle, filePath) {
315
+ const bytes = Buffer.from(filePath, "utf-8");
316
+ const nul = Buffer.alloc(bytes.length + 1);
317
+ bytes.copy(nul);
318
+ return Number(this.native.galley_parse_file(handle, ptr(nul)));
319
+ }
320
+ lastPosition(handle) {
321
+ const outLine = u32Out();
322
+ const outCol = u32Out();
323
+ if (this.native.galley_last_position(handle, ptr(outLine), ptr(outCol)) < 0n)
324
+ return null;
325
+ return [outLine[0], outCol[0]];
326
+ }
327
+ // -- arena and navigation ----------------------------------------------
328
+ nodeCount(handle) {
329
+ return Number(this.native.galley_node_count(handle));
330
+ }
331
+ reserveNodes(handle, capacity) {
332
+ return Number(this.native.galley_reserve_nodes(handle, capacity));
333
+ }
334
+ nodeCapacity(handle) {
335
+ return Number(this.native.galley_node_capacity(handle));
336
+ }
337
+ rootNode(handle) {
338
+ return this.native.galley_root_node(handle);
339
+ }
340
+ nodeValid(handle, node) {
341
+ return this.native.galley_node_is_valid(handle, node) !== 0;
342
+ }
343
+ childCount(handle, node) {
344
+ return this.native.galley_node_child_count(handle, node);
345
+ }
346
+ firstChild(handle, node) {
347
+ return this.native.galley_node_first_child(handle, node);
348
+ }
349
+ lastChild(handle, node) {
350
+ return this.native.galley_node_last_child(handle, node);
351
+ }
352
+ nextSibling(handle, node) {
353
+ return this.native.galley_node_next_sibling(handle, node);
354
+ }
355
+ priorSibling(handle, node) {
356
+ return this.native.galley_node_prior_sibling(handle, node);
357
+ }
358
+ parent(handle, node) {
359
+ return this.native.galley_node_parent(handle, node);
360
+ }
361
+ treeSnapshot(handle) {
362
+ for (let attempt = 0; attempt < 2; attempt++) {
363
+ const count = this.nodeCount(handle);
364
+ const parent = new BigUint64Array(count);
365
+ const firstChild = new BigUint64Array(count);
366
+ const next = new BigUint64Array(count);
367
+ const childCount = new Uint32Array(count);
368
+ const variable = new BigInt64Array(count);
369
+ const spanStart = new BigUint64Array(count);
370
+ const spanLen = new BigUint64Array(count);
371
+ const total = this.native.galley_tree_snapshot(handle, ptr(parent), ptr(firstChild), ptr(next), ptr(childCount), ptr(variable), ptr(spanStart), ptr(spanLen), BigInt(count));
372
+ if (total < 0n)
373
+ throw new GalleyError("galley_tree_snapshot failed", Number(total));
374
+ if (total === BigInt(count)) {
375
+ return { count, parent, firstChild, next, childCount, variable, spanStart, spanLen };
376
+ }
377
+ }
378
+ throw new GalleyError("node count changed during galley_tree_snapshot", -8);
379
+ }
380
+ // -- walker ------------------------------------------------------------
381
+ walkerCreate(handle, node, skipSemanticErrors) {
382
+ const walker = this.native.galley_walker_create(handle, node, skipSemanticErrors ? 1 : 0);
383
+ if (walker === 0 || walker === null || walker === undefined)
384
+ return null;
385
+ return walker;
386
+ }
387
+ walkerNext(walker) {
388
+ const outNode = ptrOut64();
389
+ const outDepth = u32Out();
390
+ const outFlag = u32Out();
391
+ if (this.native.galley_walker_next(walker, ptr(outNode), ptr(outDepth), ptr(outFlag)) === 0)
392
+ return null;
393
+ return { node: outNode[0], depth: outDepth[0], isSemanticError: outFlag[0] !== 0 };
394
+ }
395
+ walkerSkipChildren(walker) {
396
+ this.native.galley_walker_skip_children(walker);
397
+ }
398
+ walkerDestroy(walker) {
399
+ this.native.galley_walker_destroy(walker);
400
+ }
401
+ // -- node accessors -----------------------------------------------------
402
+ #tryCopyBytes(fn) {
403
+ const outData = ptrOut64();
404
+ const outLen = ptrOut64();
405
+ if (fn(outData, outLen) < 0n)
406
+ return null;
407
+ if (outData[0] === 0n)
408
+ return null;
409
+ return readBytes(outData[0], outLen[0]);
410
+ }
411
+ #readSemanticPair(fn) {
412
+ const outVariable = ptrOut64();
413
+ const outVariableLen = ptrOut64();
414
+ const outMessage = ptrOut64();
415
+ const outMessageLen = ptrOut64();
416
+ if (fn(outVariable, outVariableLen, outMessage, outMessageLen) < 0n)
417
+ return null;
418
+ if (outVariable[0] === 0n || outMessage[0] === 0n)
419
+ return null;
420
+ const decoder = new TextDecoder();
421
+ return [
422
+ decoder.decode(readBytes(outVariable[0], outVariableLen[0])),
423
+ decoder.decode(readBytes(outMessage[0], outMessageLen[0])),
424
+ ];
425
+ }
426
+ nodeSymbolName(handle, node) {
427
+ const h = handle;
428
+ const outData = ptrOut64();
429
+ const outLen = ptrOut64();
430
+ if (this.native.galley_node_symbol_name(h, node, ptr(outData), ptr(outLen)) < 0n)
431
+ return null;
432
+ return readBytes(outData[0], outLen[0]);
433
+ }
434
+ nodeText(handle, node) {
435
+ const h = handle;
436
+ const outData = ptrOut64();
437
+ const outLen = ptrOut64();
438
+ if (this.native.galley_node_text(h, node, ptr(outData), ptr(outLen)) < 0n)
439
+ return null;
440
+ return readBytes(outData[0], outLen[0]);
441
+ }
442
+ nodeSpan(handle, node) {
443
+ const outStart = ptrOut64();
444
+ const outLen = ptrOut64();
445
+ if (this.native.galley_node_span(handle, node, ptr(outStart), ptr(outLen)) < 0n)
446
+ return null;
447
+ return [outStart[0], outLen[0]];
448
+ }
449
+ nodeLineColumn(handle, node) {
450
+ const outLine = u32Out();
451
+ const outCol = u32Out();
452
+ if (this.native.galley_node_line_column(handle, node, ptr(outLine), ptr(outCol)) < 0n)
453
+ return null;
454
+ return [outLine[0], outCol[0]];
455
+ }
456
+ nodeVariableIndex(handle, node) {
457
+ return Number(this.native.galley_node_variable_index(handle, node));
458
+ }
459
+ symbolNameAt(handle, index) {
460
+ const h = handle;
461
+ const outData = ptrOut64();
462
+ const outLen = ptrOut64();
463
+ if (this.native.galley_symbol_name(h, BigInt(index), ptr(outData), ptr(outLen)) < 0n)
464
+ return null;
465
+ return readBytes(outData[0], outLen[0]);
466
+ }
467
+ symbolIsTerminal(handle, index) {
468
+ return this.native.galley_symbol_is_terminal(handle, BigInt(index)) !== 0;
469
+ }
470
+ variableNameAt(handle, index) {
471
+ const h = handle;
472
+ const outData = ptrOut64();
473
+ const outLen = ptrOut64();
474
+ if (this.native.galley_variable_name(h, BigInt(index), ptr(outData), ptr(outLen)) < 0n)
475
+ return null;
476
+ return readBytes(outData[0], outLen[0]);
477
+ }
478
+ // -- diagnostics ---------------------------------------------------------
479
+ hasDiagnostic(handle) {
480
+ return this.native.galley_has_diagnostic(handle) !== 0;
481
+ }
482
+ diagnosticKind(handle) {
483
+ return Number(this.native.galley_diagnostic_kind(handle));
484
+ }
485
+ diagnosticMessage(handle) {
486
+ const out = ptrOut64();
487
+ if (this.native.galley_diagnostic_message(handle, ptr(out)) !== 0n)
488
+ return null;
489
+ return readCString(out[0]);
490
+ }
491
+ diagnosticMessageAnsi(handle) {
492
+ const out = ptrOut64();
493
+ if (this.native.galley_diagnostic_message_ansi(handle, ptr(out)) !== 0n)
494
+ return null;
495
+ return readCString(out[0]);
496
+ }
497
+ diagnosticPosition(handle) {
498
+ const outLine = u32Out();
499
+ const outCol = u32Out();
500
+ if (this.native.galley_diagnostic_position(handle, ptr(outLine), ptr(outCol)) < 0n)
501
+ return null;
502
+ return [outLine[0], outCol[0]];
503
+ }
504
+ diagnosticUnexpectedToken(handle) {
505
+ const h = handle;
506
+ return this.#tryCopyBytes((od, ol) => this.native.galley_diagnostic_unexpected_token(h, ptr(od), ptr(ol)));
507
+ }
508
+ diagnosticExpectedCount(handle) {
509
+ return Number(this.native.galley_diagnostic_expected_count(handle));
510
+ }
511
+ diagnosticExpectedAt(handle, index) {
512
+ const h = handle;
513
+ return this.#tryCopyBytes((od, ol) => this.native.galley_diagnostic_expected_at(h, BigInt(index), ptr(od), ptr(ol)));
514
+ }
515
+ diagnosticContextCount(handle) {
516
+ return Number(this.native.galley_diagnostic_context_count(handle));
517
+ }
518
+ diagnosticContextAt(handle, index) {
519
+ const h = handle;
520
+ return this.#tryCopyBytes((od, ol) => this.native.galley_diagnostic_context_at(h, BigInt(index), ptr(od), ptr(ol)));
521
+ }
522
+ syntaxErrorCount(handle) {
523
+ return Number(this.native.galley_syntax_error_count(handle));
524
+ }
525
+ semanticErrorCount(handle) {
526
+ return Number(this.native.galley_semantic_error_count(handle));
527
+ }
528
+ diagnosticSemantic(handle) {
529
+ const h = handle;
530
+ return this.#readSemanticPair((ov, ovl, om, oml) => this.native.galley_diagnostic_semantic(h, ptr(ov), ptr(ovl), ptr(om), ptr(oml)));
531
+ }
532
+ diagnosticIndentation(handle) {
533
+ const outSpaces = u32Out();
534
+ const outWidth = u32Out();
535
+ if (this.native.galley_diagnostic_indentation(handle, ptr(outSpaces), ptr(outWidth)) !== 0n)
536
+ return null;
537
+ return [outSpaces[0], outWidth[0]];
538
+ }
539
+ diagnosticRecoveryKind(handle) {
540
+ return Number(this.native.galley_diagnostic_recovery_kind(handle));
541
+ }
542
+ diagnosticRecoveryTerminal(handle) {
543
+ const h = handle;
544
+ return this.#tryCopyBytes((od, ol) => this.native.galley_diagnostic_recovery_terminal(h, ptr(od), ptr(ol)));
545
+ }
546
+ diagnosticRecoveryResume(handle) {
547
+ const out = i64Out();
548
+ if (this.native.galley_diagnostic_recovery_resume(handle, ptr(out)) !== 0n)
549
+ return null;
550
+ return Number(out[0]);
551
+ }
552
+ diagnosticRecoveryLhsVariable(handle) {
553
+ const h = handle;
554
+ const outData = ptrOut64();
555
+ const outLen = ptrOut64();
556
+ if (this.native.galley_diagnostic_recovery_lhs_variable(h, ptr(outData), ptr(outLen)) < 0n || outData[0] === 0n)
557
+ return null;
558
+ return new TextDecoder().decode(readBytes(outData[0], outLen[0]));
559
+ }
560
+ diagnosticRecoveryProduction(handle) {
561
+ const h = handle;
562
+ const outVar = ptrOut64();
563
+ const outLen = ptrOut64();
564
+ const outIdx = u32Out();
565
+ if (this.native.galley_diagnostic_recovery_production(h, ptr(outVar), ptr(outLen), ptr(outIdx)) !== 0n)
566
+ return null;
567
+ return [new TextDecoder().decode(readBytes(outVar[0], outLen[0])), outIdx[0]];
568
+ }
569
+ diagnosticRecoveryOccurrence(handle) {
570
+ const h = handle;
571
+ const outParent = ptrOut64();
572
+ const outParentLen = ptrOut64();
573
+ const outRhs = u32Out();
574
+ const outSym = u32Out();
575
+ const outVar = ptrOut64();
576
+ const outVarLen = ptrOut64();
577
+ if (this.native.galley_diagnostic_recovery_occurrence(h, ptr(outParent), ptr(outParentLen), ptr(outRhs), ptr(outSym), ptr(outVar), ptr(outVarLen)) !== 0n)
578
+ return null;
579
+ const decoder = new TextDecoder();
580
+ return [
581
+ decoder.decode(readBytes(outParent[0], outParentLen[0])),
582
+ outRhs[0],
583
+ outSym[0],
584
+ decoder.decode(readBytes(outVar[0], outVarLen[0])),
585
+ ];
586
+ }
587
+ recordedDiagnosticCount(handle) {
588
+ return Number(this.native.galley_recorded_diagnostic_count(handle));
589
+ }
590
+ recordedDiagnosticKind(handle, diagIndex) {
591
+ return Number(this.native.galley_recorded_diagnostic_kind(handle, BigInt(diagIndex)));
592
+ }
593
+ recordedDiagnosticPosition(handle, diagIndex) {
594
+ const outLine = u32Out();
595
+ const outCol = u32Out();
596
+ if (this.native.galley_recorded_diagnostic_position(handle, BigInt(diagIndex), ptr(outLine), ptr(outCol)) < 0n)
597
+ return null;
598
+ return [outLine[0], outCol[0]];
599
+ }
600
+ recordedUnexpectedToken(handle, diagIndex) {
601
+ const h = handle;
602
+ const d = BigInt(diagIndex);
603
+ return this.#tryCopyBytes((od, ol) => this.native.galley_recorded_unexpected_token(h, d, ptr(od), ptr(ol)));
604
+ }
605
+ recordedDiagnosticMessage(handle, diagIndex) {
606
+ const out = ptrOut64();
607
+ if (this.native.galley_recorded_diagnostic_message(handle, BigInt(diagIndex), ptr(out)) !== 0n)
608
+ return null;
609
+ return readCString(out[0]);
610
+ }
611
+ recordedIndentation(handle, diagIndex) {
612
+ const outSpaces = u32Out();
613
+ const outWidth = u32Out();
614
+ if (this.native.galley_recorded_indentation(handle, BigInt(diagIndex), ptr(outSpaces), ptr(outWidth)) !== 0n)
615
+ return null;
616
+ return [outSpaces[0], outWidth[0]];
617
+ }
618
+ recordedSemantic(handle, diagIndex) {
619
+ const h = handle;
620
+ const d = BigInt(diagIndex);
621
+ return this.#readSemanticPair((ov, ovl, om, oml) => this.native.galley_recorded_semantic(h, d, ptr(ov), ptr(ovl), ptr(om), ptr(oml)));
622
+ }
623
+ recordedExpectedCount(handle, diagIndex) {
624
+ return Number(this.native.galley_recorded_expected_count(handle, BigInt(diagIndex)));
625
+ }
626
+ recordedExpectedToken(handle, diagIndex, tokenIndex) {
627
+ const h = handle;
628
+ const d = BigInt(diagIndex);
629
+ const t = BigInt(tokenIndex);
630
+ return this.#tryCopyBytes((od, ol) => this.native.galley_recorded_expected_token(h, d, t, ptr(od), ptr(ol)));
631
+ }
632
+ recordedContextCount(handle, diagIndex) {
633
+ return Number(this.native.galley_recorded_context_count(handle, BigInt(diagIndex)));
634
+ }
635
+ recordedContextName(handle, diagIndex, contextIndex) {
636
+ const h = handle;
637
+ const d = BigInt(diagIndex);
638
+ const c = BigInt(contextIndex);
639
+ return this.#tryCopyBytes((od, ol) => this.native.galley_recorded_context_name(h, d, c, ptr(od), ptr(ol)));
640
+ }
641
+ recordedRecoveryKind(handle, diagIndex) {
642
+ return Number(this.native.galley_recorded_diagnostic_recovery_kind(handle, BigInt(diagIndex)));
643
+ }
644
+ recordedRecoveryTerminal(handle, diagIndex) {
645
+ const h = handle;
646
+ const d = BigInt(diagIndex);
647
+ return this.#tryCopyBytes((od, ol) => this.native.galley_recorded_recovery_terminal(h, d, ptr(od), ptr(ol)));
648
+ }
649
+ recordedRecoveryResume(handle, diagIndex) {
650
+ const out = i64Out();
651
+ if (this.native.galley_recorded_recovery_resume(handle, BigInt(diagIndex), ptr(out)) !== 0n)
652
+ return null;
653
+ return Number(out[0]);
654
+ }
655
+ recordedRecoveryLhsVariable(handle, diagIndex) {
656
+ const h = handle;
657
+ const d = BigInt(diagIndex);
658
+ const outData = ptrOut64();
659
+ const outLen = ptrOut64();
660
+ if (this.native.galley_recorded_recovery_lhs_variable(h, d, ptr(outData), ptr(outLen)) < 0n || outData[0] === 0n)
661
+ return null;
662
+ return new TextDecoder().decode(readBytes(outData[0], outLen[0]));
663
+ }
664
+ recordedRecoveryProduction(handle, diagIndex) {
665
+ const h = handle;
666
+ const d = BigInt(diagIndex);
667
+ const outVar = ptrOut64();
668
+ const outLen = ptrOut64();
669
+ const outIdx = u32Out();
670
+ if (this.native.galley_recorded_recovery_production(h, d, ptr(outVar), ptr(outLen), ptr(outIdx)) !== 0n)
671
+ return null;
672
+ return [new TextDecoder().decode(readBytes(outVar[0], outLen[0])), outIdx[0]];
673
+ }
674
+ recordedRecoveryOccurrence(handle, diagIndex) {
675
+ const h = handle;
676
+ const d = BigInt(diagIndex);
677
+ const outParent = ptrOut64();
678
+ const outParentLen = ptrOut64();
679
+ const outRhs = u32Out();
680
+ const outSym = u32Out();
681
+ const outVar = ptrOut64();
682
+ const outVarLen = ptrOut64();
683
+ if (this.native.galley_recorded_recovery_occurrence(h, d, ptr(outParent), ptr(outParentLen), ptr(outRhs), ptr(outSym), ptr(outVar), ptr(outVarLen)) !== 0n)
684
+ return null;
685
+ const decoder = new TextDecoder();
686
+ return [
687
+ decoder.decode(readBytes(outParent[0], outParentLen[0])),
688
+ outRhs[0],
689
+ outSym[0],
690
+ decoder.decode(readBytes(outVar[0], outVarLen[0])),
691
+ ];
692
+ }
693
+ // -- tree editing ----------------------------------------------------------
694
+ treeAppendChildren(handle, parent, first) {
695
+ return Number(this.native.galley_tree_append_children(handle, parent, first));
696
+ }
697
+ treeInsertBefore(handle, target, first) {
698
+ return Number(this.native.galley_tree_insert_before(handle, target, first));
699
+ }
700
+ treeInsertAfter(handle, target, first) {
701
+ return Number(this.native.galley_tree_insert_after(handle, target, first));
702
+ }
703
+ treeRemoveSiblings(handle, node, count) {
704
+ const outHead = ptrOut64();
705
+ const st = this.native.galley_tree_remove_siblings(handle, node, BigInt(count), ptr(outHead));
706
+ return { status: Number(st), head: outHead[0] };
707
+ }
708
+ treeRemoveSelf(handle, node) {
709
+ const outHead = ptrOut64();
710
+ const st = this.native.galley_tree_remove_self(handle, node, ptr(outHead));
711
+ return { status: Number(st), head: outHead[0] };
712
+ }
713
+ treePromoteChildrenOverWrapper(handle, wrapper) {
714
+ const outHead = ptrOut64();
715
+ const st = this.native.galley_tree_promote_children_over_wrapper(handle, wrapper, ptr(outHead));
716
+ return { status: Number(st), head: outHead[0] };
717
+ }
718
+ treeCleanChildren(handle, node) {
719
+ const outHead = ptrOut64();
720
+ const st = this.native.galley_tree_clean_children(handle, node, ptr(outHead));
721
+ return { status: Number(st), head: outHead[0] };
722
+ }
723
+ treeUnlinkWrapper(handle, wrapper) {
724
+ return Number(this.native.galley_tree_unlink_wrapper(handle, wrapper));
725
+ }
726
+ treeInsertChildrenAt(handle, parent, index, first) {
727
+ return Number(this.native.galley_tree_insert_children_at(handle, parent, BigInt(index), first));
728
+ }
729
+ treeRemoveChildrenAt(handle, parent, index, count) {
730
+ const outHead = ptrOut64();
731
+ const st = this.native.galley_tree_remove_children_at(handle, parent, BigInt(index), BigInt(count), ptr(outHead));
732
+ return { status: Number(st), head: outHead[0] };
733
+ }
734
+ // -- procedure hooks ----------------------------------------------------------
735
+ procCurrentNode(args) {
736
+ return this.native.galley_procedure_current_node(args);
737
+ }
738
+ procSetCurrentNode(args, node) {
739
+ this.native.galley_procedure_set_current_node(args, node);
740
+ }
741
+ procDropSelf(args) {
742
+ return Number(this.native.galley_procedure_drop_self(args));
743
+ }
744
+ procDropChildren(args) {
745
+ return Number(this.native.galley_procedure_drop_children(args));
746
+ }
747
+ procDropIfEmpty(args) {
748
+ return Number(this.native.galley_procedure_drop_if_empty(args));
749
+ }
750
+ procReplaceWithChildren(args) {
751
+ return Number(this.native.galley_procedure_replace_with_children(args));
752
+ }
753
+ procContextLine(args) {
754
+ return this.native.galley_procedure_context_line(args);
755
+ }
756
+ procContextColumn(args) {
757
+ return this.native.galley_procedure_context_column(args);
758
+ }
759
+ procReportSemanticError(args, message) {
760
+ return Number(this.native.galley_procedure_report_semantic_error(args, ptr(message), BigInt(message.length)));
761
+ }
762
+ }
763
+ const portCache = new Map();
764
+ /** Port for the library at `explicitPath` (or default discovery), cached per path. */
765
+ export function getBunPort(explicitPath) {
766
+ const libPath = findLibrary(explicitPath);
767
+ const cached = portCache.get(libPath);
768
+ if (cached)
769
+ return cached;
770
+ // Libraries built for C procedures lack the JS dispatch symbol.
771
+ let native;
772
+ let supportsDispatch = true;
773
+ try {
774
+ native = openNative(libPath, 3).symbols;
775
+ }
776
+ catch {
777
+ try {
778
+ native = openNative(libPath, 2).symbols;
779
+ }
780
+ catch {
781
+ try {
782
+ native = openNative(libPath, 1).symbols;
783
+ }
784
+ catch {
785
+ native = openNative(libPath, 0).symbols;
786
+ supportsDispatch = false;
787
+ }
788
+ }
789
+ }
790
+ const port = new BunPort(native, libPath, supportsDispatch);
791
+ portCache.set(libPath, port);
792
+ return port;
793
+ }
794
+ //# sourceMappingURL=ffi.js.map