eyeleng 1.0.13 → 1.1.0

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/eyeleng.js CHANGED
@@ -14,6 +14,8 @@
14
14
  evaluate,
15
15
  parseQuery,
16
16
  queryResult,
17
+ queryProgram,
18
+ queryRunOptions,
17
19
  formatTriples,
18
20
  formatTrace,
19
21
  formatBindings,
@@ -40,7 +42,7 @@
40
42
  const VERSION = readPackageVersion();
41
43
 
42
44
  function help() {
43
- return `eyeleng ${VERSION}\n\nA dependency-free JavaScript implementation experiment for the SHACL 1.2 Rules draft, including SRL and RDF Rules syntax front-ends.\n\nUsage:\n eyeleng [options] [file ...]\n\nOptions:\n --all Print the full closure, including input facts\n --json Print JSON instead of compact triples/bindings\n --trace Print derivation trace to stderr, or include it in JSON\n --stats Print iteration and triple counts to stderr\n --check Parse and analyze only; do not run rules\n --strict Treat static warnings as errors, including recursive term generation\n --deps Print rule dependency edges during --check\n --query TEXT Run a raw SRL body pattern over the closure\n --query-file FILE Read a raw SRL body pattern from a file\n --max-iterations N Stop after N fixpoint iterations within a recursive layer\n --no-imports Parse IMPORTS/owl:imports but do not load imported rule sets\n --rdf-messages Parse input as an RDF Message Log\n --stream-messages Replay RDF Message Log envelopes\n --include-message-facts Include payload facts while parsing RDF Message Logs\n --syntax MODE Use srl, rdf, or auto syntax detection (default auto)\n --ruleset TERM In RDF syntax, run only the selected srl:RuleSet\n --version Print version\n -h, --help Print this help\n\nWith no file arguments, eyeleng reads from stdin.\n`;
45
+ return `eyeleng ${VERSION}\n\nA dependency-free JavaScript implementation experiment for the SHACL 1.2 Rules draft, including SRL and RDF Rules syntax front-ends.\n\nUsage:\n eyeleng [options] [file ...]\n\nOptions:\n --all Print the full closure, including input facts\n --json Print JSON instead of compact triples/bindings\n --trace Print derivation trace to stderr, or include it in JSON\n --stats Print iteration and triple counts to stderr\n --check Parse and analyze only; do not run rules\n --strict Treat static warnings as errors, including recursive term generation\n --deps Print rule dependency edges during --check\n --query TEXT Run a raw SRL body pattern over the closure or backward planner\n --query-file FILE Read a raw SRL body pattern from a file\n --query-mode MODE Use auto, forward, or backward query planning (default auto)\n --hybrid Orient function-like rules backward during forward execution and queries\n --max-iterations N Stop after N fixpoint iterations within a recursive layer\n --no-imports Parse IMPORTS/owl:imports but do not load imported rule sets\n --rdf-messages Parse input as an RDF Message Log\n --include-message-facts Include payload facts while parsing RDF Message Logs\n --syntax MODE Use srl, rdf, or auto syntax detection (default auto)\n --ruleset TERM In RDF syntax, run only the selected srl:RuleSet\n --version Print version\n -h, --help Print this help\n\nWith no file arguments, eyeleng reads from stdin.\n`;
44
46
  }
45
47
 
46
48
  function parseArgs(argv) {
@@ -54,6 +56,8 @@
54
56
  deps: false,
55
57
  query: null,
56
58
  queryFile: null,
59
+ queryMode: 'auto',
60
+ hybrid: false,
57
61
  maxIterations: 10000,
58
62
  imports: true,
59
63
  syntax: 'auto',
@@ -72,7 +76,8 @@
72
76
  else if (arg === '--strict') options.strict = true;
73
77
  else if (arg === '--deps') options.deps = true;
74
78
  else if (arg === '--no-imports') options.imports = false;
75
- else if (arg === '--rdf-messages' || arg === '--stream-messages') options.rdfMessages = true;
79
+ else if (arg === '--hybrid') options.hybrid = true;
80
+ else if (arg === '--rdf-messages') options.rdfMessages = true;
76
81
  else if (arg === '--include-message-facts') options.includeMessageFacts = true;
77
82
  else if (arg === '--syntax') {
78
83
  i += 1;
@@ -83,8 +88,12 @@
83
88
  i += 1;
84
89
  if (i >= argv.length) throw new Error('--ruleset requires an RDF term');
85
90
  options.ruleSet = argv[i];
86
- }
87
- else if (arg === '--query') {
91
+ } else if (arg === '--query-mode') {
92
+ i += 1;
93
+ if (i >= argv.length) throw new Error('--query-mode requires auto, forward, or backward');
94
+ options.queryMode = argv[i];
95
+ if (!['auto', 'forward', 'backward'].includes(options.queryMode)) throw new Error('--query-mode requires auto, forward, or backward');
96
+ } else if (arg === '--query') {
88
97
  i += 1;
89
98
  if (i >= argv.length) throw new Error('--query requires a value');
90
99
  options.query = argv[i];
@@ -197,15 +206,42 @@
197
206
  }
198
207
  if (fatal) return 1;
199
208
 
200
- const result = evaluate(compiled.program, { ...options, analysis: compiled.analysis });
201
- result.diagnostics = compiled.diagnostics;
202
- result.analysis = compiled.analysis;
203
-
204
209
  const queryText = options.queryFile ? fs.readFileSync(options.queryFile, 'utf8') : options.query;
205
210
  const querySpec = queryText
206
211
  ? parseQuery(queryText, { filename: options.queryFile || '<query>', prefixes: compiled.program.prefixes, baseIRI: compiled.program.baseIRI })
207
212
  : null;
208
- if (querySpec) result.query = queryResult(result, querySpec, options);
213
+
214
+ let result;
215
+ if (querySpec) {
216
+ const directQuery = queryProgram(compiled.program, querySpec, options);
217
+ if (directQuery) {
218
+ result = {
219
+ baseIRI: compiled.program.baseIRI,
220
+ prefixes: compiled.program.prefixes,
221
+ input: compiled.program.data.slice(),
222
+ inferred: [],
223
+ closure: compiled.program.data.slice(),
224
+ iterations: 0,
225
+ layers: [],
226
+ ruleApplications: 0,
227
+ perRule: [],
228
+ trace: [],
229
+ diagnostics: compiled.diagnostics,
230
+ analysis: compiled.analysis,
231
+ query: directQuery,
232
+ };
233
+ }
234
+ }
235
+
236
+ if (!result) {
237
+ const runOptions = querySpec
238
+ ? queryRunOptions(compiled.program, querySpec, options)
239
+ : { ...options, hybrid: options.hybrid };
240
+ result = evaluate(compiled.program, { ...runOptions, analysis: compiled.analysis });
241
+ result.diagnostics = compiled.diagnostics;
242
+ result.analysis = compiled.analysis;
243
+ if (querySpec) result.query = queryResult(result, querySpec, runOptions);
244
+ }
209
245
 
210
246
  if (options.json) {
211
247
  io.stdout.write(`${JSON.stringify(toJSON(result, { all: options.all, trace: options.trace, analysis: options.deps }), null, 2)}\n`);
@@ -220,7 +256,9 @@
220
256
  }
221
257
 
222
258
  if (options.stats) {
223
- io.stderr.write(`eyeleng: iterations=${result.iterations} layers=${result.layers.length} input=${result.input.length} inferred=${result.inferred.length} closure=${result.closure.length} ruleApplications=${result.ruleApplications}\n`);
259
+ io.stderr.write(`eyeleng: iterations=${result.iterations} layers=${result.layers.length} input=${result.input.length} inferred=${result.inferred.length} closure=${result.closure.length} ruleApplications=${result.ruleApplications}${result.query && result.query.mode ? ` queryMode=${result.query.mode}` : ''}\n`);
260
+ if (result.query && result.query.stats) io.stderr.write(`eyeleng: backward goals=${result.query.stats.goals} facts=${result.query.stats.facts} rules=${result.query.stats.rules} memoHits=${result.query.stats.memoHits} memoStores=${result.query.stats.memoStores}\n`);
261
+ if (result.hybridStats) io.stderr.write(`eyeleng: hybridBackward goals=${result.hybridStats.goals} facts=${result.hybridStats.facts} rules=${result.hybridStats.rules} memoHits=${result.hybridStats.memoHits} memoStores=${result.hybridStats.memoStores}\n`);
224
262
  for (const rule of result.perRule) {
225
263
  if (rule.applications > 0 || rule.added > 0) io.stderr.write(`eyeleng: rule ${rule.name}: applications=${rule.applications} added=${rule.added}${rule.runOnce ? ' runOnce=true' : ''}\n`);
226
264
  }
@@ -246,7 +284,7 @@
246
284
  const { evaluate } = require('./engine.js');
247
285
  const { analyze } = require('./analyze.js');
248
286
  const { formatTriples, sortTriples, toJSON, formatTrace, formatBindings } = require('./format.js');
249
- const { runQuery, queryResult } = require('./query.js');
287
+ const { runQuery, queryResult, queryProgram, queryRunOptions, shouldUseHybridForQuery } = require('./query.js');
250
288
  const { resultTriples } = require('./output.js');
251
289
 
252
290
  function parseInput(source, options = {}) {
@@ -360,6 +398,9 @@
360
398
  runToString,
361
399
  runQuery,
362
400
  queryResult,
401
+ queryProgram,
402
+ queryRunOptions,
403
+ shouldUseHybridForQuery,
363
404
  formatTriples,
364
405
  formatBindings,
365
406
  sortTriples,
@@ -4278,10 +4319,11 @@
4278
4319
  "src/engine.js": function (require, module, exports) {
4279
4320
  'use strict';
4280
4321
 
4281
- const { TripleStore, bindingKey } = require('./store.js');
4322
+ const { TripleStore, bindingKey, instantiateTerm } = require('./store.js');
4282
4323
  const { tripleKey, termKey, termEquals, blankNode, tripleTerm } = require('./term.js');
4283
4324
  const { evalExpression, booleanValue, asTerm } = require('./builtins.js');
4284
4325
  const { analyze } = require('./analyze.js');
4326
+ const { BackwardProver, preferredBackwardPredicates, ruleIsBackwardOriented } = require('./backward.js');
4285
4327
 
4286
4328
  function evaluate(program, options = {}) {
4287
4329
  const maxIterations = options.maxIterations ?? 10000;
@@ -4297,6 +4339,7 @@
4297
4339
  applications: 0,
4298
4340
  added: 0,
4299
4341
  runOnce: !!rule.runOnce,
4342
+ backward: false,
4300
4343
  }));
4301
4344
 
4302
4345
  const analysis = options.analysis || analyze(program, options);
@@ -4313,6 +4356,17 @@
4313
4356
  const relaxedRecursiveRunOnce = options.relaxedRecursion === false
4314
4357
  ? new Set()
4315
4358
  : recursiveTermGenerationRuleIndexes(analysis);
4359
+ const hybridBackwardPredicates = options.hybrid || options.backwardBodyCalls
4360
+ ? preferredBackwardPredicates(program, options)
4361
+ : new Set();
4362
+ const hybridBackwardRules = new Set();
4363
+ if (hybridBackwardPredicates.size > 0) {
4364
+ for (let ruleIndex = 0; ruleIndex < program.rules.length; ruleIndex += 1) {
4365
+ if (ruleIsBackwardOriented(program.rules[ruleIndex], hybridBackwardPredicates)) hybridBackwardRules.add(ruleIndex);
4366
+ }
4367
+ }
4368
+ const hybridStats = hybridBackwardPredicates.size > 0 ? emptyBackwardStats() : null;
4369
+ for (const ruleIndex of hybridBackwardRules) perRule[ruleIndex].backward = true;
4316
4370
  const baseContext = {
4317
4371
  ...evalOptions,
4318
4372
  maxIterations,
@@ -4324,12 +4378,16 @@
4324
4378
  iteration: 0,
4325
4379
  startingIterations: 0,
4326
4380
  recursiveLayer: false,
4381
+ hybridBackwardPredicates,
4382
+ hybridBackwardRules,
4383
+ hybridStats,
4327
4384
  };
4328
4385
 
4329
4386
  for (let layerIndex = 0; layerIndex < layerIndexes.length; layerIndex += 1) {
4330
4387
  const layer = layerIndexes[layerIndex];
4331
- const ordinary = layer.filter((ruleIndex) => !program.rules[ruleIndex].runOnce || relaxedRecursiveRunOnce.has(ruleIndex));
4332
- const runOnce = layer.filter((ruleIndex) => program.rules[ruleIndex].runOnce && !relaxedRecursiveRunOnce.has(ruleIndex));
4388
+ const forwardLayer = hybridBackwardRules.size > 0 ? layer.filter((ruleIndex) => !hybridBackwardRules.has(ruleIndex)) : layer;
4389
+ const ordinary = forwardLayer.filter((ruleIndex) => !program.rules[ruleIndex].runOnce || relaxedRecursiveRunOnce.has(ruleIndex));
4390
+ const runOnce = forwardLayer.filter((ruleIndex) => program.rules[ruleIndex].runOnce && !relaxedRecursiveRunOnce.has(ruleIndex));
4333
4391
 
4334
4392
  if (runOnce.length > 0) {
4335
4393
  iterations += 1;
@@ -4362,6 +4420,7 @@
4362
4420
  ruleApplications,
4363
4421
  perRule,
4364
4422
  trace,
4423
+ hybridStats,
4365
4424
  };
4366
4425
  }
4367
4426
 
@@ -4431,9 +4490,10 @@
4431
4490
  const seenBindings = dedupeBindings ? new Set() : null;
4432
4491
  const headBlankLabels = collectHeadBlankLabels(rule.head);
4433
4492
 
4434
- const bodyBindings = rule.body.length === 1 && rule.body[0].type === 'triple'
4493
+ const bodyContext = prepareBodyContext(program, store, context);
4494
+ const bodyBindings = rule.body.length === 1 && rule.body[0].type === 'triple' && !shouldUseBackwardForTriple(rule.body[0].triple, {}, bodyContext)
4435
4495
  ? store.match(rule.body[0].triple, {})
4436
- : evaluateBodyStream(rule.body, store, {}, context);
4496
+ : evaluateBodyStream(rule.body, store, {}, bodyContext);
4437
4497
 
4438
4498
  for (const binding of bodyBindings) {
4439
4499
  if (seenBindings) {
@@ -4466,9 +4526,36 @@
4466
4526
  }
4467
4527
  }
4468
4528
 
4529
+ if (bodyContext.backwardProver && context.hybridStats) mergeBackwardStats(context.hybridStats, bodyContext.backwardProver.stats);
4469
4530
  return { applications, added };
4470
4531
  }
4471
4532
 
4533
+ function prepareBodyContext(program, store, context) {
4534
+ if (!context.hybridBackwardPredicates || context.hybridBackwardPredicates.size === 0) return context;
4535
+ return {
4536
+ ...context,
4537
+ backwardProver: new BackwardProver(program, {
4538
+ ...context,
4539
+ store,
4540
+ allowedPredicates: context.hybridBackwardPredicates,
4541
+ }),
4542
+ };
4543
+ }
4544
+
4545
+ function emptyBackwardStats() {
4546
+ return { mode: 'hybrid', goals: 0, facts: 0, rules: 0, memoHits: 0, memoStores: 0, maxDepth: 0 };
4547
+ }
4548
+
4549
+ function mergeBackwardStats(total, item) {
4550
+ if (!total || !item) return;
4551
+ total.goals += item.goals || 0;
4552
+ total.facts += item.facts || 0;
4553
+ total.rules += item.rules || 0;
4554
+ total.memoHits += item.memoHits || 0;
4555
+ total.memoStores += item.memoStores || 0;
4556
+ total.maxDepth = Math.max(total.maxDepth || 0, item.maxDepth || 0);
4557
+ }
4558
+
4472
4559
  function recursiveTermGenerationRuleIndexes(analysis) {
4473
4560
  const out = new Set();
4474
4561
  if (!analysis || !analysis.dependency || !analysis.diagnostics) return out;
@@ -4577,9 +4664,20 @@
4577
4664
 
4578
4665
  const clause = clauses[index];
4579
4666
  if (clause.type === 'triple') {
4667
+ const seen = new Set();
4580
4668
  for (const matched of store.match(clause.triple, initialBinding)) {
4669
+ const key = bindingKey(matched);
4670
+ seen.add(key);
4581
4671
  yield* evaluateBodyStream(clauses, store, matched, options, index + 1);
4582
4672
  }
4673
+ if (shouldUseBackwardForTriple(clause.triple, initialBinding, options)) {
4674
+ for (const matched of options.backwardProver.solveTriple(clause.triple, initialBinding)) {
4675
+ const key = bindingKey(matched);
4676
+ if (seen.has(key)) continue;
4677
+ seen.add(key);
4678
+ yield* evaluateBodyStream(clauses, store, matched, options, index + 1);
4679
+ }
4680
+ }
4583
4681
  return;
4584
4682
  }
4585
4683
 
@@ -4625,6 +4723,12 @@
4625
4723
  throw new Error(`Unsupported body clause ${clause.type}`);
4626
4724
  }
4627
4725
 
4726
+ function shouldUseBackwardForTriple(pattern, binding, options = {}) {
4727
+ if (!options.backwardProver || !options.hybridBackwardPredicates || options.hybridBackwardPredicates.size === 0) return false;
4728
+ const predicate = instantiateTerm(pattern.p, binding);
4729
+ return !!(predicate && predicate.type === 'iri' && options.hybridBackwardPredicates.has(predicate.value));
4730
+ }
4731
+
4628
4732
  function bodyHasAny(clauses, store, initialBinding, options) {
4629
4733
  for (const _ of evaluateBodyStream(clauses, store, initialBinding, options)) return true;
4630
4734
  return false;
@@ -4657,6 +4761,7 @@
4657
4761
  this.byPredicate = new Map();
4658
4762
  this.byPredicateSubject = new Map();
4659
4763
  this.byPredicateObject = new Map();
4764
+ this.version = 0;
4660
4765
  for (const triple of triples) this.add(triple);
4661
4766
  }
4662
4767
 
@@ -4671,6 +4776,7 @@
4671
4776
  addIndex(this.byPredicate, predicate, key, normalized);
4672
4777
  addNestedIndex(this.byPredicateSubject, predicate, subject, key, normalized);
4673
4778
  addNestedIndex(this.byPredicateObject, predicate, object, key, normalized);
4779
+ this.version += 1;
4674
4780
  return true;
4675
4781
  }
4676
4782
 
@@ -5652,6 +5758,499 @@
5652
5758
  canPossiblyGenerate,
5653
5759
  };
5654
5760
 
5761
+ },
5762
+ "src/backward.js": function (require, module, exports) {
5763
+ 'use strict';
5764
+
5765
+ const { TripleStore, bindingKey } = require('./store.js');
5766
+ const { tripleKey, termKey, termEquals } = require('./term.js');
5767
+ const { evalExpression, booleanValue, asTerm } = require('./builtins.js');
5768
+
5769
+ function backwardQuery(program, querySpec, options = {}) {
5770
+ const planner = planBackwardQuery(program, querySpec, options);
5771
+ if (!planner.ok) return { ok: false, reason: planner.reason };
5772
+ const prover = new BackwardProver(program, { ...options, allowedRuleIndexes: planner.ruleIndexes });
5773
+ const bindings = uniqueBindings(Array.from(prover.solveBody(querySpec.body, {})));
5774
+ return { ok: true, bindings, stats: prover.stats, plan: planner };
5775
+ }
5776
+
5777
+ function planBackwardQuery(program, querySpec, options = {}) {
5778
+ const clauses = querySpec && Array.isArray(querySpec.body) ? querySpec.body : [];
5779
+ if (!bodySupported(clauses, options)) return { ok: false, reason: 'query body contains clauses not supported by the backward prover yet' };
5780
+
5781
+ const reachable = reachableBackwardRuleIndexes(program, clauses, options);
5782
+ for (const ruleIndex of reachable.ruleIndexes) {
5783
+ const rule = (program.rules || [])[ruleIndex];
5784
+ if (!ruleSupported(rule, options)) return { ok: false, reason: `reachable rule ${rule.name || '<anonymous>'} is not supported by the backward prover yet` };
5785
+ }
5786
+ return { ok: true, ruleIndexes: reachable.ruleIndexes, predicates: reachable.predicates };
5787
+ }
5788
+
5789
+ function bodySupported(clauses, options = {}) {
5790
+ for (const clause of clauses || []) {
5791
+ if (clause.type === 'triple' || clause.type === 'filter' || clause.type === 'set' || clause.type === 'bind') continue;
5792
+ if (clause.type === 'not') {
5793
+ if (options.backwardNegation === false) return false;
5794
+ if (!bodySupported(clause.body, options)) return false;
5795
+ continue;
5796
+ }
5797
+ return false;
5798
+ }
5799
+ return true;
5800
+ }
5801
+
5802
+ function ruleSupported(rule, options = {}) {
5803
+ if (!Array.isArray(rule.head) || rule.head.length === 0) return false;
5804
+ for (const head of rule.head) {
5805
+ if (!head || !head.p || head.p.type !== 'iri') return false;
5806
+ if (containsBlank(head.s) || containsBlank(head.p) || containsBlank(head.o)) return false;
5807
+ }
5808
+ return bodySupported(rule.body || [], options);
5809
+ }
5810
+
5811
+ class BackwardProver {
5812
+ constructor(program, options = {}) {
5813
+ this.program = program;
5814
+ this.options = options;
5815
+ this.store = options.store || new TripleStore(program.data || []);
5816
+ this.maxDepth = options.backwardMaxDepth || options.maxDepth || 10000;
5817
+ this.solutionLimit = options.backwardSolutionLimit || options.solutionLimit || 1000000;
5818
+ this.allowedPredicates = normalizePredicateSet(options.allowedPredicates || options.backwardPredicates || null);
5819
+ this.allowedRuleIndexes = normalizeRuleIndexSet(options.allowedRuleIndexes || null);
5820
+ this.ruleHeads = indexRuleHeads(program.rules || [], { allowedPredicates: this.allowedPredicates, allowedRuleIndexes: this.allowedRuleIndexes });
5821
+ this.memo = new Map();
5822
+ this.active = new Set();
5823
+ this.freshCounter = 0;
5824
+ this.solutionCount = 0;
5825
+ this.stats = {
5826
+ mode: 'backward',
5827
+ goals: 0,
5828
+ facts: 0,
5829
+ rules: 0,
5830
+ memoHits: 0,
5831
+ memoStores: 0,
5832
+ maxDepth: 0,
5833
+ };
5834
+ }
5835
+
5836
+ *solveBody(clauses, binding = {}, depth = 0, index = 0) {
5837
+ if (depth > this.maxDepth) throw new Error(`Reached backwardMaxDepth=${this.maxDepth}; backward query may not terminate`);
5838
+ this.stats.maxDepth = Math.max(this.stats.maxDepth, depth);
5839
+ if (this.solutionCount >= this.solutionLimit) return;
5840
+ if (index >= clauses.length) {
5841
+ this.solutionCount += 1;
5842
+ yield resolveBinding(binding);
5843
+ return;
5844
+ }
5845
+
5846
+ const clause = clauses[index];
5847
+ if (clause.type === 'triple') {
5848
+ for (const matched of this.solveTriple(clause.triple, binding, depth + 1)) {
5849
+ yield* this.solveBody(clauses, matched, depth + 1, index + 1);
5850
+ }
5851
+ return;
5852
+ }
5853
+
5854
+ if (clause.type === 'filter') {
5855
+ try {
5856
+ if (booleanValue(evalExpression(clause.expr, resolveBinding(binding), this.options))) {
5857
+ yield* this.solveBody(clauses, binding, depth + 1, index + 1);
5858
+ }
5859
+ } catch (_) {
5860
+ // SPARQL-style FILTER errors reject the current solution.
5861
+ }
5862
+ return;
5863
+ }
5864
+
5865
+ if (clause.type === 'set' || clause.type === 'bind') {
5866
+ try {
5867
+ const resolved = resolveBinding(binding);
5868
+ const value = asTerm(evalExpression(clause.expr, resolved, this.options));
5869
+ const next = unifyTerms({ type: 'var', value: clause.variable }, value, binding);
5870
+ if (next) yield* this.solveBody(clauses, next, depth + 1, index + 1);
5871
+ } catch (_) {
5872
+ // Assignment errors drop the current solution.
5873
+ }
5874
+ return;
5875
+ }
5876
+
5877
+ if (clause.type === 'not') {
5878
+ let found = false;
5879
+ for (const _ of this.solveBody(clause.body, { ...binding }, depth + 1, 0)) { found = true; break; }
5880
+ if (!found) yield* this.solveBody(clauses, binding, depth + 1, index + 1);
5881
+ return;
5882
+ }
5883
+
5884
+ throw new Error(`Unsupported backward body clause ${clause.type}`);
5885
+ }
5886
+
5887
+ *solveTriple(pattern, binding = {}, depth = 0) {
5888
+ if (depth > this.maxDepth) throw new Error(`Reached backwardMaxDepth=${this.maxDepth}; backward query may not terminate`);
5889
+ this.stats.goals += 1;
5890
+ const resolvedPattern = resolvePattern(pattern, binding);
5891
+ const key = `${goalKey(resolvedPattern)}@store:${this.store.version || 0}`;
5892
+ const entry = this.memo.get(key);
5893
+ if (entry && entry.complete) {
5894
+ this.stats.memoHits += 1;
5895
+ for (const answer of entry.answers) {
5896
+ const next = unifyTriples(pattern, answer, binding);
5897
+ if (next) yield next;
5898
+ }
5899
+ return;
5900
+ }
5901
+ if (this.active.has(key)) return;
5902
+
5903
+ const answers = [];
5904
+ const answerKeys = new Set();
5905
+ this.active.add(key);
5906
+ try {
5907
+ for (const fact of this.factCandidates(resolvedPattern, binding)) {
5908
+ const next = unifyTriples(pattern, fact, binding);
5909
+ if (!next) continue;
5910
+ rememberAnswer(answers, answerKeys, pattern, next);
5911
+ this.stats.facts += 1;
5912
+ yield next;
5913
+ }
5914
+
5915
+ for (const item of this.ruleCandidates(resolvedPattern)) {
5916
+ const suffix = `__b${++this.freshCounter}_${item.ruleIndex}`;
5917
+ const freshHead = freshTriple(item.head, suffix);
5918
+ const next = unifyTriples(pattern, freshHead, binding);
5919
+ if (!next) continue;
5920
+ const freshBody = (item.rule.body || []).map((clause) => freshClause(clause, suffix));
5921
+ for (const solved of this.solveBody(freshBody, next, depth + 1, 0)) {
5922
+ rememberAnswer(answers, answerKeys, pattern, solved);
5923
+ this.stats.rules += 1;
5924
+ yield solved;
5925
+ }
5926
+ }
5927
+ } finally {
5928
+ this.active.delete(key);
5929
+ }
5930
+
5931
+ this.memo.set(key, { complete: true, answers });
5932
+ this.stats.memoStores += 1;
5933
+ }
5934
+
5935
+ factCandidates(pattern, binding) {
5936
+ return this.store.candidates(pattern, binding);
5937
+ }
5938
+
5939
+ ruleCandidates(pattern) {
5940
+ const predicate = pattern.p && pattern.p.type === 'iri' ? pattern.p.value : null;
5941
+ if (predicate) return this.ruleHeads.byPredicate.get(predicate) || [];
5942
+ return this.ruleHeads.all;
5943
+ }
5944
+ }
5945
+
5946
+ function indexRuleHeads(rules, options = {}) {
5947
+ const allowedPredicates = options.allowedPredicates || null;
5948
+ const allowedRuleIndexes = options.allowedRuleIndexes || null;
5949
+ const byPredicate = new Map();
5950
+ const all = [];
5951
+ for (let ruleIndex = 0; ruleIndex < rules.length; ruleIndex += 1) {
5952
+ if (allowedRuleIndexes && !allowedRuleIndexes.has(ruleIndex)) continue;
5953
+ const rule = rules[ruleIndex];
5954
+ for (let headIndex = 0; headIndex < (rule.head || []).length; headIndex += 1) {
5955
+ const head = rule.head[headIndex];
5956
+ if (!head || !head.p || head.p.type !== 'iri') continue;
5957
+ if (allowedPredicates && !allowedPredicates.has(head.p.value)) continue;
5958
+ const item = { ruleIndex, headIndex, rule, head };
5959
+ all.push(item);
5960
+ const bucket = byPredicate.get(head.p.value);
5961
+ if (bucket) bucket.push(item);
5962
+ else byPredicate.set(head.p.value, [item]);
5963
+ }
5964
+ }
5965
+ return { byPredicate, all };
5966
+ }
5967
+
5968
+ function freshClause(clause, suffix) {
5969
+ if (clause.type === 'triple') return { ...clause, triple: freshTriple(clause.triple, suffix) };
5970
+ if (clause.type === 'filter') return { ...clause, expr: freshExpr(clause.expr, suffix) };
5971
+ if (clause.type === 'set' || clause.type === 'bind') return { ...clause, variable: freshVarName(clause.variable, suffix), expr: freshExpr(clause.expr, suffix) };
5972
+ if (clause.type === 'not') return { ...clause, body: clause.body.map((item) => freshClause(item, suffix)) };
5973
+ return clause;
5974
+ }
5975
+
5976
+ function freshTriple(triple, suffix) {
5977
+ return { s: freshTerm(triple.s, suffix), p: freshTerm(triple.p, suffix), o: freshTerm(triple.o, suffix) };
5978
+ }
5979
+
5980
+ function freshTerm(term, suffix) {
5981
+ if (!term) return term;
5982
+ if (term.type === 'var') return { type: 'var', value: freshVarName(term.value, suffix) };
5983
+ if (term.type === 'triple') return { type: 'triple', s: freshTerm(term.s, suffix), p: freshTerm(term.p, suffix), o: freshTerm(term.o, suffix) };
5984
+ return term;
5985
+ }
5986
+
5987
+ function freshExpr(expr, suffix) {
5988
+ if (!expr) return expr;
5989
+ if (expr.type === 'var') return { ...expr, name: freshVarName(expr.name, suffix) };
5990
+ if (expr.type === 'term') return { ...expr, value: freshTerm(expr.value, suffix) };
5991
+ if (expr.type === 'unary') return { ...expr, expr: freshExpr(expr.expr, suffix) };
5992
+ if (expr.type === 'binary') return { ...expr, left: freshExpr(expr.left, suffix), right: freshExpr(expr.right, suffix) };
5993
+ if (expr.type === 'call') return { ...expr, args: expr.args.map((arg) => freshExpr(arg, suffix)) };
5994
+ if (expr.type === 'list') return { ...expr, items: expr.items.map((item) => freshExpr(item, suffix)) };
5995
+ return expr;
5996
+ }
5997
+
5998
+ function freshVarName(name, suffix) {
5999
+ return `${name}${suffix}`;
6000
+ }
6001
+
6002
+ function resolvePattern(pattern, binding) {
6003
+ return { s: resolveTerm(pattern.s, binding, false), p: resolveTerm(pattern.p, binding, false), o: resolveTerm(pattern.o, binding, false) };
6004
+ }
6005
+
6006
+ function resolveBinding(binding) {
6007
+ const out = {};
6008
+ for (const name of Object.keys(binding)) out[name] = resolveTerm(binding[name], binding, false);
6009
+ return out;
6010
+ }
6011
+
6012
+ function resolveTerm(term, binding, preserveUnbound = true, seen = new Set()) {
6013
+ if (!term) return term;
6014
+ if (term.type === 'var') {
6015
+ const name = term.value;
6016
+ if (seen.has(name)) return preserveUnbound ? term : { type: 'var', value: name };
6017
+ if (!Object.prototype.hasOwnProperty.call(binding, name)) return preserveUnbound ? term : { type: 'var', value: name };
6018
+ seen.add(name);
6019
+ return resolveTerm(binding[name], binding, preserveUnbound, seen);
6020
+ }
6021
+ if (term.type === 'triple') {
6022
+ return {
6023
+ type: 'triple',
6024
+ s: resolveTerm(term.s, binding, preserveUnbound, new Set(seen)),
6025
+ p: resolveTerm(term.p, binding, preserveUnbound, new Set(seen)),
6026
+ o: resolveTerm(term.o, binding, preserveUnbound, new Set(seen)),
6027
+ };
6028
+ }
6029
+ return term;
6030
+ }
6031
+
6032
+ function unifyTriples(left, right, binding) {
6033
+ let next = unifyTerms(left.s, right.s, binding);
6034
+ if (!next) return null;
6035
+ next = unifyTerms(left.p, right.p, next);
6036
+ if (!next) return null;
6037
+ return unifyTerms(left.o, right.o, next);
6038
+ }
6039
+
6040
+ function unifyTerms(left, right, binding) {
6041
+ const a = resolveTerm(left, binding);
6042
+ const b = resolveTerm(right, binding);
6043
+ if (a.type === 'var' && b.type === 'var' && a.value === b.value) return binding;
6044
+ if (a.type === 'var') return bindVariable(a.value, b, binding);
6045
+ if (b.type === 'var') return bindVariable(b.value, a, binding);
6046
+ if (a.type === 'triple' || b.type === 'triple') {
6047
+ if (a.type !== 'triple' || b.type !== 'triple') return null;
6048
+ let next = unifyTerms(a.s, b.s, binding);
6049
+ if (!next) return null;
6050
+ next = unifyTerms(a.p, b.p, next);
6051
+ if (!next) return null;
6052
+ return unifyTerms(a.o, b.o, next);
6053
+ }
6054
+ return termEquals(a, b) ? binding : null;
6055
+ }
6056
+
6057
+ function bindVariable(name, term, binding) {
6058
+ const existing = binding[name];
6059
+ if (existing) return unifyTerms(existing, term, binding);
6060
+ if (term.type === 'var' && term.value === name) return binding;
6061
+ return { ...binding, [name]: term };
6062
+ }
6063
+
6064
+ function rememberAnswer(answers, answerKeys, pattern, binding) {
6065
+ const triple = {
6066
+ s: resolveTerm(pattern.s, binding),
6067
+ p: resolveTerm(pattern.p, binding),
6068
+ o: resolveTerm(pattern.o, binding),
6069
+ };
6070
+ if (triple.s.type === 'var' || triple.p.type === 'var' || triple.o.type === 'var') return;
6071
+ const key = tripleKey(triple);
6072
+ if (answerKeys.has(key)) return;
6073
+ answerKeys.add(key);
6074
+ answers.push(triple);
6075
+ }
6076
+
6077
+ function goalKey(pattern) {
6078
+ return `${safeTermKey(pattern.s)} ${safeTermKey(pattern.p)} ${safeTermKey(pattern.o)}`;
6079
+ }
6080
+
6081
+ function safeTermKey(term) {
6082
+ return term && term.type === 'var' ? '_' : termKey(term);
6083
+ }
6084
+
6085
+ function uniqueBindings(bindings) {
6086
+ const seen = new Set();
6087
+ const out = [];
6088
+ for (const binding of bindings) {
6089
+ const resolved = resolveBinding(binding);
6090
+ const key = bindingKey(resolved);
6091
+ if (seen.has(key)) continue;
6092
+ seen.add(key);
6093
+ out.push(resolved);
6094
+ }
6095
+ return out;
6096
+ }
6097
+
6098
+ function containsBlank(term) {
6099
+ if (!term) return false;
6100
+ if (term.type === 'blank') return true;
6101
+ if (term.type === 'triple') return containsBlank(term.s) || containsBlank(term.p) || containsBlank(term.o);
6102
+ return false;
6103
+ }
6104
+
6105
+
6106
+
6107
+ function reachableBackwardRuleIndexes(program, rootClauses, options = {}) {
6108
+ const rules = program.rules || [];
6109
+ const headIndex = new Map();
6110
+ const allHeadPredicates = new Set();
6111
+ const allRuleIndexes = new Set();
6112
+ for (let ruleIndex = 0; ruleIndex < rules.length; ruleIndex += 1) {
6113
+ const rule = rules[ruleIndex];
6114
+ for (const head of rule.head || []) {
6115
+ if (!head || !head.p || head.p.type !== 'iri') continue;
6116
+ allRuleIndexes.add(ruleIndex);
6117
+ allHeadPredicates.add(head.p.value);
6118
+ if (!headIndex.has(head.p.value)) headIndex.set(head.p.value, new Set());
6119
+ headIndex.get(head.p.value).add(ruleIndex);
6120
+ }
6121
+ }
6122
+
6123
+ const predicates = new Set();
6124
+ const ruleIndexes = new Set();
6125
+ const work = [];
6126
+ const enqueue = (predicate) => {
6127
+ if (!predicate) {
6128
+ for (const item of allHeadPredicates) enqueue(item);
6129
+ return;
6130
+ }
6131
+ if (predicates.has(predicate)) return;
6132
+ predicates.add(predicate);
6133
+ work.push(predicate);
6134
+ };
6135
+
6136
+ for (const predicate of bodyPredicateDemands(rootClauses || [])) enqueue(predicate);
6137
+
6138
+ while (work.length > 0) {
6139
+ const predicate = work.shift();
6140
+ const indexes = headIndex.get(predicate);
6141
+ if (!indexes) continue;
6142
+ for (const ruleIndex of indexes) {
6143
+ if (ruleIndexes.has(ruleIndex)) continue;
6144
+ ruleIndexes.add(ruleIndex);
6145
+ const rule = rules[ruleIndex];
6146
+ for (const needed of bodyPredicateDemands(rule.body || [])) enqueue(needed);
6147
+ }
6148
+ }
6149
+
6150
+ return { ruleIndexes, predicates };
6151
+ }
6152
+
6153
+ function bodyPredicateDemands(clauses) {
6154
+ const out = [];
6155
+ for (const clause of clauses || []) {
6156
+ if (clause.type === 'triple') {
6157
+ out.push(predicateDemand(clause.triple.p));
6158
+ continue;
6159
+ }
6160
+ if (clause.type === 'not') {
6161
+ out.push(...bodyPredicateDemands(clause.body || []));
6162
+ }
6163
+ }
6164
+ return out;
6165
+ }
6166
+
6167
+ function predicateDemand(term) {
6168
+ return term && term.type === 'iri' ? term.value : null;
6169
+ }
6170
+
6171
+ function normalizePredicateSet(value) {
6172
+ if (!value) return null;
6173
+ if (value instanceof Set) return value;
6174
+ if (Array.isArray(value)) return new Set(value);
6175
+ return new Set(String(value).split(',').map((item) => item.trim()).filter(Boolean));
6176
+ }
6177
+
6178
+ function normalizeRuleIndexSet(value) {
6179
+ if (!value) return null;
6180
+ if (value instanceof Set) return value;
6181
+ if (Array.isArray(value)) return new Set(value);
6182
+ return null;
6183
+ }
6184
+
6185
+ function supportedBackwardPredicates(program, options = {}) {
6186
+ const explicit = normalizePredicateSet(options.backwardPredicates || options.hybridPredicates || null);
6187
+ const byPredicate = new Map();
6188
+ for (const rule of program.rules || []) {
6189
+ const predicates = new Set();
6190
+ for (const head of rule.head || []) {
6191
+ if (head && head.p && head.p.type === 'iri') predicates.add(head.p.value);
6192
+ }
6193
+ for (const predicate of predicates) {
6194
+ if (!byPredicate.has(predicate)) byPredicate.set(predicate, []);
6195
+ byPredicate.get(predicate).push(rule);
6196
+ }
6197
+ }
6198
+
6199
+ const supported = new Set();
6200
+ for (const [predicate, rules] of byPredicate) {
6201
+ if (explicit && !explicit.has(predicate)) continue;
6202
+ if (rules.length > 0 && rules.every((rule) => ruleSupported(rule, options))) supported.add(predicate);
6203
+ }
6204
+ return supported;
6205
+ }
6206
+
6207
+ function preferredBackwardPredicates(program, options = {}) {
6208
+ const explicit = normalizePredicateSet(options.hybridPredicates || null);
6209
+ if (explicit) return supportedBackwardPredicates(program, { ...options, hybridPredicates: explicit });
6210
+ const supported = supportedBackwardPredicates(program, options);
6211
+ const preferred = new Set();
6212
+ for (const rule of program.rules || []) {
6213
+ if (!ruleIsFunctionLike(rule)) continue;
6214
+ for (const head of rule.head || []) {
6215
+ if (head && head.p && head.p.type === 'iri' && supported.has(head.p.value)) preferred.add(head.p.value);
6216
+ }
6217
+ }
6218
+ return preferred;
6219
+ }
6220
+
6221
+ function ruleIsFunctionLike(rule) {
6222
+ return (rule.body || []).some((clause) => clause.type === 'set' || clause.type === 'bind');
6223
+ }
6224
+
6225
+ function ruleHeadPredicates(rule) {
6226
+ const predicates = new Set();
6227
+ for (const head of rule.head || []) {
6228
+ if (!head || !head.p || head.p.type !== 'iri') return null;
6229
+ predicates.add(head.p.value);
6230
+ }
6231
+ return predicates;
6232
+ }
6233
+
6234
+ function ruleIsBackwardOriented(rule, predicates) {
6235
+ if (!predicates || predicates.size === 0) return false;
6236
+ const heads = ruleHeadPredicates(rule);
6237
+ if (!heads || heads.size === 0) return false;
6238
+ for (const predicate of heads) if (!predicates.has(predicate)) return false;
6239
+ return true;
6240
+ }
6241
+
6242
+ module.exports = {
6243
+ BackwardProver,
6244
+ backwardQuery,
6245
+ planBackwardQuery,
6246
+ supportedBackwardPredicates,
6247
+ preferredBackwardPredicates,
6248
+ reachableBackwardRuleIndexes,
6249
+ ruleIsBackwardOriented,
6250
+ ruleSupported,
6251
+ resolveBinding,
6252
+ };
6253
+
5655
6254
  },
5656
6255
  "src/format.js": function (require, module, exports) {
5657
6256
  'use strict';
@@ -5745,6 +6344,7 @@
5745
6344
  const { parseQuery } = require('./parser.js');
5746
6345
  const { TripleStore, bindingKey } = require('./store.js');
5747
6346
  const { evaluateBody } = require('./engine.js');
6347
+ const { backwardQuery, planBackwardQuery, preferredBackwardPredicates } = require('./backward.js');
5748
6348
 
5749
6349
  function queryResult(result, querySpec, options = {}) {
5750
6350
  const store = new TripleStore(result.closure || []);
@@ -5755,28 +6355,89 @@
5755
6355
  prefixes: result.prefixes,
5756
6356
  select,
5757
6357
  bindings: projectBindings(bindings, select),
6358
+ mode: options.queryMode === 'hybrid' || options.hybrid ? 'hybrid' : 'forward',
5758
6359
  };
5759
6360
  }
5760
6361
 
6362
+ function queryProgram(program, querySpec, options = {}) {
6363
+ const mode = options.queryMode || 'auto';
6364
+ if (mode !== 'forward' && mode !== 'hybrid') {
6365
+ const planned = planBackwardQuery(program, querySpec, options);
6366
+ if (planned.ok) {
6367
+ const result = backwardQuery(program, querySpec, options);
6368
+ if (result.ok) {
6369
+ const select = normalizeSelect(querySpec.select, result.bindings);
6370
+ return {
6371
+ baseIRI: program.baseIRI,
6372
+ prefixes: program.prefixes,
6373
+ select,
6374
+ bindings: projectBindings(result.bindings, select),
6375
+ mode: 'backward',
6376
+ stats: result.stats,
6377
+ };
6378
+ }
6379
+ if (mode === 'backward') throw new Error(result.reason || 'Backward query failed');
6380
+ } else if (mode === 'backward') {
6381
+ throw new Error(`Backward query is not supported for this ruleset: ${planned.reason}`);
6382
+ }
6383
+ }
6384
+ return null;
6385
+ }
6386
+
5761
6387
  function runQuery(source, querySource = null, options = {}) {
5762
6388
  const { run, compile } = require('./api.js');
5763
- const { program, diagnostics } = compile(source, options);
5764
- const result = run(program, options);
5765
- result.diagnostics = diagnostics;
6389
+ const { program, diagnostics, analysis } = compile(source, options);
5766
6390
 
5767
6391
  let querySpec;
5768
6392
  if (querySource) querySpec = parseQuery(querySource, { ...options, prefixes: program.prefixes, baseIRI: program.baseIRI });
5769
6393
  else throw new Error('No query supplied. Use --query or --query-file with a raw body pattern.');
5770
6394
 
5771
- const query = queryResult(result, querySpec, options);
5772
- return { ...result, query };
6395
+ const direct = queryProgram(program, querySpec, options);
6396
+ if (direct) {
6397
+ return {
6398
+ baseIRI: program.baseIRI,
6399
+ version: program.version || null,
6400
+ imports: program.imports || [],
6401
+ prefixes: program.prefixes,
6402
+ input: program.data.slice(),
6403
+ inferred: [],
6404
+ closure: program.data.slice(),
6405
+ iterations: 0,
6406
+ layers: [],
6407
+ ruleApplications: 0,
6408
+ perRule: [],
6409
+ trace: [],
6410
+ diagnostics,
6411
+ analysis,
6412
+ query: direct,
6413
+ };
6414
+ }
6415
+
6416
+ const runOptions = queryRunOptions(program, querySpec, options);
6417
+ const result = run(program, runOptions);
6418
+ result.diagnostics = diagnostics;
6419
+ result.query = queryResult(result, querySpec, runOptions);
6420
+ return result;
6421
+ }
6422
+
6423
+ function queryRunOptions(program, querySpec, options = {}) {
6424
+ if (shouldUseHybridForQuery(program, querySpec, options)) return { ...options, hybrid: true };
6425
+ return options;
6426
+ }
6427
+
6428
+ function shouldUseHybridForQuery(program, querySpec, options = {}) {
6429
+ const mode = options.queryMode || 'auto';
6430
+ if (options.hybrid || mode === 'hybrid') return true;
6431
+ if (mode !== 'auto') return false;
6432
+ if (!querySpec) return false;
6433
+ return preferredBackwardPredicates(program, options).size > 0;
5773
6434
  }
5774
6435
 
5775
6436
  function normalizeSelect(select, bindings) {
5776
6437
  if (select && select.length > 0) return select.slice();
5777
6438
  const vars = new Set();
5778
6439
  for (const binding of bindings) for (const key of Object.keys(binding)) vars.add(key);
5779
- return Array.from(vars).sort();
6440
+ return Array.from(vars).sort().filter((name) => !name.includes('__b'));
5780
6441
  }
5781
6442
 
5782
6443
  function projectBindings(bindings, select) {
@@ -5794,7 +6455,7 @@
5794
6455
  return out;
5795
6456
  }
5796
6457
 
5797
- module.exports = { runQuery, queryResult, parseQuery, normalizeSelect, projectBindings };
6458
+ module.exports = { runQuery, queryResult, queryProgram, queryRunOptions, shouldUseHybridForQuery, parseQuery, normalizeSelect, projectBindings };
5798
6459
 
5799
6460
  },
5800
6461
  "src/output.js": function (require, module, exports) {
@@ -5808,7 +6469,7 @@
5808
6469
 
5809
6470
  },
5810
6471
  };
5811
- const __mappings = {"src/tokenizer.js":{},"src/assignments.js":{},"src/term.js":{},"src/rdfSyntax.js":{"./tokenizer.js":"src/tokenizer.js","./assignments.js":"src/assignments.js","./term.js":"src/term.js"},"src/builtins.js":{"./term.js":"src/term.js"},"src/parser.js":{"./tokenizer.js":"src/tokenizer.js","./rdfSyntax.js":"src/rdfSyntax.js","./builtins.js":"src/builtins.js","./assignments.js":"src/assignments.js","./term.js":"src/term.js"},"src/rdfMessages.js":{"./rdfSyntax.js":"src/rdfSyntax.js","./term.js":"src/term.js"},"src/store.js":{"./term.js":"src/term.js"},"src/analyze.js":{"./term.js":"src/term.js","./assignments.js":"src/assignments.js"},"src/engine.js":{"./store.js":"src/store.js","./term.js":"src/term.js","./builtins.js":"src/builtins.js","./analyze.js":"src/analyze.js"},"src/format.js":{"./term.js":"src/term.js"},"src/query.js":{"./parser.js":"src/parser.js","./store.js":"src/store.js","./engine.js":"src/engine.js","./api.js":"src/api.js"},"src/output.js":{},"src/api.js":{"./parser.js":"src/parser.js","./rdfSyntax.js":"src/rdfSyntax.js","./rdfMessages.js":"src/rdfMessages.js","./engine.js":"src/engine.js","./analyze.js":"src/analyze.js","./format.js":"src/format.js","./query.js":"src/query.js","./output.js":"src/output.js"},"src/cli.js":{"./api.js":"src/api.js","./term.js":"src/term.js"}};
6472
+ const __mappings = {"src/tokenizer.js":{},"src/assignments.js":{},"src/term.js":{},"src/rdfSyntax.js":{"./tokenizer.js":"src/tokenizer.js","./assignments.js":"src/assignments.js","./term.js":"src/term.js"},"src/builtins.js":{"./term.js":"src/term.js"},"src/parser.js":{"./tokenizer.js":"src/tokenizer.js","./rdfSyntax.js":"src/rdfSyntax.js","./builtins.js":"src/builtins.js","./assignments.js":"src/assignments.js","./term.js":"src/term.js"},"src/rdfMessages.js":{"./rdfSyntax.js":"src/rdfSyntax.js","./term.js":"src/term.js"},"src/store.js":{"./term.js":"src/term.js"},"src/analyze.js":{"./term.js":"src/term.js","./assignments.js":"src/assignments.js"},"src/backward.js":{"./store.js":"src/store.js","./term.js":"src/term.js","./builtins.js":"src/builtins.js"},"src/engine.js":{"./store.js":"src/store.js","./term.js":"src/term.js","./builtins.js":"src/builtins.js","./analyze.js":"src/analyze.js","./backward.js":"src/backward.js"},"src/format.js":{"./term.js":"src/term.js"},"src/query.js":{"./parser.js":"src/parser.js","./store.js":"src/store.js","./engine.js":"src/engine.js","./backward.js":"src/backward.js","./api.js":"src/api.js"},"src/output.js":{},"src/api.js":{"./parser.js":"src/parser.js","./rdfSyntax.js":"src/rdfSyntax.js","./rdfMessages.js":"src/rdfMessages.js","./engine.js":"src/engine.js","./analyze.js":"src/analyze.js","./format.js":"src/format.js","./query.js":"src/query.js","./output.js":"src/output.js"},"src/cli.js":{"./api.js":"src/api.js","./term.js":"src/term.js"}};
5812
6473
  const __cache = {};
5813
6474
  function __require(id) {
5814
6475
  if (!id.startsWith("src/")) return __nativeRequire(id);