eyeleng 1.0.5 → 1.0.7
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 +311 -11
- package/dist/browser/eyeleng.browser.js +2649 -1162
- package/examples/output/collection-nesting.trig +1 -1
- package/examples/output/rdf-messages.trig +3 -0
- package/examples/rdf-messages.srl +15 -0
- package/examples/rdf-messages.trig +12 -0
- package/eyeleng.js +2631 -1138
- package/package.json +9 -2
- package/playground.html +1 -1
- package/reports/w3c-rdf-earl.ttl +11707 -0
- package/reports/w3c-shacl12-rules-earl.ttl +1055 -1336
- package/src/api.js +4 -0
- package/src/cli.js +6 -0
- package/src/parser.js +171 -3
- package/src/rdfEntailment.js +571 -0
- package/src/rdfManifest.js +737 -0
- package/src/rdfMessages.js +321 -0
- package/src/rdfSyntax.js +955 -0
- package/src/shacl12RulesManifest.js +386 -0
- package/src/tokenizer.js +47 -11
- package/test/api.test.js +95 -0
- package/test/harness.js +38 -10
- package/test/run.js +6 -3
- package/test/shacl12-rules.test.js +40 -217
- package/test/w3c-rdf.test.js +205 -0
- package/tools/browser-bundle.js +0 -0
- package/tools/bundle.js +0 -0
- package/tools/w3c-rdf.js +55 -0
- package/tools/w3c-shacl12-rules.js +55 -0
- package/HANDBOOK.md +0 -1070
package/README.md
CHANGED
|
@@ -3,30 +3,330 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/eyeleng)
|
|
4
4
|
[](https://doi.org/10.5281/zenodo.20342577)
|
|
5
5
|
|
|
6
|
-
`eyeleng` stands for **EYE Logic Engine**.
|
|
6
|
+
`eyeleng` stands for **EYE Logic Engine**. It is a compact JavaScript implementation of SHACL 1.2 Rules with two rule front-ends:
|
|
7
|
+
|
|
8
|
+
- **SRL** — the Shape Rules Language syntax used by the SHACL 1.2 Rules draft.
|
|
9
|
+
- **RDF Rules** — a Turtle/RDF syntax for rule sets.
|
|
10
|
+
|
|
11
|
+
Eyeleng is a forward-chaining reasoner over RDF-style triples. It is deliberately small, dependency-free at runtime, readable as ordinary JavaScript, and usable from the CLI, Node.js, and the browser playground.
|
|
12
|
+
|
|
13
|
+
Eyeleng implements the rules/reasoning surface. It is **not** a SHACL validation engine and does not emit SHACL validation reports.
|
|
7
14
|
|
|
8
15
|
## Quick start
|
|
9
16
|
|
|
10
17
|
```sh
|
|
18
|
+
npm install
|
|
11
19
|
npm test
|
|
12
20
|
./eyeleng.js examples/family.srl
|
|
13
|
-
./eyeleng.js examples/
|
|
14
|
-
./eyeleng.js examples/deep-taxonomy-100.srl
|
|
21
|
+
./eyeleng.js --all examples/family.srl
|
|
15
22
|
./eyeleng.js examples/basic-ruleset.ttl
|
|
16
|
-
./eyeleng.js --syntax rdf examples/w3c-rule-set-snippet.ttl
|
|
17
23
|
./eyeleng.js --check --deps examples/stratified-negation.srl
|
|
18
24
|
```
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
A minimal SRL program:
|
|
27
|
+
|
|
28
|
+
```srl
|
|
29
|
+
PREFIX : <http://example/>
|
|
30
|
+
|
|
31
|
+
DATA {
|
|
32
|
+
:Socrates a :Man .
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
RULE { ?x a :Mortal } WHERE { ?x a :Man }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
It derives:
|
|
39
|
+
|
|
40
|
+
```srl
|
|
41
|
+
:Socrates a :Mortal .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Open the [Playground](https://eyereasoner.github.io/eyeleng/playground) for a self-contained browser UI with URL loading, autosave, share links, diagnostics, queries, and SRL/RDF Rules syntax selection.
|
|
45
|
+
|
|
46
|
+
## How the reasoner works
|
|
47
|
+
|
|
48
|
+
Eyeleng computes the closure of a rule set:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
parse source
|
|
52
|
+
analyze dependencies and strata
|
|
53
|
+
match rule bodies against known triples
|
|
54
|
+
instantiate rule heads
|
|
55
|
+
add new triples
|
|
56
|
+
repeat until stable
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
A rule has a body and a head:
|
|
60
|
+
|
|
61
|
+
```srl
|
|
62
|
+
RULE { ?child :childOf ?parent } WHERE { ?parent :parentOf ?child }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If the graph contains:
|
|
66
|
+
|
|
67
|
+
```srl
|
|
68
|
+
:alice :parentOf :bob .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
then the body matches with `?parent = :alice` and `?child = :bob`, and the head derives:
|
|
72
|
+
|
|
73
|
+
```srl
|
|
74
|
+
:bob :childOf :alice .
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Negation is handled by stratified evaluation: rules are grouped into dependency layers, and recursion through negation is rejected so the result stays deterministic.
|
|
78
|
+
|
|
79
|
+
## Language surface
|
|
80
|
+
|
|
81
|
+
SRL supports the practical rule features used by the SHACL 1.2 Rules tests and examples:
|
|
82
|
+
|
|
83
|
+
```srl
|
|
84
|
+
PREFIX : <http://example/>
|
|
85
|
+
|
|
86
|
+
DATA {
|
|
87
|
+
:alice :score 7 .
|
|
88
|
+
:bob :score 3 .
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
RULE { ?x :grade ?grade } WHERE {
|
|
92
|
+
?x :score ?score .
|
|
93
|
+
FILTER(?score >= 5) .
|
|
94
|
+
BIND(concat("pass-", str(?score)) AS ?grade)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
RULE { ?x :eligible true } WHERE {
|
|
98
|
+
?x :grade ?grade .
|
|
99
|
+
NOT { ?x :blocked true . }
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Implemented syntax includes:
|
|
104
|
+
|
|
105
|
+
- `PREFIX`, `BASE`, `VERSION`, and `IMPORTS`
|
|
106
|
+
- `DATA`, `RULE`, `WHERE`, `FILTER`, `BIND`, `SET`, and `NOT`
|
|
107
|
+
- variables such as `?x`
|
|
108
|
+
- IRIs, prefixed names, blank nodes, literals, RDF collections, and RDF 1.2 triple terms
|
|
109
|
+
- Turtle-style `;`, `,`, `a`, blank-node property lists, lists, annotations, and reifiers where supported
|
|
110
|
+
- property paths in rule bodies
|
|
111
|
+
- language tags, base-direction literals, and common XML Schema datatypes
|
|
112
|
+
- SRL and RDF Rules syntax front-ends
|
|
113
|
+
|
|
114
|
+
The RDF parsing path is shared with the W3C RDF syntax harness, so SRL `DATA { ... }` uses the same grammar-hardened RDF parser surface as Turtle/TriG input.
|
|
115
|
+
|
|
116
|
+
## Builtins and expressions
|
|
117
|
+
|
|
118
|
+
`FILTER`, `BIND`, and `SET` use expression evaluation. Supported operations include comparisons, boolean operators, arithmetic, `IN`, `NOT IN`, datatype/language checks, string functions, numeric functions, and selected date/time helpers.
|
|
119
|
+
|
|
120
|
+
Common builtins include:
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
str, concat, lcase, ucase, replace
|
|
124
|
+
abs, round, floor, ceil
|
|
125
|
+
datatype, lang, iri, uri
|
|
126
|
+
now, year, month, day
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The goal is useful SHACL Rules/SRL behavior, not complete SPARQL expression coverage.
|
|
130
|
+
|
|
131
|
+
## RDF 1.2 features
|
|
132
|
+
|
|
133
|
+
Eyeleng includes grammar-hardened RDF 1.1/1.2 parsing support in `src/rdfSyntax.js` and W3C manifest runners in `src/rdfManifest.js` / `src/rdfEntailment.js`.
|
|
134
|
+
|
|
135
|
+
Covered surfaces include:
|
|
136
|
+
|
|
137
|
+
- N-Triples and N-Quads
|
|
138
|
+
- Turtle and TriG
|
|
139
|
+
- RDF 1.2 triple terms
|
|
140
|
+
- reifiers and annotation blocks
|
|
141
|
+
- language-direction literals
|
|
142
|
+
- graph isomorphism for blank nodes
|
|
143
|
+
- simple, RDF, and RDFS entailment checks for RDF-MT / RDF 1.2 Semantics manifests
|
|
144
|
+
|
|
145
|
+
W3C checks:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
npm run w3c:rules
|
|
149
|
+
npm run w3c:rdf
|
|
150
|
+
npm run w3c:all
|
|
151
|
+
npm run w3c:rdf:json
|
|
152
|
+
npm run w3c:rdf:earl
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`npm test` includes the W3C harnesses. When W3C URLs are reachable, progress is printed test by test. In offline environments, remote W3C checks are reported as unreachable unless `EYELENG_W3C_REQUIRED=1` is set.
|
|
156
|
+
|
|
157
|
+
The official Eyeleng EARL 1.0 report for the W3C SHACL 1.2 Rules manifest is in [reports/w3c-shacl12-rules-earl.ttl](./reports/w3c-shacl12-rules-earl.ttl).
|
|
158
|
+
|
|
159
|
+
## RDF Message Logs
|
|
21
160
|
|
|
22
|
-
|
|
161
|
+
Eyeleng can parse RDF Message Logs with Eyeling-compatible message delimiters and expose a replay view under the `eymsg:` vocabulary. A message log starts with `VERSION "1.2-messages"` and separates payloads with `MESSAGE` or `@message .`.
|
|
23
162
|
|
|
24
|
-
|
|
163
|
+
```trig
|
|
164
|
+
VERSION "1.2-messages"
|
|
165
|
+
PREFIX : <http://example/messages#>
|
|
25
166
|
|
|
26
|
-
|
|
167
|
+
_:reading :sensor :s1 .
|
|
168
|
+
MESSAGE
|
|
169
|
+
# empty heartbeat
|
|
170
|
+
MESSAGE
|
|
171
|
+
_:reading :sensor :s2 .
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Use message logs directly, import them from SRL, or force message-log parsing from the CLI:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
./eyeleng.js examples/rdf-messages.srl
|
|
178
|
+
./eyeleng.js --rdf-messages --all examples/rdf-messages.trig
|
|
179
|
+
./eyeleng.js --stream-messages --all examples/rdf-messages.trig
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The replay data includes message streams, envelopes, offsets, next-envelope links, payload kind, payload graph, and `eymsg:payloadTriple` triple terms. Blank-node labels are scoped per message. For Eyeleng, each payload graph is also represented as a closed RDF list of RDF 1.2 triple terms via `log:nameOf`.
|
|
183
|
+
|
|
184
|
+
## CLI
|
|
185
|
+
|
|
186
|
+
Common commands:
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
./eyeleng.js examples/family.srl
|
|
190
|
+
./eyeleng.js --all examples/family.srl
|
|
191
|
+
./eyeleng.js --check --deps examples/stratified-negation.srl
|
|
192
|
+
./eyeleng.js --json --trace --stats examples/if-then.srl
|
|
193
|
+
./eyeleng.js --query-file examples/query-body.txt examples/query.srl
|
|
194
|
+
./eyeleng.js --syntax rdf examples/w3c-rule-set-snippet.ttl
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Important options:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
--all print input and inferred triples
|
|
201
|
+
--check parse and analyze only
|
|
202
|
+
--strict warnings become fatal
|
|
203
|
+
--deps print dependency edges and layers
|
|
204
|
+
--trace show rule firings
|
|
205
|
+
--stats show iteration and rule counts
|
|
206
|
+
--json structured output
|
|
207
|
+
--query run a raw body pattern over the closure
|
|
208
|
+
--query-file FILE read a query body from a file
|
|
209
|
+
--max-iterations N recursive-layer fixpoint safety guard
|
|
210
|
+
--no-imports parse imports but do not load them
|
|
211
|
+
--rdf-messages parse input as an RDF Message Log
|
|
212
|
+
--stream-messages replay RDF Message Log envelopes
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Public API
|
|
216
|
+
|
|
217
|
+
Typical API use:
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
const { run, formatTriples } = require('./src/index.js');
|
|
221
|
+
|
|
222
|
+
const result = run(`
|
|
223
|
+
PREFIX : <http://example/>
|
|
224
|
+
DATA { :Socrates a :Man . }
|
|
225
|
+
RULE { ?x a :Mortal } WHERE { ?x a :Man }
|
|
226
|
+
`);
|
|
227
|
+
|
|
228
|
+
console.log(formatTriples(result.inferred, result.prefixes));
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Query mode:
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
const { runQuery, formatBindings } = require('./src/index.js');
|
|
235
|
+
|
|
236
|
+
const result = runQuery(source, '?x :ancestorOf ?y');
|
|
237
|
+
console.log(formatBindings(result.query.bindings, result.prefixes));
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Imports:
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
const result = run(source, {
|
|
244
|
+
baseIRI: 'file:///main.srl',
|
|
245
|
+
importResolver(target) {
|
|
246
|
+
return {
|
|
247
|
+
source: readSomehow(target),
|
|
248
|
+
options: { baseIRI: target, filename: target }
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The API returns structured parsed programs, diagnostics, inferred triples, closure triples, traces, stats, and query bindings.
|
|
255
|
+
|
|
256
|
+
## Project layout
|
|
257
|
+
|
|
258
|
+
```text
|
|
259
|
+
src/tokenizer.js source text -> tokens
|
|
260
|
+
src/parser.js SRL parser -> program object
|
|
261
|
+
src/rdfSyntax.js RDF 1.1/1.2 N-Triples/N-Quads/Turtle/TriG syntax
|
|
262
|
+
src/rdfManifest.js W3C RDF manifest runner
|
|
263
|
+
src/rdfEntailment.js simple/RDF/RDFS entailment checks
|
|
264
|
+
src/rdfMessages.js RDF Message Log replay support
|
|
265
|
+
src/term.js terms, keys, equality, formatting
|
|
266
|
+
src/store.js triple set, predicate index, matching, paths
|
|
267
|
+
src/builtins.js expression evaluation and built-in functions
|
|
268
|
+
src/analyze.js diagnostics, dependencies, strata
|
|
269
|
+
src/engine.js layered forward-chaining evaluator
|
|
270
|
+
src/query.js external raw-body query operation
|
|
271
|
+
src/format.js text and JSON output
|
|
272
|
+
src/api.js public JavaScript API and import merging
|
|
273
|
+
src/cli.js command-line interface
|
|
274
|
+
tools/bundle.js self-contained bundle generator
|
|
275
|
+
test/*.test.js executable regression and conformance tests
|
|
276
|
+
examples/*.srl runnable SRL examples
|
|
277
|
+
examples/*.ttl RDF Rules / Turtle examples
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
A good reading order is `term.js`, `tokenizer.js`, `parser.js`, `rdfSyntax.js`, `store.js`, `builtins.js`, `analyze.js`, `engine.js`, then `api.js` and `cli.js`.
|
|
281
|
+
|
|
282
|
+
## Tests and build
|
|
283
|
+
|
|
284
|
+
```sh
|
|
285
|
+
npm test
|
|
286
|
+
npm run build
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
`npm run build` writes the command-line bundle to `eyeleng.js` and the browser API bundle to `dist/browser/eyeleng.browser.js`. In a browser, the bundle exposes `window.eyeleng`.
|
|
290
|
+
|
|
291
|
+
The tests are executable documentation. They cover parsing, recursion, filters, negation, assignment, typed/language literals, RDF 1.2 syntax, property paths, stratification, imports, queries, examples, deep taxonomy benchmarks, W3C SHACL Rules, W3C RDF syntax, and RDF/RDFS entailment.
|
|
292
|
+
|
|
293
|
+
## Examples
|
|
294
|
+
|
|
295
|
+
Examples live in [examples/](./examples/):
|
|
296
|
+
|
|
297
|
+
- `family.srl` — small recursive rules
|
|
298
|
+
- `negation.srl` — stratified negation
|
|
299
|
+
- `assignment.srl` — assignment and expressions
|
|
300
|
+
- `property-paths.srl` — path matching in bodies
|
|
301
|
+
- `basic-ruleset.ttl` — RDF Rules syntax
|
|
302
|
+
- `rdf-messages.srl` / `rdf-messages.trig` — RDF Message Log replay
|
|
303
|
+
- `deep-taxonomy-*.srl` — generated benchmark programs
|
|
304
|
+
|
|
305
|
+
## Known boundaries
|
|
306
|
+
|
|
307
|
+
Eyeleng intentionally remains a compact reasoner:
|
|
308
|
+
|
|
309
|
+
- it does not implement SHACL validation or validation reports
|
|
310
|
+
- it does not aim to be a full RDF database
|
|
311
|
+
- RDF Rules syntax support is a front-end for rule execution, not a shapes-validation layer
|
|
312
|
+
- property paths and SPARQL expressions are practical subsets
|
|
313
|
+
- W3C manifests are used as executable alignment tests, but implementation status should be read from the current test reports
|
|
314
|
+
|
|
315
|
+
## Extending Eyeleng safely
|
|
316
|
+
|
|
317
|
+
Preserve the pipeline:
|
|
318
|
+
|
|
319
|
+
```text
|
|
320
|
+
syntax -> AST/program -> analysis -> evaluation -> formatting
|
|
321
|
+
```
|
|
27
322
|
|
|
28
|
-
|
|
323
|
+
Avoid making the evaluator parse strings. Parsing belongs in `parser.js` or `rdfSyntax.js`. Avoid making the parser derive triples. Inference belongs in `engine.js`.
|
|
29
324
|
|
|
30
|
-
|
|
325
|
+
A safe extension usually needs:
|
|
31
326
|
|
|
32
|
-
|
|
327
|
+
1. syntax support
|
|
328
|
+
2. one focused example
|
|
329
|
+
3. parser/API tests
|
|
330
|
+
4. execution tests
|
|
331
|
+
5. README or handbook notes
|
|
332
|
+
6. bundle regeneration
|