mini_kraken 0.1.03 → 0.1.08
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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -1
- data/CHANGELOG.md +54 -3
- data/Gemfile +3 -1
- data/README.md +22 -1
- data/Rakefile +5 -3
- data/lib/mini_kraken.rb +3 -1
- data/lib/mini_kraken/core/any_value.rb +9 -7
- data/lib/mini_kraken/core/association.rb +20 -7
- data/lib/mini_kraken/core/association_walker.rb +5 -1
- data/lib/mini_kraken/core/atomic_term.rb +5 -3
- data/lib/mini_kraken/core/binary_relation.rb +8 -6
- data/lib/mini_kraken/core/composite_goal.rb +46 -0
- data/lib/mini_kraken/core/composite_term.rb +7 -20
- data/lib/mini_kraken/core/conj2.rb +77 -0
- data/lib/mini_kraken/core/cons_cell.rb +51 -41
- data/lib/mini_kraken/core/designation.rb +55 -0
- data/lib/mini_kraken/core/disj2.rb +71 -0
- data/lib/mini_kraken/core/duck_fiber.rb +4 -2
- data/lib/mini_kraken/core/environment.rb +25 -11
- data/lib/mini_kraken/core/equals.rb +128 -189
- data/lib/mini_kraken/core/fail.rb +20 -14
- data/lib/mini_kraken/core/freshness.rb +11 -8
- data/lib/mini_kraken/core/goal.rb +8 -4
- data/lib/mini_kraken/core/goal_arg.rb +10 -0
- data/lib/mini_kraken/core/goal_relation.rb +28 -0
- data/lib/mini_kraken/core/k_integer.rb +4 -3
- data/lib/mini_kraken/core/k_symbol.rb +4 -3
- data/lib/mini_kraken/core/nullary_relation.rb +3 -1
- data/lib/mini_kraken/core/outcome.rb +29 -25
- data/lib/mini_kraken/core/relation.rb +4 -18
- data/lib/mini_kraken/core/succeed.rb +20 -14
- data/lib/mini_kraken/core/term.rb +7 -2
- data/lib/mini_kraken/core/variable.rb +11 -25
- data/lib/mini_kraken/core/variable_ref.rb +12 -59
- data/lib/mini_kraken/core/vocabulary.rb +267 -48
- data/lib/mini_kraken/glue/fresh_env.rb +5 -3
- data/lib/mini_kraken/glue/run_star_expression.rb +18 -8
- data/lib/mini_kraken/version.rb +3 -1
- data/mini_kraken.gemspec +15 -13
- data/spec/core/association_spec.rb +4 -4
- data/spec/core/association_walker_spec.rb +25 -24
- data/spec/core/conj2_spec.rb +114 -0
- data/spec/core/cons_cell_spec.rb +12 -3
- data/spec/core/disj2_spec.rb +99 -0
- data/spec/core/duck_fiber_spec.rb +22 -12
- data/spec/core/environment_spec.rb +16 -28
- data/spec/core/equals_spec.rb +7 -7
- data/spec/core/fail_spec.rb +7 -7
- data/spec/core/goal_spec.rb +10 -10
- data/spec/core/k_symbol_spec.rb +5 -6
- data/spec/core/succeed_spec.rb +4 -4
- data/spec/core/variable_ref_spec.rb +0 -4
- data/spec/core/vocabulary_spec.rb +33 -27
- data/spec/glue/fresh_env_spec.rb +1 -1
- data/spec/glue/run_star_expression_spec.rb +213 -60
- data/spec/mini_kraken_spec.rb +4 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/support/factory_methods.rb +20 -2
- metadata +12 -2
data/spec/glue/fresh_env_spec.rb
CHANGED
@@ -15,7 +15,7 @@ module MiniKraken
|
|
15
15
|
let(:pea) { Core::KSymbol.new(:pea) }
|
16
16
|
let(:pod) { Core::KSymbol.new(:pod) }
|
17
17
|
let(:sample_goal) do
|
18
|
-
Core::Goal.new(Core::Equals.instance, [pea, pod])
|
18
|
+
Core::Goal.new(Core::Equals.instance, [pea, pod])
|
19
19
|
end
|
20
20
|
subject { FreshEnv.new(['q'], sample_goal) }
|
21
21
|
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
4
|
require_relative '../../lib/mini_kraken/core/goal'
|
5
|
+
require_relative '../../lib/mini_kraken/core/conj2'
|
6
|
+
require_relative '../../lib/mini_kraken/core/disj2'
|
5
7
|
require_relative '../../lib/mini_kraken/core/equals'
|
6
8
|
require_relative '../../lib/mini_kraken/core/fail'
|
7
9
|
require_relative '../../lib/mini_kraken/core/succeed'
|
@@ -37,24 +39,30 @@ module MiniKraken
|
|
37
39
|
end # context
|
38
40
|
|
39
41
|
context 'Provided services:' do
|
42
|
+
let(:corn) { k_symbol(:corn) }
|
43
|
+
let(:meal) { k_symbol(:meal) }
|
44
|
+
let(:oil) { k_symbol(:oil) }
|
45
|
+
let(:olive) { k_symbol(:olive) }
|
46
|
+
let(:virgin) { k_symbol(:virgin) }
|
40
47
|
let(:ref_q) { Core::VariableRef.new('q') }
|
41
48
|
let(:ref_x) { Core::VariableRef.new('x') }
|
42
49
|
let(:ref_y) { Core::VariableRef.new('y') }
|
43
50
|
let(:ref_s) { Core::VariableRef.new('s') }
|
44
51
|
let(:ref_t) { Core::VariableRef.new('t') }
|
45
|
-
let(:ref_u) { Core::VariableRef.new('u') }
|
52
|
+
let(:ref_u) { Core::VariableRef.new('u') }
|
53
|
+
let(:fails) { Core::Goal.new(Core::Fail.instance, []) }
|
54
|
+
let(:succeeds) { Core::Goal.new(Core::Succeed.instance, []) }
|
46
55
|
|
47
|
-
it
|
56
|
+
it 'should return a null list with the fail goal' do
|
48
57
|
# Reasoned S2, frame 1:7
|
49
58
|
# (run* q #u) ;; => ()
|
50
59
|
failing = Core::Goal.new(Core::Fail.instance, [])
|
51
60
|
instance = RunStarExpression.new('q', failing)
|
52
61
|
|
53
62
|
expect(instance.run).to be_null
|
54
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
55
63
|
end
|
56
64
|
|
57
|
-
it
|
65
|
+
it 'should return a null list when a goal fails' do
|
58
66
|
# Reasoned S2, frame 1:10
|
59
67
|
# (run* q (== 'pea 'pod) ;; => ()
|
60
68
|
|
@@ -69,7 +77,6 @@ module MiniKraken
|
|
69
77
|
# Reasoned S2, frame 1:11
|
70
78
|
# (run* q (== q 'pea) ;; => (pea)
|
71
79
|
expect(instance.run.car).to eq(pea)
|
72
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
73
80
|
end
|
74
81
|
|
75
82
|
it 'should unify the righthand variable(s)' do
|
@@ -79,19 +86,14 @@ module MiniKraken
|
|
79
86
|
# Reasoned S2, frame 1:12
|
80
87
|
# (run* q (== 'pea q) ;; => (pea)
|
81
88
|
expect(instance.run.car).to eq(pea)
|
82
|
-
|
83
|
-
# Reasoned S2, frame 1:15
|
84
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
85
89
|
end
|
86
90
|
|
87
91
|
it 'should return a null list with the succeed goal' do
|
88
|
-
|
89
|
-
instance = RunStarExpression.new('q', success)
|
92
|
+
instance = RunStarExpression.new('q', succeeds)
|
90
93
|
|
91
94
|
# (display (run* q succeed)) ;; => (_0)
|
92
95
|
# Reasoned S2, frame 1:16
|
93
96
|
result = instance.run
|
94
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
95
97
|
|
96
98
|
# Reasoned S2, frame 1:17
|
97
99
|
expect(result.car).to eq(any_value(0))
|
@@ -104,11 +106,10 @@ module MiniKraken
|
|
104
106
|
# (display (run* q (== 'pea 'pea))) ;; => (_0)
|
105
107
|
# Reasoned S2, frame 1:19
|
106
108
|
result = instance.run
|
107
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
108
109
|
expect(result.car).to eq(any_value(0))
|
109
110
|
end
|
110
111
|
|
111
|
-
it 'should keep variable fresh when no unification occurs (
|
112
|
+
it 'should keep variable fresh when no unification occurs (II)' do
|
112
113
|
ref1_q = Core::VariableRef.new('q')
|
113
114
|
ref2_q = Core::VariableRef.new('q')
|
114
115
|
goal = equals_goal(ref1_q, ref2_q)
|
@@ -117,7 +118,6 @@ module MiniKraken
|
|
117
118
|
# (display (run* q (== q q))) ;; => (_0)
|
118
119
|
# Reasoned S2, frame 1:20
|
119
120
|
result = instance.run
|
120
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
121
121
|
expect(result.car).to eq(any_value(0))
|
122
122
|
end
|
123
123
|
|
@@ -129,8 +129,6 @@ module MiniKraken
|
|
129
129
|
# Reasoned S2, frame 1:21..23
|
130
130
|
# (run* q (fresh (x) (== 'pea q))) ;; => (pea)
|
131
131
|
result = instance.run
|
132
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
133
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
134
132
|
|
135
133
|
# Reasoned S2, frame 1:40
|
136
134
|
expect(ref_q.different_from?(ref_x, fresh_env)).to be_truthy
|
@@ -145,8 +143,6 @@ module MiniKraken
|
|
145
143
|
# Reasoned S2, frame 1:24
|
146
144
|
# (run* q (fresh (x) (== 'pea x))) ;; => (_0)
|
147
145
|
result = instance.run
|
148
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
149
|
-
expect(ref_x.fresh?(fresh_env)).to be_falsey
|
150
146
|
expect(result.car).to eq(any_value(0))
|
151
147
|
end
|
152
148
|
|
@@ -158,8 +154,6 @@ module MiniKraken
|
|
158
154
|
# Reasoned S2, frame 1:25
|
159
155
|
# (run* q (fresh (x) (== (cons x '()) q))) ;; => ((_0))
|
160
156
|
result = instance.run
|
161
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
162
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
163
157
|
expect(result.car).to eq(cons(any_value(0)))
|
164
158
|
end
|
165
159
|
|
@@ -190,7 +184,6 @@ module MiniKraken
|
|
190
184
|
# Reasoned S2, frame 1:32
|
191
185
|
# (run* q (== '(((pea)) pod) '(((pea)) pod))) ;; => (_0)
|
192
186
|
result = instance.run
|
193
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
194
187
|
expect(result.car).to eq(any_value(0))
|
195
188
|
end
|
196
189
|
|
@@ -204,7 +197,6 @@ module MiniKraken
|
|
204
197
|
# Reasoned S2, frame 1:33
|
205
198
|
# (run* q (== '(((pea)) pod) `(((pea)) ,q))) ;; => ('pod)
|
206
199
|
result = instance.run
|
207
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
208
200
|
expect(result.car).to eq(pod)
|
209
201
|
end
|
210
202
|
|
@@ -217,11 +209,10 @@ module MiniKraken
|
|
217
209
|
# Reasoned S2, frame 1:34
|
218
210
|
# (run* q (== '(((,q)) pod) `(((pea)) pod))) ;; => ('pod)
|
219
211
|
result = instance.run
|
220
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
221
212
|
expect(result.car).to eq(pea)
|
222
213
|
end
|
223
214
|
|
224
|
-
it 'should unify complex equality expressions (
|
215
|
+
it 'should unify complex equality expressions (III)' do
|
225
216
|
expr1 = cons(cons(cons(ref_q)), pod)
|
226
217
|
expr2 = cons(cons(cons(ref_x)), pod)
|
227
218
|
goal = equals_goal(expr1, expr2)
|
@@ -231,12 +222,10 @@ module MiniKraken
|
|
231
222
|
# Reasoned S2, frame 1:35
|
232
223
|
# (run* q (fresh (x) (== '(((,q)) pod) `(((,x)) pod)))) ;; => (_0)
|
233
224
|
result = instance.run
|
234
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
235
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
236
225
|
expect(result.car).to eq(any_value(0))
|
237
226
|
end
|
238
227
|
|
239
|
-
it 'should unify complex equality expressions (
|
228
|
+
it 'should unify complex equality expressions (IV)' do
|
240
229
|
# Reasoned S2, frame 1:36
|
241
230
|
# (run* q (fresh (x) (== '(((,q)) (,x)) `(((,x)) pod)))) ;; => ('pod)
|
242
231
|
expr1 = cons(cons(cons(ref_q)), ref_x)
|
@@ -246,11 +235,6 @@ module MiniKraken
|
|
246
235
|
instance = RunStarExpression.new('q', fresh_env)
|
247
236
|
|
248
237
|
result = instance.run
|
249
|
-
|
250
|
-
# Does propagate work correctly?
|
251
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy # x isn't defined here
|
252
|
-
expect(ref_q.fresh?(fresh_env)).to be_falsey
|
253
|
-
expect(ref_x.fresh?(fresh_env)).to be_falsey
|
254
238
|
expect(result.car).to eq(pod)
|
255
239
|
end
|
256
240
|
|
@@ -263,9 +247,6 @@ module MiniKraken
|
|
263
247
|
instance = RunStarExpression.new('q', fresh_env)
|
264
248
|
|
265
249
|
result = instance.run
|
266
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy # x isn't defined here
|
267
|
-
expect(ref_q.fresh?(fresh_env)).to be_truthy
|
268
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
269
250
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(0))))
|
270
251
|
end
|
271
252
|
|
@@ -280,17 +261,16 @@ module MiniKraken
|
|
280
261
|
instance = RunStarExpression.new('q', fresh_env_x)
|
281
262
|
|
282
263
|
result = instance.run
|
283
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
284
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
285
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
286
|
-
expect(ref_x.bound?(fresh_env_y)).to be_truthy
|
287
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
288
|
-
expect(ref_y.bound?(fresh_env_y)).to be_truthy
|
289
264
|
|
290
265
|
# y should be fused with x...
|
266
|
+
var_x = fresh_env_y.name2var('x')
|
267
|
+
var_y = fresh_env_y.name2var('y')
|
268
|
+
expect(var_x.i_name).to eq(var_y.i_name)
|
291
269
|
expect(ref_y.fused_with?(ref_x, fresh_env_y)).to be_truthy
|
292
270
|
expect(ref_x.names_fused(fresh_env_y)).to eq(['y'])
|
293
271
|
expect(ref_y.names_fused(fresh_env_y)).to eq(['x'])
|
272
|
+
|
273
|
+
# q should be bound to '(,x ,x)
|
294
274
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(0))))
|
295
275
|
end
|
296
276
|
|
@@ -304,16 +284,10 @@ module MiniKraken
|
|
304
284
|
instance = RunStarExpression.new('q', fresh_env_x)
|
305
285
|
|
306
286
|
result = instance.run
|
307
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
308
287
|
# q should be bound to '(,x ,y)
|
309
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
310
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
311
|
-
expect(ref_x.bound?(fresh_env_y)).to be_falsey
|
312
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
313
|
-
expect(ref_y.bound?(fresh_env_y)).to be_falsey
|
314
288
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
315
289
|
end
|
316
|
-
|
290
|
+
|
317
291
|
it 'should work with variable names' do
|
318
292
|
# Reasoned S2, frame 1:42
|
319
293
|
# (run* s (fresh (t) (fresh (u) (== '( ,t ,u) s)))) ;; => (_0 _1)
|
@@ -324,15 +298,9 @@ module MiniKraken
|
|
324
298
|
instance = RunStarExpression.new('s', fresh_env_t)
|
325
299
|
|
326
300
|
result = instance.run
|
327
|
-
expect(ref_s.fresh?(fresh_env_u)).to be_truthy
|
328
301
|
# s should be bound to '(,t ,u)
|
329
|
-
expect(ref_s.bound?(fresh_env_u)).to be_truthy
|
330
|
-
expect(ref_t.fresh?(fresh_env_u)).to be_truthy
|
331
|
-
expect(ref_t.bound?(fresh_env_u)).to be_falsey
|
332
|
-
expect(ref_u.fresh?(fresh_env_u)).to be_truthy
|
333
|
-
expect(ref_u.bound?(fresh_env_u)).to be_falsey
|
334
302
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
335
|
-
end
|
303
|
+
end
|
336
304
|
|
337
305
|
it 'should support repeated variables' do
|
338
306
|
# Reasoned S2, frame 1:43
|
@@ -344,13 +312,198 @@ module MiniKraken
|
|
344
312
|
instance = RunStarExpression.new('q', fresh_env_x)
|
345
313
|
|
346
314
|
result = instance.run
|
347
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
348
315
|
# q should be bound to '(,x ,y, ,x)
|
349
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
350
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
351
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
352
316
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1), cons(any_value(0)))))
|
353
|
-
end
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'should support conjunction of two succeed' do
|
320
|
+
goal = conj2_goal(succeeds, succeeds)
|
321
|
+
instance = RunStarExpression.new('q', goal)
|
322
|
+
|
323
|
+
# Reasoned S2, frame 1:50
|
324
|
+
# (run* q (conj2 succeed succeed)) ;; => (_0)
|
325
|
+
result = instance.run
|
326
|
+
expect(result.car).to eq(any_value(0))
|
327
|
+
end
|
328
|
+
|
329
|
+
# TODO: fix erratic RSpec failure
|
330
|
+
it 'should support conjunction of one succeed and a successful goal' do
|
331
|
+
subgoal = equals_goal(corn, ref_q)
|
332
|
+
goal = conj2_goal(succeeds, subgoal)
|
333
|
+
instance = RunStarExpression.new('q', goal)
|
334
|
+
|
335
|
+
# Reasoned S2, frame 1:51
|
336
|
+
# (run* q (conj2 succeed (== 'corn q)) ;; => ('corn)
|
337
|
+
result = instance.run
|
338
|
+
expect(result.car).to eq(corn)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'should support conjunction of one fail and a successful goal' do
|
342
|
+
subgoal = equals_goal(corn, ref_q)
|
343
|
+
goal = conj2_goal(fails, subgoal)
|
344
|
+
instance = RunStarExpression.new('q', goal)
|
345
|
+
|
346
|
+
# Reasoned S2, frame 1:52
|
347
|
+
# (run* q (conj2 fail (== 'corn q)) ;; => ()
|
348
|
+
expect(instance.run).to be_null
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'should support conjunction of two contradictory goals' do
|
352
|
+
subgoal1 = equals_goal(corn, ref_q)
|
353
|
+
subgoal2 = equals_goal(meal, ref_q)
|
354
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
355
|
+
instance = RunStarExpression.new('q', goal)
|
356
|
+
|
357
|
+
# Reasoned S2, frame 1:53
|
358
|
+
# (run* q (conj2 (== 'corn q)(== 'meal q)) ;; => ()
|
359
|
+
expect(instance.run).to be_null
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'should succeed the conjunction of two identical goals' do
|
363
|
+
subgoal1 = equals_goal(corn, ref_q)
|
364
|
+
subgoal2 = equals_goal(corn, ref_q)
|
365
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
366
|
+
instance = RunStarExpression.new('q', goal)
|
367
|
+
|
368
|
+
# Reasoned S2, frame 1:54
|
369
|
+
# (run* q (conj2 (== 'corn q)(== 'corn q)) ;; => ('corn)
|
370
|
+
result = instance.run
|
371
|
+
expect(result.car).to eq(corn)
|
372
|
+
end
|
373
|
+
|
374
|
+
it 'should not yield solution when both disjunction arguments fail' do
|
375
|
+
goal = disj2_goal(fails, fails)
|
376
|
+
instance = RunStarExpression.new('q', goal)
|
377
|
+
|
378
|
+
# Reasoned S2, frame 1:55
|
379
|
+
# (run* q (disj2 fail fail)) ;; => ()
|
380
|
+
expect(instance.run).to be_null
|
381
|
+
end
|
382
|
+
|
383
|
+
it 'should yield solution when first argument succeed' do
|
384
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_q])
|
385
|
+
goal = disj2_goal(subgoal, fails)
|
386
|
+
instance = RunStarExpression.new('q', goal)
|
387
|
+
|
388
|
+
# Reasoned S2, frame 1:56
|
389
|
+
# (run* q (disj2 (equals 'olive q) fail)) ;; => ('olive)
|
390
|
+
result = instance.run
|
391
|
+
expect(result.car).to eq(olive)
|
392
|
+
end
|
393
|
+
|
394
|
+
it 'should yield solution when second argument succeed' do
|
395
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_q])
|
396
|
+
goal = disj2_goal(fails, subgoal)
|
397
|
+
instance = RunStarExpression.new('q', goal)
|
398
|
+
|
399
|
+
# Reasoned S2, frame 1:57
|
400
|
+
# (run* q (disj2 fail (equals 'oil q)) ;; => (oil)
|
401
|
+
result = instance.run
|
402
|
+
expect(result.car).to eq(oil)
|
403
|
+
end
|
404
|
+
|
405
|
+
it 'should yield solutions when both arguments succeed' do
|
406
|
+
subgoal1 = Core::Goal.new(Core::Equals.instance, [olive, ref_q])
|
407
|
+
subgoal2 = Core::Goal.new(Core::Equals.instance, [oil, ref_q])
|
408
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
409
|
+
instance = RunStarExpression.new('q', goal)
|
410
|
+
|
411
|
+
# Reasoned S2, frame 1:58
|
412
|
+
# (run* q (disj2 (equals 'olive q) (equals 'oil q)) ;; => (olive oil)
|
413
|
+
result = instance.run
|
414
|
+
expect(result.car).to eq(olive)
|
415
|
+
expect(result.cdr.car).to eq(oil)
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'should support the nesting of variables and disjunction' do
|
419
|
+
# Reasoned S2, frame 1:59
|
420
|
+
# (run* q (fresh (x) (fresh (y) (disj2 (== '( ,x ,y ) q) (== '( ,x ,y ) q)))))
|
421
|
+
# ;; => ((_0 _1) (_0 _1))
|
422
|
+
expr1 = cons(ref_x, cons(ref_y))
|
423
|
+
subgoal1 = equals_goal(expr1, ref_q)
|
424
|
+
expr2 = cons(ref_y, cons(ref_x))
|
425
|
+
subgoal2 = equals_goal(expr2, ref_q)
|
426
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
427
|
+
fresh_env_y = FreshEnv.new(['y'], goal)
|
428
|
+
fresh_env_x = FreshEnv.new(['x'], fresh_env_y)
|
429
|
+
instance = RunStarExpression.new('q', fresh_env_x)
|
430
|
+
|
431
|
+
result = instance.run
|
432
|
+
# q should be bound to '(,x ,y), then to '(,y ,x)
|
433
|
+
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
434
|
+
expect(result.cdr.car).to eq(cons(any_value(0), cons(any_value(1))))
|
435
|
+
end
|
436
|
+
|
437
|
+
it 'should accept nesting of disj2 and conj2 (I)' do
|
438
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
439
|
+
conjunction = conj2_goal(conj_subgoal, fails)
|
440
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
441
|
+
goal = disj2_goal(conjunction, subgoal)
|
442
|
+
instance = RunStarExpression.new('x', goal)
|
443
|
+
|
444
|
+
# Reasoned S2, frame 1:62
|
445
|
+
# (run* x (disj2
|
446
|
+
# (conj2 (== 'olive x) fail)
|
447
|
+
# ('oil x))) ;; => (oil)
|
448
|
+
result = instance.run
|
449
|
+
expect(result.car).to eq(oil)
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'should accept nesting of disj2 and conj2 (II)' do
|
453
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
454
|
+
conjunction = conj2_goal(conj_subgoal, succeeds)
|
455
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
456
|
+
goal = disj2_goal(conjunction, subgoal)
|
457
|
+
instance = RunStarExpression.new('x', goal)
|
458
|
+
|
459
|
+
# Reasoned S2, frame 1:63
|
460
|
+
# (run* x (disj2
|
461
|
+
# (conj2 (== 'olive x) succeed)
|
462
|
+
# ('oil x))) ;; => (olive oil)
|
463
|
+
result = instance.run
|
464
|
+
expect(result.car).to eq(olive)
|
465
|
+
expect(result.cdr.car).to eq(oil)
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'should accept nesting of disj2 and conj2 (III)' do
|
469
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
470
|
+
conjunction = conj2_goal(conj_subgoal, succeeds)
|
471
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
472
|
+
goal = disj2_goal(subgoal, conjunction)
|
473
|
+
instance = RunStarExpression.new('x', goal)
|
474
|
+
|
475
|
+
# Reasoned S2, frame 1:64
|
476
|
+
# (run* x (disj2
|
477
|
+
# ('oil x)
|
478
|
+
# (conj2 (== 'olive x) succeed))) ;; => (oil olive)
|
479
|
+
result = instance.run
|
480
|
+
expect(result.car).to eq(oil)
|
481
|
+
expect(result.cdr.car).to eq(olive)
|
482
|
+
end
|
483
|
+
|
484
|
+
it 'should accept nesting of disj2 and conj2 (IV)' do
|
485
|
+
oil_goal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
486
|
+
disja = disj2_goal(succeeds, oil_goal)
|
487
|
+
olive_goal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
488
|
+
disjb = disj2_goal(olive_goal, disja)
|
489
|
+
virgin_goal = Core::Goal.new(Core::Equals.instance, [virgin, ref_x])
|
490
|
+
conjunction = conj2_goal(virgin_goal, fails)
|
491
|
+
goal = disj2_goal(conjunction, disjb)
|
492
|
+
instance = RunStarExpression.new('x', goal)
|
493
|
+
|
494
|
+
# Reasoned S2, frame 1:65
|
495
|
+
# (run* x (disj2
|
496
|
+
# (conj2(== 'virgin x) fails)
|
497
|
+
# (disj2
|
498
|
+
# (== 'olive x)
|
499
|
+
# (dis2
|
500
|
+
# succeeds
|
501
|
+
# (== 'oil x))))) ;; => (olive _0 oil)
|
502
|
+
result = instance.run
|
503
|
+
expect(result.car).to eq(olive)
|
504
|
+
expect(result.cdr.car).to eq(any_value(0))
|
505
|
+
expect(result.cdr.cdr.car).to eq(oil)
|
506
|
+
end
|
354
507
|
end # context
|
355
508
|
end # describe
|
356
509
|
end # module
|