rubylog 1.0.0 → 2.0pre1

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 (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