eyeling 1.7.10 → 1.7.12
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/examples/bind.n3 +1 -1
- package/examples/snaf.n3 +1 -1
- package/eyeling.js +88 -45
- package/package.json +1 -1
package/examples/bind.n3
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
|
|
5
5
|
:phayes a :Person ; :givenName "Pat"; :familyName "Hayes" .
|
|
6
6
|
|
|
7
|
-
{ ?x a :Person .
|
|
7
|
+
{ ?x a :Person . (1 { ?x :name ?someName . } ()) log:collectAllIn ?SCOPE . ?x :givenName ?name1 . ?x :familyName ?name2 . (?name1 " " ?name2) string:concatenation ?FN . } => { ?x :name ?FN } .
|
package/examples/snaf.n3
CHANGED
package/eyeling.js
CHANGED
|
@@ -16,8 +16,20 @@
|
|
|
16
16
|
* 5) Print only newly derived forward facts with explanations.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
// -----------------------------------------------------------------------------
|
|
20
|
+
// Browser/Worker-safe version + crypto wiring
|
|
21
|
+
// -----------------------------------------------------------------------------
|
|
22
|
+
let version = 'dev';
|
|
23
|
+
try {
|
|
24
|
+
// Node: keep package.json version if available
|
|
25
|
+
if (typeof require === 'function') version = require('./package.json').version || version;
|
|
26
|
+
} catch (_) {}
|
|
27
|
+
|
|
28
|
+
let nodeCrypto = null;
|
|
29
|
+
try {
|
|
30
|
+
// Node: crypto available
|
|
31
|
+
if (typeof require === 'function') nodeCrypto = require('crypto');
|
|
32
|
+
} catch (_) {}
|
|
21
33
|
|
|
22
34
|
// ===========================================================================
|
|
23
35
|
// Namespace constants
|
|
@@ -5533,62 +5545,40 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
5533
5545
|
return results;
|
|
5534
5546
|
}
|
|
5535
5547
|
|
|
5536
|
-
// log:includes
|
|
5548
|
+
// log:includes
|
|
5537
5549
|
// Schema: $s+ log:includes $o+
|
|
5538
|
-
//
|
|
5539
|
-
// Otherwise, the scope is the current document scope (facts + backward rules).
|
|
5550
|
+
// Object may be a concrete formula or the literal `true` (empty formula).
|
|
5540
5551
|
if (pv === LOG_NS + 'includes') {
|
|
5552
|
+
if (!(g.s instanceof GraphTerm)) return [];
|
|
5553
|
+
|
|
5541
5554
|
// Empty formula is always included.
|
|
5542
5555
|
if (g.o instanceof Literal && g.o.value === 'true') return [{ ...subst }];
|
|
5543
5556
|
if (!(g.o instanceof GraphTerm)) return [];
|
|
5544
5557
|
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
let scopeBackRules = backRules;
|
|
5549
|
-
|
|
5550
|
-
// If the subject is a formula, treat it as a concrete scope graph.
|
|
5551
|
-
// Also support `true` as the empty formula.
|
|
5552
|
-
if (g.s instanceof GraphTerm) {
|
|
5553
|
-
scopeFacts = g.s.triples.slice();
|
|
5554
|
-
ensureFactIndexes(scopeFacts);
|
|
5555
|
-
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5556
|
-
scopeBackRules = []; // concrete scope = syntactic containment (no extra rules)
|
|
5557
|
-
} else if (g.s instanceof Literal && g.s.value === 'true') {
|
|
5558
|
-
scopeFacts = [];
|
|
5559
|
-
ensureFactIndexes(scopeFacts);
|
|
5560
|
-
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5561
|
-
scopeBackRules = [];
|
|
5562
|
-
} else {
|
|
5563
|
-
scopeFacts = facts; // dynamic scope
|
|
5564
|
-
}
|
|
5558
|
+
const scopeFacts = g.s.triples.slice();
|
|
5559
|
+
ensureFactIndexes(scopeFacts);
|
|
5560
|
+
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5565
5561
|
|
|
5566
5562
|
const visited2 = [];
|
|
5567
5563
|
// Start from the incoming substitution so bindings flow outward.
|
|
5568
|
-
return proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts,
|
|
5564
|
+
return proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts, [], depth + 1, visited2, varGen);
|
|
5569
5565
|
}
|
|
5570
5566
|
|
|
5571
|
-
// log:notIncludes
|
|
5572
|
-
//
|
|
5567
|
+
// log:notIncludes
|
|
5568
|
+
// Schema: $s+ log:notIncludes $o+
|
|
5573
5569
|
if (pv === LOG_NS + 'notIncludes') {
|
|
5574
|
-
if (!(g.
|
|
5570
|
+
if (!(g.s instanceof GraphTerm)) return [];
|
|
5575
5571
|
|
|
5576
|
-
|
|
5577
|
-
|
|
5572
|
+
// Empty formula is always included, so it is never "not included".
|
|
5573
|
+
if (g.o instanceof Literal && g.o.value === 'true') return [];
|
|
5574
|
+
if (!(g.o instanceof GraphTerm)) return [];
|
|
5578
5575
|
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
ensureFactIndexes(scopeFacts);
|
|
5583
|
-
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5584
|
-
scopeBackRules = []; // concrete scope = syntactic containment (no extra rules)
|
|
5585
|
-
} else {
|
|
5586
|
-
scopeFacts = facts.__scopedSnapshot || null;
|
|
5587
|
-
if (!scopeFacts) return []; // DELAY until saturation snapshot exists
|
|
5588
|
-
}
|
|
5576
|
+
const scopeFacts = g.s.triples.slice();
|
|
5577
|
+
ensureFactIndexes(scopeFacts);
|
|
5578
|
+
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5589
5579
|
|
|
5590
5580
|
const visited2 = [];
|
|
5591
|
-
const sols = proveGoals(Array.from(g.o.triples), {}, scopeFacts,
|
|
5581
|
+
const sols = proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts, [], depth + 1, visited2, varGen);
|
|
5592
5582
|
return sols.length ? [] : [{ ...subst }];
|
|
5593
5583
|
}
|
|
5594
5584
|
|
|
@@ -6259,7 +6249,7 @@ function proveGoals(goals, subst, facts, backRules, depth, visited, varGen) {
|
|
|
6259
6249
|
// Forward chaining to fixpoint
|
|
6260
6250
|
// ===========================================================================
|
|
6261
6251
|
|
|
6262
|
-
function forwardChain(facts, forwardRules, backRules) {
|
|
6252
|
+
function forwardChain(facts, forwardRules, backRules, onDerived /* optional */) {
|
|
6263
6253
|
ensureFactIndexes(facts);
|
|
6264
6254
|
ensureBackRuleIndexes(backRules);
|
|
6265
6255
|
|
|
@@ -6344,7 +6334,10 @@ function forwardChain(facts, forwardRules, backRules) {
|
|
|
6344
6334
|
if (!hasFactIndexed(facts, instantiated)) {
|
|
6345
6335
|
factList.push(instantiated);
|
|
6346
6336
|
pushFactIndexed(facts, instantiated);
|
|
6347
|
-
|
|
6337
|
+
const df = new DerivedFact(instantiated, r, instantiatedPremises.slice(), { ...s });
|
|
6338
|
+
derivedForward.push(df);
|
|
6339
|
+
if (typeof onDerived === 'function') onDerived(df);
|
|
6340
|
+
|
|
6348
6341
|
changed = true;
|
|
6349
6342
|
}
|
|
6350
6343
|
|
|
@@ -6408,7 +6401,10 @@ function forwardChain(facts, forwardRules, backRules) {
|
|
|
6408
6401
|
|
|
6409
6402
|
factList.push(inst);
|
|
6410
6403
|
pushFactIndexed(facts, inst);
|
|
6411
|
-
|
|
6404
|
+
const df = new DerivedFact(inst, r, instantiatedPremises.slice(), { ...s });
|
|
6405
|
+
derivedForward.push(df);
|
|
6406
|
+
if (typeof onDerived === 'function') onDerived(df);
|
|
6407
|
+
|
|
6412
6408
|
changed = true;
|
|
6413
6409
|
}
|
|
6414
6410
|
}
|
|
@@ -6744,6 +6740,53 @@ function __collectOutputStringsFromFacts(facts, prefixes) {
|
|
|
6744
6740
|
return pairs.map((p) => p.text).join('');
|
|
6745
6741
|
}
|
|
6746
6742
|
|
|
6743
|
+
function reasonStream(n3Text, opts = {}) {
|
|
6744
|
+
const { baseIri = null, proof = false, onDerived = null, includeInputFactsInClosure = true } = opts;
|
|
6745
|
+
|
|
6746
|
+
proofCommentsEnabled = !!proof;
|
|
6747
|
+
|
|
6748
|
+
const toks = lex(n3Text);
|
|
6749
|
+
const parser = new Parser(toks);
|
|
6750
|
+
if (baseIri) parser.prefixes.setBase(baseIri);
|
|
6751
|
+
|
|
6752
|
+
let prefixes, triples, frules, brules;
|
|
6753
|
+
[prefixes, triples, frules, brules] = parser.parseDocument();
|
|
6754
|
+
|
|
6755
|
+
materializeRdfLists(triples, frules, brules);
|
|
6756
|
+
|
|
6757
|
+
// facts becomes the saturated closure because pushFactIndexed(...) appends into it
|
|
6758
|
+
const facts = triples.filter((tr) => isGroundTriple(tr));
|
|
6759
|
+
|
|
6760
|
+
const derived = forwardChain(facts, frules, brules, (df) => {
|
|
6761
|
+
if (typeof onDerived === 'function') {
|
|
6762
|
+
onDerived({
|
|
6763
|
+
triple: tripleToN3(df.fact, prefixes),
|
|
6764
|
+
df,
|
|
6765
|
+
});
|
|
6766
|
+
}
|
|
6767
|
+
});
|
|
6768
|
+
|
|
6769
|
+
const closureTriples = includeInputFactsInClosure ? facts : derived.map((d) => d.fact);
|
|
6770
|
+
|
|
6771
|
+
return {
|
|
6772
|
+
prefixes,
|
|
6773
|
+
facts, // saturated closure (Triple[])
|
|
6774
|
+
derived, // DerivedFact[]
|
|
6775
|
+
closureN3: closureTriples.map((t) => tripleToN3(t, prefixes)).join('\n'),
|
|
6776
|
+
};
|
|
6777
|
+
}
|
|
6778
|
+
|
|
6779
|
+
// Minimal export surface for Node + browser/worker
|
|
6780
|
+
const EYELING_API = { reasonStream };
|
|
6781
|
+
|
|
6782
|
+
try {
|
|
6783
|
+
if (typeof module !== 'undefined' && module.exports) module.exports = EYELING_API;
|
|
6784
|
+
} catch (_) {}
|
|
6785
|
+
|
|
6786
|
+
try {
|
|
6787
|
+
if (typeof self !== 'undefined') self.eyeling = EYELING_API;
|
|
6788
|
+
} catch (_) {}
|
|
6789
|
+
|
|
6747
6790
|
function main() {
|
|
6748
6791
|
// Drop "node" and script name; keep only user-provided args
|
|
6749
6792
|
const argv = process.argv.slice(2);
|