rubylog 1.0.0 → 2.0pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/Gemfile +3 -12
  2. data/Gemfile.lock +22 -48
  3. data/README.rdoc +38 -38
  4. data/README.rdoc.orig +284 -0
  5. data/RELEASE_NOTES.rdoc +51 -0
  6. data/Rakefile +14 -18
  7. data/TODO.txt +0 -0
  8. data/VERSION +1 -1
  9. data/examples/a_plus_b.rb +6 -0
  10. data/examples/checkmate.rb +88 -0
  11. data/examples/combination.rb +17 -0
  12. data/examples/dcg.rb +3 -2
  13. data/examples/dcg2.rb +2 -2
  14. data/{logic → examples}/directory_structure_logic.rb +3 -5
  15. data/examples/dirlist.rb +4 -0
  16. data/examples/divisors.rb +6 -0
  17. data/examples/enumerators.rb +3 -3
  18. data/examples/factorial.rb +2 -3
  19. data/examples/file_search.rb +14 -0
  20. data/examples/hanoi.rb +4 -5
  21. data/examples/hello.rb +6 -4
  22. data/examples/mice.rb +92 -0
  23. data/examples/mice2.rb +19 -0
  24. data/examples/n_queens.rb +32 -0
  25. data/examples/object_oriented.rb +14 -0
  26. data/examples/palindrome_detection.rb +18 -0
  27. data/examples/parsing.rb +6 -4
  28. data/examples/permutation.rb +12 -0
  29. data/examples/prefix.rb +13 -0
  30. data/examples/primality_by_division.rb +22 -0
  31. data/examples/primitives.rb +10 -8
  32. data/examples/sieve_of_eratosthenes.rb +14 -0
  33. data/examples/string_interpolation.rb +4 -0
  34. data/examples/sudoku.rb +52 -0
  35. data/examples/tracing.rb +19 -0
  36. data/lib/rspec/rubylog.rb +29 -0
  37. data/lib/rubylog/assertable.rb +24 -0
  38. data/lib/rubylog/builtins/arithmetics.rb +63 -0
  39. data/lib/rubylog/builtins/assumption.rb +71 -0
  40. data/lib/rubylog/builtins/ensure.rb +13 -0
  41. data/lib/rubylog/builtins/file_system.rb +30 -8
  42. data/lib/rubylog/builtins/logic.rb +69 -38
  43. data/lib/rubylog/builtins/reflection.rb +35 -50
  44. data/lib/rubylog/builtins/term.rb +15 -17
  45. data/lib/rubylog/builtins.rb +11 -0
  46. data/lib/rubylog/clause.rb +19 -0
  47. data/lib/rubylog/{interfaces/composite_term.rb → compound_term.rb} +3 -3
  48. data/lib/rubylog/context.rb +24 -0
  49. data/lib/rubylog/context_creation.rb +71 -0
  50. data/lib/rubylog/context_modules/checks.rb +35 -0
  51. data/lib/rubylog/context_modules/demonstration.rb +16 -0
  52. data/lib/rubylog/context_modules/predicates.rb +86 -0
  53. data/lib/rubylog/context_modules/primitives.rb +18 -0
  54. data/lib/rubylog/context_modules/thats.rb +13 -0
  55. data/lib/rubylog/default_context.rb +9 -0
  56. data/lib/rubylog/dsl/array_splat.rb +11 -3
  57. data/lib/rubylog/dsl/primitives.rb +24 -12
  58. data/lib/rubylog/dsl/thats.rb +6 -0
  59. data/lib/rubylog/dsl/variables.rb +56 -21
  60. data/lib/rubylog/errors.rb +26 -15
  61. data/lib/rubylog/mixins/array.rb +95 -62
  62. data/lib/rubylog/mixins/kernel.rb +3 -2
  63. data/lib/rubylog/mixins/method.rb +0 -1
  64. data/lib/rubylog/mixins/object.rb +2 -1
  65. data/lib/rubylog/mixins/proc.rb +9 -12
  66. data/lib/rubylog/mixins/string.rb +15 -23
  67. data/lib/rubylog/mixins/symbol.rb +7 -24
  68. data/lib/rubylog/nullary_predicates.rb +3 -0
  69. data/lib/rubylog/predicate.rb +53 -0
  70. data/lib/rubylog/primitive.rb +15 -0
  71. data/lib/rubylog/procedure.rb +42 -0
  72. data/lib/rubylog/rule.rb +24 -0
  73. data/lib/rubylog/structure.rb +19 -38
  74. data/lib/rubylog/{interfaces/term.rb → term.rb} +2 -7
  75. data/lib/rubylog/tracing.rb +75 -0
  76. data/lib/rubylog/variable.rb +31 -12
  77. data/lib/rubylog.rb +36 -32
  78. data/rubylog.gemspec +92 -84
  79. data/spec/inriasuite_spec.rb +906 -9
  80. data/spec/integration/custom_classes_spec.rb +61 -0
  81. data/spec/integration/dsl_spec.rb +38 -0
  82. data/spec/integration/recursion_spec.rb +14 -0
  83. data/spec/integration/theory_as_module_spec.rb +20 -0
  84. data/spec/integration/theory_as_module_with_include_spec.rb +14 -0
  85. data/spec/rspec/rubylog_spec.rb +75 -0
  86. data/spec/rubylog/assertable_spec.rb +111 -0
  87. data/spec/rubylog/builtins/arithmetics_spec.rb +94 -0
  88. data/spec/rubylog/builtins/assumption_spec.rb +70 -0
  89. data/spec/rubylog/builtins/ensure_spec.rb +8 -0
  90. data/spec/rubylog/builtins/file_system_spec.rb +40 -0
  91. data/spec/rubylog/builtins/logic_spec.rb +340 -0
  92. data/spec/rubylog/builtins/reflection_spec.rb +43 -0
  93. data/spec/rubylog/builtins/term_spec.rb +85 -0
  94. data/spec/rubylog/context_modules/demonstration_spec.rb +132 -0
  95. data/spec/rubylog/context_modules/predicates_spec.rb +57 -0
  96. data/spec/rubylog/context_modules/thats_spec.rb +94 -0
  97. data/spec/rubylog/dsl/array_splat_spec.rb +15 -0
  98. data/spec/rubylog/dsl/primitives_spec.rb +43 -0
  99. data/spec/rubylog/errors_spec.rb +18 -0
  100. data/spec/{unification_spec.rb → rubylog/interfaces/term_spec.rb} +8 -9
  101. data/spec/rubylog/mixins/array_spec.rb +80 -0
  102. data/spec/rubylog/mixins/composite_term_spec.rb +66 -0
  103. data/spec/rubylog/mixins/proc_spec.rb +59 -0
  104. data/spec/rubylog/mixins/string_spec.rb +48 -0
  105. data/spec/rubylog/mixins/symbol_spec.rb +9 -0
  106. data/spec/{clause_spec.rb → rubylog/structure_spec.rb} +16 -15
  107. data/spec/rubylog/term_spec.rb +7 -0
  108. data/spec/rubylog/tracing_spec.input +27 -0
  109. data/spec/rubylog/tracing_spec.rb +44 -0
  110. data/spec/rubylog/variable_spec.rb +279 -0
  111. data/spec/spec_helper.rb +1 -0
  112. data/vimrc +11 -0
  113. metadata +103 -123
  114. data/README.hu.rb +0 -58
  115. data/bin/rubylog +0 -18
  116. data/examples/theory.rb +0 -32
  117. data/lib/rubylog/builtins/default.rb +0 -10
  118. data/lib/rubylog/dsl.rb +0 -70
  119. data/lib/rubylog/interfaces/assertable.rb +0 -16
  120. data/lib/rubylog/interfaces/callable.rb +0 -18
  121. data/lib/rubylog/interfaces/predicate.rb +0 -8
  122. data/lib/rubylog/interfaces/procedure.rb +0 -60
  123. data/lib/rubylog/mixins/class.rb +0 -11
  124. data/lib/rubylog/simple_procedure.rb +0 -8
  125. data/lib/rubylog/theory.rb +0 -422
  126. data/logic/builtins/file_system_logic.rb +0 -23
  127. data/logic/builtins/reflection_logic.rb +0 -40
  128. data/logic/dereference_logic.rb +0 -23
  129. data/logic/dsl_logic.rb +0 -29
  130. data/logic/errors_logic.rb +0 -9
  131. data/logic/guard_logic.rb +0 -115
  132. data/logic/list_logic.rb +0 -55
  133. data/logic/map_logic.rb +0 -15
  134. data/logic/multitheory.rb +0 -23
  135. data/logic/recursion_logic.rb +0 -12
  136. data/logic/string_logic.rb +0 -41
  137. data/logic/thats_logic.rb +0 -51
  138. data/logic/variable_logic.rb +0 -24
  139. data/spec/bartak_guide_spec.rb +0 -86
  140. data/spec/builtins/all_spec.rb +0 -99
  141. data/spec/builtins/and_spec.rb +0 -22
  142. data/spec/builtins/array_spec.rb +0 -16
  143. data/spec/builtins/branch_or_spec.rb +0 -27
  144. data/spec/builtins/cut_spec.rb +0 -44
  145. data/spec/builtins/fail_spec.rb +0 -5
  146. data/spec/builtins/false_spec.rb +0 -5
  147. data/spec/builtins/in_spec.rb +0 -38
  148. data/spec/builtins/is_false_spec.rb +0 -12
  149. data/spec/builtins/is_spec.rb +0 -26
  150. data/spec/builtins/matches_spec.rb +0 -23
  151. data/spec/builtins/or_spec.rb +0 -22
  152. data/spec/builtins/splits_to.rb +0 -18
  153. data/spec/builtins/then_spec.rb +0 -27
  154. data/spec/builtins/true_spec.rb +0 -5
  155. data/spec/compilation_spec.rb +0 -61
  156. data/spec/custom_classes_spec.rb +0 -43
  157. data/spec/dereference.rb +0 -10
  158. data/spec/queries_spec.rb +0 -150
  159. data/spec/recursion_spec.rb +0 -18
  160. data/spec/ruby_code_spec.rb +0 -52
  161. data/spec/rules_spec.rb +0 -97
  162. data/spec/theory_spec.rb +0 -29
  163. data/spec/variable_spec.rb +0 -26
@@ -0,0 +1,340 @@
1
+ require 'spec_helper'
2
+
3
+ describe "logic builtins", :rubylog => true do
4
+ before do
5
+ predicate_for Symbol, ".likes() .happy"
6
+ end
7
+
8
+ specify "true" do
9
+ :john.happy.if :true
10
+ :john.should be_happy
11
+ end
12
+
13
+ specify "fail" do
14
+ :john.happy.if :fail
15
+ :john.should_not be_happy
16
+ end
17
+
18
+ describe "false" do
19
+ specify do
20
+ :john.happy.if :true.false
21
+ :john.should_not be_happy
22
+ end
23
+
24
+ specify do
25
+ :john.happy.if :fail.false
26
+ :john.should be_happy
27
+ end
28
+ end
29
+
30
+ describe "and" do
31
+ it "works 1" do
32
+ :john.happy.if :fail.and :true
33
+ :john.should_not be_happy
34
+ end
35
+
36
+ it "works 2" do
37
+ :john.happy.if :true.and :fail
38
+ :john.should_not be_happy
39
+ end
40
+
41
+ it "works 3" do
42
+ :john.happy.if :fail.and :fail
43
+ :john.should_not be_happy
44
+ end
45
+
46
+ it "works 4" do
47
+ :john.happy.if :true.and :true
48
+ :john.should be_happy
49
+ end
50
+ end
51
+
52
+
53
+ describe "or" do
54
+ it "works 1" do
55
+ :john.happy.if :fail.or :true
56
+ :john.should be_happy
57
+ end
58
+
59
+ it "works 2" do
60
+ :john.happy.if :true.or :fail
61
+ :john.should be_happy
62
+ end
63
+
64
+ it "works 3" do
65
+ :john.happy.if :fail.or :fail
66
+ :john.should_not be_happy
67
+ end
68
+
69
+ it "works 4" do
70
+ :john.happy.if :true.or :true
71
+ :john.should be_happy
72
+ end
73
+ end
74
+
75
+
76
+ describe "branch or" do
77
+ it "works 1" do
78
+ :john.happy.if :fail
79
+ :john.happy.if :true
80
+ :john.should be_happy
81
+ end
82
+
83
+ it "works 2" do
84
+ :john.happy.if :true
85
+ :john.happy.if :fail
86
+ :john.should be_happy
87
+ end
88
+
89
+ it "works 3" do
90
+ :john.happy.if :fail
91
+ :john.happy.if :fail
92
+ :john.should_not be_happy
93
+ end
94
+
95
+ it "works 4" do
96
+ :john.happy.if :true
97
+ :john.happy.if :true
98
+ :john.should be_happy
99
+ end
100
+ end
101
+
102
+ describe "iff" do
103
+ it "works 1" do
104
+ :john.happy.if :fail.iff :true
105
+ :john.should_not be_happy
106
+ end
107
+
108
+ it "works 2" do
109
+ :john.happy.if :true.iff :fail
110
+ :john.should_not be_happy
111
+ end
112
+
113
+ it "works 3" do
114
+ :john.happy.if :fail.iff :fail
115
+ :john.should be_happy
116
+ end
117
+
118
+ it "works 4" do
119
+ :john.happy.if :true.iff :true
120
+ :john.should be_happy
121
+ end
122
+ end
123
+
124
+ describe "cut" do
125
+ it "works with branch or" do
126
+ :john.happy.if :true.and :cut!.and :fail
127
+ :john.happy.if :true
128
+ :john.should_not be_happy
129
+ end
130
+ it "works with branch or (control)" do
131
+ :john.happy.if :true.and :fail
132
+ :john.happy.if :true
133
+ :john.should be_happy
134
+ end
135
+
136
+ it "works with or" do
137
+ :john.happy.if((:true.and :cut!.and :fail).or :true)
138
+ :john.should_not be_happy
139
+ end
140
+
141
+ it "works with or (control)" do
142
+ :john.happy.if((:true.and :fail).or :true)
143
+ :john.should be_happy
144
+ end
145
+
146
+ it "returns true with branch or" do
147
+ :john.happy.if :true.and :cut!.and :true
148
+ :john.happy.if :true
149
+ :john.should be_happy
150
+ end
151
+ it "returns true with branch or (control)" do
152
+ :john.happy.if :true.and :true
153
+ :john.happy.if :true
154
+ :john.should be_happy
155
+ end
156
+
157
+ it "returns true with or" do
158
+ :john.happy.if((:true.and :cut!.and :true).or :true)
159
+ :john.should be_happy
160
+ end
161
+
162
+ it "returns true with or (control)" do
163
+ :john.happy.if((:true.and :true).or :true)
164
+ :john.should be_happy
165
+ end
166
+ end
167
+
168
+ describe "all,any,one,none,every" do
169
+ before do
170
+ :john.likes! :water
171
+ :john.likes! :beer
172
+
173
+ :jane.likes! :water
174
+ :jane.likes! :milk
175
+ :jane.likes! :beer
176
+
177
+ :jeff.likes! :water
178
+ :jeff.likes! :absinth
179
+
180
+ :todd.likes! :milk
181
+
182
+ @predicates = [:all, :any, :one, :none]
183
+ @names = :john, :jane, :jeff, :todd
184
+ @good =
185
+ [
186
+ [[1,1,0,0], [0,1,0,0], [0,0,1,0], [0,1,0,1]], # all
187
+ [[1,1,1,0], [1,1,1,1], [1,1,1,0], [0,1,0,1]], # any
188
+ [[0,0,1,0], [0,0,1,1], [1,1,0,0], [0,1,0,1]], # one
189
+ [[0,0,0,1], [0,0,0,0], [0,0,0,1], [1,0,1,0]] # none
190
+ ]
191
+ end
192
+
193
+ it "work" do
194
+ @predicates.map{|p| @names.map{|n| @names.map{|m|
195
+ (n.likes(K).send p, m.likes(K)).true? ? 1 : 0
196
+ }}}.should == @good
197
+ end
198
+
199
+ it "mimic well enumerators' predicates" do
200
+ @predicates.map{|p| @names.map{|n| @names.map{|m|
201
+ n.likes(K).map{K}.send(:"#{p}?"){|x| m.likes?(x) } ? 1 : 0
202
+ }}}.should == @good
203
+ end
204
+
205
+
206
+
207
+ specify "all works" do
208
+ (:john.likes(X).all(:john.likes(X))).true?.should be_true
209
+ (:john.likes(X).all(:jane.likes(X))).true?.should be_true
210
+ (:john.likes(X).all(:jeff.likes(X))).true?.should_not be_true
211
+ (:john.likes(X).all(:todd.likes(X))).true?.should_not be_true
212
+
213
+ (:jane.likes(X).all(:john.likes(X))).true?.should_not be_true
214
+ (:jane.likes(X).all(:jane.likes(X))).true?.should be_true
215
+ (:jane.likes(X).all(:jeff.likes(X))).true?.should_not be_true
216
+ (:jane.likes(X).all(:todd.likes(X))).true?.should_not be_true
217
+
218
+ (:jeff.likes(X).all(:john.likes(X))).true?.should_not be_true
219
+ (:jeff.likes(X).all(:jane.likes(X))).true?.should_not be_true
220
+ (:jeff.likes(X).all(:jeff.likes(X))).true?.should be_true
221
+ (:jeff.likes(X).all(:todd.likes(X))).true?.should_not be_true
222
+
223
+ (:todd.likes(X).all(:john.likes(X))).true?.should_not be_true
224
+ (:todd.likes(X).all(:jane.likes(X))).true?.should be_true
225
+ (:todd.likes(X).all(:jeff.likes(X))).true?.should_not be_true
226
+ (:todd.likes(X).all(:todd.likes(X))).true?.should be_true
227
+ end
228
+
229
+ specify "all works with procs" do
230
+ (:john.likes(X).all{:john.likes?(X)}).true?.should be_true
231
+ (:john.likes(X).all{:jane.likes?(X)}).true?.should be_true
232
+ (:john.likes(X).all{:jeff.likes?(X)}).true?.should_not be_true
233
+ (:john.likes(X).all{:todd.likes?(X)}).true?.should_not be_true
234
+
235
+ (:jane.likes(X).all{:john.likes?(X)}).true?.should_not be_true
236
+ (:jane.likes(X).all{:jane.likes?(X)}).true?.should be_true
237
+ (:jane.likes(X).all{:jeff.likes?(X)}).true?.should_not be_true
238
+ (:jane.likes(X).all{:todd.likes?(X)}).true?.should_not be_true
239
+
240
+ (:jeff.likes(X).all{:john.likes?(X)}).true?.should_not be_true
241
+ (:jeff.likes(X).all{:jane.likes?(X)}).true?.should_not be_true
242
+ (:jeff.likes(X).all{:jeff.likes?(X)}).true?.should be_true
243
+ (:jeff.likes(X).all{:todd.likes?(X)}).true?.should_not be_true
244
+
245
+ (:todd.likes(X).all{:john.likes?(X)}).true?.should_not be_true
246
+ (:todd.likes(X).all{:jane.likes?(X)}).true?.should be_true
247
+ (:todd.likes(X).all{:jeff.likes?(X)}).true?.should_not be_true
248
+ (:todd.likes(X).all{:todd.likes?(X)}).true?.should be_true
249
+ end
250
+
251
+ it "can be called with global functor syntax" do
252
+ all(:john.likes(X), :jane.likes(X)).true?.should be_true
253
+ all(:jane.likes(X), :john.likes(X)).true?.should_not be_true
254
+ any(:jane.likes(X), :todd.likes(X)).true?.should be_true
255
+ any(:john.likes(X), :todd.likes(X)).true?.should_not be_true
256
+ end
257
+
258
+ it "one, any, none can be called unarily" do
259
+ one(:john.likes(X)).true?.should_not be_true
260
+ one(:jane.likes(X)).true?.should_not be_true
261
+ one(:jeff.likes(X)).true?.should_not be_true
262
+ one(:todd.likes(X)).true?.should be_true
263
+ one(:jim.likes(X)).true?.should_not be_true
264
+
265
+ any(:john.likes(X)).true?.should be_true
266
+ any(:jane.likes(X)).true?.should be_true
267
+ any(:jeff.likes(X)).true?.should be_true
268
+ any(:todd.likes(X)).true?.should be_true
269
+ any(:jim.likes(X)).true?.should_not be_true
270
+
271
+ none(:john.likes(X)).true?.should_not be_true
272
+ none(:jane.likes(X)).true?.should_not be_true
273
+ none(:jeff.likes(X)).true?.should_not be_true
274
+ none(:todd.likes(X)).true?.should_not be_true
275
+ none(:jim.likes(X)).true?.should be_true
276
+ end
277
+
278
+ it "does not hijack variables" do
279
+ A.is(X.is(5)).and(A.all{X<10}).true?.should == true
280
+ end
281
+
282
+ describe "every" do
283
+ specify "works like all" do
284
+ every(:john.likes(X),:john.likes(X)).true?.should be_true
285
+ every(:john.likes(X),:jane.likes(X)).true?.should be_true
286
+ every(:john.likes(X),:jeff.likes(X)).true?.should_not be_true
287
+ every(:john.likes(X),:todd.likes(X)).true?.should_not be_true
288
+
289
+ every(:jane.likes(X),:john.likes(X)).true?.should_not be_true
290
+ every(:jane.likes(X),:jane.likes(X)).true?.should be_true
291
+ every(:jane.likes(X),:jeff.likes(X)).true?.should_not be_true
292
+ every(:jane.likes(X),:todd.likes(X)).true?.should_not be_true
293
+
294
+ every(:jeff.likes(X),:john.likes(X)).true?.should_not be_true
295
+ every(:jeff.likes(X),:jane.likes(X)).true?.should_not be_true
296
+ every(:jeff.likes(X),:jeff.likes(X)).true?.should be_true
297
+ every(:jeff.likes(X),:todd.likes(X)).true?.should_not be_true
298
+
299
+ every(:todd.likes(X),:john.likes(X)).true?.should_not be_true
300
+ every(:todd.likes(X),:jane.likes(X)).true?.should be_true
301
+ every(:todd.likes(X),:jeff.likes(X)).true?.should_not be_true
302
+ every(:todd.likes(X),:todd.likes(X)).true?.should be_true
303
+ end
304
+
305
+ specify "works like all with procs" do
306
+ every(:john.likes(X)){:john.likes?(X)}.true?.should be_true
307
+ every(:john.likes(X)){:jane.likes?(X)}.true?.should be_true
308
+ every(:john.likes(X)){:jeff.likes?(X)}.true?.should_not be_true
309
+ every(:john.likes(X)){:todd.likes?(X)}.true?.should_not be_true
310
+
311
+ every(:jane.likes(X)){:john.likes?(X)}.true?.should_not be_true
312
+ every(:jane.likes(X)){:jane.likes?(X)}.true?.should be_true
313
+ every(:jane.likes(X)){:jeff.likes?(X)}.true?.should_not be_true
314
+ every(:jane.likes(X)){:todd.likes?(X)}.true?.should_not be_true
315
+
316
+ every(:jeff.likes(X)){:john.likes?(X)}.true?.should_not be_true
317
+ every(:jeff.likes(X)){:jane.likes?(X)}.true?.should_not be_true
318
+ every(:jeff.likes(X)){:jeff.likes?(X)}.true?.should be_true
319
+ every(:jeff.likes(X)){:todd.likes?(X)}.true?.should_not be_true
320
+
321
+ every(:todd.likes(X)){:john.likes?(X)}.true?.should_not be_true
322
+ every(:todd.likes(X)){:jane.likes?(X)}.true?.should be_true
323
+ every(:todd.likes(X)){:jeff.likes?(X)}.true?.should_not be_true
324
+ every(:todd.likes(X)){:todd.likes?(X)}.true?.should be_true
325
+ end
326
+
327
+
328
+ specify "can be used for assumptions" do
329
+ predicate_for Symbol, ".good"
330
+ # assumptions reverse the order
331
+ every(:john.likes(X), X.good.assumed).and(Y.good).map{Y}.should == [:beer, :water]
332
+ end
333
+
334
+ end
335
+
336
+
337
+
338
+ end
339
+
340
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+ require "rubylog/builtins/reflection"
3
+
4
+ describe "reflection builtins", :rubylog => true do
5
+ before do
6
+ predicate_for String, ".likes() .drinks()"
7
+ end
8
+
9
+ describe "fact" do
10
+ specify do
11
+ "John".likes! "beer"
12
+ check "John".likes("beer").fact
13
+ check { A.likes(B).fact.map{A.likes(B)} == ["John".likes("beer")] }
14
+ end
15
+ end
16
+
17
+ describe "follows_from" do
18
+ specify do
19
+ A.drinks(B).if A.likes(B)
20
+ check A.drinks(B).follows_from A.likes(B)
21
+ check {A.drinks(B).follows_from(K).map{K} == [A.likes(B)] }
22
+ end
23
+ end
24
+
25
+ describe "structure" do
26
+ specify do
27
+ check A.likes(B).structure(A.likes(B).predicate, :likes, [A,B])
28
+ check { A.likes(B).structure(P,X,Y).map{[P,X,Y]} == [[A.likes.predicate, :likes, [A,B]]] }
29
+ end
30
+ end
31
+
32
+ describe "structures with variable functor and partial argument list" do
33
+ specify do
34
+ check { K.structure(ANY.drinks(ANY).predicate, :drinks, ["John", "beer"]).map{K} == ["John".drinks("beer")] }
35
+ check { K.structure(Rubylog::Procedure.new(:drinks, 2), A,[*B]).
36
+ and(A.is(:drinks)).
37
+ and(B.is(["John","beer"])).
38
+ map{K} == ["John".drinks("beer")] }
39
+ end
40
+ end
41
+
42
+
43
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Term builtins", :rubylog => true do
4
+ before do
5
+ predicate_for Symbol, ".likes"
6
+ end
7
+
8
+ describe "in" do
9
+ before do
10
+ :john.likes! :beer
11
+ :jane.likes! :milk
12
+ end
13
+
14
+ it "works for variables" do
15
+ (A.likes(B).and(B.in [])).map{[A,B]}.should == []
16
+ (A.likes(B).and(B.in [:milk])).map{[A,B]}.should == [[:jane, :milk]]
17
+ (A.likes(B).and(B.in [:beer])).map{[A,B]}.should == [[:john, :beer]]
18
+ (A.likes(B).and(B.in [:milk, :beer])).map{[A,B]}.should == [[:john, :beer], [:jane, :milk]]
19
+ end
20
+
21
+ it "works with blocks" do
22
+ (A.likes(B).and(B.in {[]})).map{[A,B]}.should == []
23
+ (A.likes(B).and(B.in {[A,:milk]})).map{[A,B]}.should == [[:jane, :milk]]
24
+ (A.likes(B).and(B.in {[:beer]})).map{[A,B]}.should == [[:john, :beer]]
25
+ (A.likes(B).and(B.in {[B]})).map{[A,B]}.should == [[:john, :beer], [:jane, :milk]]
26
+ end
27
+
28
+ it "works as iterator" do
29
+ (A.in{[1,3,4]}).map{A}.should == [1,3,4]
30
+ (A.in [1,3,4]).map{A}.should == [1,3,4]
31
+ end
32
+
33
+ it "works as search" do
34
+ (1.in{[1,3,4]}).to_a.should == [nil]
35
+ (2.in{[1,3,4]}).to_a.should == []
36
+ (1.in [1,3,4]).to_a.should == [nil]
37
+ (2.in [1,3,4]).to_a.should == []
38
+ end
39
+
40
+ it "works with clauses" do
41
+ (A.likes(B).and B.in{:john.likes(X).map{X}}).map{[A,B]}.should == [[:john, :beer]]
42
+ end
43
+
44
+ it "checks instatiation" do
45
+ expect { 5.in(B).map{B} }.to raise_error Rubylog::InstantiationError
46
+ end
47
+
48
+ end
49
+
50
+ describe "not_in" do
51
+ specify do
52
+ (1.not_in{[1,3,4]}).to_a.should == []
53
+ (2.not_in{[1,3,4]}).to_a.should == [nil]
54
+ (1.not_in [1,3,4]).to_a.should == []
55
+ (2.not_in [1,3,4]).to_a.should == [nil]
56
+ end
57
+ end
58
+
59
+ describe "is" do
60
+ before do
61
+ :john.likes! :beer
62
+ :jane.likes! :milk
63
+ end
64
+
65
+ it "works for variables" do
66
+ (A.likes(B).and(B.is :milk)).map{[A,B]}.should == [[:jane, :milk]]
67
+ (A.likes(B).and(:milk.is B)).map{[A,B]}.should == [[:jane, :milk]]
68
+ end
69
+
70
+ it "works as calculation" do
71
+ (A.is {|| 4+4}).map{A}.should == [8]
72
+ (A.is {4+4}).map{A}.should == [8]
73
+ (A.is(4).and A.is{2*2}).map{A}.should == [4]
74
+ (A.is(4).and A.is{2*3}).map{A}.should == []
75
+ end
76
+
77
+ it "works as calculation with vars" do
78
+ (A.is(4).and B.is{A*4}).map{[A,B]}.should == [[4,16]]
79
+ (A.is(4).and A.is{A*1}).map{A}.should == [4]
80
+ (A.is(4).and A.is{A*2}).map{A}.should == []
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -0,0 +1,132 @@
1
+ require "spec_helper"
2
+
3
+ describe "queries", :rubylog=>true do
4
+ before do
5
+ predicate_for Symbol, ".likes(Drink)"
6
+ end
7
+
8
+ it "can be run with true?" do
9
+ true?(:john.likes :beer).should be_false
10
+ :john.likes! :beer
11
+ true?(:john.likes :beer).should be_true
12
+ end
13
+
14
+ it "can be run with question mark" do
15
+ :john.likes?(:beer).should be_false
16
+ :john.likes! :beer
17
+ :john.likes?(:beer).should be_true
18
+ end
19
+
20
+ it "can be run with true?" do
21
+ (:john.likes(:beer)).true?.should be_false
22
+ :john.likes! :beer
23
+ (:john.likes(:beer)).true?.should be_true
24
+ end
25
+
26
+ it "can be run with solve" do
27
+ result = false
28
+ solve(:john.likes(:beer)) { result = true }
29
+ result.should == false
30
+ :john.likes! :beer
31
+ solve(:john.likes(:beer)) { result = true }
32
+ result.should == true
33
+ end
34
+
35
+ it "work with variables" do
36
+ :john.likes?(X).should be_false
37
+ :john.likes! :water
38
+ :john.likes?(X).should be_true
39
+ end
40
+
41
+ it "yield all solutions" do
42
+ :john.likes! :beer
43
+ :john.likes! :milk
44
+
45
+ k=[]
46
+ (:john.likes X).each{k << X}
47
+ k.should == [:beer, :milk]
48
+ end
49
+
50
+ it "yield all solutions with solve" do
51
+ :john.likes! :beer
52
+ :john.likes! :milk
53
+
54
+ k=[]
55
+ (:john.likes X).solve{k << X}
56
+ k.should == [:beer, :milk]
57
+ end
58
+
59
+ it "yield all solutions with solve and multiple vars and multiple block parameters" do
60
+ :john.likes! :beer
61
+ :jane.likes! :milk
62
+ :jane.likes! :water
63
+
64
+ k=[]
65
+ (X.likes Y).solve{k << [X,Y]}
66
+ k.should == [[:john, :beer], [:jane, :milk], [:jane, :water]]
67
+ end
68
+
69
+ it "ignore don't-care variables" do
70
+ :john.likes! :beer
71
+
72
+ k=[]
73
+ ANYONE.likes(X).each{k << [ANYONE,X]}
74
+ k.should == [[ANYONE, :beer]]
75
+
76
+ k=[]
77
+ X.likes(ANYTHING).each{k << [X,ANYTHING]}
78
+ k.should == [[:john, ANYTHING]]
79
+ end
80
+
81
+ it "leaves unboud variables as they are" do
82
+ res = []
83
+ A.likes(B).if {res << A << B }
84
+ A.likes? :beer
85
+ res.should eql [A,:beer]
86
+ end
87
+
88
+ it "substitutes deeper variables" do
89
+ res = []
90
+ A.likes(B).if {res << A << B; true}
91
+ (A.is(:john).and B.is(:swimming.in C).and \
92
+ C.is(:sea).and A.likes B).map{[A,B,C]}.should == [[:john,:swimming.in(:sea),:sea]]
93
+ res.should == [:john, :swimming.in(:sea)]
94
+ end
95
+
96
+ it "leaves deeper unboud variables as they are" do
97
+ res = []
98
+ A.likes(B).if {res << A << B; true}
99
+ (A.is(:john).and B.is(:swimming.in C).and A.likes B).map{[A,B,C]}.should eql [[:john,:swimming.in(C),C]]
100
+ res.should == [:john, :swimming.in(C)]
101
+ end
102
+
103
+ describe "support Enumerable" do
104
+ before do
105
+ :john.likes! :beer
106
+ :john.likes! :milk
107
+ end
108
+
109
+ it "#all?, #any? and #none?" do
110
+ (:john.likes A).all?{Symbol===A}.should be_true
111
+ (:john.likes A).all?{A == :beer}.should be_false
112
+ (:john.likes A).all?{A == :beer or A == :milk}.should be_true
113
+ (:john.likes A).any?{A == :beer}.should be_true
114
+ (:john.likes A).any?{A == :milk}.should be_true
115
+ (:john.likes A).any?{A == :water}.should be_false
116
+ (:john.likes A).none?{A == :water}.should be_true
117
+ (:john.likes A).none?{A == :beer}.should be_false
118
+ end
119
+
120
+ it "#to_a" do
121
+ (:john.likes A).to_a.should == [nil, nil]
122
+ (X.likes A).to_a.should == [nil, nil]
123
+ (ANYONE.likes A).to_a.should == [nil, nil]
124
+ end
125
+
126
+ it "#map" do
127
+ (:john.likes A).map{A.to_s}.should == ['beer', 'milk']
128
+ end
129
+
130
+ end
131
+
132
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ describe Rubylog::ContextModules::Predicates, :rubylog=>true do
4
+ describe "#predicate_for" do
5
+
6
+ specify "can accept humanized predicate" do
7
+ predicate_for String, ".long"
8
+ L.long.if { L.length > 10 }
9
+ "0123456789".should_not be_long
10
+ "01234567890".should be_long
11
+ end
12
+
13
+ specify "can accept space-separated predicates" do
14
+ predicate_for String, ".long .short"
15
+ L.long.if { L.length > 10 }
16
+ L.short.unless L.long
17
+ "01234567890".should_not be_short
18
+ end
19
+
20
+ specify "can accept list of predicates" do
21
+ predicate_for String, ".long", ".short"
22
+ L.long.if { L.length > 10 }
23
+ L.short.unless L.long
24
+ "01234567890".should_not be_short
25
+ end
26
+
27
+ specify "can accept array of predicates" do
28
+ predicate_for String, %w".long .short"
29
+ L.long.if { L.length > 10 }
30
+ L.short.unless L.long
31
+ "01234567890".should_not be_short
32
+ end
33
+ end
34
+
35
+ describe "#humanize_indicator" do
36
+ specify { humanize_indicator([:fail,0]).should == ":fail" }
37
+ specify { humanize_indicator([:false,1]).should == ".false" }
38
+ specify { humanize_indicator([:and,2]).should == ".and()" }
39
+ specify { humanize_indicator([:splits,3]).should == ".splits(,)" }
40
+ specify { humanize_indicator([:is,4]).should == ".is(,,)" }
41
+ end
42
+
43
+ describe "#unhumanize_indicator" do
44
+ specify { unhumanize_indicator(":fail" ).should == [:fail,0] }
45
+ specify { unhumanize_indicator(".false" ).should == [:false,1] }
46
+ specify { unhumanize_indicator(".and()" ).should == [:and,2] }
47
+ specify { unhumanize_indicator(".splits(,)" ).should == [:splits,3] }
48
+ specify { unhumanize_indicator(".is(,,)" ).should == [:is,4] }
49
+
50
+ describe "with comment variables" do
51
+ specify { unhumanize_indicator("Predicate.false" ).should == [:false,1] }
52
+ specify { unhumanize_indicator("a.and(b)" ).should == [:and,2] }
53
+ specify { unhumanize_indicator("LIST.splits(HEAD,TAIL)" ).should == [:splits,3] }
54
+ specify { unhumanize_indicator("C.is(A,OP,B)" ).should == [:is,4] }
55
+ end
56
+ end
57
+ end