eyeling 1.5.12 → 1.5.14

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 (96) hide show
  1. package/README.md +1 -2
  2. package/examples/age.n3 +29 -0
  3. package/examples/backward.n3 +24 -0
  4. package/examples/basic-monadic.n3 +10032 -0
  5. package/examples/cat-koko.n3 +29 -0
  6. package/examples/collect-all-in.n3 +32 -0
  7. package/examples/complex.n3 +142 -0
  8. package/examples/control-system.n3 +77 -0
  9. package/examples/crypto-builtins-tests.n3 +60 -0
  10. package/examples/deep-taxonomy-10.n3 +21 -0
  11. package/examples/deep-taxonomy-100.n3 +111 -0
  12. package/examples/deep-taxonomy-1000.n3 +1011 -0
  13. package/examples/deep-taxonomy-10000.n3 +10011 -0
  14. package/examples/derived-backward-rule-2.n3 +28 -0
  15. package/examples/derived-backward-rule.n3 +32 -0
  16. package/examples/derived-rule.n3 +19 -0
  17. package/examples/dijkstra.n3 +64 -0
  18. package/examples/dog.n3 +21 -0
  19. package/examples/equals.n3 +12 -0
  20. package/examples/existential-rule.n3 +18 -0
  21. package/examples/fibonacci.n3 +34 -0
  22. package/examples/for-all-in.n3 +21 -0
  23. package/examples/french-cities.n3 +32 -0
  24. package/examples/fuse.n3 +13 -0
  25. package/examples/good-cobbler.n3 +18 -0
  26. package/examples/gray-code-counter.n3 +64 -0
  27. package/examples/hanoi.n3 +21 -0
  28. package/examples/liar.n3 +6 -0
  29. package/examples/list-builtins-tests.n3 +84 -0
  30. package/examples/lldm.n3 +133 -0
  31. package/examples/math-builtins-tests.n3 +612 -0
  32. package/examples/monkey.n3 +11 -0
  33. package/examples/output/age.n3 +20 -0
  34. package/examples/output/backward.n3 +18 -0
  35. package/examples/output/basic-monadic.n3 +122 -0
  36. package/examples/output/cat-koko.n3 +125 -0
  37. package/examples/output/collect-all-in.n3 +122 -0
  38. package/examples/output/complex.n3 +57 -0
  39. package/examples/output/control-system.n3 +79 -0
  40. package/examples/output/crypto-builtins-tests.n3 +66 -0
  41. package/examples/output/deep-taxonomy-10.n3 +636 -0
  42. package/examples/output/deep-taxonomy-100.n3 +6036 -0
  43. package/examples/output/deep-taxonomy-1000.n3 +60036 -0
  44. package/examples/output/deep-taxonomy-10000.n3 +600036 -0
  45. package/examples/output/derived-backward-rule-2.n3 +71 -0
  46. package/examples/output/derived-backward-rule.n3 +53 -0
  47. package/examples/output/derived-rule.n3 +52 -0
  48. package/examples/output/dijkstra.n3 +315 -0
  49. package/examples/output/dog.n3 +33 -0
  50. package/examples/output/equals.n3 +18 -0
  51. package/examples/output/existential-rule.n3 +38 -0
  52. package/examples/output/fibonacci.n3 +44 -0
  53. package/examples/output/for-all-in.n3 +30 -0
  54. package/examples/output/french-cities.n3 +507 -0
  55. package/examples/output/fuse.n3 +1 -0
  56. package/examples/output/good-cobbler.n3 +27 -0
  57. package/examples/output/gray-code-counter.n3 +20 -0
  58. package/examples/output/hanoi.n3 +20 -0
  59. package/examples/output/liar.n3 +1 -0
  60. package/examples/output/list-builtins-tests.n3 +148 -0
  61. package/examples/output/lldm.n3 +1000 -0
  62. package/examples/output/math-builtins-tests.n3 +4479 -0
  63. package/examples/output/monkey.n3 +40 -0
  64. package/examples/output/peano.n3 +26 -0
  65. package/examples/output/pi.n3 +20 -0
  66. package/examples/output/polygon.n3 +20 -0
  67. package/examples/output/reordering.n3 +29 -0
  68. package/examples/output/rule-matching.n3 +29 -0
  69. package/examples/output/self-referential.n3 +88 -0
  70. package/examples/output/similar.n3 +18 -0
  71. package/examples/output/skolem.n3 +20 -0
  72. package/examples/output/snaf.n3 +26 -0
  73. package/examples/output/socrates.n3 +24 -0
  74. package/examples/output/string-builtins-tests.n3 +258 -0
  75. package/examples/output/turing.n3 +44 -0
  76. package/examples/output/uri.n3 +46 -0
  77. package/examples/output/witch.n3 +115 -0
  78. package/examples/output/zebra.n3 +114 -0
  79. package/examples/peano.n3 +45 -0
  80. package/examples/pi.n3 +32 -0
  81. package/examples/polygon.n3 +26 -0
  82. package/examples/reordering.n3 +23 -0
  83. package/examples/rule-matching.n3 +15 -0
  84. package/examples/self-referential.n3 +32 -0
  85. package/examples/similar.n3 +28 -0
  86. package/examples/skolem.n3 +15 -0
  87. package/examples/snaf.n3 +18 -0
  88. package/examples/socrates.n3 +19 -0
  89. package/examples/string-builtins-tests.n3 +210 -0
  90. package/examples/test +154 -0
  91. package/examples/turing.n3 +93 -0
  92. package/examples/uri.n3 +17 -0
  93. package/examples/witch.n3 +33 -0
  94. package/examples/zebra.n3 +47 -0
  95. package/package.json +7 -2
  96. package/test/api.test.js +22 -0
@@ -0,0 +1,210 @@
1
+ # ---------------------
2
+ # string builtins tests
3
+ # ---------------------
4
+
5
+ @prefix : <https://eyereasoner.github.io/ns#> .
6
+ @prefix string: <http://www.w3.org/2000/10/swap/string#> .
7
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
8
+ @prefix list: <http://www.w3.org/2000/10/swap/list#> .
9
+ @prefix math: <http://www.w3.org/2000/10/swap/math#> .
10
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
11
+
12
+ # Each rule checks one builtin and, if it behaves as specified,
13
+ # derives a single marker triple:
14
+ # :ok_string_<name>_1 a :Pass .
15
+
16
+ # ----------------------------------------------------------------------
17
+ # 4.6.1 string:concatenation
18
+ # ----------------------------------------------------------------------
19
+
20
+ {
21
+ ("hello" " " "world!") string:concatenation "hello world!" .
22
+ }
23
+ =>
24
+ {
25
+ :ok_string_concatenation_1 a :Pass .
26
+ } .
27
+
28
+ # ----------------------------------------------------------------------
29
+ # 4.6.2 string:contains
30
+ # ----------------------------------------------------------------------
31
+
32
+ {
33
+ "hello world!" string:contains "llo worl" .
34
+ }
35
+ =>
36
+ {
37
+ :ok_string_contains_1 a :Pass .
38
+ } .
39
+
40
+ # ----------------------------------------------------------------------
41
+ # 4.6.3 string:containsIgnoringCase
42
+ # ----------------------------------------------------------------------
43
+
44
+ {
45
+ "hello world!" string:containsIgnoringCase "lLO woRl" .
46
+ }
47
+ =>
48
+ {
49
+ :ok_string_containsIgnoringCase_1 a :Pass .
50
+ } .
51
+
52
+ # ----------------------------------------------------------------------
53
+ # 4.6.4 string:endsWith
54
+ # ----------------------------------------------------------------------
55
+
56
+ {
57
+ "hello world!" string:endsWith "orld!" .
58
+ }
59
+ =>
60
+ {
61
+ :ok_string_endsWith_1 a :Pass .
62
+ } .
63
+
64
+ # ----------------------------------------------------------------------
65
+ # 4.6.5 string:equalIgnoringCase
66
+ # ----------------------------------------------------------------------
67
+
68
+ {
69
+ "hello world!" string:equalIgnoringCase "hELLo wORld!" .
70
+ }
71
+ =>
72
+ {
73
+ :ok_string_equalIgnoringCase_1 a :Pass .
74
+ } .
75
+
76
+ # ----------------------------------------------------------------------
77
+ # 4.6.6 string:format
78
+ # (eyeling implementation: only %s and %% are required / used here)
79
+ # ----------------------------------------------------------------------
80
+
81
+ {
82
+ ("%s://%s/%s" "https" "w3c.github.io" "N3/spec/")
83
+ string:format "https://w3c.github.io/N3/spec/" .
84
+ }
85
+ =>
86
+ {
87
+ :ok_string_format_1 a :Pass .
88
+ } .
89
+
90
+ # ----------------------------------------------------------------------
91
+ # 4.6.7 string:greaterThan
92
+ # ----------------------------------------------------------------------
93
+
94
+ {
95
+ "Penguin" string:greaterThan "Cat" .
96
+ }
97
+ =>
98
+ {
99
+ :ok_string_greaterThan_1 a :Pass .
100
+ } .
101
+
102
+ # ----------------------------------------------------------------------
103
+ # 4.6.8 string:lessThan
104
+ # ----------------------------------------------------------------------
105
+
106
+ {
107
+ "Cat" string:lessThan "Penguin" .
108
+ }
109
+ =>
110
+ {
111
+ :ok_string_lessThan_1 a :Pass .
112
+ } .
113
+
114
+ # ----------------------------------------------------------------------
115
+ # 4.6.9 string:matches
116
+ # ----------------------------------------------------------------------
117
+
118
+ {
119
+ "hello world!" string:matches ".*(l)+o wo.*" .
120
+ }
121
+ =>
122
+ {
123
+ :ok_string_matches_1 a :Pass .
124
+ } .
125
+
126
+ # ----------------------------------------------------------------------
127
+ # 4.6.10 string:notEqualIgnoringCase
128
+ # ----------------------------------------------------------------------
129
+
130
+ {
131
+ "hello world!" string:notEqualIgnoringCase "hELLo dunia!" .
132
+ }
133
+ =>
134
+ {
135
+ :ok_string_notEqualIgnoringCase_1 a :Pass .
136
+ } .
137
+
138
+ # ----------------------------------------------------------------------
139
+ # 4.6.11 string:notGreaterThan
140
+ # ----------------------------------------------------------------------
141
+
142
+ {
143
+ "Cat" string:notGreaterThan "Penguin" .
144
+ }
145
+ =>
146
+ {
147
+ :ok_string_notGreaterThan_1 a :Pass .
148
+ } .
149
+
150
+ # ----------------------------------------------------------------------
151
+ # 4.6.12 string:notLessThan
152
+ # ----------------------------------------------------------------------
153
+
154
+ {
155
+ "Penguin" string:notLessThan "Cat" .
156
+ }
157
+ =>
158
+ {
159
+ :ok_string_notLessThan_1 a :Pass .
160
+ } .
161
+
162
+ # ----------------------------------------------------------------------
163
+ # 4.6.13 string:notMatches
164
+ # ----------------------------------------------------------------------
165
+
166
+ {
167
+ "hello world!" string:notMatches ".*(l)+o dunia.*" .
168
+ }
169
+ =>
170
+ {
171
+ :ok_string_notMatches_1 a :Pass .
172
+ } .
173
+
174
+ # ----------------------------------------------------------------------
175
+ # 4.6.14 string:replace
176
+ # ----------------------------------------------------------------------
177
+
178
+ {
179
+ ("fofof bar" "of" "baz") string:replace "fbazbaz bar" .
180
+ }
181
+ =>
182
+ {
183
+ :ok_string_replace_1 a :Pass .
184
+ } .
185
+
186
+ # ----------------------------------------------------------------------
187
+ # 4.6.15 string:scrape
188
+ # (extracts the first capturing group)
189
+ # ----------------------------------------------------------------------
190
+
191
+ {
192
+ ("id=abc&x=123&y=zzz" "x=([0-9]+)") string:scrape "123" .
193
+ }
194
+ =>
195
+ {
196
+ :ok_string_scrape_1 a :Pass .
197
+ } .
198
+
199
+ # ----------------------------------------------------------------------
200
+ # 4.6.16 string:startsWith
201
+ # ----------------------------------------------------------------------
202
+
203
+ {
204
+ "hello world!" string:startsWith "hello" .
205
+ }
206
+ =>
207
+ {
208
+ :ok_string_startsWith_1 a :Pass .
209
+ } .
210
+
package/examples/test ADDED
@@ -0,0 +1,154 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ RED="\e[31m"
5
+ GREEN="\e[32m"
6
+ YELLOW="\e[33m"
7
+ NORMAL="\e[0;39m"
8
+
9
+ OK=0
10
+ DIFF=0
11
+
12
+ pad() {
13
+ # pad "text" width
14
+ local s="$1" w="$2"
15
+ printf "%-${w}s" "$s"
16
+ }
17
+
18
+ now_ms() {
19
+ echo $(( $(date +%s%N) / 1000000 ))
20
+ }
21
+
22
+ in_git_worktree() {
23
+ command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1
24
+ }
25
+
26
+ # Expectation logic:
27
+ # 1) If the .n3 contains a comment like: # expect-exit: 2 -> use that
28
+ # 2) Else, if it contains "=> false" -> expect exit 2
29
+ # 3) Else -> expect exit 0
30
+ expected_exit_code() {
31
+ local file="$1"
32
+ local line
33
+ if line=$(grep -Em1 '^[[:space:]]*#[: ]*expect-exit:[[:space:]]*[0-9]+' "$file" 2>/dev/null); then
34
+ if [[ "$line" =~ ([0-9]+) ]]; then
35
+ echo "${BASH_REMATCH[1]}"
36
+ return
37
+ fi
38
+ fi
39
+ if grep -Eq '=>[[:space:]]*false\b' "$file"; then
40
+ echo 2
41
+ else
42
+ echo 0
43
+ fi
44
+ }
45
+
46
+ echo -e "${YELLOW}-------------------------------------------------${NORMAL}"
47
+ echo -e "${YELLOW}running eyeling examples${NORMAL}"
48
+ echo -e "${YELLOW}using $(../eyeling.js -v) and node $(node --version)${NORMAL}"
49
+ echo -e "${YELLOW}-------------------------------------------------${NORMAL}"
50
+ echo ""
51
+
52
+ IN_GIT=0
53
+ if in_git_worktree; then IN_GIT=1; fi
54
+
55
+ # In maintainer mode we write expected outputs (tracked) to output/
56
+ if [[ $IN_GIT -eq 1 ]]; then
57
+ mkdir -p output
58
+ fi
59
+
60
+ begin="$(now_ms)"
61
+
62
+ for file in *.n3; do
63
+ printf "%s" "$(pad "$file" 36)"
64
+ start="$(now_ms)"
65
+
66
+ expected_rc="$(expected_exit_code "$file")"
67
+
68
+ # Decide where we write generated output
69
+ tmp=""
70
+ generated=""
71
+ expected="output/${file}"
72
+
73
+ if [[ $IN_GIT -eq 1 ]]; then
74
+ generated="$expected" # overwrite expected output in working tree
75
+ else
76
+ # npm-installed / no .git: never modify output/ in node_modules
77
+ if [[ ! -f "$expected" ]]; then
78
+ end="$(now_ms)"
79
+ ms=$((end-start))
80
+ echo -en "${YELLOW}$(pad "${ms} ms" 10)${NORMAL} "
81
+ echo -e "${RED}MISSING expected ${expected}${NORMAL}"
82
+ ((++DIFF))
83
+ continue
84
+ fi
85
+ tmp="$(mktemp)"
86
+ generated="$tmp"
87
+ fi
88
+
89
+ # Run eyeling, capture exit code without breaking the loop
90
+ rc=0
91
+ if ../eyeling.js "$file" > "$generated"; then
92
+ rc=0
93
+ else
94
+ rc=$?
95
+ fi
96
+
97
+ end="$(now_ms)"
98
+ ms=$((end-start))
99
+ echo -en "${YELLOW}$(pad "${ms} ms" 10)${NORMAL} "
100
+
101
+ # Compare output
102
+ diff_ok=0
103
+ if [[ $IN_GIT -eq 1 ]]; then
104
+ if git diff --quiet -- "$expected"; then diff_ok=1; fi
105
+ else
106
+ if command -v git >/dev/null 2>&1; then
107
+ if git diff --no-index --quiet -- "$expected" "$generated" >/dev/null 2>&1; then diff_ok=1; fi
108
+ else
109
+ if diff -u "$expected" "$generated" >/dev/null 2>&1; then diff_ok=1; fi
110
+ fi
111
+ fi
112
+
113
+ # Decide pass/fail
114
+ if [[ $diff_ok -eq 1 && $rc -eq $expected_rc ]]; then
115
+ if [[ $rc -eq 0 ]]; then
116
+ echo -e "${GREEN}OK${NORMAL}"
117
+ else
118
+ echo -e "${GREEN}OK${NORMAL} (exit ${rc})"
119
+ fi
120
+ ((++OK))
121
+ else
122
+ if [[ $rc -ne $expected_rc ]]; then
123
+ echo -e "${RED}DIFF${NORMAL} (exit ${rc}, expected ${expected_rc})"
124
+ else
125
+ echo -e "${RED}DIFF${NORMAL}"
126
+ fi
127
+ ((++DIFF))
128
+
129
+ # In npm mode, show a git-style diff when available (nice UX)
130
+ if [[ $IN_GIT -eq 0 ]]; then
131
+ if command -v git >/dev/null 2>&1; then
132
+ git diff --no-index -- "$expected" "$generated" || true
133
+ else
134
+ diff -u "$expected" "$generated" || true
135
+ fi
136
+ fi
137
+ fi
138
+
139
+ # cleanup tmp file
140
+ if [[ -n "$tmp" ]]; then rm -f "$tmp"; fi
141
+ done
142
+
143
+ end="$(now_ms)"
144
+ total=$((end-begin))
145
+
146
+ echo ""
147
+ echo -e "${YELLOW}${total} ms${NORMAL} ${GREEN}${OK} OK${NORMAL} ${RED}${DIFF} DIFF${NORMAL}"
148
+
149
+ if [[ ${DIFF} -eq 0 ]]; then
150
+ exit 0
151
+ else
152
+ exit 2
153
+ fi
154
+
@@ -0,0 +1,93 @@
1
+ # --------------
2
+ # Turing Machine
3
+ # --------------
4
+ #
5
+ # Turing completeness test case.
6
+ # See http://en.wikipedia.org/wiki/Prolog#Turing_completeness
7
+
8
+ @prefix list: <http://www.w3.org/2000/10/swap/list#>.
9
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
10
+ @prefix : <http://example.org/#>.
11
+
12
+ # interpreter for Turing machine
13
+ {() :compute ?OutTape} <= {
14
+ ?Machine :start ?I.
15
+ (?I () "#" ()) :find ?OutTape.
16
+ }.
17
+
18
+ {?List :compute ?OutTape} <= {
19
+ ?List list:firstRest (?Head ?Tail).
20
+ ?Machine :start ?I.
21
+ (?I () ?Head ?Tail) :find ?OutTape.
22
+ }.
23
+
24
+ {(?State ?Left ?Cell ?Right) :find ?OutTape} <= {
25
+ (?State ?Cell ?Write ?Move) :tape ?Next.
26
+ (?Move ?Left ?Write ?Right ?A ?B ?C) :move true.
27
+ (?Next ?A ?B ?C) :continue ?OutTape.
28
+ }.
29
+
30
+ {(:halt ?Left ?Cell ?Right) :continue ?OutTape} <= {
31
+ ?Left :reverse ?R.
32
+ ?List list:firstRest (?Cell ?Right).
33
+ (?R ?List) list:append ?OutTape.
34
+ }.
35
+
36
+ {(?State ?Left ?Cell ?Right) :continue ?OutTape} <= {
37
+ (?State ?Left ?Cell ?Right) :find ?OutTape.
38
+ }.
39
+
40
+ {(:left () ?Cell ?Right () "#" ?L) :move true} <= {
41
+ ?L list:firstRest (?Cell ?Right).
42
+ }.
43
+
44
+ {(:left ?List ?Cell ?Right ?Tail ?Head ?L) :move true} <= {
45
+ ?List list:firstRest (?Head ?Tail).
46
+ ?L list:firstRest (?Cell ?Right).
47
+ }.
48
+
49
+ {(:stop ?Left ?Cell ?Right ?Left ?Cell ?Right) :move true} <= true.
50
+
51
+ {(:right ?Left ?Cell () ?L "#" ()) :move true} <= {
52
+ ?L list:firstRest (?Cell ?Left).
53
+ }.
54
+
55
+ {(:right ?Left ?Cell ?List ?L ?Head ?Tail) :move true} <= {
56
+ ?List list:firstRest (?Head ?Tail).
57
+ ?L list:firstRest (?Cell ?Left).
58
+ }.
59
+
60
+ {() :reverse ()} <= true.
61
+
62
+ {?List :reverse ?Reverse} <= {
63
+ ?List list:firstRest (?Head ?Tail).
64
+ ?Tail :reverse ?R.
65
+ (?R (?Head)) list:append ?Reverse.
66
+ }.
67
+
68
+ # a Turing machine to add 1 to a binary number
69
+ :add1 :start 0.
70
+
71
+ (0 0 0 :right) :tape 0.
72
+ (0 1 1 :right) :tape 0.
73
+ (0 "#" "#" :left) :tape 1.
74
+ (1 0 1 :stop) :tape :halt.
75
+ (1 1 0 :left) :tape 1.
76
+ (1 "#" 1 :stop) :tape :halt.
77
+
78
+ @prefix : <http://example.org/#>.
79
+
80
+ # query
81
+ {
82
+ (1 0 1 0 0 1) :compute ?A1.
83
+ (1 0 1 1 1 1) :compute ?A2.
84
+ (1 1 1 1 1 1) :compute ?A3.
85
+ () :compute ?A4.
86
+ } => {
87
+ :test :is {
88
+ (1 0 1 0 0 1) :compute ?A1.
89
+ (1 0 1 1 1 1) :compute ?A2.
90
+ (1 1 1 1 1 1) :compute ?A3.
91
+ () :compute ?A4.
92
+ }.
93
+ }.
@@ -0,0 +1,17 @@
1
+ # ---------------
2
+ # log:uri example
3
+ # ---------------
4
+
5
+ @prefix : <http://example.org/> .
6
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
7
+
8
+ {
9
+ <https://www.w3.org> log:uri ?s .
10
+ ?r log:uri "https://www.w3.org" .
11
+ }
12
+ =>
13
+ {
14
+ :uriString :is ?s .
15
+ :uriResource :is ?r .
16
+ }.
17
+
@@ -0,0 +1,33 @@
1
+ # --------------
2
+ # Burn the witch
3
+ # --------------
4
+ #
5
+ # http://clarkparsia.com/weblog/2007/01/02/burn-the-witch/
6
+ # http://www.netfunny.com/rhf/jokes/90q4/burnher.html
7
+
8
+ # original http://www.w3.org/2000/10/swap/test/reason/witch.n3
9
+
10
+ @prefix : <https://eyereasoner.github.io/eye/reasoning/witch#>.
11
+
12
+ #[1] BURNS(x) /\ WOMAN(x) => WITCH(x)
13
+ { ?x a :BURNS. ?x a :WOMAN } => { ?x a :WITCH }.
14
+
15
+ #[2] WOMAN(GIRL)
16
+ :GIRL a :WOMAN.
17
+
18
+ #[3] \forall x, ISMADEOFWOOD(x) => BURNS(x)
19
+ { ?x a :ISMADEOFWOOD } => { ?x a :BURNS }.
20
+
21
+ #[4] \forall x, FLOATS(x) => ISMADEOFWOOD(x)
22
+ { ?x a :FLOATS } => { ?x a :ISMADEOFWOOD }.
23
+
24
+ #[5] FLOATS(DUCK)
25
+
26
+ :DUCK a :FLOATS.
27
+
28
+ #[6] \forall x,y FLOATS(x) /\ SAMEWEIGHT(x,y) => FLOATS(y)
29
+ { ?x a :FLOATS. ?x :SAMEWEIGHT ?y } => { ?y a :FLOATS }.
30
+
31
+ # and, by experiment
32
+ # [7] SAMEWEIGHT(DUCK,GIRL)
33
+ :DUCK :SAMEWEIGHT :GIRL.
@@ -0,0 +1,47 @@
1
+ # ---------------
2
+ # Einstein Riddle
3
+ # ---------------
4
+ #
5
+ # The situation:
6
+ # - There are 5 houses in five different colors.
7
+ # - In each house lives a person with a different nationality.
8
+ # - These five owners drink a certain type of beverage, smoke a certain brand of cigar and keep a certain pet.
9
+ # - No owners have the same pet, smoke the same brand of cigar or drink the same beverage.
10
+ #
11
+ # The question is:
12
+ # Who owns the fish?
13
+
14
+ @prefix list: <http://www.w3.org/2000/10/swap/list#>.
15
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
16
+ @prefix : <http://eulersharp.sourceforge.net/2005/11swap/zebra#>.
17
+
18
+ { ?L log:equalTo ((?A1 :norwegian ?A2 ?A3 ?A4) (:blue ?A5 ?A6 ?A7 ?A8) (?A9 ?A10 ?A11 :milk ?A12) ?A13 ?A14);
19
+ :pair ((?A15 ?A16 ?A17 ?A18 :blends) (?A19 ?A20 :cats ?A21 ?A22));
20
+ :pair ((?A23 ?A24 :horse ?A25 ?A26) (?A27 ?A28 ?A29 ?A30 :dunhill));
21
+ :sublist ((:green ?A31 ?A32 :coffee ?A33) (:white ?A34 ?A35 ?A36 ?A37));
22
+ :pair ((?A38 ?A39 ?A40 ?A41 :blends) (?A42 ?A43 ?A44 :water ?A45));
23
+ list:member (:red :brit ?A46 ?A47 ?A48);
24
+ list:member (?A49 :swede :dogs ?A50 ?A51);
25
+ list:member (?A52 :dane ?A53 :tea ?A54);
26
+ list:member (?A55 ?A56 :birds ?A57 :pallmall);
27
+ list:member (:yellow ?A58 ?A59 ?A60 :dunhill);
28
+ list:member (?A61 ?A62 ?A63 :beer :bluemasters);
29
+ list:member (?A64 :german ?A65 ?A66 :prince);
30
+ list:member (?A67 ?B :fish ?A69 ?A70).
31
+ }
32
+ =>
33
+ { ?B :eats :fish.
34
+ }.
35
+
36
+ {?A :pair (?B ?C)} <=
37
+ { ?A :sublist (?B ?C).
38
+ }.
39
+
40
+ {?A :pair (?B ?C)} <=
41
+ { ?A :sublist (?C ?B).
42
+ }.
43
+
44
+ {?A :sublist ?B} <=
45
+ { (?C ?D) list:append ?A.
46
+ (?E ?B) list:append ?C.
47
+ }.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.5.12",
3
+ "version": "1.5.14",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
@@ -20,6 +20,8 @@
20
20
  "files": [
21
21
  "index.js",
22
22
  "eyeling.js",
23
+ "test",
24
+ "examples",
23
25
  "README.md",
24
26
  "LICENSE.md"
25
27
  ],
@@ -27,6 +29,9 @@
27
29
  "node": ">=18"
28
30
  },
29
31
  "scripts": {
30
- "test": "node test/api.test.js"
32
+ "test:api": "node test/api.test.js",
33
+ "test:examples": "bash -lc 'cd examples && ./test'",
34
+ "test:package": "bash test/package-smoke.sh",
35
+ "test": "npm run test:api && npm run test:examples"
31
36
  }
32
37
  }
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const assert = require('node:assert/strict');
4
+ const { reason } = require('..'); // gebruikt package main: ./index.js
5
+
6
+ const input = `
7
+ { <http://example.org/s> <http://example.org/p> <http://example.org/o>. }
8
+ => { <http://example.org/s> <http://example.org/q> <http://example.org/o>. }.
9
+
10
+ <http://example.org/s> <http://example.org/p> <http://example.org/o>.
11
+ `;
12
+
13
+ const out = reason({ proofComments: false }, input);
14
+
15
+ // Verwacht dat de afgeleide triple aanwezig is (tolerant voor formatting)
16
+ assert.match(
17
+ out,
18
+ /<http:\/\/example\.org\/s>\s+<http:\/\/example\.org\/q>\s+<http:\/\/example\.org\/o>\s*\./
19
+ );
20
+
21
+ console.log('OK: reason() inferred expected triple');
22
+