eyeling 1.6.9 → 1.6.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/eyeling.js +67 -5
- package/package.json +1 -1
package/eyeling.js
CHANGED
|
@@ -36,6 +36,12 @@ const STRING_NS = 'http://www.w3.org/2000/10/swap/string#';
|
|
|
36
36
|
const SKOLEM_NS = 'https://eyereasoner.github.io/.well-known/genid/';
|
|
37
37
|
const RDF_JSON_DT = RDF_NS + 'JSON';
|
|
38
38
|
|
|
39
|
+
function resolveIriRef(ref, base) {
|
|
40
|
+
if (!base) return ref;
|
|
41
|
+
if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(ref)) return ref; // already absolute
|
|
42
|
+
try { return new URL(ref, base).toString(); } catch { return ref; }
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
function isRdfJsonDatatype(dt) {
|
|
40
46
|
// dt comes from literalParts() and may be expanded or prefixed depending on parsing/printing.
|
|
41
47
|
return dt === null || dt === RDF_JSON_DT || dt === 'rdf:JSON';
|
|
@@ -864,9 +870,9 @@ class Parser {
|
|
|
864
870
|
}
|
|
865
871
|
|
|
866
872
|
if (typ === 'IriRef') {
|
|
867
|
-
|
|
873
|
+
const base = this.prefixes.map[''] || '';
|
|
874
|
+
return new Iri(resolveIriRef(val || '', base));
|
|
868
875
|
}
|
|
869
|
-
|
|
870
876
|
if (typ === 'Ident') {
|
|
871
877
|
const name = val || '';
|
|
872
878
|
if (name === 'a') {
|
|
@@ -4065,6 +4071,61 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4065
4071
|
return [{ ...subst }];
|
|
4066
4072
|
}
|
|
4067
4073
|
|
|
4074
|
+
// log:dtlit
|
|
4075
|
+
// Schema: ( $s.1? $s.2? )? log:dtlit $o?
|
|
4076
|
+
// true iff $o is a datatyped literal with string value $s.1 and datatype IRI $s.2
|
|
4077
|
+
if (g.p instanceof Iri && g.p.value === LOG_NS + 'dtlit') {
|
|
4078
|
+
// Fully unbound (both arguments '?'-mode): treat as satisfiable, succeed once.
|
|
4079
|
+
// Required by notation3tests "success-fullUnbound-*".
|
|
4080
|
+
if (g.s instanceof Var && g.o instanceof Var) return [{ ...subst }];
|
|
4081
|
+
|
|
4082
|
+
const results = [];
|
|
4083
|
+
|
|
4084
|
+
// Direction 1: object literal -> subject list (string, datatype)
|
|
4085
|
+
if (g.o instanceof Literal) {
|
|
4086
|
+
const [oLex, oDt0] = literalParts(g.o.value);
|
|
4087
|
+
let oDt = oDt0;
|
|
4088
|
+
|
|
4089
|
+
// literalParts() strips @lang into the lexical part and leaves dt null,
|
|
4090
|
+
// but RDF 1.1 language-tagged strings have datatype rdf:langString.
|
|
4091
|
+
if (oDt === null) {
|
|
4092
|
+
if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
|
|
4093
|
+
else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
|
|
4094
|
+
}
|
|
4095
|
+
|
|
4096
|
+
if (oDt !== null) {
|
|
4097
|
+
const strLit = isQuotedLexical(oLex) ? new Literal(oLex) : makeStringLiteral(String(oLex));
|
|
4098
|
+
const subjList = new ListTerm([strLit, new Iri(oDt)]);
|
|
4099
|
+
const s2 = unifyTerm(goal.s, subjList, subst);
|
|
4100
|
+
if (s2 !== null) results.push(s2);
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
// Direction 2: subject list -> object literal
|
|
4105
|
+
if (g.s instanceof ListTerm && g.s.elems.length === 2) {
|
|
4106
|
+
const a = g.s.elems[0];
|
|
4107
|
+
const b = g.s.elems[1];
|
|
4108
|
+
|
|
4109
|
+
if (a instanceof Literal && b instanceof Iri) {
|
|
4110
|
+
const [sLex, sDt0] = literalParts(a.value);
|
|
4111
|
+
|
|
4112
|
+
// $s.1 must be xsd:string (plain or ^^xsd:string), not language-tagged.
|
|
4113
|
+
const okString =
|
|
4114
|
+
(sDt0 === null && isPlainStringLiteralValue(a.value)) || sDt0 === XSD_NS + 'string';
|
|
4115
|
+
if (okString) {
|
|
4116
|
+
const dtIri = b.value;
|
|
4117
|
+
// For xsd:string, prefer the plain string literal form.
|
|
4118
|
+
const outLit =
|
|
4119
|
+
dtIri === XSD_NS + 'string' ? new Literal(sLex) : new Literal(`${sLex}^^<${dtIri}>`);
|
|
4120
|
+
const s2 = unifyTerm(goal.o, outLit, subst);
|
|
4121
|
+
if (s2 !== null) results.push(s2);
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
|
|
4126
|
+
return results;
|
|
4127
|
+
}
|
|
4128
|
+
|
|
4068
4129
|
// log:implies — expose internal forward rules as data
|
|
4069
4130
|
if (g.p instanceof Iri && g.p.value === LOG_NS + 'implies') {
|
|
4070
4131
|
const allFw = backRules.__allForwardRules || [];
|
|
@@ -4241,9 +4302,10 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4241
4302
|
return s2 !== null ? [s2] : [];
|
|
4242
4303
|
}
|
|
4243
4304
|
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
return [];
|
|
4305
|
+
const sOk = (g.s instanceof Var) || (g.s instanceof Blank) || (g.s instanceof Iri);
|
|
4306
|
+
const oOk = (g.o instanceof Var) || (g.o instanceof Blank) || (g.o instanceof Literal);
|
|
4307
|
+
if (!sOk || !oOk) return [];
|
|
4308
|
+
return [{ ...subst }];
|
|
4247
4309
|
}
|
|
4248
4310
|
|
|
4249
4311
|
// -----------------------------------------------------------------
|