eyeling 1.29.0 → 1.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/dist/browser/eyeling.browser.js +391 -46
- package/eyeling.js +391 -46
- package/lib/cli.js +211 -37
- package/lib/engine.js +160 -1
- package/lib/lexer.js +14 -5
- package/lib/parser.js +2 -2
- package/lib/store.js +4 -1
- package/package.json +1 -1
- package/test/api.test.js +69 -0
- package/test/store.test.js +29 -0
- package/test/stream_messages.test.js +13 -0
package/eyeling.js
CHANGED
|
@@ -5842,10 +5842,12 @@ function runParsedDocumentOnce(mergedDocument, { rdfMode = false, outputPrefixes
|
|
|
5842
5842
|
|
|
5843
5843
|
let derived = [];
|
|
5844
5844
|
let outTriples = [];
|
|
5845
|
+
let queryDerived = [];
|
|
5845
5846
|
if (hasQueries) {
|
|
5846
5847
|
const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, { prefixes });
|
|
5847
5848
|
derived = res.derived;
|
|
5848
5849
|
outTriples = res.queryTriples;
|
|
5850
|
+
queryDerived = res.queryDerived || [];
|
|
5849
5851
|
} else {
|
|
5850
5852
|
const skipDerivedCollection = mayAutoRenderOutputStrings;
|
|
5851
5853
|
derived = engine.forwardChain(facts, frules, brules, null, {
|
|
@@ -5859,7 +5861,7 @@ function runParsedDocumentOnce(mergedDocument, { rdfMode = false, outputPrefixes
|
|
|
5859
5861
|
const renderedOutputTriples = hasQueries ? outTriples : facts;
|
|
5860
5862
|
if (factsContainOutputStrings(renderedOutputTriples)) {
|
|
5861
5863
|
process.stdout.write(engine.collectOutputStringsFromFacts(renderedOutputTriples, prefixes));
|
|
5862
|
-
return;
|
|
5864
|
+
return { facts, derived, outTriples, queryDerived, queryMode: !!hasQueries };
|
|
5863
5865
|
}
|
|
5864
5866
|
|
|
5865
5867
|
const outPrefixEnv = outputPrefixes || prefixes;
|
|
@@ -5871,9 +5873,99 @@ function runParsedDocumentOnce(mergedDocument, { rdfMode = false, outputPrefixes
|
|
|
5871
5873
|
} else {
|
|
5872
5874
|
for (const df of derived) console.log(engine.tripleToN3(df.fact, outPrefixEnv));
|
|
5873
5875
|
}
|
|
5876
|
+
return { facts, derived, outTriples, queryDerived, queryMode: !!hasQueries };
|
|
5877
|
+
}
|
|
5878
|
+
|
|
5879
|
+
async function createCliStore({ storeName, storePath = null, storeClear = false } = {}) {
|
|
5880
|
+
if (!storeName) return null;
|
|
5881
|
+
return engine.createFactStore({ name: storeName, path: storePath || undefined, clear: !!storeClear });
|
|
5882
|
+
}
|
|
5883
|
+
|
|
5884
|
+
async function persistRunResultToStore(store, runResult) {
|
|
5885
|
+
if (!store || !runResult) return;
|
|
5886
|
+
await store.batchAdd(runResult.facts || [], 'explicit');
|
|
5887
|
+
await store.batchAdd((runResult.derived || []).map((df) => df.fact), 'inferred');
|
|
5888
|
+
await store.batchAdd((runResult.queryDerived || []).map((df) => df.fact), 'inferred');
|
|
5889
|
+
await store.batchAdd(runResult.outTriples || [], 'inferred');
|
|
5890
|
+
}
|
|
5891
|
+
|
|
5892
|
+
function sourceLooksLikeLineBasedRdf(sourceLabel) {
|
|
5893
|
+
if (typeof sourceLabel !== 'string') return false;
|
|
5894
|
+
const clean = sourceLabel.split(/[?#]/, 1)[0].toLowerCase();
|
|
5895
|
+
return /\.(?:nt|nq)(?:\.gz|\.br|\.deflate)?$/.test(clean);
|
|
5896
|
+
}
|
|
5897
|
+
|
|
5898
|
+
function parseLineBasedRdfLine(line, { sourceLabel, lineNumber, rdfMode }) {
|
|
5899
|
+
const text = String(line || '');
|
|
5900
|
+
if (!text.trim() || /^\s*#/.test(text)) return [];
|
|
5901
|
+
const doc = parseN3Text(text, {
|
|
5902
|
+
baseIri: __sourceLabelToBaseIri(sourceLabel),
|
|
5903
|
+
label: `${sourceLabel}:${lineNumber}`,
|
|
5904
|
+
keepSourceArtifacts: false,
|
|
5905
|
+
sourceLocations: false,
|
|
5906
|
+
rdf: rdfMode,
|
|
5907
|
+
});
|
|
5908
|
+
return doc.triples || [];
|
|
5909
|
+
}
|
|
5910
|
+
|
|
5911
|
+
async function ingestLineBasedRdfSourceToStore(sourceLabel, store, { rdfMode = true } = {}) {
|
|
5912
|
+
let lineNumber = 0;
|
|
5913
|
+
let count = 0;
|
|
5914
|
+
const onLine = async (line) => {
|
|
5915
|
+
lineNumber += 1;
|
|
5916
|
+
let triples;
|
|
5917
|
+
try {
|
|
5918
|
+
triples = parseLineBasedRdfLine(line, { sourceLabel, lineNumber, rdfMode });
|
|
5919
|
+
} catch (e) {
|
|
5920
|
+
if (e && e.name === 'N3SyntaxError') {
|
|
5921
|
+
throw new Error(formatN3SyntaxError(e, line, `${sourceLabel}:${lineNumber}`));
|
|
5922
|
+
}
|
|
5923
|
+
throw e;
|
|
5924
|
+
}
|
|
5925
|
+
count += await store.batchAdd(triples, 'explicit');
|
|
5926
|
+
};
|
|
5927
|
+
|
|
5928
|
+
const filePath = __localPathForSource(sourceLabel);
|
|
5929
|
+
if (filePath) {
|
|
5930
|
+
const fd = fs.openSync(filePath, 'r');
|
|
5931
|
+
const decoder = new TextDecoder('utf8');
|
|
5932
|
+
const buf = Buffer.allocUnsafe(64 * 1024);
|
|
5933
|
+
let carry = '';
|
|
5934
|
+
try {
|
|
5935
|
+
for (;;) {
|
|
5936
|
+
const n = fs.readSync(fd, buf, 0, buf.length, null);
|
|
5937
|
+
if (n === 0) break;
|
|
5938
|
+
carry += decoder.decode(buf.subarray(0, n), { stream: true });
|
|
5939
|
+
for (;;) {
|
|
5940
|
+
const m = /\r\n|\n|\r/.exec(carry);
|
|
5941
|
+
if (!m) break;
|
|
5942
|
+
const end = m.index + m[0].length;
|
|
5943
|
+
await onLine(carry.slice(0, end));
|
|
5944
|
+
carry = carry.slice(end);
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
carry += decoder.decode();
|
|
5948
|
+
if (carry) await onLine(carry);
|
|
5949
|
+
} finally {
|
|
5950
|
+
fs.closeSync(fd);
|
|
5951
|
+
}
|
|
5952
|
+
return count;
|
|
5953
|
+
}
|
|
5954
|
+
|
|
5955
|
+
if (__isHttpSource(sourceLabel)) {
|
|
5956
|
+
const body = await __openHttpTextStream(sourceLabel);
|
|
5957
|
+
const rl = readline.createInterface({ input: body, crlfDelay: Infinity });
|
|
5958
|
+
for await (const line of rl) await onLine(line + '\n');
|
|
5959
|
+
return count;
|
|
5960
|
+
}
|
|
5961
|
+
|
|
5962
|
+
const text = __readInputSourceSync(sourceLabel);
|
|
5963
|
+
for (const line of text.match(/.*(?:\r\n|\n|\r)|.+$/g) || []) await onLine(line);
|
|
5964
|
+
return count;
|
|
5874
5965
|
}
|
|
5875
5966
|
|
|
5876
|
-
|
|
5967
|
+
|
|
5968
|
+
async function runStreamMessagesMode(sourceLabels, { rdfMode, storeName = null, storePath = null, storeClear = false } = {}) {
|
|
5877
5969
|
const ordinarySourceLabels = [];
|
|
5878
5970
|
const messageSourceLabels = [];
|
|
5879
5971
|
|
|
@@ -5922,40 +6014,49 @@ async function runStreamMessagesMode(sourceLabels, { rdfMode }) {
|
|
|
5922
6014
|
}
|
|
5923
6015
|
}
|
|
5924
6016
|
|
|
6017
|
+
const store = await createCliStore({ storeName, storePath, storeClear });
|
|
6018
|
+
let pendingStoreWrites = Promise.resolve();
|
|
6019
|
+
|
|
5925
6020
|
const fullIriPrefixes = new PrefixEnv({});
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
let messageDoc;
|
|
5936
|
-
try {
|
|
5937
|
-
messageDoc = parseN3Text(messageText, {
|
|
5938
|
-
baseIri: `${__sourceLabelToBaseIri(messageSourceLabel)}#message-${messageIndex}`,
|
|
5939
|
-
label: `${messageSourceLabel}#message-${messageIndex}`,
|
|
5940
|
-
keepSourceArtifacts: false,
|
|
5941
|
-
sourceLocations: false,
|
|
5942
|
-
rdf: false,
|
|
6021
|
+
try {
|
|
6022
|
+
for (const messageSourceLabel of messageSourceLabels) {
|
|
6023
|
+
try {
|
|
6024
|
+
await __forEachRdfMessageChunk(messageSourceLabel, ({ messageIndex, chunk, directives }) => {
|
|
6025
|
+
const messageText = buildSingleMessageReplayDocument({
|
|
6026
|
+
sourceLabel: messageSourceLabel,
|
|
6027
|
+
messageIndex,
|
|
6028
|
+
chunk,
|
|
6029
|
+
directives,
|
|
5943
6030
|
});
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
6031
|
+
let messageDoc;
|
|
6032
|
+
try {
|
|
6033
|
+
messageDoc = parseN3Text(messageText, {
|
|
6034
|
+
baseIri: `${__sourceLabelToBaseIri(messageSourceLabel)}#message-${messageIndex}`,
|
|
6035
|
+
label: `${messageSourceLabel}#message-${messageIndex}`,
|
|
6036
|
+
keepSourceArtifacts: false,
|
|
6037
|
+
sourceLocations: false,
|
|
6038
|
+
rdf: false,
|
|
6039
|
+
});
|
|
6040
|
+
} catch (e) {
|
|
6041
|
+
if (e && e.name === 'N3SyntaxError') {
|
|
6042
|
+
console.error(formatN3SyntaxError(e, messageText, `${messageSourceLabel}#message-${messageIndex}`));
|
|
6043
|
+
process.exit(1);
|
|
6044
|
+
}
|
|
6045
|
+
throw e;
|
|
5948
6046
|
}
|
|
5949
|
-
throw e;
|
|
5950
|
-
}
|
|
5951
6047
|
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
6048
|
+
const merged = mergeParsedDocuments(programSources.concat([messageDoc]));
|
|
6049
|
+
const result = runParsedDocumentOnce(merged, { rdfMode, outputPrefixes: fullIriPrefixes });
|
|
6050
|
+
if (store) pendingStoreWrites = pendingStoreWrites.then(() => persistRunResultToStore(store, result));
|
|
6051
|
+
});
|
|
6052
|
+
} catch (e) {
|
|
6053
|
+
console.error(`Error streaming RDF Message Log ${JSON.stringify(messageSourceLabel)}: ${e && e.message ? e.message : String(e)}`);
|
|
6054
|
+
process.exit(1);
|
|
6055
|
+
}
|
|
5958
6056
|
}
|
|
6057
|
+
await pendingStoreWrites;
|
|
6058
|
+
} finally {
|
|
6059
|
+
if (store && typeof store.close === 'function') await store.close();
|
|
5959
6060
|
}
|
|
5960
6061
|
}
|
|
5961
6062
|
|
|
@@ -6091,10 +6192,6 @@ async function main() {
|
|
|
6091
6192
|
|
|
6092
6193
|
|
|
6093
6194
|
if (streamMessagesMode) {
|
|
6094
|
-
if (storeName) {
|
|
6095
|
-
console.error('Error: --store cannot be combined with --stream-messages yet.');
|
|
6096
|
-
process.exit(1);
|
|
6097
|
-
}
|
|
6098
6195
|
if (!rdfMode) {
|
|
6099
6196
|
console.error('Error: --stream-messages requires -r/--rdf.');
|
|
6100
6197
|
process.exit(1);
|
|
@@ -6130,17 +6227,94 @@ async function main() {
|
|
|
6130
6227
|
}
|
|
6131
6228
|
}
|
|
6132
6229
|
|
|
6133
|
-
|
|
6230
|
+
let sourceLabels = useImplicitStdin ? ['<stdin>'] : positional.map((item) => (item === '-' ? '<stdin>' : item));
|
|
6134
6231
|
if (sourceLabels.filter((item) => item === '<stdin>').length > 1) {
|
|
6135
6232
|
console.error('Error: stdin can only be used once.');
|
|
6136
6233
|
process.exit(1);
|
|
6137
6234
|
}
|
|
6138
6235
|
|
|
6139
6236
|
if (streamMessagesMode) {
|
|
6140
|
-
await runStreamMessagesMode(sourceLabels, { rdfMode });
|
|
6237
|
+
await runStreamMessagesMode(sourceLabels, { rdfMode, storeName, storePath, storeClear });
|
|
6141
6238
|
return;
|
|
6142
6239
|
}
|
|
6143
6240
|
|
|
6241
|
+
if (storeName && rdfMode) {
|
|
6242
|
+
const lineBasedSources = sourceLabels.filter(sourceLooksLikeLineBasedRdf);
|
|
6243
|
+
if (lineBasedSources.length) {
|
|
6244
|
+
if (showAst) {
|
|
6245
|
+
console.error('Error: line-based --store ingestion cannot be combined with --ast.');
|
|
6246
|
+
process.exit(1);
|
|
6247
|
+
}
|
|
6248
|
+
if (streamMode) {
|
|
6249
|
+
console.error('Error: line-based --store ingestion cannot be combined with --stream.');
|
|
6250
|
+
process.exit(1);
|
|
6251
|
+
}
|
|
6252
|
+
if (engine.getProofCommentsEnabled()) {
|
|
6253
|
+
console.error('Error: line-based --store ingestion currently does not support proof output.');
|
|
6254
|
+
process.exit(1);
|
|
6255
|
+
}
|
|
6256
|
+
|
|
6257
|
+
const store = await createCliStore({ storeName, storePath, storeClear });
|
|
6258
|
+
try {
|
|
6259
|
+
for (const sourceLabel of lineBasedSources) {
|
|
6260
|
+
try {
|
|
6261
|
+
await ingestLineBasedRdfSourceToStore(sourceLabel, store, { rdfMode });
|
|
6262
|
+
} catch (e) {
|
|
6263
|
+
console.error(`Error streaming RDF source ${JSON.stringify(sourceLabel)}: ${e && e.message ? e.message : String(e)}`);
|
|
6264
|
+
process.exit(1);
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
|
|
6268
|
+
sourceLabels = sourceLabels.filter((sourceLabel) => !sourceLooksLikeLineBasedRdf(sourceLabel));
|
|
6269
|
+
if (!sourceLabels.length) return;
|
|
6270
|
+
|
|
6271
|
+
const parsedRuleSources = [];
|
|
6272
|
+
for (const sourceLabel of sourceLabels) {
|
|
6273
|
+
let text;
|
|
6274
|
+
try {
|
|
6275
|
+
text = __readInputSourceSync(sourceLabel);
|
|
6276
|
+
} catch (e) {
|
|
6277
|
+
if (sourceLabel === '<stdin>') console.error(`Error reading stdin: ${e.message}`);
|
|
6278
|
+
else console.error(`Error reading source ${JSON.stringify(sourceLabel)}: ${e.message}`);
|
|
6279
|
+
process.exit(1);
|
|
6280
|
+
}
|
|
6281
|
+
|
|
6282
|
+
try {
|
|
6283
|
+
parsedRuleSources.push(
|
|
6284
|
+
parseN3Text(text, {
|
|
6285
|
+
baseIri: __sourceLabelToBaseIri(sourceLabel),
|
|
6286
|
+
label: sourceLabel,
|
|
6287
|
+
collectUsedPrefixes: false,
|
|
6288
|
+
keepSourceArtifacts: false,
|
|
6289
|
+
sourceLocations: false,
|
|
6290
|
+
rdf: rdfMode,
|
|
6291
|
+
}),
|
|
6292
|
+
);
|
|
6293
|
+
} catch (e) {
|
|
6294
|
+
if (e && e.name === 'N3SyntaxError') {
|
|
6295
|
+
console.error(formatN3SyntaxError(e, text, sourceLabel));
|
|
6296
|
+
process.exit(1);
|
|
6297
|
+
}
|
|
6298
|
+
throw e;
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6301
|
+
|
|
6302
|
+
const mergedRuleDocument = mergeParsedDocuments(parsedRuleSources);
|
|
6303
|
+
const result = await engine.runStoreBacked(mergedRuleDocument, store, { rdf: rdfMode });
|
|
6304
|
+
const outTriples = result.queryMode ? result.queryTriples || [] : (result.derived || []).map((df) => df.fact);
|
|
6305
|
+
if (result.queryMode) {
|
|
6306
|
+
const bodyText = engine.prettyPrintQueryTriples(outTriples, result.prefixes);
|
|
6307
|
+
if (bodyText) process.stdout.write(String(bodyText).replace(/\s*$/g, '') + '\n');
|
|
6308
|
+
} else {
|
|
6309
|
+
for (const tr of outTriples) console.log(engine.tripleToRdfCompatible(tr, result.prefixes));
|
|
6310
|
+
}
|
|
6311
|
+
return;
|
|
6312
|
+
} finally {
|
|
6313
|
+
if (store && typeof store.close === 'function') await store.close();
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
}
|
|
6317
|
+
|
|
6144
6318
|
const parsedSources = [];
|
|
6145
6319
|
for (const sourceLabel of sourceLabels) {
|
|
6146
6320
|
let text;
|
|
@@ -6997,7 +7171,7 @@ const trace = require('./trace');
|
|
|
6997
7171
|
const { deterministicSkolemIdFromKey } = require('./skolem');
|
|
6998
7172
|
|
|
6999
7173
|
const deref = require('./deref');
|
|
7000
|
-
const { createFactStore, collectStore, MemoryFactStore, PersistentFactStore } = require('./store');
|
|
7174
|
+
const { createFactStore, collectStore, MemoryFactStore, PersistentFactStore, tripleToStoreKey } = require('./store');
|
|
7001
7175
|
|
|
7002
7176
|
const hasOwn = Object.prototype.hasOwnProperty;
|
|
7003
7177
|
|
|
@@ -10704,6 +10878,164 @@ async function __parseRunAsyncInput(input, opts) {
|
|
|
10704
10878
|
});
|
|
10705
10879
|
}
|
|
10706
10880
|
|
|
10881
|
+
function __storePatternTerm(t, subst) {
|
|
10882
|
+
const applied = applySubstTerm(t, subst || __emptySubst());
|
|
10883
|
+
return containsVarTerm(applied) ? null : applied;
|
|
10884
|
+
}
|
|
10885
|
+
|
|
10886
|
+
function __mergeStoreSubst(base, delta) {
|
|
10887
|
+
let out = base;
|
|
10888
|
+
for (const k of Object.keys(delta || {})) {
|
|
10889
|
+
const v = delta[k];
|
|
10890
|
+
if (Object.prototype.hasOwnProperty.call(out, k)) {
|
|
10891
|
+
if (!termsEqual(out[k], v)) return null;
|
|
10892
|
+
} else {
|
|
10893
|
+
if (out === base) out = __cloneSubst(base);
|
|
10894
|
+
out[k] = v;
|
|
10895
|
+
}
|
|
10896
|
+
}
|
|
10897
|
+
return out;
|
|
10898
|
+
}
|
|
10899
|
+
|
|
10900
|
+
async function __proveGoalsAgainstStore(goals, subst, store, backRules, localFacts, depth, varGen, opts = {}) {
|
|
10901
|
+
if (!Array.isArray(goals) || goals.length === 0) return [subst || __emptySubst()];
|
|
10902
|
+
if (depth > 64) return [];
|
|
10903
|
+
|
|
10904
|
+
const goal0 = applySubstTriple(goals[0], subst || __emptySubst());
|
|
10905
|
+
const rest = goals.slice(1);
|
|
10906
|
+
const out = [];
|
|
10907
|
+
|
|
10908
|
+
if (isBuiltinPred(goal0.p)) {
|
|
10909
|
+
const deltas = evalBuiltin(goal0, __emptySubst(), localFacts || [], backRules || [], depth, varGen, undefined);
|
|
10910
|
+
for (const delta of deltas) {
|
|
10911
|
+
const nextSubst = __mergeStoreSubst(subst || __emptySubst(), delta);
|
|
10912
|
+
if (nextSubst === null) continue;
|
|
10913
|
+
out.push(...await __proveGoalsAgainstStore(rest, nextSubst, store, backRules, localFacts, depth + 1, varGen, opts));
|
|
10914
|
+
if (opts.maxResults && out.length >= opts.maxResults) return out.slice(0, opts.maxResults);
|
|
10915
|
+
}
|
|
10916
|
+
return out;
|
|
10917
|
+
}
|
|
10918
|
+
|
|
10919
|
+
// Backward rules are kept in memory; they may call back into the persistent
|
|
10920
|
+
// fact store for their own premises.
|
|
10921
|
+
if (goal0.p instanceof Iri && Array.isArray(backRules) && backRules.length) {
|
|
10922
|
+
ensureBackRuleIndexes(backRules);
|
|
10923
|
+
const candRules = (backRules.__byHeadPred.get(goal0.p.__tid) || []).concat(backRules.__wildHeadPred || []);
|
|
10924
|
+
for (const r of candRules) {
|
|
10925
|
+
if (!r || !Array.isArray(r.conclusion) || r.conclusion.length !== 1) continue;
|
|
10926
|
+
const rStd = standardizeRule(r, varGen);
|
|
10927
|
+
const head = rStd.conclusion[0];
|
|
10928
|
+
const s2 = unifyTriple(head, goal0, subst || __emptySubst());
|
|
10929
|
+
if (s2 === null) continue;
|
|
10930
|
+
const newGoals = (rStd.premise || []).concat(rest);
|
|
10931
|
+
out.push(...await __proveGoalsAgainstStore(newGoals, s2, store, backRules, localFacts, depth + 1, varGen, opts));
|
|
10932
|
+
if (opts.maxResults && out.length >= opts.maxResults) return out.slice(0, opts.maxResults);
|
|
10933
|
+
}
|
|
10934
|
+
}
|
|
10935
|
+
|
|
10936
|
+
const sPat = __storePatternTerm(goal0.s, subst || __emptySubst());
|
|
10937
|
+
const pPat = __storePatternTerm(goal0.p, subst || __emptySubst());
|
|
10938
|
+
const oPat = __storePatternTerm(goal0.o, subst || __emptySubst());
|
|
10939
|
+
|
|
10940
|
+
for await (const fact of store.match(sPat, pPat, oPat)) {
|
|
10941
|
+
const s2 = unifyTriple(goal0, fact, subst || __emptySubst());
|
|
10942
|
+
if (s2 === null) continue;
|
|
10943
|
+
out.push(...await __proveGoalsAgainstStore(rest, s2, store, backRules, localFacts, depth + 1, varGen, opts));
|
|
10944
|
+
if (opts.maxResults && out.length >= opts.maxResults) return out.slice(0, opts.maxResults);
|
|
10945
|
+
}
|
|
10946
|
+
|
|
10947
|
+
return out;
|
|
10948
|
+
}
|
|
10949
|
+
|
|
10950
|
+
async function runStoreBacked(input, store, opts = {}) {
|
|
10951
|
+
const parsed = parseN3SourceList(input, {
|
|
10952
|
+
baseIri: opts.baseIri || null,
|
|
10953
|
+
rdf: !!opts.rdf,
|
|
10954
|
+
sourceLocations: !!opts.proof,
|
|
10955
|
+
}) || input;
|
|
10956
|
+
|
|
10957
|
+
const prefixes = parsed.prefixes;
|
|
10958
|
+
const triples = parsed.triples || [];
|
|
10959
|
+
const frules = parsed.frules || [];
|
|
10960
|
+
const brules = parsed.brules || [];
|
|
10961
|
+
const qrules = parsed.logQueryRules || [];
|
|
10962
|
+
|
|
10963
|
+
materializeRdfLists(triples, frules.concat(qrules || []), brules);
|
|
10964
|
+
await store.batchAdd(triples, 'explicit');
|
|
10965
|
+
|
|
10966
|
+
const derived = [];
|
|
10967
|
+
const derivedKeys = new Set();
|
|
10968
|
+
const varGen = [0];
|
|
10969
|
+
const maxIterations = Number.isInteger(opts.maxIterations) && opts.maxIterations > 0 ? opts.maxIterations : 1024;
|
|
10970
|
+
|
|
10971
|
+
for (let iteration = 0; iteration < maxIterations; iteration += 1) {
|
|
10972
|
+
let changed = false;
|
|
10973
|
+
for (let ruleIndex = 0; ruleIndex < frules.length; ruleIndex += 1) {
|
|
10974
|
+
const r = frules[ruleIndex];
|
|
10975
|
+
if (!r || r.isFuse || r.__dynamicConclusionTerm) continue;
|
|
10976
|
+
__prepareForwardRule(r);
|
|
10977
|
+
const solutions = await __proveGoalsAgainstStore(r.premise || [], __emptySubst(), store, brules, triples, 0, varGen, {});
|
|
10978
|
+
for (const subst of solutions) {
|
|
10979
|
+
for (const cpat of r.conclusion || []) {
|
|
10980
|
+
const fact = applySubstTriple(cpat, subst);
|
|
10981
|
+
if (!isGroundTriple(fact)) continue;
|
|
10982
|
+
if (await store.add(fact, 'inferred')) {
|
|
10983
|
+
const df = makeDerivedRecord(fact, r, (r.premise || []).map((p) => applySubstTriple(p, subst)), subst, false);
|
|
10984
|
+
const key = tripleToStoreKey(fact);
|
|
10985
|
+
if (!derivedKeys.has(key)) {
|
|
10986
|
+
derivedKeys.add(key);
|
|
10987
|
+
derived.push(df);
|
|
10988
|
+
}
|
|
10989
|
+
changed = true;
|
|
10990
|
+
}
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10993
|
+
}
|
|
10994
|
+
if (!changed) break;
|
|
10995
|
+
}
|
|
10996
|
+
|
|
10997
|
+
let queryTriples = [];
|
|
10998
|
+
const queryDerived = [];
|
|
10999
|
+
if (qrules.length) {
|
|
11000
|
+
for (const r of qrules) {
|
|
11001
|
+
const solutions = await __proveGoalsAgainstStore(r.premise || [], __emptySubst(), store, brules, triples, 0, varGen, {});
|
|
11002
|
+
for (const subst of solutions) {
|
|
11003
|
+
for (const cpat of r.conclusion || []) {
|
|
11004
|
+
const fact = applySubstTriple(cpat, subst);
|
|
11005
|
+
if (!isGroundTriple(fact)) continue;
|
|
11006
|
+
queryTriples.push(fact);
|
|
11007
|
+
queryDerived.push(makeDerivedRecord(fact, r, (r.premise || []).map((p) => applySubstTriple(p, subst)), subst, false));
|
|
11008
|
+
}
|
|
11009
|
+
}
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
11012
|
+
|
|
11013
|
+
if (queryTriples.length) {
|
|
11014
|
+
const seen = new Set();
|
|
11015
|
+
queryTriples = queryTriples.filter((tr) => {
|
|
11016
|
+
const key = tripleToStoreKey(tr);
|
|
11017
|
+
if (seen.has(key)) return false;
|
|
11018
|
+
seen.add(key);
|
|
11019
|
+
return true;
|
|
11020
|
+
});
|
|
11021
|
+
}
|
|
11022
|
+
|
|
11023
|
+
return {
|
|
11024
|
+
prefixes,
|
|
11025
|
+
facts: [],
|
|
11026
|
+
derived,
|
|
11027
|
+
queryMode: !!qrules.length,
|
|
11028
|
+
queryTriples,
|
|
11029
|
+
queryDerived,
|
|
11030
|
+
closureN3: qrules.length
|
|
11031
|
+
? prettyPrintQueryTriples(queryTriples, prefixes)
|
|
11032
|
+
: derived.map((df) => (opts.rdf ? tripleToRdfCompatible(df.fact, prefixes) : tripleToN3(df.fact, prefixes))).join('\n'),
|
|
11033
|
+
store,
|
|
11034
|
+
storeBacked: true,
|
|
11035
|
+
};
|
|
11036
|
+
}
|
|
11037
|
+
|
|
11038
|
+
|
|
10707
11039
|
function __withoutStoreOptions(opts) {
|
|
10708
11040
|
const out = { ...(opts || {}) };
|
|
10709
11041
|
delete out.store;
|
|
@@ -10898,6 +11230,7 @@ function setTracePrefixes(v) {
|
|
|
10898
11230
|
module.exports = {
|
|
10899
11231
|
reasonStream,
|
|
10900
11232
|
runAsync,
|
|
11233
|
+
runStoreBacked,
|
|
10901
11234
|
reasonRdfJs,
|
|
10902
11235
|
collectLogQueryConclusions,
|
|
10903
11236
|
forwardChainAndCollectLogQueryConclusions,
|
|
@@ -13553,12 +13886,21 @@ function lex(inputText, opts = {}) {
|
|
|
13553
13886
|
numChars.push(chars[i]);
|
|
13554
13887
|
i++;
|
|
13555
13888
|
}
|
|
13556
|
-
if (i < n && chars[i] === '.'
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13889
|
+
if (i < n && chars[i] === '.') {
|
|
13890
|
+
const next = i + 1 < n ? chars[i + 1] : null;
|
|
13891
|
+
let exponentAfterDot = false;
|
|
13892
|
+
if (next === 'e' || next === 'E') {
|
|
13893
|
+
let j = i + 2;
|
|
13894
|
+
if (j < n && (chars[j] === '+' || chars[j] === '-')) j++;
|
|
13895
|
+
exponentAfterDot = j < n && isAsciiDigit(chars[j]);
|
|
13896
|
+
}
|
|
13897
|
+
if (isAsciiDigit(next) || exponentAfterDot) {
|
|
13898
|
+
numChars.push('.');
|
|
13561
13899
|
i++;
|
|
13900
|
+
while (i < n && isAsciiDigit(chars[i])) {
|
|
13901
|
+
numChars.push(chars[i]);
|
|
13902
|
+
i++;
|
|
13903
|
+
}
|
|
13562
13904
|
}
|
|
13563
13905
|
}
|
|
13564
13906
|
}
|
|
@@ -14878,7 +15220,7 @@ class Parser {
|
|
|
14878
15220
|
}
|
|
14879
15221
|
|
|
14880
15222
|
if (this.peek().typ === 'Semicolon') {
|
|
14881
|
-
this.next();
|
|
15223
|
+
while (this.peek().typ === 'Semicolon') this.next();
|
|
14882
15224
|
if (this.peek().typ === closingTyp) break;
|
|
14883
15225
|
continue;
|
|
14884
15226
|
}
|
|
@@ -15005,7 +15347,7 @@ class Parser {
|
|
|
15005
15347
|
}
|
|
15006
15348
|
|
|
15007
15349
|
if (this.peek().typ === 'Semicolon') {
|
|
15008
|
-
this.next();
|
|
15350
|
+
while (this.peek().typ === 'Semicolon') this.next();
|
|
15009
15351
|
if (this.peek().typ === 'Dot') break;
|
|
15010
15352
|
continue;
|
|
15011
15353
|
}
|
|
@@ -17705,7 +18047,10 @@ class ClassicLevelKv {
|
|
|
17705
18047
|
const classic = __dynamicRequire('classic-level');
|
|
17706
18048
|
const ClassicLevel = classic && (classic.ClassicLevel || classic.Level || classic.default);
|
|
17707
18049
|
if (!ClassicLevel) throw new Error('classic-level is not installed');
|
|
17708
|
-
|
|
18050
|
+
const fs = __dynamicRequire('node:fs');
|
|
18051
|
+
const path = __dynamicRequire('node:path');
|
|
18052
|
+
if (fs && path) fs.mkdirSync(path.dirname(location), { recursive: true });
|
|
18053
|
+
this.db = new ClassicLevel(location, { valueEncoding: 'json', createIfMissing: true, errorIfExists: false });
|
|
17709
18054
|
this.opened = false;
|
|
17710
18055
|
}
|
|
17711
18056
|
|