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