porolog 0.0.7 → 0.0.8
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/README.md +18 -4
- data/bin/porolog +38 -2
- data/coverage/badge.svg +1 -1
- data/coverage/index.html +52327 -6692
- data/doc/Array.html +113 -33
- data/doc/Object.html +11 -17
- data/doc/Porolog.html +3681 -73
- data/doc/Symbol.html +17 -20
- data/doc/_index.html +181 -13
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +28 -38
- data/doc/index.html +28 -38
- data/doc/method_list.html +871 -167
- data/doc/top-level-namespace.html +2 -2
- data/lib/porolog.rb +1015 -2
- data/lib/porolog/arguments.rb +16 -14
- data/lib/porolog/core_ext.rb +6 -0
- data/lib/porolog/error.rb +6 -0
- data/lib/porolog/goal.rb +205 -68
- data/lib/porolog/instantiation.rb +300 -0
- data/lib/porolog/predicate.rb +33 -16
- data/lib/porolog/rule.rb +129 -2
- data/lib/porolog/scope.rb +3 -3
- data/lib/porolog/tail.rb +52 -0
- data/lib/porolog/value.rb +9 -12
- data/lib/porolog/variable.rb +307 -0
- data/test/porolog/arguments_test.rb +217 -135
- data/test/porolog/core_ext_test.rb +24 -17
- data/test/porolog/goal_test.rb +481 -74
- data/test/porolog/instantiation_test.rb +874 -0
- data/test/porolog/porolog_test.rb +2121 -13
- data/test/porolog/predicate_test.rb +1 -1
- data/test/porolog/rule_test.rb +395 -0
- data/test/porolog/scope_test.rb +0 -2
- data/test/porolog/tail_test.rb +127 -0
- data/test/porolog/value_test.rb +1 -1
- data/test/porolog/variable_test.rb +1625 -0
- data/test/test_helper.rb +78 -5
- metadata +12 -4
@@ -172,7 +172,7 @@ describe 'Porolog' do
|
|
172
172
|
|
173
173
|
it 'can create predicates in different scopes' do
|
174
174
|
left = Scope.new :left
|
175
|
-
#right = Scope.new :right
|
175
|
+
#right = Scope.new :right # Not explicitly creating scope :right
|
176
176
|
|
177
177
|
assert_equal left, Predicate.scope(:left)
|
178
178
|
assert_equal :left, Predicate.scope.name
|
data/test/porolog/rule_test.rb
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
# created
|
6
6
|
#
|
7
7
|
|
8
|
+
|
8
9
|
require_relative '../test_helper'
|
9
10
|
|
10
11
|
describe 'Porolog' do
|
@@ -108,6 +109,400 @@ describe 'Porolog' do
|
|
108
109
|
|
109
110
|
end
|
110
111
|
|
112
|
+
describe '#satisfy' do
|
113
|
+
|
114
|
+
it 'should create a subgoal and unify with the goal' do
|
115
|
+
pred = Predicate.new :pred
|
116
|
+
args = Arguments.new pred, [:a,:b,:c]
|
117
|
+
defn = [true]
|
118
|
+
rule = Rule.new args, defn
|
119
|
+
|
120
|
+
goal = new_goal :pred, :x, :y, :z
|
121
|
+
|
122
|
+
called = false
|
123
|
+
rule.satisfy(goal) do |solution_goal|
|
124
|
+
called = true
|
125
|
+
|
126
|
+
assert_Goal solution_goal, :pred, [:a, :b, :c].map{|name| solution_goal.variable(name) }
|
127
|
+
assert_Goal_variables solution_goal, { a: nil, b: nil, c: nil }, [
|
128
|
+
'Goal2.:a',
|
129
|
+
' Goal1.:x',
|
130
|
+
'Goal2.:b',
|
131
|
+
' Goal1.:y',
|
132
|
+
'Goal2.:c',
|
133
|
+
' Goal1.:z',
|
134
|
+
].join("\n")
|
135
|
+
|
136
|
+
assert_equal goal, solution_goal.calling_goal
|
137
|
+
end
|
138
|
+
|
139
|
+
assert called, 'the satisfy block should be called'
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should delete the subgoal even if it does not unify with the goal' do
|
143
|
+
pred = Predicate.new :alpha
|
144
|
+
args = Arguments.new pred, [1,2,3,4]
|
145
|
+
defn = [true]
|
146
|
+
rule = Rule.new args, defn
|
147
|
+
|
148
|
+
goal = new_goal :beta, :x, :y
|
149
|
+
|
150
|
+
subgoal = new_goal :gamma, :x, :y
|
151
|
+
subgoal.expects(:delete!).with().times(1)
|
152
|
+
subgoal_spy = Spy.on(Goal, :new).and_return(subgoal)
|
153
|
+
called = false
|
154
|
+
|
155
|
+
rule.satisfy(goal) do |solution_goal|
|
156
|
+
#:nocov:
|
157
|
+
called = true
|
158
|
+
#:nocov:
|
159
|
+
end
|
160
|
+
refute called, 'the satisfy block should not be called'
|
161
|
+
assert_equal 1, subgoal_spy.calls.size
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#satisfy_definition' do
|
167
|
+
|
168
|
+
it 'should call block with subgoal and return true when the definition is true' do
|
169
|
+
pred = Predicate.new :normal
|
170
|
+
args = Arguments.new pred, [12]
|
171
|
+
rule = Rule.new args, true
|
172
|
+
|
173
|
+
check = 56
|
174
|
+
result = rule.satisfy_definition(12, 34) do |subgoal|
|
175
|
+
assert_equal 34, subgoal
|
176
|
+
check = 78
|
177
|
+
end
|
178
|
+
assert_equal true, result
|
179
|
+
assert_equal 78, check
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should not call block but return false when the definition is false' do
|
183
|
+
pred = Predicate.new :negative
|
184
|
+
args = Arguments.new pred, [12]
|
185
|
+
rule = Rule.new args, false
|
186
|
+
|
187
|
+
check = 56
|
188
|
+
result = rule.satisfy_definition(12, 34) do |subgoal|
|
189
|
+
#:nocov:
|
190
|
+
check = 78
|
191
|
+
#:nocov:
|
192
|
+
end
|
193
|
+
assert_equal false, result
|
194
|
+
assert_equal 56, check
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should call block with subgoal when the definition is an Array' do
|
198
|
+
pred1 = Predicate.new :success
|
199
|
+
args1 = Arguments.new pred1, [:any]
|
200
|
+
Rule.new args1, true
|
201
|
+
|
202
|
+
pred2 = Predicate.new :conjunction
|
203
|
+
args2 = Arguments.new pred2, [12]
|
204
|
+
rule2 = Rule.new args2, [true,true,true]
|
205
|
+
|
206
|
+
check = 56
|
207
|
+
result = rule2.satisfy_definition(args1.goal, args2.goal) do |subgoal|
|
208
|
+
check = 78
|
209
|
+
end
|
210
|
+
assert_equal true, result
|
211
|
+
assert_equal 78, check
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'should raise an exception when the definition is unknown' do
|
215
|
+
predicate :strange
|
216
|
+
|
217
|
+
strange(12) << 3.4
|
218
|
+
|
219
|
+
exception = assert_raises Rule::DefinitionError do
|
220
|
+
strange(:X).solve
|
221
|
+
end
|
222
|
+
assert_equal 'UNEXPECTED TYPE OF DEFINITION: 3.4 (Float)', exception.message
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
describe '#satisfy_conjunction' do
|
228
|
+
|
229
|
+
let(:pred1 ) { Predicate.new :parent }
|
230
|
+
let(:pred2 ) { Predicate.new :child }
|
231
|
+
let(:args1 ) { Arguments.new pred1, [1,2,3,4] }
|
232
|
+
let(:args2 ) { Arguments.new pred2, [:x,:y] }
|
233
|
+
let(:goal ) { Goal.new args1, nil }
|
234
|
+
let(:subgoal) { Goal.new args2, goal }
|
235
|
+
|
236
|
+
it 'should handle CUT expression' do
|
237
|
+
rule = Rule.new args1, [:CUT,true]
|
238
|
+
|
239
|
+
goal.expects(:terminate!).with().times(1)
|
240
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
241
|
+
called = false
|
242
|
+
|
243
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
244
|
+
called = true
|
245
|
+
end
|
246
|
+
|
247
|
+
assert result, 'satisfy_conjunction should succeed'
|
248
|
+
assert called, 'the satisfy block should be called'
|
249
|
+
assert_equal 2, rule_spy.calls.size
|
250
|
+
assert_equal [goal, subgoal, [true]], rule_spy.calls[0].args # innermost call; finishes first
|
251
|
+
assert_equal [goal, subgoal, [:CUT,true]], rule_spy.calls[1].args # outermost call; finishes last
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should handle CUT expression at the end of a conjunction' do
|
255
|
+
rule = Rule.new args1, [:CUT]
|
256
|
+
|
257
|
+
goal.expects(:terminate!).with().times(1)
|
258
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
259
|
+
called = false
|
260
|
+
|
261
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
262
|
+
called = true
|
263
|
+
end
|
264
|
+
|
265
|
+
assert result, 'satisfy_conjunction should succeed'
|
266
|
+
assert called, 'the satisfy block should be called'
|
267
|
+
assert_equal 1, rule_spy.calls.size
|
268
|
+
assert_equal [goal, subgoal, [:CUT]], rule_spy.calls[0].args
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'should handle true expression' do
|
272
|
+
rule = Rule.new args1, [true]
|
273
|
+
|
274
|
+
goal.expects(:terminate!).with().times(0)
|
275
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
276
|
+
called = false
|
277
|
+
|
278
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
279
|
+
called = true
|
280
|
+
end
|
281
|
+
|
282
|
+
assert result, 'satisfy_conjunction should succeed'
|
283
|
+
assert called, 'the satisfy block should be called'
|
284
|
+
assert_equal 1, rule_spy.calls.size
|
285
|
+
assert_equal [goal, subgoal, [true]], rule_spy.calls[0].args
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'should handle false expression' do
|
289
|
+
rule = Rule.new args1, [false]
|
290
|
+
|
291
|
+
goal.expects(:terminate!).with().times(0)
|
292
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
293
|
+
called = false
|
294
|
+
|
295
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
296
|
+
#:nocov:
|
297
|
+
called = true
|
298
|
+
#:nocov:
|
299
|
+
end
|
300
|
+
|
301
|
+
refute result, 'satisfy_conjunction should not succeed'
|
302
|
+
refute called, 'the satisfy block should not be called'
|
303
|
+
assert_equal 1, rule_spy.calls.size
|
304
|
+
assert_equal [goal, subgoal, [false]], rule_spy.calls[0].args
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'should evaluate conjunctions until a fail' do
|
308
|
+
conjunction = [true, true, true, false, true, :CUT, true]
|
309
|
+
rule = Rule.new args1, conjunction
|
310
|
+
|
311
|
+
goal.expects(:terminate!).with().times(0)
|
312
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
313
|
+
called = false
|
314
|
+
|
315
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
316
|
+
#:nocov:
|
317
|
+
called = true
|
318
|
+
#:nocov:
|
319
|
+
end
|
320
|
+
|
321
|
+
refute result, 'satisfy_conjunction should not succeed'
|
322
|
+
refute called, 'the satisfy block should not be called'
|
323
|
+
assert_equal 4, rule_spy.calls.size
|
324
|
+
assert_equal [goal, subgoal, conjunction[3..-1]], rule_spy.calls[0].args
|
325
|
+
assert_equal [goal, subgoal, conjunction[2..-1]], rule_spy.calls[1].args
|
326
|
+
assert_equal [goal, subgoal, conjunction[1..-1]], rule_spy.calls[2].args
|
327
|
+
assert_equal [goal, subgoal, conjunction[0..-1]], rule_spy.calls[3].args
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'should unify and instantiate variables with a subgoal and satisfy the subgoal and uninstantiate the instantiations' do
|
331
|
+
goal = Goal.new args1, nil
|
332
|
+
subgoal = Goal.new args2, goal
|
333
|
+
|
334
|
+
predicate :gamma
|
335
|
+
|
336
|
+
gamma(8,5).fact!
|
337
|
+
|
338
|
+
rule = Rule.new args1, [gamma(:j,:k)]
|
339
|
+
|
340
|
+
subsubgoal = new_goal :gamma, :y, :z
|
341
|
+
subsubgoal_spy = Spy.on(Goal, :new).and_return do |*args|
|
342
|
+
Spy.off(Goal, :new)
|
343
|
+
subsubgoal
|
344
|
+
end
|
345
|
+
|
346
|
+
goal.expects(:terminate!).with().times(0)
|
347
|
+
subgoal.expects(:terminate!).with().times(0)
|
348
|
+
subsubgoal.expects(:terminate!).with().times(0)
|
349
|
+
|
350
|
+
goal.expects(:delete!).with().times(0)
|
351
|
+
subgoal.expects(:delete!).with().times(0)
|
352
|
+
subsubgoal.expects(:delete!).with().times(1)
|
353
|
+
|
354
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
355
|
+
called = false
|
356
|
+
|
357
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
358
|
+
called = true
|
359
|
+
assert_Goal goal, :parent, [1,2,3,4]
|
360
|
+
assert_Goal_variables goal, {}, ''
|
361
|
+
assert_Goal_variables subgoal, { x: nil, y: 8, z: 5 }, [
|
362
|
+
'Goal2.:x',
|
363
|
+
' Goal3.:x',
|
364
|
+
'Goal2.:y',
|
365
|
+
' Goal3.:y',
|
366
|
+
' Goal4.8',
|
367
|
+
'Goal2.:z',
|
368
|
+
' Goal3.:z',
|
369
|
+
' Goal4.5',
|
370
|
+
].join("\n")
|
371
|
+
assert_Goal_variables subsubgoal, { x: nil, y: 8, z: 5 }, [
|
372
|
+
'Goal3.:y',
|
373
|
+
' Goal2.:y',
|
374
|
+
' Goal4.8',
|
375
|
+
'Goal3.:z',
|
376
|
+
' Goal2.:z',
|
377
|
+
' Goal4.5',
|
378
|
+
'Goal3.:x',
|
379
|
+
' Goal2.:x',
|
380
|
+
].join("\n")
|
381
|
+
end
|
382
|
+
|
383
|
+
assert result, 'satisfy_conjunction should succeed'
|
384
|
+
assert called, 'the satisfy block should be called'
|
385
|
+
assert_equal 1, subsubgoal_spy.calls.size
|
386
|
+
assert_equal 1, rule_spy.calls.size
|
387
|
+
assert_equal [goal, subgoal, [gamma(:j,:k)]], rule_spy.calls[0].args
|
388
|
+
|
389
|
+
assert_Goal_variables subgoal, { x: nil, y: nil, z: nil }, [
|
390
|
+
'Goal2.:x',
|
391
|
+
' Goal3.:x',
|
392
|
+
'Goal2.:y',
|
393
|
+
' Goal3.:y',
|
394
|
+
'Goal2.:z',
|
395
|
+
' Goal3.:z',
|
396
|
+
].join("\n")
|
397
|
+
assert_Goal_variables subsubgoal, { x: nil, y: nil, z: nil }, [
|
398
|
+
'Goal3.:y',
|
399
|
+
' Goal2.:y',
|
400
|
+
'Goal3.:z',
|
401
|
+
' Goal2.:z',
|
402
|
+
'Goal3.:x',
|
403
|
+
' Goal2.:x',
|
404
|
+
].join("\n")
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'should not unify and not instantiate variables with a subgoal nor satisfy the subgoal when it cannot be unified' do
|
408
|
+
# -- Create Goals --
|
409
|
+
goal = Goal.new args1, nil
|
410
|
+
subgoal = Goal.new args2, goal
|
411
|
+
subgoal.instantiate :y, 7
|
412
|
+
|
413
|
+
# -- Create goal for satisfy_conjunction() --
|
414
|
+
subsubgoal = new_goal :gamma, :y, :y, :z
|
415
|
+
subsubgoal.instantiate :y, 3
|
416
|
+
|
417
|
+
# -- Check goals are setup correctly --
|
418
|
+
assert_Goal goal, :parent, [1,2,3,4]
|
419
|
+
assert_Goal subgoal, :child, [:x,:y]
|
420
|
+
assert_equal 'Goal1 -- Solve parent(1,2,3,4)', goal.inspect
|
421
|
+
assert_equal 'Goal2 -- Solve child(:x,:y)', subgoal.inspect
|
422
|
+
|
423
|
+
assert_Goal_variables goal, {}, [].join("\n")
|
424
|
+
|
425
|
+
assert_Goal_variables subgoal, { x: nil, y: 7 }, [
|
426
|
+
'Goal2.:x',
|
427
|
+
'Goal2.:y',
|
428
|
+
' Goal2.7',
|
429
|
+
].join("\n")
|
430
|
+
|
431
|
+
assert_Goal_variables subsubgoal, { y: 3, z: nil }, [
|
432
|
+
'Goal3.:y',
|
433
|
+
' Goal3.3',
|
434
|
+
'Goal3.:z',
|
435
|
+
].join("\n")
|
436
|
+
|
437
|
+
# -- Define Predicate --
|
438
|
+
predicate :gamma
|
439
|
+
|
440
|
+
gamma(8,5).fact!
|
441
|
+
|
442
|
+
rule = Rule.new args1, [gamma(:j,:k)]
|
443
|
+
|
444
|
+
# -- Prepare Checks for satisfy_conjunction() --
|
445
|
+
subsubgoal_spy = Spy.on(Goal, :new).and_return do |*args|
|
446
|
+
Spy.off(Goal, :new)
|
447
|
+
subsubgoal
|
448
|
+
end
|
449
|
+
|
450
|
+
goal. expects(:terminate!).with().times(0)
|
451
|
+
subgoal. expects(:terminate!).with().times(0)
|
452
|
+
subsubgoal.expects(:terminate!).with().times(0)
|
453
|
+
|
454
|
+
goal. expects(:delete!).with().times(0)
|
455
|
+
subgoal. expects(:delete!).with().times(0)
|
456
|
+
subsubgoal.expects(:delete!).with().times(1)
|
457
|
+
|
458
|
+
rule_spy = Spy.on(rule, :satisfy_conjunction).and_call_through
|
459
|
+
called = false
|
460
|
+
|
461
|
+
# -- Pre-execution Checks --
|
462
|
+
assert_Goal_variables goal, {}, [].join("\n")
|
463
|
+
assert_Goal_variables subgoal, { x: nil, y: 7 }, [
|
464
|
+
'Goal2.:x',
|
465
|
+
'Goal2.:y',
|
466
|
+
' Goal2.7',
|
467
|
+
].join("\n")
|
468
|
+
assert_Goal_variables subsubgoal, { y: 3, z: nil }, [
|
469
|
+
'Goal3.:y',
|
470
|
+
' Goal3.3',
|
471
|
+
'Goal3.:z',
|
472
|
+
].join("\n")
|
473
|
+
|
474
|
+
# -- Execute Code --
|
475
|
+
result = rule.satisfy_conjunction(goal, subgoal, rule.definition) do |solution_goal|
|
476
|
+
#:nocov:
|
477
|
+
called = true
|
478
|
+
#:nocov:
|
479
|
+
end
|
480
|
+
|
481
|
+
# -- Peform Checks --
|
482
|
+
refute result, 'satisfy_conjunction should not succeed'
|
483
|
+
refute called, 'the satisfy block should not be called'
|
484
|
+
assert_equal 1, subsubgoal_spy.calls.size
|
485
|
+
assert_equal 1, rule_spy.calls.size
|
486
|
+
assert_equal [goal, subgoal, [gamma(:j,:k)]], rule_spy.calls[0].args
|
487
|
+
|
488
|
+
assert_Goal_variables goal, {}, [].join("\n")
|
489
|
+
|
490
|
+
assert_Goal_variables subgoal, { x: nil, y: 7 }, [
|
491
|
+
'Goal2.:x',
|
492
|
+
'Goal2.:y',
|
493
|
+
' Goal2.7',
|
494
|
+
].join("\n")
|
495
|
+
|
496
|
+
assert_Goal_variables subsubgoal, { x: nil, y: 3, z: nil }, [
|
497
|
+
'Goal3.:y',
|
498
|
+
' Goal3.3',
|
499
|
+
'Goal3.:z',
|
500
|
+
'Goal3.:x',
|
501
|
+
].join("\n")
|
502
|
+
end
|
503
|
+
|
504
|
+
end
|
505
|
+
|
111
506
|
end
|
112
507
|
|
113
508
|
end
|
data/test/porolog/scope_test.rb
CHANGED
@@ -0,0 +1,127 @@
|
|
1
|
+
#
|
2
|
+
# test/porolog/tail_test.rb - Test Suite for Porolog::Tail
|
3
|
+
#
|
4
|
+
# Luis Esteban 2 May 2018
|
5
|
+
# created
|
6
|
+
#
|
7
|
+
|
8
|
+
require_relative '../test_helper'
|
9
|
+
|
10
|
+
describe 'Porolog' do
|
11
|
+
|
12
|
+
before(:all) do
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'Tail' do
|
17
|
+
|
18
|
+
describe '.new' do
|
19
|
+
|
20
|
+
it 'creates an unknown tail when no value is provided' do
|
21
|
+
tail = Tail.new
|
22
|
+
|
23
|
+
assert_Tail tail, '*...'
|
24
|
+
assert_equal UNKNOWN_TAIL, tail.value
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates a tail with a value' do
|
28
|
+
tail = Tail.new [2,3,5,7,11,13]
|
29
|
+
|
30
|
+
assert_Tail tail, '*[2, 3, 5, 7, 11, 13]'
|
31
|
+
assert_equal [2,3,5,7,11,13], tail.value
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'creates a tail with a variable' do
|
35
|
+
tail = Tail.new :x
|
36
|
+
|
37
|
+
assert_Tail tail, '*:x'
|
38
|
+
assert_equal :x, tail.value
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#value' do
|
44
|
+
|
45
|
+
let(:object) { Object.new }
|
46
|
+
|
47
|
+
before do
|
48
|
+
def object.inspect
|
49
|
+
super.gsub(/Object:0x[[:xdigit:]]+/,'Object:0xXXXXXX')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns its value' do
|
54
|
+
tail = Tail.new object
|
55
|
+
|
56
|
+
assert_Tail tail, '*#<Object:0xXXXXXX>'
|
57
|
+
assert_equal object, tail.value
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#inspect' do
|
63
|
+
|
64
|
+
it 'returns a string showing a splat operation is implied' do
|
65
|
+
tail = Tail.new [2,3,5,7,11,13]
|
66
|
+
|
67
|
+
assert_equal '*[2, 3, 5, 7, 11, 13]', tail.inspect
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#variables' do
|
73
|
+
|
74
|
+
it 'returns an empty Array when it was created without arguments' do
|
75
|
+
tail = Tail.new
|
76
|
+
|
77
|
+
assert_equal [], tail.variables
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns an empty Array when it was created with an Array of atomics' do
|
81
|
+
tail = Tail.new [2,3,5,7,11,13]
|
82
|
+
|
83
|
+
assert_equal [], tail.variables
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns an Array of Symbols when it was created with a Symbol' do
|
87
|
+
tail = Tail.new :t
|
88
|
+
|
89
|
+
assert_equal [:t], tail.variables
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns an Array of Symbols when it was created with an Array with embedded Symbols' do
|
93
|
+
tail = Tail.new [2,3,:x,7,[:y,[:z]],13]
|
94
|
+
|
95
|
+
assert_equal [:x,:y,:z], tail.variables
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#==' do
|
101
|
+
|
102
|
+
it 'returns true for unknown tails' do
|
103
|
+
tail1 = Tail.new
|
104
|
+
tail2 = Tail.new
|
105
|
+
|
106
|
+
assert tail1 == tail2, name
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'returns false for different symbols' do
|
110
|
+
tail1 = Tail.new :t
|
111
|
+
tail2 = Tail.new :x
|
112
|
+
|
113
|
+
refute tail1 == tail2, name
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'returns true for equal values' do
|
117
|
+
tail1 = Tail.new 12.34
|
118
|
+
tail2 = Tail.new 12.34
|
119
|
+
|
120
|
+
assert tail1 == tail2, name
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|