eyeling 1.10.21 → 1.11.0

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.
Files changed (47) hide show
  1. package/HANDBOOK.md +2 -88
  2. package/eyeling-builtins.ttl +0 -48
  3. package/eyeling.js +67 -314
  4. package/lib/engine.js +67 -309
  5. package/lib/rules.js +0 -5
  6. package/package.json +1 -1
  7. package/test/n3gen.test.js +4 -4
  8. package/test/package.test.js +1 -1
  9. package/tools/n3gen.js +6 -1883
  10. package/examples/bind-builtins.n3 +0 -11
  11. package/examples/bind.n3 +0 -7
  12. package/examples/brussels-brew-club.n3 +0 -119
  13. package/examples/builtins-string-math.n3 +0 -11
  14. package/examples/builtins-triple-termtests.n3 +0 -7
  15. package/examples/family.n3 +0 -10
  16. package/examples/filter-demorgan.n3 +0 -9
  17. package/examples/filter-in-notin.n3 +0 -10
  18. package/examples/filter-nested-or.n3 +0 -10
  19. package/examples/filter.n3 +0 -8
  20. package/examples/input/bind-builtins.srl +0 -30
  21. package/examples/input/bind.srl +0 -12
  22. package/examples/input/builtins-string-math.srl +0 -38
  23. package/examples/input/builtins-triple-termtests.srl +0 -27
  24. package/examples/input/family.srl +0 -12
  25. package/examples/input/filter-demorgan.srl +0 -15
  26. package/examples/input/filter-in-notin.srl +0 -15
  27. package/examples/input/filter-nested-or.srl +0 -15
  28. package/examples/input/filter.srl +0 -9
  29. package/examples/input/snaf.srl +0 -6
  30. package/examples/it-is-about-time.n3 +0 -580
  31. package/examples/json-pointer.n3 +0 -75
  32. package/examples/json-reconcile-vat.n3 +0 -361
  33. package/examples/output/bind-builtins.n3 +0 -9
  34. package/examples/output/bind.n3 +0 -3
  35. package/examples/output/brussels-brew-club.n3 +0 -22
  36. package/examples/output/builtins-string-math.n3 +0 -0
  37. package/examples/output/builtins-triple-termtests.n3 +0 -0
  38. package/examples/output/family.n3 +0 -13
  39. package/examples/output/filter-demorgan.n3 +0 -3
  40. package/examples/output/filter-in-notin.n3 +0 -4
  41. package/examples/output/filter-nested-or.n3 +0 -4
  42. package/examples/output/filter.n3 +0 -3
  43. package/examples/output/it-is-about-time.n3 +0 -0
  44. package/examples/output/json-pointer.n3 +0 -13
  45. package/examples/output/json-reconcile-vat.n3 +0 -226
  46. package/examples/output/snaf.n3 +0 -3
  47. package/examples/snaf.n3 +0 -6
@@ -1,11 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
3
- @prefix string: <http://www.w3.org/2000/10/swap/string#> .
4
- @prefix time: <http://www.w3.org/2000/10/swap/time#> .
5
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
6
- @prefix math: <http://www.w3.org/2000/10/swap/math#> .
7
- @prefix crypto: <http://www.w3.org/2000/10/swap/crypto#> .
8
-
9
- :p1 :givenName "Ada" ; :familyName "Lovelace" ; :born "1815-12-10T00:00:00Z"^^xsd:dateTime .
10
-
11
- { ?p :givenName ?g . ?p :familyName ?f . ?p :born ?d . (?g " " ?f) string:concatenation ?full . (?full " " "_") string:replace ?lbl . (?lbl "en") log:langlit ?lblEn . ?lbl crypto:sha ?h . ?d time:year ?y . (?y 1) math:sum ?__e1 . (?__e1 2) math:product ?z . ("42" xsd:integer) log:dtlit ?i . } => { ?p :label ?lbl ; :labelEn ?lblEn ; :hash ?h ; :birthYear ?y ; :calc ?z ; :intLit ?i . } .
package/examples/bind.n3 DELETED
@@ -1,7 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
- @prefix string: <http://www.w3.org/2000/10/swap/string#> .
4
-
5
- :phayes a :Person ; :givenName "Pat"; :familyName "Hayes" .
6
-
7
- { ?x a :Person . ?SCOPE log:notIncludes { ?x :name ?someName . } . ?x :givenName ?name1 . ?x :familyName ?name2 . (?name1 " " ?name2) string:concatenation ?FN . } => { ?x :name ?FN } .
@@ -1,119 +0,0 @@
1
- # ==================
2
- # Brussels Brew Club
3
- # ==================
4
- #
5
- # A tiny loyalty + compliance reasoner with:
6
- # - JSON profile parsing (rdf:JSON + string:jsonPointer)
7
- # - backward rules (<=) used during forward chaining
8
- # - stable IDs with log:skolem
9
- # - timestamps with time:localTime
10
-
11
- @prefix : <http://example.org/brewclub#> .
12
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
13
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
14
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
15
- @prefix math: <http://www.w3.org/2000/10/swap/math#> .
16
- @prefix string:<http://www.w3.org/2000/10/swap/string#> .
17
- @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
18
-
19
- # ---------------------------
20
- # Deterministic "run context"
21
- # ---------------------------
22
-
23
- :run :now "2000-01-01T00:00:00+00:00"^^xsd:dateTime .
24
-
25
- # -----
26
- # Facts
27
- # -----
28
-
29
- :alice :profileJson """{ "name": "Alice", "age": 23, "city": "Brussels" }"""^^rdf:JSON .
30
- :bob :profileJson """{ "name": "Bob", "age": 16, "city": "Brussels" }"""^^rdf:JSON .
31
-
32
- :order1 a :Order ;
33
- :id "ORD-2025-001" ;
34
- :by :alice ;
35
- :total "31.50"^^xsd:decimal ;
36
- :contains :Espresso, :Croissant .
37
-
38
- :order2 a :Order ;
39
- :id "ORD-2025-002" ;
40
- :by :bob ;
41
- :total "12.00"^^xsd:decimal ;
42
- :contains :HotChocolate .
43
-
44
- :Beer a :AlcoholicDrink .
45
- :Espresso a :Drink .
46
- :HotChocolate a :Drink .
47
- :Croissant a :Food .
48
-
49
- # -----
50
- # Rules
51
- # -----
52
-
53
- # 1) Extract fields from JSON profile into normal triples
54
- {
55
- ?p :profileJson ?j .
56
- (?j "/age") string:jsonPointer ?age .
57
- (?j "/name") string:jsonPointer ?name .
58
- (?j "/city") string:jsonPointer ?city .
59
- }
60
- =>
61
- {
62
- ?p :age ?age ;
63
- :name ?name ;
64
- :city ?city .
65
- }.
66
-
67
- # 2) Backward rule: Adult is defined by age > 17
68
- { ?p a :Adult }
69
- <=
70
- { ?p :age ?a . ?a math:greaterThan 17 }.
71
-
72
- # 3) Backward rule: BigOrder is defined by total > 25.00
73
- { ?o a :BigOrder }
74
- <=
75
- { ?o :total ?t . ?t math:greaterThan "25.00"^^xsd:decimal }.
76
-
77
- # 4) Deterministic membership card rule:
78
- # Uses :run :now ?now instead of time:localTime ?now
79
- {
80
- ?p a :Adult .
81
- ?p :name ?name .
82
- :run :now ?now .
83
-
84
- (?p) log:skolem ?card .
85
- ("Brew Club card for " ?name) string:concatenation ?label .
86
- }
87
- =>
88
- {
89
- ?card a :MembershipCard ;
90
- :holder ?p ;
91
- :issuedAt ?now ;
92
- rdfs:label ?label .
93
- }.
94
-
95
- # 5) Discounts: BigOrder + Adult -> discount eligibility
96
- {
97
- ?o a :Order .
98
- ?o a :BigOrder .
99
- ?o :by ?p .
100
- ?p a :Adult .
101
- }
102
- =>
103
- {
104
- ?o :eligibleDiscount "true"^^xsd:boolean .
105
- }.
106
-
107
- # 6) Stable receipt IRI from the order id
108
- {
109
- ?o a :Order .
110
- ?o :id ?id .
111
- (?id) log:skolem ?receipt .
112
- }
113
- =>
114
- {
115
- ?receipt a :Receipt ;
116
- :forOrder ?o ;
117
- :receiptId ?id .
118
- }.
119
-
@@ -1,11 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
3
- @prefix string: <http://www.w3.org/2000/10/swap/string#> .
4
- @prefix time: <http://www.w3.org/2000/10/swap/time#> .
5
- @prefix math: <http://www.w3.org/2000/10/swap/math#> .
6
-
7
- :x :num 1.2 ;
8
- :txt "Hello World" ;
9
- :dt "2020-01-01T13:14:15Z"^^xsd:dateTime .
10
-
11
- { :x :num ?v . :x :txt ?s . :x :dt ?dt . ?v math:ceiling ?c . ?v math:floor ?f . (?s 1 5) string:substring ?sub . ?s string:length ?len . ?s string:upperCase ?up . ?s string:lowerCase ?lo . ?s string:encodeForURI ?enc . ?dt time:hour ?h . } => { :x :ceil ?c ; :floor ?f ; :substr ?sub ; :strlen ?len ; :ucase ?up ; :lcase ?lo ; :encoded ?enc ; :hours ?h . } .
@@ -1,7 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
-
4
- :alice :knows :bob .
5
- :bob :age 42 .
6
-
7
- { :alice :knows :bob . ?t log:isTriple true . ?s log:isIRI true . ?t log:equalTo { :alice :knows :bob . } . ?t log:includes { ?s ?__e2 ?__e3 . } . ?t log:includes { ?__e4 ?p ?__e6 . } . ?t log:includes { ?__e7 ?__e8 ?o . } . } => { :test :triple ?t ; :subject ?s ; :predicate ?p ; :object ?o ; :subjectIsIRI true ; :tripleOk true . } .
@@ -1,10 +0,0 @@
1
- @prefix : <http://example.org/#> .
2
-
3
- :A :fatherOf :X . :B :motherOf :X . :C :motherOf :A .
4
-
5
- { ?y :fatherOf ?x . } => { ?x :childOf ?y } .
6
- { ?y :motherOf ?x . } => { ?x :childOf ?y } .
7
- { ?x :childOf ?y . } => { ?x :descendedFrom ?y } .
8
- { ?x :childOf ?z . ?z :childOf ?y . } => { ?x :descendedFrom ?y } .
9
- { ?y :descendedFrom ?x . } => { ?x :ancestorOf ?y } .
10
- { ?a :ancestorOf ?c . ?c :ancestorOf ?b . } => { ?a :ancestorOf ?b } .
@@ -1,9 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix string: <http://www.w3.org/2000/10/swap/string#> .
3
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
4
-
5
- :alice :name "Alice" .
6
- :bob :name "Bob" .
7
- :eve :name "Eve" .
8
-
9
- { ?p :name ?n . ?SCOPE log:notIncludes { ?n string:contains "o" . } . ?SCOPE log:notIncludes { ?n string:startsWith "E" . } . } => { ?p :passesNameFilter true . } .
@@ -1,10 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
- @prefix list: <http://www.w3.org/2000/10/swap/list#> .
4
-
5
- :a :score 1 .
6
- :b :score 2 .
7
- :c :score 3 .
8
- :d :score 4 .
9
-
10
- { ?x :score ?s . ?s list:in (1 3 5) . ?SCOPE log:notIncludes { ?s list:in (2 4) . } . } => { ?x :isSpecial true . } .
@@ -1,10 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix math: <http://www.w3.org/2000/10/swap/math#> .
3
- @prefix string: <http://www.w3.org/2000/10/swap/string#> .
4
-
5
- :bob :age 20 ; :name "Bob" .
6
- :alice :age 15 ; :name "Alice" .
7
- :bea :age 22 ; :name "Bea" .
8
-
9
- { ?p :age ?age . ?p :name ?name . ?age math:notLessThan 18 . ?name string:startsWith "A" . } => { ?p :adultNamedByRule true . } .
10
- { ?p :age ?age . ?p :name ?name . ?age math:notLessThan 18 . ?name string:matches "^B" . } => { ?p :adultNamedByRule true . } .
@@ -1,8 +0,0 @@
1
- @prefix : <http://example/#> .
2
- @prefix math: <http://www.w3.org/2000/10/swap/math#> .
3
-
4
- :x :p 1 ; :q 2 .
5
-
6
- { ?x :p ?v1 . ?x :q ?v2 . ?v1 math:greaterThan 0 . ?v2 math:greaterThan 0 . } => { ?x :bothPositive true . } .
7
- { ?x :p ?v1 . ?x :q ?v2 . ?v1 math:equalTo 0 . } => { ?x :oneIsZero true . } .
8
- { ?x :p ?v1 . ?x :q ?v2 . ?v2 math:equalTo 0 . } => { ?x :oneIsZero true . } .
@@ -1,30 +0,0 @@
1
- PREFIX : <http://example/#>
2
- PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
3
-
4
- DATA {
5
- # NOTE: Eyeling's time:* extractors currently operate on xsd:dateTime (not xsd:date).
6
- :p1 :givenName "Ada" ; :familyName "Lovelace" ; :born "1815-12-10T00:00:00Z"^^xsd:dateTime .
7
- }
8
-
9
- # Demonstrates BIND compilation to N3 builtins:
10
- # - concat/replace (string:)
11
- # - sha1 (crypto:)
12
- # - year (time:)
13
- # - arithmetic (+,*) (math:)
14
- # - strlang/strdt (log:)
15
- RULE {
16
- ?p :label ?lbl ; :labelEn ?lblEn ; :hash ?h ; :birthYear ?y ; :calc ?z ; :intLit ?i .
17
- }
18
- WHERE {
19
- ?p :givenName ?g ; :familyName ?f ; :born ?d .
20
-
21
- BIND(concat(?g, " ", ?f) AS ?full)
22
- BIND(replace(?full, " ", "_") AS ?lbl)
23
- BIND(strlang(?lbl, "en") AS ?lblEn)
24
- BIND(sha1(?lbl) AS ?h)
25
-
26
- BIND(year(?d) AS ?y)
27
- BIND((?y + 1) * 2 AS ?z)
28
-
29
- BIND(strdt("42", xsd:integer) AS ?i)
30
- }
@@ -1,12 +0,0 @@
1
- PREFIX : <http://example/#>
2
-
3
- DATA { :phayes a :Person ; :givenName "Pat"; :familyName "Hayes" . }
4
-
5
- # Default value - calculate a name
6
- RULE { ?x :name ?FN } WHERE {
7
- ?x a :Person
8
- NOT { ?x :name ?someName }
9
- ?x :givenName ?name1 ;
10
- :familyName ?name2 .
11
- BIND(concat(?name1, " ", ?name2) AS ?FN)
12
- }
@@ -1,38 +0,0 @@
1
- PREFIX : <http://example/#>
2
- PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
3
-
4
- DATA {
5
- :x :num 1.2 ;
6
- :txt "Hello World" ;
7
- :dt "2020-01-01T13:14:15Z"^^xsd:dateTime .
8
- }
9
-
10
- RULE {
11
- :x :ceil ?c ;
12
- :floor ?f ;
13
- :substr ?sub ;
14
- :strlen ?len ;
15
- :ucase ?up ;
16
- :lcase ?lo ;
17
- :encoded ?enc ;
18
- :hours ?h .
19
- }
20
- WHERE {
21
- :x :num ?v ;
22
- :txt ?s ;
23
- :dt ?dt .
24
-
25
- BIND(CEIL(?v) AS ?c)
26
- BIND(FLOOR(?v) AS ?f)
27
-
28
- # SPARQL SUBSTR is 1-based; this should produce "Hello"
29
- BIND(SUBSTR(?s, 1, 5) AS ?sub)
30
-
31
- BIND(STRLEN(?s) AS ?len)
32
- BIND(UCASE(?s) AS ?up)
33
- BIND(LCASE(?s) AS ?lo)
34
- BIND(ENCODE_FOR_URI(?s) AS ?enc)
35
-
36
- BIND(HOURS(?dt) AS ?h)
37
- }
38
-
@@ -1,27 +0,0 @@
1
- PREFIX : <http://example/#>
2
-
3
- DATA {
4
- :alice :knows :bob .
5
- :bob :age 42 .
6
- }
7
-
8
- RULE {
9
- :test :triple ?t ;
10
- :subject ?s ;
11
- :predicate ?p ;
12
- :object ?o ;
13
- :subjectIsIRI true ;
14
- :tripleOk true .
15
- }
16
- WHERE {
17
- :alice :knows :bob .
18
-
19
- BIND(TRIPLE(:alice, :knows, :bob) AS ?t)
20
- BIND(SUBJECT(?t) AS ?s)
21
- BIND(PREDICATE(?t) AS ?p)
22
- BIND(OBJECT(?t) AS ?o)
23
-
24
- # Term-test builtins (as in SPARQL)
25
- FILTER ( isTRIPLE(?t) && isIRI(?s) )
26
- }
27
-
@@ -1,12 +0,0 @@
1
- PREFIX : <http://example.org/#>
2
-
3
- DATA { :A :fatherOf :X . :B :motherOf :X . :C :motherOf :A . }
4
-
5
- RULE { ?x :childOf ?y } WHERE { ?y :fatherOf ?x }
6
- RULE { ?x :childOf ?y } WHERE { ?y :motherOf ?x }
7
-
8
- RULE { ?x :descendedFrom ?y } WHERE { ?x :childOf ?y }
9
- RULE { ?x :descendedFrom ?y } WHERE { ?x :childOf ?z . ?z :childOf ?y }
10
-
11
- RULE { ?x :ancestorOf ?y } WHERE { ?y :descendedFrom ?x }
12
- RULE { ?a :ancestorOf ?b } WHERE { ?a :ancestorOf ?c . ?c :ancestorOf ?b }
@@ -1,15 +0,0 @@
1
- PREFIX : <http://example/#>
2
-
3
- DATA {
4
- :alice :name "Alice" .
5
- :bob :name "Bob" .
6
- :eve :name "Eve" .
7
- }
8
-
9
- # Demonstrates De Morgan push-down:
10
- # !(A || B) ==> (!A && !B)
11
- RULE { ?p :passesNameFilter true . }
12
- WHERE {
13
- ?p :name ?n .
14
- FILTER ( !( CONTAINS(?n, "o") || STRSTARTS(?n, "E") ) )
15
- }
@@ -1,15 +0,0 @@
1
- PREFIX : <http://example/#>
2
-
3
- DATA {
4
- :a :score 1 .
5
- :b :score 2 .
6
- :c :score 3 .
7
- :d :score 4 .
8
- }
9
-
10
- # Demonstrates IN/NOT IN (mapped to list:in + log:notIncludes)
11
- RULE { ?x :isSpecial true . }
12
- WHERE {
13
- ?x :score ?s .
14
- FILTER ( (?s IN (1, 3, 5)) && (?s NOT IN (2, 4)) )
15
- }
@@ -1,15 +0,0 @@
1
- PREFIX : <http://example/#>
2
-
3
- DATA {
4
- :bob :age 20 ; :name "Bob" .
5
- :alice :age 15 ; :name "Alice" .
6
- :bea :age 22 ; :name "Bea" .
7
- }
8
-
9
- # Demonstrates nested OR distribution:
10
- # ?age >= 18 && ( STRSTARTS(?name,"A") || REGEX(?name,"^B") )
11
- RULE { ?p :adultNamedByRule true . }
12
- WHERE {
13
- ?p :age ?age ; :name ?name .
14
- FILTER ( ?age >= 18 && ( STRSTARTS(?name, "A") || REGEX(?name, "^B") ) )
15
- }
@@ -1,9 +0,0 @@
1
- PREFIX : <http://example/#>
2
-
3
- DATA { :x :p 1 ; :q 2 . }
4
-
5
- RULE { ?x :bothPositive true . }
6
- WHERE { ?x :p ?v1 FILTER ( ?v1 > 0 ) ?x :q ?v2 FILTER ( ?v2 > 0 ) }
7
-
8
- RULE { ?x :oneIsZero true . }
9
- WHERE { ?x :p ?v1 ; :q ?v2 FILTER ( ( ?v1 = 0 ) || ( ?v2 = 0 ) ) }
@@ -1,6 +0,0 @@
1
- PREFIX log: <http://www.w3.org/2000/10/swap/log#>
2
- PREFIX : <http://example.org/#>
3
-
4
- DATA { :Alice :loves :Bob. :Bob a :Person. }
5
-
6
- RULE { :Alice :hates :Nobody. } WHERE { NOT { :Alice :hates ?X } ?X a :Person. }