eyeling 1.28.9 → 1.29.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/lib/engine.js CHANGED
@@ -97,6 +97,7 @@ const {
97
97
  getDataFactory,
98
98
  internalTripleToRdfJsQuads,
99
99
  normalizeParsedReasonerInputSync,
100
+ normalizeParsedReasonerInputAsync,
100
101
  normalizeReasonerInputSync,
101
102
  normalizeReasonerInputAsync,
102
103
  } = require('./rdfjs');
@@ -105,6 +106,7 @@ const trace = require('./trace');
105
106
  const { deterministicSkolemIdFromKey } = require('./skolem');
106
107
 
107
108
  const deref = require('./deref');
109
+ const { createFactStore, collectStore, MemoryFactStore, PersistentFactStore, tripleToStoreKey } = require('./store');
108
110
 
109
111
  const hasOwn = Object.prototype.hasOwnProperty;
110
112
 
@@ -3783,6 +3785,278 @@ function reasonStream(input, opts = {}) {
3783
3785
  return __out;
3784
3786
  }
3785
3787
 
3788
+
3789
+ async function __parseRunAsyncInput(input, opts) {
3790
+ const {
3791
+ baseIri = null,
3792
+ proof = false,
3793
+ rdf = false,
3794
+ sourceLabel = '<input>',
3795
+ } = opts || {};
3796
+
3797
+ const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: !!rdf, sourceLocations: !!proof });
3798
+ if (parsedSourceList) return parsedSourceList;
3799
+
3800
+ const parsedObject = await normalizeParsedReasonerInputAsync(input);
3801
+ if (parsedObject) {
3802
+ if (baseIri && parsedObject.prefixes && typeof parsedObject.prefixes.setBase === 'function') parsedObject.prefixes.setBase(baseIri);
3803
+ return parsedObject;
3804
+ }
3805
+
3806
+ const n3Text = await normalizeReasonerInputAsync(input);
3807
+ return parseN3Text(n3Text, {
3808
+ baseIri: baseIri || '',
3809
+ label: sourceLabel || '<input>',
3810
+ keepSourceArtifacts: false,
3811
+ sourceLocations: !!proof,
3812
+ rdf: !!rdf,
3813
+ });
3814
+ }
3815
+
3816
+ function __storePatternTerm(t, subst) {
3817
+ const applied = applySubstTerm(t, subst || __emptySubst());
3818
+ return containsVarTerm(applied) ? null : applied;
3819
+ }
3820
+
3821
+ function __mergeStoreSubst(base, delta) {
3822
+ let out = base;
3823
+ for (const k of Object.keys(delta || {})) {
3824
+ const v = delta[k];
3825
+ if (Object.prototype.hasOwnProperty.call(out, k)) {
3826
+ if (!termsEqual(out[k], v)) return null;
3827
+ } else {
3828
+ if (out === base) out = __cloneSubst(base);
3829
+ out[k] = v;
3830
+ }
3831
+ }
3832
+ return out;
3833
+ }
3834
+
3835
+ async function __proveGoalsAgainstStore(goals, subst, store, backRules, localFacts, depth, varGen, opts = {}) {
3836
+ if (!Array.isArray(goals) || goals.length === 0) return [subst || __emptySubst()];
3837
+ if (depth > 64) return [];
3838
+
3839
+ const goal0 = applySubstTriple(goals[0], subst || __emptySubst());
3840
+ const rest = goals.slice(1);
3841
+ const out = [];
3842
+
3843
+ if (isBuiltinPred(goal0.p)) {
3844
+ const deltas = evalBuiltin(goal0, __emptySubst(), localFacts || [], backRules || [], depth, varGen, undefined);
3845
+ for (const delta of deltas) {
3846
+ const nextSubst = __mergeStoreSubst(subst || __emptySubst(), delta);
3847
+ if (nextSubst === null) continue;
3848
+ out.push(...await __proveGoalsAgainstStore(rest, nextSubst, store, backRules, localFacts, depth + 1, varGen, opts));
3849
+ if (opts.maxResults && out.length >= opts.maxResults) return out.slice(0, opts.maxResults);
3850
+ }
3851
+ return out;
3852
+ }
3853
+
3854
+ // Backward rules are kept in memory; they may call back into the persistent
3855
+ // fact store for their own premises.
3856
+ if (goal0.p instanceof Iri && Array.isArray(backRules) && backRules.length) {
3857
+ ensureBackRuleIndexes(backRules);
3858
+ const candRules = (backRules.__byHeadPred.get(goal0.p.__tid) || []).concat(backRules.__wildHeadPred || []);
3859
+ for (const r of candRules) {
3860
+ if (!r || !Array.isArray(r.conclusion) || r.conclusion.length !== 1) continue;
3861
+ const rStd = standardizeRule(r, varGen);
3862
+ const head = rStd.conclusion[0];
3863
+ const s2 = unifyTriple(head, goal0, subst || __emptySubst());
3864
+ if (s2 === null) continue;
3865
+ const newGoals = (rStd.premise || []).concat(rest);
3866
+ out.push(...await __proveGoalsAgainstStore(newGoals, s2, store, backRules, localFacts, depth + 1, varGen, opts));
3867
+ if (opts.maxResults && out.length >= opts.maxResults) return out.slice(0, opts.maxResults);
3868
+ }
3869
+ }
3870
+
3871
+ const sPat = __storePatternTerm(goal0.s, subst || __emptySubst());
3872
+ const pPat = __storePatternTerm(goal0.p, subst || __emptySubst());
3873
+ const oPat = __storePatternTerm(goal0.o, subst || __emptySubst());
3874
+
3875
+ for await (const fact of store.match(sPat, pPat, oPat)) {
3876
+ const s2 = unifyTriple(goal0, fact, subst || __emptySubst());
3877
+ if (s2 === null) continue;
3878
+ out.push(...await __proveGoalsAgainstStore(rest, s2, store, backRules, localFacts, depth + 1, varGen, opts));
3879
+ if (opts.maxResults && out.length >= opts.maxResults) return out.slice(0, opts.maxResults);
3880
+ }
3881
+
3882
+ return out;
3883
+ }
3884
+
3885
+ async function runStoreBacked(input, store, opts = {}) {
3886
+ const parsed = parseN3SourceList(input, {
3887
+ baseIri: opts.baseIri || null,
3888
+ rdf: !!opts.rdf,
3889
+ sourceLocations: !!opts.proof,
3890
+ }) || input;
3891
+
3892
+ const prefixes = parsed.prefixes;
3893
+ const triples = parsed.triples || [];
3894
+ const frules = parsed.frules || [];
3895
+ const brules = parsed.brules || [];
3896
+ const qrules = parsed.logQueryRules || [];
3897
+
3898
+ materializeRdfLists(triples, frules.concat(qrules || []), brules);
3899
+ await store.batchAdd(triples, 'explicit');
3900
+
3901
+ const derived = [];
3902
+ const derivedKeys = new Set();
3903
+ const varGen = [0];
3904
+ const maxIterations = Number.isInteger(opts.maxIterations) && opts.maxIterations > 0 ? opts.maxIterations : 1024;
3905
+
3906
+ for (let iteration = 0; iteration < maxIterations; iteration += 1) {
3907
+ let changed = false;
3908
+ for (let ruleIndex = 0; ruleIndex < frules.length; ruleIndex += 1) {
3909
+ const r = frules[ruleIndex];
3910
+ if (!r || r.isFuse || r.__dynamicConclusionTerm) continue;
3911
+ __prepareForwardRule(r);
3912
+ const solutions = await __proveGoalsAgainstStore(r.premise || [], __emptySubst(), store, brules, triples, 0, varGen, {});
3913
+ for (const subst of solutions) {
3914
+ for (const cpat of r.conclusion || []) {
3915
+ const fact = applySubstTriple(cpat, subst);
3916
+ if (!isGroundTriple(fact)) continue;
3917
+ if (await store.add(fact, 'inferred')) {
3918
+ const df = makeDerivedRecord(fact, r, (r.premise || []).map((p) => applySubstTriple(p, subst)), subst, false);
3919
+ const key = tripleToStoreKey(fact);
3920
+ if (!derivedKeys.has(key)) {
3921
+ derivedKeys.add(key);
3922
+ derived.push(df);
3923
+ }
3924
+ changed = true;
3925
+ }
3926
+ }
3927
+ }
3928
+ }
3929
+ if (!changed) break;
3930
+ }
3931
+
3932
+ let queryTriples = [];
3933
+ const queryDerived = [];
3934
+ if (qrules.length) {
3935
+ for (const r of qrules) {
3936
+ const solutions = await __proveGoalsAgainstStore(r.premise || [], __emptySubst(), store, brules, triples, 0, varGen, {});
3937
+ for (const subst of solutions) {
3938
+ for (const cpat of r.conclusion || []) {
3939
+ const fact = applySubstTriple(cpat, subst);
3940
+ if (!isGroundTriple(fact)) continue;
3941
+ queryTriples.push(fact);
3942
+ queryDerived.push(makeDerivedRecord(fact, r, (r.premise || []).map((p) => applySubstTriple(p, subst)), subst, false));
3943
+ }
3944
+ }
3945
+ }
3946
+ }
3947
+
3948
+ if (queryTriples.length) {
3949
+ const seen = new Set();
3950
+ queryTriples = queryTriples.filter((tr) => {
3951
+ const key = tripleToStoreKey(tr);
3952
+ if (seen.has(key)) return false;
3953
+ seen.add(key);
3954
+ return true;
3955
+ });
3956
+ }
3957
+
3958
+ return {
3959
+ prefixes,
3960
+ facts: [],
3961
+ derived,
3962
+ queryMode: !!qrules.length,
3963
+ queryTriples,
3964
+ queryDerived,
3965
+ closureN3: qrules.length
3966
+ ? prettyPrintQueryTriples(queryTriples, prefixes)
3967
+ : derived.map((df) => (opts.rdf ? tripleToRdfCompatible(df.fact, prefixes) : tripleToN3(df.fact, prefixes))).join('\n'),
3968
+ store,
3969
+ storeBacked: true,
3970
+ };
3971
+ }
3972
+
3973
+
3974
+ function __withoutStoreOptions(opts) {
3975
+ const out = { ...(opts || {}) };
3976
+ delete out.store;
3977
+ delete out.storePath;
3978
+ delete out.storeClear;
3979
+ return out;
3980
+ }
3981
+
3982
+ function __normalizeStoreOption(opts) {
3983
+ const cfg = opts && opts.store;
3984
+ if (!cfg) return null;
3985
+ if (typeof cfg === 'string') return { name: cfg, path: opts.storePath || undefined, clear: !!opts.storeClear };
3986
+ if (typeof cfg === 'object') {
3987
+ return {
3988
+ ...cfg,
3989
+ path: cfg.path || opts.storePath || undefined,
3990
+ clear: !!(cfg.clear || opts.storeClear),
3991
+ };
3992
+ }
3993
+ throw new TypeError('runAsync option "store" must be a store name string or a store options object');
3994
+ }
3995
+
3996
+ async function runAsync(input, opts = {}) {
3997
+ const storeConfig = __normalizeStoreOption(opts);
3998
+ const runOpts = __withoutStoreOptions(opts);
3999
+
4000
+ // No store configured: keep ordinary in-memory behavior, but accept async RDF/JS
4001
+ // iterables by normalizing the input before calling the synchronous engine.
4002
+ if (!storeConfig) {
4003
+ const normalizedInput = parseN3SourceList(input, {
4004
+ baseIri: runOpts.baseIri || null,
4005
+ rdf: !!runOpts.rdf,
4006
+ sourceLocations: !!runOpts.proof,
4007
+ }) || (await normalizeReasonerInputAsync(input));
4008
+ return reasonStream(normalizedInput, runOpts);
4009
+ }
4010
+
4011
+ const store = await createFactStore(storeConfig);
4012
+ let closeStore = true;
4013
+ try {
4014
+ const parsed = await __parseRunAsyncInput(input, runOpts);
4015
+
4016
+ // Persist the newly supplied explicit facts first, then include all stored
4017
+ // facts as the starting closure for this run. This lets --store reuse facts
4018
+ // across runs while keeping the current in-memory prover semantics intact.
4019
+ await store.batchAdd(parsed.triples || [], 'explicit');
4020
+ const storedTriples = await collectStore(store);
4021
+
4022
+ const storedKeys = new Set();
4023
+ for (const tr of storedTriples) storedKeys.add(require('./store').tripleToStoreKey(tr));
4024
+ const mergedTriples = storedTriples.slice();
4025
+ for (const tr of parsed.triples || []) {
4026
+ const key = require('./store').tripleToStoreKey(tr);
4027
+ if (!storedKeys.has(key)) {
4028
+ storedKeys.add(key);
4029
+ mergedTriples.push(tr);
4030
+ }
4031
+ }
4032
+
4033
+ const result = reasonStream(
4034
+ {
4035
+ prefixes: parsed.prefixes,
4036
+ triples: mergedTriples,
4037
+ frules: parsed.frules,
4038
+ brules: parsed.brules,
4039
+ logQueryRules: parsed.logQueryRules,
4040
+ },
4041
+ runOpts,
4042
+ );
4043
+
4044
+ await store.batchAdd((result.derived || []).map((df) => df.fact), 'inferred');
4045
+ result.store = store;
4046
+ closeStore = false;
4047
+ return result;
4048
+ } catch (e) {
4049
+ await store.close();
4050
+ throw e;
4051
+ } finally {
4052
+ // Keep result.store usable for callers. On exceptional paths it is closed
4053
+ // above; on success callers may close it when they are done.
4054
+ if (closeStore) {
4055
+ try { await store.close(); } catch {}
4056
+ }
4057
+ }
4058
+ }
4059
+
3786
4060
  function reasonRdfJs(input, opts = {}) {
3787
4061
  const { dataFactory = null, skipUnsupportedRdfJs = false, ...restOpts } = opts || {};
3788
4062
  const rdfFactory = getDataFactory(dataFactory);
@@ -3890,6 +4164,8 @@ function setTracePrefixes(v) {
3890
4164
 
3891
4165
  module.exports = {
3892
4166
  reasonStream,
4167
+ runAsync,
4168
+ runStoreBacked,
3893
4169
  reasonRdfJs,
3894
4170
  collectLogQueryConclusions,
3895
4171
  forwardChainAndCollectLogQueryConclusions,
@@ -3926,4 +4202,7 @@ module.exports = {
3926
4202
  loadBuiltinModule,
3927
4203
  listBuiltinIris,
3928
4204
  INFERENCE_FUSE_EXIT_CODE,
4205
+ createFactStore,
4206
+ MemoryFactStore,
4207
+ PersistentFactStore,
3929
4208
  };
package/lib/entry.js CHANGED
@@ -17,6 +17,7 @@ const { dataFactory } = require('./rdfjs');
17
17
  module.exports = {
18
18
  // public
19
19
  reasonStream: engine.reasonStream,
20
+ runAsync: engine.runAsync,
20
21
  reasonRdfJs: engine.reasonRdfJs,
21
22
  rdfjs: dataFactory,
22
23
  main: engine.main,
@@ -41,6 +42,9 @@ module.exports = {
41
42
  registerBuiltinModule: engine.registerBuiltinModule,
42
43
  loadBuiltinModule: engine.loadBuiltinModule,
43
44
  listBuiltinIris: engine.listBuiltinIris,
45
+ createFactStore: engine.createFactStore,
46
+ MemoryFactStore: engine.MemoryFactStore,
47
+ PersistentFactStore: engine.PersistentFactStore,
44
48
  getEnforceHttpsEnabled: engine.getEnforceHttpsEnabled,
45
49
  setEnforceHttpsEnabled: engine.setEnforceHttpsEnabled,
46
50
  getProofCommentsEnabled: engine.getProofCommentsEnabled,
package/lib/rdfjs.js CHANGED
@@ -952,6 +952,7 @@ module.exports = {
952
952
  internalTripleToRdfJsQuads,
953
953
  internalTripleToRdfJsQuadInGraph,
954
954
  normalizeParsedReasonerInputSync,
955
+ normalizeParsedReasonerInputAsync,
955
956
  normalizeReasonerInputSync,
956
957
  normalizeReasonerInputAsync,
957
958
  hasEyelingObjectInput,