eyeling 1.7.9 → 1.7.11
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 +2 -2
- package/examples/bind.n3 +1 -1
- package/examples/output/time.n3 +8 -0
- package/examples/snaf.n3 +1 -1
- package/examples/time.n3 +29 -0
- package/eyeling.js +226 -80
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -216,10 +216,10 @@ Commonly used N3/Turtle features:
|
|
|
216
216
|
|
|
217
217
|
- **crypto**: `crypto:md5` `crypto:sha` `crypto:sha256` `crypto:sha512`
|
|
218
218
|
- **list**: `list:append` `list:first` `list:firstRest` `list:in` `list:iterate` `list:last` `list:length` `list:map` `list:member` `list:memberAt` `list:notMember` `list:remove` `list:rest` `list:reverse` `list:sort`
|
|
219
|
-
- **log**: `log:collectAllIn` `log:content` `log:equalTo` `log:forAllIn` `log:impliedBy` `log:implies` `log:notEqualTo` `log:notIncludes` `log:semantics` `log:skolem` `log:uri`
|
|
219
|
+
- **log**: `log:collectAllIn` `log:content` `log:dtlit` `log:equalTo` `log:forAllIn` `log:impliedBy` `log:implies` `log:includes` `log:langlit` `log:notEqualTo` `log:notIncludes` `log:outputString` `log:parsedAsN3` `log:rawType` `log:semantics` `log:semanticsOrError` `log:skolem` `log:uri`
|
|
220
220
|
- **math**: `math:absoluteValue` `math:acos` `math:asin` `math:atan` `math:cos` `math:cosh` `math:degrees` `math:difference` `math:equalTo` `math:exponentiation` `math:greaterThan` `math:integerQuotient` `math:lessThan` `math:negation` `math:notEqualTo` `math:notGreaterThan` `math:notLessThan` `math:product` `math:quotient` `math:remainder` `math:rounded` `math:sin` `math:sinh` `math:sum` `math:tan` `math:tanh`
|
|
221
221
|
- **string**: `string:concatenation` `string:contains` `string:containsIgnoringCase` `string:endsWith` `string:equalIgnoringCase` `string:format` `string:greaterThan` `string:jsonPointer` `string:lessThan` `string:matches` `string:notEqualIgnoringCase` `string:notGreaterThan` `string:notLessThan` `string:notMatches` `string:replace` `string:scrape` `string:startsWith`
|
|
222
|
-
- **time**: `time:localTime`
|
|
222
|
+
- **time**: `time:day` `time:localTime` `time:minute` `time:month` `time:second` `time:timeZone` `time:year`
|
|
223
223
|
|
|
224
224
|
## License
|
|
225
225
|
|
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/examples/time.n3
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# =======================
|
|
2
|
+
# time: builtins examples
|
|
3
|
+
# =======================
|
|
4
|
+
|
|
5
|
+
@prefix : <http://example.org/> .
|
|
6
|
+
@prefix time: <http://www.w3.org/2000/10/swap/time#> .
|
|
7
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
8
|
+
|
|
9
|
+
:Let :dt "2023-04-01T18:06:04Z"^^xsd:dateTime .
|
|
10
|
+
|
|
11
|
+
{
|
|
12
|
+
:Let :dt ?d .
|
|
13
|
+
?d time:year ?y ;
|
|
14
|
+
time:month ?m ;
|
|
15
|
+
time:day ?day ;
|
|
16
|
+
time:minute ?min ;
|
|
17
|
+
time:second ?sec ;
|
|
18
|
+
time:timeZone ?tz .
|
|
19
|
+
}
|
|
20
|
+
=>
|
|
21
|
+
{
|
|
22
|
+
:out :year ?y ;
|
|
23
|
+
:month ?m ;
|
|
24
|
+
:day ?day ;
|
|
25
|
+
:minute ?min ;
|
|
26
|
+
:second ?sec ;
|
|
27
|
+
:tz ?tz .
|
|
28
|
+
} .
|
|
29
|
+
|
package/eyeling.js
CHANGED
|
@@ -95,9 +95,7 @@ const __logConclusionCache = new WeakMap(); // GraphTerm -> GraphTerm (deductive
|
|
|
95
95
|
// Environment detection (Node vs Browser/Worker).
|
|
96
96
|
// Eyeling is primarily synchronous, so we use sync XHR in browsers for log:content/log:semantics.
|
|
97
97
|
// Note: Browser fetches are subject to CORS; use CORS-enabled resources or a proxy.
|
|
98
|
-
const __IS_NODE =
|
|
99
|
-
typeof process !== 'undefined' &&
|
|
100
|
-
!!(process.versions && process.versions.node);
|
|
98
|
+
const __IS_NODE = typeof process !== 'undefined' && !!(process.versions && process.versions.node);
|
|
101
99
|
|
|
102
100
|
function __hasXmlHttpRequest() {
|
|
103
101
|
return typeof XMLHttpRequest !== 'undefined';
|
|
@@ -107,10 +105,7 @@ function __resolveBrowserUrl(ref) {
|
|
|
107
105
|
if (!ref) return ref;
|
|
108
106
|
// If already absolute, keep as-is.
|
|
109
107
|
if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(ref)) return ref;
|
|
110
|
-
const base =
|
|
111
|
-
(typeof document !== 'undefined' && document.baseURI) ||
|
|
112
|
-
(typeof location !== 'undefined' && location.href) ||
|
|
113
|
-
'';
|
|
108
|
+
const base = (typeof document !== 'undefined' && document.baseURI) || (typeof location !== 'undefined' && location.href) || '';
|
|
114
109
|
try {
|
|
115
110
|
return new URL(ref, base).toString();
|
|
116
111
|
} catch {
|
|
@@ -124,10 +119,7 @@ function __fetchHttpTextSyncBrowser(url) {
|
|
|
124
119
|
const xhr = new XMLHttpRequest();
|
|
125
120
|
xhr.open('GET', url, false); // synchronous
|
|
126
121
|
try {
|
|
127
|
-
xhr.setRequestHeader(
|
|
128
|
-
'Accept',
|
|
129
|
-
'text/n3, text/turtle, application/n-triples, application/n-quads, text/plain;q=0.1, */*;q=0.01'
|
|
130
|
-
);
|
|
122
|
+
xhr.setRequestHeader('Accept', 'text/n3, text/turtle, application/n-triples, application/n-quads, text/plain;q=0.1, */*;q=0.01');
|
|
131
123
|
} catch {
|
|
132
124
|
// Some environments restrict setting headers (ignore).
|
|
133
125
|
}
|
|
@@ -232,7 +224,7 @@ function __fetchHttpTextViaSubprocess(url) {
|
|
|
232
224
|
`;
|
|
233
225
|
const r = cp.spawnSync(process.execPath, ['-e', script, url], {
|
|
234
226
|
encoding: 'utf8',
|
|
235
|
-
maxBuffer: 32 * 1024 * 1024
|
|
227
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
236
228
|
});
|
|
237
229
|
if (r.status !== 0) return null;
|
|
238
230
|
return r.stdout;
|
|
@@ -297,8 +289,8 @@ function __derefSemanticsSync(iriNoFrag) {
|
|
|
297
289
|
return null;
|
|
298
290
|
}
|
|
299
291
|
try {
|
|
300
|
-
const baseIri =
|
|
301
|
-
|
|
292
|
+
const baseIri = typeof key === 'string' && key ? key : iriNoFrag;
|
|
293
|
+
const formula = __parseSemanticsToFormula(text, baseIri);
|
|
302
294
|
__logSemanticsCache.set(key, formula);
|
|
303
295
|
return formula;
|
|
304
296
|
} catch {
|
|
@@ -387,8 +379,6 @@ function __computeConclusionFromFormula(formula) {
|
|
|
387
379
|
return out;
|
|
388
380
|
}
|
|
389
381
|
|
|
390
|
-
|
|
391
|
-
|
|
392
382
|
// Controls whether human-readable proof comments are printed.
|
|
393
383
|
let proofCommentsEnabled = false;
|
|
394
384
|
// Super restricted mode: disable *all* builtins except => / <= (log:implies / log:impliedBy)
|
|
@@ -3489,6 +3479,33 @@ function parseXsdDatetimeTerm(t) {
|
|
|
3489
3479
|
return d; // Date in local/UTC, we only use timestamp
|
|
3490
3480
|
}
|
|
3491
3481
|
|
|
3482
|
+
function parseXsdDateTimeLexParts(t) {
|
|
3483
|
+
// Parse *lexical* components of an xsd:dateTime literal without timezone normalization.
|
|
3484
|
+
// Returns { yearStr, month, day, minute, second, tz } or null.
|
|
3485
|
+
if (!(t instanceof Literal)) return null;
|
|
3486
|
+
const [lex, dt] = literalParts(t.value);
|
|
3487
|
+
if (dt !== XSD_NS + 'dateTime') return null;
|
|
3488
|
+
const val = stripQuotes(lex);
|
|
3489
|
+
|
|
3490
|
+
// xsd:dateTime lexical: YYYY-MM-DDThh:mm:ss(.s+)?(Z|(+|-)hh:mm)?
|
|
3491
|
+
const m = /^(-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(Z|[+-]\d{2}:\d{2})?$/.exec(val);
|
|
3492
|
+
if (!m) return null;
|
|
3493
|
+
|
|
3494
|
+
const yearStr = m[1];
|
|
3495
|
+
const month = parseInt(m[2], 10);
|
|
3496
|
+
const day = parseInt(m[3], 10);
|
|
3497
|
+
const minute = parseInt(m[5], 10);
|
|
3498
|
+
const second = parseInt(m[6], 10);
|
|
3499
|
+
const tz = m[7] || null;
|
|
3500
|
+
|
|
3501
|
+
if (!(month >= 1 && month <= 12)) return null;
|
|
3502
|
+
if (!(day >= 1 && day <= 31)) return null;
|
|
3503
|
+
if (!(minute >= 0 && minute <= 59)) return null;
|
|
3504
|
+
if (!(second >= 0 && second <= 59)) return null;
|
|
3505
|
+
|
|
3506
|
+
return { yearStr, month, day, minute, second, tz };
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3492
3509
|
function parseDatetimeLike(t) {
|
|
3493
3510
|
const d = parseXsdDateTerm(t);
|
|
3494
3511
|
if (d !== null) return d;
|
|
@@ -4579,6 +4596,162 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4579
4596
|
// 4.3 time: builtins
|
|
4580
4597
|
// -----------------------------------------------------------------
|
|
4581
4598
|
|
|
4599
|
+
// time:day
|
|
4600
|
+
// Gets as object the integer day component of the subject xsd:dateTime.
|
|
4601
|
+
// Schema: $s+ time:day $o-
|
|
4602
|
+
if (pv === TIME_NS + 'day') {
|
|
4603
|
+
const parts = parseXsdDateTimeLexParts(g.s);
|
|
4604
|
+
if (!parts) return [];
|
|
4605
|
+
const out = internLiteral(String(parts.day));
|
|
4606
|
+
|
|
4607
|
+
if (g.o instanceof Var) {
|
|
4608
|
+
const s2 = { ...subst };
|
|
4609
|
+
s2[g.o.name] = out;
|
|
4610
|
+
return [s2];
|
|
4611
|
+
}
|
|
4612
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4613
|
+
|
|
4614
|
+
const oi = parseIntLiteral(g.o);
|
|
4615
|
+
if (oi !== null) {
|
|
4616
|
+
try {
|
|
4617
|
+
if (oi === BigInt(parts.day)) return [{ ...subst }];
|
|
4618
|
+
} catch {}
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
const s2 = unifyTerm(g.o, out, subst);
|
|
4622
|
+
return s2 !== null ? [s2] : [];
|
|
4623
|
+
}
|
|
4624
|
+
|
|
4625
|
+
// time:minute
|
|
4626
|
+
// Gets as object the integer minutes component of the subject xsd:dateTime.
|
|
4627
|
+
// Schema: $s+ time:minute $o-
|
|
4628
|
+
if (pv === TIME_NS + 'minute') {
|
|
4629
|
+
const parts = parseXsdDateTimeLexParts(g.s);
|
|
4630
|
+
if (!parts) return [];
|
|
4631
|
+
const out = internLiteral(String(parts.minute));
|
|
4632
|
+
|
|
4633
|
+
if (g.o instanceof Var) {
|
|
4634
|
+
const s2 = { ...subst };
|
|
4635
|
+
s2[g.o.name] = out;
|
|
4636
|
+
return [s2];
|
|
4637
|
+
}
|
|
4638
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4639
|
+
|
|
4640
|
+
const oi = parseIntLiteral(g.o);
|
|
4641
|
+
if (oi !== null) {
|
|
4642
|
+
try {
|
|
4643
|
+
if (oi === BigInt(parts.minute)) return [{ ...subst }];
|
|
4644
|
+
} catch {}
|
|
4645
|
+
}
|
|
4646
|
+
|
|
4647
|
+
const s2 = unifyTerm(g.o, out, subst);
|
|
4648
|
+
return s2 !== null ? [s2] : [];
|
|
4649
|
+
}
|
|
4650
|
+
|
|
4651
|
+
// time:month
|
|
4652
|
+
// Gets as object the integer month component of the subject xsd:dateTime.
|
|
4653
|
+
// Schema: $s+ time:month $o-
|
|
4654
|
+
if (pv === TIME_NS + 'month') {
|
|
4655
|
+
const parts = parseXsdDateTimeLexParts(g.s);
|
|
4656
|
+
if (!parts) return [];
|
|
4657
|
+
const out = internLiteral(String(parts.month));
|
|
4658
|
+
|
|
4659
|
+
if (g.o instanceof Var) {
|
|
4660
|
+
const s2 = { ...subst };
|
|
4661
|
+
s2[g.o.name] = out;
|
|
4662
|
+
return [s2];
|
|
4663
|
+
}
|
|
4664
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4665
|
+
|
|
4666
|
+
const oi = parseIntLiteral(g.o);
|
|
4667
|
+
if (oi !== null) {
|
|
4668
|
+
try {
|
|
4669
|
+
if (oi === BigInt(parts.month)) return [{ ...subst }];
|
|
4670
|
+
} catch {}
|
|
4671
|
+
}
|
|
4672
|
+
|
|
4673
|
+
const s2 = unifyTerm(g.o, out, subst);
|
|
4674
|
+
return s2 !== null ? [s2] : [];
|
|
4675
|
+
}
|
|
4676
|
+
|
|
4677
|
+
// time:second
|
|
4678
|
+
// Gets as object the integer seconds component of the subject xsd:dateTime.
|
|
4679
|
+
// Schema: $s+ time:second $o-
|
|
4680
|
+
if (pv === TIME_NS + 'second') {
|
|
4681
|
+
const parts = parseXsdDateTimeLexParts(g.s);
|
|
4682
|
+
if (!parts) return [];
|
|
4683
|
+
const out = internLiteral(String(parts.second));
|
|
4684
|
+
|
|
4685
|
+
if (g.o instanceof Var) {
|
|
4686
|
+
const s2 = { ...subst };
|
|
4687
|
+
s2[g.o.name] = out;
|
|
4688
|
+
return [s2];
|
|
4689
|
+
}
|
|
4690
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4691
|
+
|
|
4692
|
+
const oi = parseIntLiteral(g.o);
|
|
4693
|
+
if (oi !== null) {
|
|
4694
|
+
try {
|
|
4695
|
+
if (oi === BigInt(parts.second)) return [{ ...subst }];
|
|
4696
|
+
} catch {}
|
|
4697
|
+
}
|
|
4698
|
+
|
|
4699
|
+
const s2 = unifyTerm(g.o, out, subst);
|
|
4700
|
+
return s2 !== null ? [s2] : [];
|
|
4701
|
+
}
|
|
4702
|
+
|
|
4703
|
+
// time:timeZone
|
|
4704
|
+
// Gets as object the trailing timezone offset of the subject xsd:dateTime (e.g., "-05:00" or "Z").
|
|
4705
|
+
// Schema: $s+ time:timeZone $o-
|
|
4706
|
+
if (pv === TIME_NS + 'timeZone') {
|
|
4707
|
+
const parts = parseXsdDateTimeLexParts(g.s);
|
|
4708
|
+
if (!parts) return [];
|
|
4709
|
+
if (parts.tz === null) return [];
|
|
4710
|
+
const out = internLiteral(`"${parts.tz}"`);
|
|
4711
|
+
|
|
4712
|
+
if (g.o instanceof Var) {
|
|
4713
|
+
const s2 = { ...subst };
|
|
4714
|
+
s2[g.o.name] = out;
|
|
4715
|
+
return [s2];
|
|
4716
|
+
}
|
|
4717
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4718
|
+
|
|
4719
|
+
if (termsEqual(g.o, out)) return [{ ...subst }];
|
|
4720
|
+
|
|
4721
|
+
// Also accept explicitly typed xsd:string literals.
|
|
4722
|
+
if (g.o instanceof Literal) {
|
|
4723
|
+
const [lexO, dtO] = literalParts(g.o.value);
|
|
4724
|
+
if (dtO === XSD_NS + 'string' && stripQuotes(lexO) === parts.tz) return [{ ...subst }];
|
|
4725
|
+
}
|
|
4726
|
+
return [];
|
|
4727
|
+
}
|
|
4728
|
+
|
|
4729
|
+
// time:year
|
|
4730
|
+
// Gets as object the integer year component of the subject xsd:dateTime.
|
|
4731
|
+
// Schema: $s+ time:year $o-
|
|
4732
|
+
if (pv === TIME_NS + 'year') {
|
|
4733
|
+
const parts = parseXsdDateTimeLexParts(g.s);
|
|
4734
|
+
if (!parts) return [];
|
|
4735
|
+
const out = internLiteral(String(parts.yearStr));
|
|
4736
|
+
|
|
4737
|
+
if (g.o instanceof Var) {
|
|
4738
|
+
const s2 = { ...subst };
|
|
4739
|
+
s2[g.o.name] = out;
|
|
4740
|
+
return [s2];
|
|
4741
|
+
}
|
|
4742
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4743
|
+
|
|
4744
|
+
const oi = parseIntLiteral(g.o);
|
|
4745
|
+
if (oi !== null) {
|
|
4746
|
+
try {
|
|
4747
|
+
if (oi === BigInt(parts.yearStr)) return [{ ...subst }];
|
|
4748
|
+
} catch {}
|
|
4749
|
+
}
|
|
4750
|
+
|
|
4751
|
+
const s2 = unifyTerm(g.o, out, subst);
|
|
4752
|
+
return s2 !== null ? [s2] : [];
|
|
4753
|
+
}
|
|
4754
|
+
|
|
4582
4755
|
// time:localTime
|
|
4583
4756
|
// "" time:localTime ?D. binds ?D to “now” as xsd:dateTime.
|
|
4584
4757
|
if (pv === TIME_NS + 'localTime') {
|
|
@@ -5021,30 +5194,29 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
5021
5194
|
return s2 !== null ? [s2] : [];
|
|
5022
5195
|
}
|
|
5023
5196
|
|
|
5197
|
+
// log:conclusion
|
|
5198
|
+
// Schema: $s+ log:conclusion $o?
|
|
5199
|
+
// $o is the deductive closure of the subject formula $s (including rule inferences).
|
|
5200
|
+
if (pv === LOG_NS + 'conclusion') {
|
|
5201
|
+
// Accept 'true' as the empty formula.
|
|
5202
|
+
let inFormula = null;
|
|
5203
|
+
if (g.s instanceof GraphTerm) inFormula = g.s;
|
|
5204
|
+
else if (g.s instanceof Literal && g.s.value === 'true') inFormula = new GraphTerm([]);
|
|
5205
|
+
else return [];
|
|
5024
5206
|
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
// $o is the deductive closure of the subject formula $s (including rule inferences).
|
|
5028
|
-
if (pv === LOG_NS + 'conclusion') {
|
|
5029
|
-
// Accept 'true' as the empty formula.
|
|
5030
|
-
let inFormula = null;
|
|
5031
|
-
if (g.s instanceof GraphTerm) inFormula = g.s;
|
|
5032
|
-
else if (g.s instanceof Literal && g.s.value === 'true') inFormula = new GraphTerm([]);
|
|
5033
|
-
else return [];
|
|
5207
|
+
const conclusion = __computeConclusionFromFormula(inFormula);
|
|
5208
|
+
if (!(conclusion instanceof GraphTerm)) return [];
|
|
5034
5209
|
|
|
5035
|
-
|
|
5036
|
-
|
|
5210
|
+
if (g.o instanceof Var) {
|
|
5211
|
+
const s2 = { ...subst };
|
|
5212
|
+
s2[g.o.name] = conclusion;
|
|
5213
|
+
return [s2];
|
|
5214
|
+
}
|
|
5215
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
5037
5216
|
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
s2[g.o.name] = conclusion;
|
|
5041
|
-
return [s2];
|
|
5217
|
+
const s2 = unifyTerm(g.o, conclusion, subst);
|
|
5218
|
+
return s2 !== null ? [s2] : [];
|
|
5042
5219
|
}
|
|
5043
|
-
if (g.o instanceof Blank) return [{ ...subst }];
|
|
5044
|
-
|
|
5045
|
-
const s2 = unifyTerm(g.o, conclusion, subst);
|
|
5046
|
-
return s2 !== null ? [s2] : [];
|
|
5047
|
-
}
|
|
5048
5220
|
|
|
5049
5221
|
// log:content
|
|
5050
5222
|
// Schema: $s+ log:content $o?
|
|
@@ -5195,8 +5367,6 @@ if (pv === LOG_NS + 'conclusion') {
|
|
|
5195
5367
|
return s2 !== null ? [s2] : [];
|
|
5196
5368
|
}
|
|
5197
5369
|
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
5370
|
// log:dtlit
|
|
5201
5371
|
// Schema: ( $s.1? $s.2? )? log:dtlit $o?
|
|
5202
5372
|
// true iff $o is a datatyped literal with string value $s.1 and datatype IRI $s.2
|
|
@@ -5363,62 +5533,40 @@ if (pv === LOG_NS + 'conclusion') {
|
|
|
5363
5533
|
return results;
|
|
5364
5534
|
}
|
|
5365
5535
|
|
|
5366
|
-
// log:includes
|
|
5536
|
+
// log:includes
|
|
5367
5537
|
// Schema: $s+ log:includes $o+
|
|
5368
|
-
//
|
|
5369
|
-
// Otherwise, the scope is the current document scope (facts + backward rules).
|
|
5538
|
+
// Object may be a concrete formula or the literal `true` (empty formula).
|
|
5370
5539
|
if (pv === LOG_NS + 'includes') {
|
|
5540
|
+
if (!(g.s instanceof GraphTerm)) return [];
|
|
5541
|
+
|
|
5371
5542
|
// Empty formula is always included.
|
|
5372
5543
|
if (g.o instanceof Literal && g.o.value === 'true') return [{ ...subst }];
|
|
5373
5544
|
if (!(g.o instanceof GraphTerm)) return [];
|
|
5374
5545
|
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
let scopeBackRules = backRules;
|
|
5379
|
-
|
|
5380
|
-
// If the subject is a formula, treat it as a concrete scope graph.
|
|
5381
|
-
// Also support `true` as the empty formula.
|
|
5382
|
-
if (g.s instanceof GraphTerm) {
|
|
5383
|
-
scopeFacts = g.s.triples.slice();
|
|
5384
|
-
ensureFactIndexes(scopeFacts);
|
|
5385
|
-
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5386
|
-
scopeBackRules = []; // concrete scope = syntactic containment (no extra rules)
|
|
5387
|
-
} else if (g.s instanceof Literal && g.s.value === 'true') {
|
|
5388
|
-
scopeFacts = [];
|
|
5389
|
-
ensureFactIndexes(scopeFacts);
|
|
5390
|
-
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5391
|
-
scopeBackRules = [];
|
|
5392
|
-
} else {
|
|
5393
|
-
scopeFacts = facts; // dynamic scope
|
|
5394
|
-
}
|
|
5546
|
+
const scopeFacts = g.s.triples.slice();
|
|
5547
|
+
ensureFactIndexes(scopeFacts);
|
|
5548
|
+
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5395
5549
|
|
|
5396
5550
|
const visited2 = [];
|
|
5397
5551
|
// Start from the incoming substitution so bindings flow outward.
|
|
5398
|
-
return proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts,
|
|
5552
|
+
return proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts, [], depth + 1, visited2, varGen);
|
|
5399
5553
|
}
|
|
5400
5554
|
|
|
5401
|
-
// log:notIncludes
|
|
5402
|
-
//
|
|
5555
|
+
// log:notIncludes
|
|
5556
|
+
// Schema: $s+ log:notIncludes $o+
|
|
5403
5557
|
if (pv === LOG_NS + 'notIncludes') {
|
|
5558
|
+
if (!(g.s instanceof GraphTerm)) return [];
|
|
5559
|
+
|
|
5560
|
+
// Empty formula is always included, so it is never "not included".
|
|
5561
|
+
if (g.o instanceof Literal && g.o.value === 'true') return [];
|
|
5404
5562
|
if (!(g.o instanceof GraphTerm)) return [];
|
|
5405
5563
|
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
// If the subject is a formula, treat it as the concrete scope graph
|
|
5410
|
-
if (g.s instanceof GraphTerm) {
|
|
5411
|
-
scopeFacts = g.s.triples.slice();
|
|
5412
|
-
ensureFactIndexes(scopeFacts);
|
|
5413
|
-
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5414
|
-
scopeBackRules = []; // concrete scope = syntactic containment (no extra rules)
|
|
5415
|
-
} else {
|
|
5416
|
-
scopeFacts = facts.__scopedSnapshot || null;
|
|
5417
|
-
if (!scopeFacts) return []; // DELAY until saturation snapshot exists
|
|
5418
|
-
}
|
|
5564
|
+
const scopeFacts = g.s.triples.slice();
|
|
5565
|
+
ensureFactIndexes(scopeFacts);
|
|
5566
|
+
Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
|
|
5419
5567
|
|
|
5420
5568
|
const visited2 = [];
|
|
5421
|
-
const sols = proveGoals(Array.from(g.o.triples), {}, scopeFacts,
|
|
5569
|
+
const sols = proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts, [], depth + 1, visited2, varGen);
|
|
5422
5570
|
return sols.length ? [] : [{ ...subst }];
|
|
5423
5571
|
}
|
|
5424
5572
|
|
|
@@ -5436,7 +5584,6 @@ if (pv === LOG_NS + 'conclusion') {
|
|
|
5436
5584
|
return [{ ...subst }];
|
|
5437
5585
|
}
|
|
5438
5586
|
|
|
5439
|
-
|
|
5440
5587
|
// log:collectAllIn (scoped)
|
|
5441
5588
|
if (pv === LOG_NS + 'collectAllIn') {
|
|
5442
5589
|
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 3) return [];
|
|
@@ -6575,7 +6722,6 @@ function __collectOutputStringsFromFacts(facts, prefixes) {
|
|
|
6575
6722
|
return pairs.map((p) => p.text).join('');
|
|
6576
6723
|
}
|
|
6577
6724
|
|
|
6578
|
-
|
|
6579
6725
|
function main() {
|
|
6580
6726
|
// Drop "node" and script name; keep only user-provided args
|
|
6581
6727
|
const argv = process.argv.slice(2);
|