mini_kraken 0.2.03 → 0.3.03

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +378 -333
  3. data/CHANGELOG.md +48 -0
  4. data/README.md +29 -21
  5. data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
  6. data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
  7. data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
  8. data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
  9. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  10. data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
  11. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  12. data/lib/mini_kraken/composite/composite_term.rb +27 -0
  13. data/lib/mini_kraken/composite/cons_cell.rb +301 -0
  14. data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
  15. data/lib/mini_kraken/composite/list.rb +32 -0
  16. data/lib/mini_kraken/core/all_core.rb +8 -0
  17. data/lib/mini_kraken/core/any_value.rb +31 -7
  18. data/lib/mini_kraken/core/arity.rb +69 -0
  19. data/lib/mini_kraken/core/association.rb +29 -4
  20. data/lib/mini_kraken/core/association_copy.rb +50 -0
  21. data/lib/mini_kraken/core/base_term.rb +13 -0
  22. data/lib/mini_kraken/core/blackboard.rb +315 -0
  23. data/lib/mini_kraken/core/bookmark.rb +46 -0
  24. data/lib/mini_kraken/core/context.rb +492 -0
  25. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  26. data/lib/mini_kraken/core/entry.rb +40 -0
  27. data/lib/mini_kraken/core/fail.rb +20 -18
  28. data/lib/mini_kraken/core/fusion.rb +29 -0
  29. data/lib/mini_kraken/core/goal.rb +20 -29
  30. data/lib/mini_kraken/core/log_var.rb +22 -0
  31. data/lib/mini_kraken/core/log_var_ref.rb +108 -0
  32. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  33. data/lib/mini_kraken/core/parametrized_term.rb +68 -0
  34. data/lib/mini_kraken/core/relation.rb +14 -28
  35. data/lib/mini_kraken/core/scope.rb +67 -0
  36. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  37. data/lib/mini_kraken/core/specification.rb +48 -0
  38. data/lib/mini_kraken/core/succeed.rb +21 -17
  39. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  40. data/lib/mini_kraken/core/term.rb +15 -4
  41. data/lib/mini_kraken/glue/dsl.rb +44 -88
  42. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  43. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  44. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  45. data/lib/mini_kraken/rela/conde.rb +143 -0
  46. data/lib/mini_kraken/rela/conj2.rb +65 -0
  47. data/lib/mini_kraken/rela/def_relation.rb +93 -0
  48. data/lib/mini_kraken/rela/disj2.rb +70 -0
  49. data/lib/mini_kraken/rela/fresh.rb +98 -0
  50. data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
  51. data/lib/mini_kraken/rela/unify.rb +265 -0
  52. data/lib/mini_kraken/version.rb +1 -1
  53. data/mini_kraken.gemspec +2 -2
  54. data/spec/.rubocop.yml +1 -1
  55. data/spec/atomic/atomic_term_spec.rb +98 -0
  56. data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
  57. data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
  58. data/spec/composite/cons_cell_spec.rb +225 -0
  59. data/spec/{core → composite}/cons_cell_visitor_spec.rb +36 -20
  60. data/spec/composite/list_spec.rb +50 -0
  61. data/spec/core/any_value_spec.rb +52 -0
  62. data/spec/core/arity_spec.rb +92 -0
  63. data/spec/core/association_copy_spec.rb +69 -0
  64. data/spec/core/association_spec.rb +31 -4
  65. data/spec/core/blackboard_spec.rb +287 -0
  66. data/spec/core/bookmark_spec.rb +40 -0
  67. data/spec/core/context_spec.rb +245 -0
  68. data/spec/core/core_spec.rb +40 -0
  69. data/spec/core/duck_fiber_spec.rb +16 -46
  70. data/spec/core/fail_spec.rb +5 -6
  71. data/spec/core/goal_spec.rb +22 -12
  72. data/spec/core/log_var_ref_spec.rb +105 -0
  73. data/spec/core/log_var_spec.rb +64 -0
  74. data/spec/core/nullary_relation_spec.rb +33 -0
  75. data/spec/core/parametrized_tem_spec.rb +39 -0
  76. data/spec/core/relation_spec.rb +33 -0
  77. data/spec/core/scope_spec.rb +73 -0
  78. data/spec/core/solver_adapter_spec.rb +70 -0
  79. data/spec/core/specification_spec.rb +43 -0
  80. data/spec/core/succeed_spec.rb +5 -5
  81. data/spec/core/symbol_table_spec.rb +142 -0
  82. data/spec/glue/dsl_chap1_spec.rb +88 -144
  83. data/spec/glue/dsl_chap2_spec.rb +454 -19
  84. data/spec/glue/run_star_expression_spec.rb +81 -906
  85. data/spec/rela/conde_spec.rb +153 -0
  86. data/spec/rela/conj2_spec.rb +123 -0
  87. data/spec/rela/def_relation_spec.rb +119 -0
  88. data/spec/rela/disj2_spec.rb +117 -0
  89. data/spec/rela/fresh_spec.rb +147 -0
  90. data/spec/rela/unify_spec.rb +369 -0
  91. data/spec/support/factory_atomic.rb +29 -0
  92. data/spec/support/factory_composite.rb +21 -0
  93. data/spec/support/factory_methods.rb +11 -26
  94. metadata +98 -70
  95. data/lib/mini_kraken/core/association_walker.rb +0 -183
  96. data/lib/mini_kraken/core/atomic_term.rb +0 -67
  97. data/lib/mini_kraken/core/base_arg.rb +0 -10
  98. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  99. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  100. data/lib/mini_kraken/core/composite_term.rb +0 -41
  101. data/lib/mini_kraken/core/conde.rb +0 -143
  102. data/lib/mini_kraken/core/conj2.rb +0 -79
  103. data/lib/mini_kraken/core/cons_cell.rb +0 -82
  104. data/lib/mini_kraken/core/cons_cell_visitor.rb +0 -102
  105. data/lib/mini_kraken/core/def_relation.rb +0 -53
  106. data/lib/mini_kraken/core/designation.rb +0 -55
  107. data/lib/mini_kraken/core/disj2.rb +0 -72
  108. data/lib/mini_kraken/core/environment.rb +0 -73
  109. data/lib/mini_kraken/core/equals.rb +0 -193
  110. data/lib/mini_kraken/core/formal_arg.rb +0 -22
  111. data/lib/mini_kraken/core/formal_ref.rb +0 -25
  112. data/lib/mini_kraken/core/freshness.rb +0 -45
  113. data/lib/mini_kraken/core/goal_arg.rb +0 -12
  114. data/lib/mini_kraken/core/goal_template.rb +0 -102
  115. data/lib/mini_kraken/core/k_boolean.rb +0 -35
  116. data/lib/mini_kraken/core/outcome.rb +0 -63
  117. data/lib/mini_kraken/core/variable.rb +0 -41
  118. data/lib/mini_kraken/core/variable_ref.rb +0 -84
  119. data/lib/mini_kraken/core/vocabulary.rb +0 -446
  120. data/lib/mini_kraken/glue/fresh_env.rb +0 -103
  121. data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
  122. data/spec/core/association_walker_spec.rb +0 -192
  123. data/spec/core/conde_spec.rb +0 -147
  124. data/spec/core/conj2_spec.rb +0 -114
  125. data/spec/core/cons_cell_spec.rb +0 -107
  126. data/spec/core/def_relation_spec.rb +0 -97
  127. data/spec/core/disj2_spec.rb +0 -99
  128. data/spec/core/environment_spec.rb +0 -142
  129. data/spec/core/equals_spec.rb +0 -317
  130. data/spec/core/goal_template_spec.rb +0 -74
  131. data/spec/core/outcome_spec.rb +0 -56
  132. data/spec/core/variable_ref_spec.rb +0 -30
  133. data/spec/core/variable_spec.rb +0 -35
  134. data/spec/core/vocabulary_spec.rb +0 -219
  135. data/spec/glue/fresh_env_factory_spec.rb +0 -97
  136. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -4,10 +4,10 @@ require_relative '../spec_helper' # Use the RSpec framework
4
4
  require 'ostruct'
5
5
 
6
6
  # Load the class under test
7
- require_relative '../../lib/mini_kraken/core/k_boolean'
7
+ require_relative '../../lib/mini_kraken/atomic/k_boolean'
8
8
 
9
9
  module MiniKraken
10
- module Core
10
+ module Atomic
11
11
  describe KBoolean do
12
12
  subject { KBoolean.new('#t') }
13
13
 
@@ -28,12 +28,23 @@ module MiniKraken
28
28
  end
29
29
 
30
30
  it 'should know its value' do
31
- expect(subject.value).to eq(true)
32
- end
31
+ other = KBoolean.new(true)
32
+ expect(other.value).to eq(true)
33
+
34
+ other = KBoolean.new('#t')
35
+ expect(other.value).to eq(true)
36
+
37
+ other = KBoolean.new(:"#t")
38
+ expect(other.value).to eq(true)
39
+
40
+ other = KBoolean.new(false)
41
+ expect(other.value).to eq(false)
42
+
43
+ other = KBoolean.new('#f')
44
+ expect(other.value).to eq(false)
33
45
 
34
- it 'should know that it is a ground term' do
35
- env = double('mock-env')
36
- expect(subject.ground?(env)).to be_truthy
46
+ other = KBoolean.new(:"#f")
47
+ expect(other.value).to eq(false)
37
48
  end
38
49
  end # context
39
50
 
@@ -43,27 +54,13 @@ module MiniKraken
43
54
  other = KBoolean.new(true)
44
55
  expect(subject).to be_eql(other)
45
56
 
46
- other = KBoolean.new(:"#t")
47
- expect(subject).to be_eql(other)
48
-
49
- other = KBoolean.new('#t')
50
- expect(subject).to be_eql(other)
51
-
52
57
  # Same type, other value
53
58
  another = KBoolean.new(false)
54
59
  expect(subject).not_to be_eql(another)
55
60
 
56
- # Same type, other value
57
- another = KBoolean.new(:"#f")
58
- expect(subject).not_to be_eql(another)
59
-
60
61
  # Same type, other value
61
62
  another = KBoolean.new('#f')
62
63
  expect(subject).not_to be_eql(another)
63
-
64
- # Different type, same value
65
- yet_another = OpenStruct.new(value: true)
66
- expect(subject).not_to be_eql(yet_another)
67
64
  end
68
65
 
69
66
  it 'should know whether it has same value than other object' do
@@ -71,27 +68,15 @@ module MiniKraken
71
68
  other = KBoolean.new(true)
72
69
  expect(subject == other).to be_truthy
73
70
 
74
- other = KBoolean.new(:"#t")
75
- expect(subject == other).to be_truthy
76
-
77
- other = KBoolean.new('#t')
78
- expect(subject == other).to be_truthy
79
-
80
71
  # Same type, other value
81
72
  another = KBoolean.new(false)
82
73
  expect(subject == another).to be_falsy
83
74
 
84
- another = KBoolean.new(:"#f")
85
- expect(subject == another).to be_falsy
86
-
87
- another = KBoolean.new('#f')
88
- expect(subject == another).to be_falsy
89
-
90
75
  # Same duck type, same value
91
76
  yet_another = OpenStruct.new(value: true)
92
77
  expect(subject == yet_another).to be_truthy
93
78
 
94
- # Different duck type, different value
79
+ # Same duck type, different value
95
80
  still_another = OpenStruct.new(value: false)
96
81
  expect(subject == still_another).to be_falsy
97
82
 
@@ -4,10 +4,10 @@ require_relative '../spec_helper' # Use the RSpec framework
4
4
  require 'ostruct'
5
5
 
6
6
  # Load the class under test
7
- require_relative '../../lib/mini_kraken/core/k_symbol'
7
+ require_relative '../../lib/mini_kraken/atomic/k_symbol'
8
8
 
9
9
  module MiniKraken
10
- module Core
10
+ module Atomic
11
11
  describe KSymbol do
12
12
  let(:a_value) { :pea }
13
13
  subject { KSymbol.new(a_value) }
@@ -20,11 +20,6 @@ module MiniKraken
20
20
  it 'should know its value' do
21
21
  expect(subject.value).to eq(a_value)
22
22
  end
23
-
24
- it 'should know that it is a ground term' do
25
- env = double('mock-env')
26
- expect(subject.ground?(env)).to be_truthy
27
- end
28
23
  end # context
29
24
 
30
25
  context 'Provided services:' do
@@ -37,7 +32,7 @@ module MiniKraken
37
32
  another = KSymbol.new(:pod)
38
33
  expect(subject).not_to be_eql(another)
39
34
 
40
- # Different type, same value
35
+ # Different duck type, same value
41
36
  yet_another = OpenStruct.new(value: :pea)
42
37
  expect(subject).not_to be_eql(yet_another)
43
38
  end
@@ -51,14 +46,6 @@ module MiniKraken
51
46
  another = KSymbol.new(:pod)
52
47
  expect(subject == another).to be_falsy
53
48
 
54
- # Same duck type, same value
55
- yet_another = OpenStruct.new(value: :pea)
56
- expect(subject == yet_another).to be_truthy
57
-
58
- # Different duck type, different value
59
- still_another = OpenStruct.new(value: :pod)
60
- expect(subject == still_another).to be_falsy
61
-
62
49
  # Default Ruby representation, same value
63
50
  expect(subject == :pea).to be_truthy
64
51
 
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+ require_relative '../support/factory_atomic'
5
+ require_relative '../../lib/mini_kraken/core/context'
6
+ require_relative '../../lib/mini_kraken/core/log_var'
7
+ require_relative '../../lib/mini_kraken/core/log_var_ref'
8
+
9
+ # Load the class under test
10
+ require_relative '../../lib/mini_kraken/composite/cons_cell'
11
+
12
+ module MiniKraken
13
+ module Composite
14
+ describe ConsCell do
15
+ include MiniKraken::FactoryAtomic # Use mix-in module
16
+
17
+ let(:pea) { k_symbol(:pea) }
18
+ let(:pod) { k_symbol(:pod) }
19
+ let(:corn) { k_symbol(:corn) }
20
+ let(:ctx) { Core::Context.new }
21
+ subject { ConsCell.new(pea, pod) }
22
+
23
+ context 'Initialization:' do
24
+ it 'could be initialized with one argument' do
25
+ expect { ConsCell.new(pea) }.not_to raise_error
26
+ end
27
+
28
+ it 'could be initialized with a second optional argument' do
29
+ expect { ConsCell.new(pea, pod) }.not_to raise_error
30
+ end
31
+
32
+ it 'could be initialized as null list' do
33
+ expect { ConsCell.null }.not_to raise_error
34
+ end
35
+
36
+ it 'should know its car child' do
37
+ expect(subject.car).to eq(pea)
38
+ end
39
+
40
+ it 'should know its cdr child' do
41
+ expect(subject.cdr).to eq(pod)
42
+ end
43
+
44
+
45
+ it 'should know its children' do
46
+ expect(subject.children).to eq([pea, pod])
47
+ end
48
+
49
+ it 'should know if it is empty (null)' do
50
+ expect(subject).not_to be_null
51
+ expect(ConsCell.new(nil, nil)).to be_null
52
+ expect(ConsCell.null).to be_null
53
+ expect(NullList).to be_null
54
+ end
55
+
56
+ it 'initialize cdr if its referencing the null list' do
57
+ instance = ConsCell.new(pea, NullList)
58
+ expect(instance.car).to eq(pea)
59
+ expect(instance.cdr).to be_null
60
+ end
61
+ end # context
62
+
63
+ context 'Provided services:' do
64
+ it 'should compare to itself' do
65
+ expect(subject.eql?(subject)).to be_truthy
66
+ synonym = subject
67
+ expect(subject == synonym).to be_truthy
68
+ end
69
+
70
+ it 'should compare to another instance' do
71
+ same = ConsCell.new(pea, pod)
72
+ expect(subject.eql?(same)).to be_truthy
73
+
74
+ different = ConsCell.new(pod, pea)
75
+ expect(subject.eql?(different)).to be_falsey
76
+
77
+ different = ConsCell.new(pea)
78
+ expect(subject.eql?(different)).to be_falsey
79
+ end
80
+
81
+ it 'should set_car! another cons cell' do
82
+ instance = ConsCell.new(pea)
83
+ head = ConsCell.new(pod)
84
+ instance.set_car!(head)
85
+ expect(instance.car).to eq(head)
86
+ expect(instance.cdr).to be_null
87
+ end
88
+
89
+ it 'should set_cdr! another cons cell' do
90
+ instance = ConsCell.new(pea)
91
+ trail = ConsCell.new(pod)
92
+ instance.set_cdr!(trail)
93
+ expect(instance.car).to eq(pea)
94
+ expect(instance.cdr).to eq(trail)
95
+ end
96
+
97
+ it 'should set a member to some term' do
98
+ instance = ConsCell.null
99
+ head = ConsCell.new(pea)
100
+ trail = ConsCell.new(pod)
101
+ instance.set!(:car, head)
102
+ instance.set!(:cdr, trail)
103
+ expect(instance.car).to eq(head)
104
+ expect(instance.cdr).to eq(trail)
105
+ end
106
+
107
+ it 'should know whether it is pinned or not' do
108
+ # Case: all pair members are atomic items
109
+ expect(subject).to be_pinned(ctx)
110
+
111
+ # Case: cdr is nil
112
+ instance = ConsCell.new(pea)
113
+ expect(instance).to be_pinned(ctx)
114
+
115
+ # Case: embedded composite
116
+ nested = ConsCell.new(ConsCell.new(pod, pea), ConsCell.new(pea))
117
+ expect(nested).to be_pinned(ctx)
118
+
119
+ ctx.add_vars('q')
120
+ nested.set_cdr!(Core::LogVarRef.new('q'))
121
+ expect(nested).not_to be_pinned(ctx)
122
+ expect(nested).to be_floating(ctx)
123
+
124
+ ctx.associate('q', ConsCell.new(pea))
125
+ expect(nested).to be_pinned(ctx)
126
+ end
127
+
128
+ it 'should provide a list representation of itself' do
129
+ # Case of null list
130
+ expect(NullList.to_s).to eq '()'
131
+
132
+ # Case of one element proper list
133
+ cell = ConsCell.new(pea)
134
+ expect(cell.to_s).to eq '(:pea)'
135
+
136
+ # Case of two elements proper list
137
+ cell = ConsCell.new(pea, ConsCell.new(pod))
138
+ expect(cell.to_s).to eq '(:pea :pod)'
139
+
140
+ # Case of two elements improper list
141
+ expect(subject.to_s).to eq '(:pea . :pod)'
142
+
143
+ # Case of one element plus null list
144
+ cell = ConsCell.new(pea)
145
+ cell.set_cdr!(ConsCell.null)
146
+ expect(cell.to_s).to eq '(:pea)'
147
+
148
+ # Case of three elements proper list
149
+ cell = ConsCell.new(pea, ConsCell.new(pod, ConsCell.new(corn)))
150
+ expect(cell.to_s).to eq '(:pea :pod :corn)'
151
+
152
+ # Case of three elements improper list
153
+ cell = ConsCell.new(pea, ConsCell.new(pod, corn))
154
+ expect(cell.to_s).to eq '(:pea :pod . :corn)'
155
+
156
+ # Case of a nested list
157
+ cell = ConsCell.new(ConsCell.new(pea), ConsCell.new(pod))
158
+ expect(cell.to_s).to eq '((:pea) :pod)'
159
+ end
160
+
161
+ it 'should know its dependencies' do
162
+ # Case: no var ref...
163
+ lst = ConsCell.new(ConsCell.new(pod, pea), ConsCell.new(pea))
164
+ expect(lst.dependencies(ctx)).to be_empty
165
+
166
+ # Case: multiple var refs
167
+ ctx.add_vars(%w[q x])
168
+ q_ref = Core::LogVarRef.new('q')
169
+ x_ref = Core::LogVarRef.new('x')
170
+ list2 = ConsCell.new(ConsCell.new(q_ref, pea), ConsCell.new(x_ref))
171
+ expect(list2.dependencies(ctx).size).to eq(2)
172
+ q_var = ctx.lookup('q')
173
+ x_var = ctx.lookup('x')
174
+ predicted = Set.new([q_var.i_name, x_var.i_name])
175
+ expect(list2.dependencies(ctx)).to eq(predicted)
176
+ end
177
+
178
+ it 'should, as list with atomic terms, provide an expanded copy' do
179
+ # Case of a list of atomic terms
180
+ lst = ConsCell.new(ConsCell.new(ConsCell.new(pea), pod))
181
+ representation = lst.to_s
182
+
183
+ copy = lst.expand(ctx, {})
184
+ expect(copy.to_s).to eq(representation)
185
+ end
186
+
187
+ it 'should, as list with variable refs, provide an expanded copy' do
188
+ # Case of a list of variable refs
189
+ ctx.add_vars(['x'])
190
+ x_ref = Core::LogVarRef.new('x')
191
+ x_var = ctx.lookup('x')
192
+ ctx.associate('x', Core::AnyValue.new(0))
193
+ lst = ConsCell.new(x_ref, ConsCell.new(x_ref))
194
+ substitutions = {}
195
+ substitutions[x_var.i_name] = Core::AnyValue.new(0)
196
+
197
+ copy = lst.expand(ctx, substitutions)
198
+ expect(copy.to_s).to eq('(_0 _0)')
199
+ end
200
+
201
+ it 'should provide a duplicate with variable replaced by their value' do
202
+ q_ref = Core::LogVarRef.new('q')
203
+ x_ref = Core::LogVarRef.new('x')
204
+ y_ref = Core::LogVarRef.new('y')
205
+ substitutions = {
206
+ 'q' => ConsCell.new(pea, ConsCell.new(x_ref, y_ref)),
207
+ 'x' => pod,
208
+ 'y' => corn
209
+ }
210
+
211
+ # Basic case: variable ref points to an atomic value
212
+ expr = ConsCell.new(pea, x_ref)
213
+ duplicate = expr.dup_cond(substitutions)
214
+ expect(duplicate.to_s).to eq('(:pea . :pod)')
215
+
216
+ expr = ConsCell.new(pod, ConsCell.new(q_ref, y_ref))
217
+ duplicate = expr.dup_cond(substitutions)
218
+ expect(duplicate.car).to eq(pod)
219
+ expect(duplicate.cdr.car.to_s).to eq('(:pea :pod . :corn)')
220
+ expect(duplicate.to_s).to eq('(:pod (:pea :pod . :corn) . :corn)')
221
+ end
222
+ end # context
223
+ end # describe
224
+ end # module
225
+ end # module
@@ -1,38 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../spec_helper' # Use the RSpec framework
4
- require_relative '../../lib/mini_kraken/core/k_symbol'
5
- require_relative '../../lib/mini_kraken/core/variable_ref'
4
+ require_relative '../support/factory_atomic'
5
+ require_relative '../../lib/mini_kraken/core/log_var_ref'
6
6
 
7
7
  # Load the class under test
8
- require_relative '../../lib/mini_kraken/core/cons_cell_visitor'
9
-
8
+ require_relative '../../lib/mini_kraken/composite/cons_cell_visitor'
10
9
 
11
10
  module MiniKraken
12
- module Core
11
+ module Composite
13
12
  describe ConsCellVisitor do
14
- let(:pea) { KSymbol.new(:pea) }
15
- let(:pod) { KSymbol.new(:pod) }
16
- let(:corn) { KSymbol.new(:corn) }
17
- let(:ref_q) { VariableRef.new('q') }
13
+ include MiniKraken::FactoryAtomic # Use mix-in module
14
+
15
+ let(:pea) { k_symbol(:pea) }
16
+ let(:pod) { k_symbol(:pod) }
17
+ let(:corn) { k_symbol(:corn) }
18
+ let(:ref_q) { LogVarRef.new('q') }
18
19
  let(:l_pea) { ConsCell.new(pea) }
19
20
  let(:l_pea_pod) { ConsCell.new(pea, ConsCell.new(pod)) }
20
21
  let(:l_pea_pod_corn) { ConsCell.new(pea, ConsCell.new(pod, ConsCell.new(corn))) }
21
22
  subject { ConsCellVisitor }
22
23
 
23
24
  context 'Provided services:' do
24
- it 'acts as a factory of Enumerator' do
25
+ it 'acts as a factory of Fiber objects' do
25
26
  expect(subject.df_visitor(l_pea)).to be_kind_of(Fiber)
26
27
  end
27
28
  end # context
28
29
 
29
30
  context 'proper list visiting:' do
30
31
  it 'can visit a null list' do
31
- null_list = ConsCell.new(nil)
32
+ null_list = ConsCell.null
32
33
  visitor = subject.df_visitor(null_list)
33
34
  expect(visitor.resume).to eq([:car, null_list])
34
- expect(visitor.resume).to eq([:car, nil])
35
- expect(visitor.resume).to eq([:cdr, nil])
35
+
36
+ # The car and cdr fields aren't visited
36
37
  expect(visitor.resume).to eq([:stop, nil])
37
38
  end
38
39
 
@@ -40,7 +41,7 @@ module MiniKraken
40
41
  visitor = subject.df_visitor(l_pea)
41
42
  expect(visitor.resume).to eq([:car, l_pea])
42
43
  expect(visitor.resume).to eq([:car, pea])
43
- expect(visitor.resume).to eq([:cdr, nil])
44
+ expect(visitor.resume).to eq([:cdr, NullList])
44
45
  expect(visitor.resume).to eq([:stop, nil])
45
46
  end
46
47
 
@@ -50,7 +51,7 @@ module MiniKraken
50
51
  expect(visitor.resume).to eq([:car, pea])
51
52
  expect(visitor.resume).to eq([:cdr, l_pea_pod.cdr])
52
53
  expect(visitor.resume).to eq([:car, pod])
53
- expect(visitor.resume).to eq([:cdr, nil])
54
+ expect(visitor.resume).to eq([:cdr, NullList])
54
55
  expect(visitor.resume).to eq([:stop, nil])
55
56
  end
56
57
 
@@ -62,7 +63,7 @@ module MiniKraken
62
63
  expect(visitor.resume).to eq([:car, pod])
63
64
  expect(visitor.resume).to eq([:cdr, l_pea_pod_corn.cdr.cdr])
64
65
  expect(visitor.resume).to eq([:car, corn])
65
- expect(visitor.resume).to eq([:cdr, nil])
66
+ expect(visitor.resume).to eq([:cdr, NullList])
66
67
  expect(visitor.resume).to eq([:stop, nil])
67
68
  end
68
69
  end # context
@@ -88,6 +89,7 @@ module MiniKraken
88
89
 
89
90
  it 'can visit a three elements improper list' do
90
91
  l_improper = ConsCell.new(pea, ConsCell.new(pod, corn))
92
+ expect(l_improper.to_s).to eq('(:pea :pod . :corn)')
91
93
  visitor = subject.df_visitor(l_improper)
92
94
  expect(visitor.resume).to eq([:car, l_improper])
93
95
  expect(visitor.resume).to eq([:car, pea])
@@ -96,6 +98,18 @@ module MiniKraken
96
98
  expect(visitor.resume).to eq([:cdr, corn])
97
99
  expect(visitor.resume).to eq([:stop, nil])
98
100
  end
101
+
102
+ it 'smurch' do
103
+ composite = ConsCell.new(ConsCell.new(ConsCell.new(pea)), pod)
104
+ visitor = subject.df_visitor(composite)
105
+ expect(visitor.resume).to eq([:car, composite])
106
+ expect(visitor.resume).to eq([:car, composite.car])
107
+ expect(visitor.resume).to eq([:car, composite.car.car])
108
+ expect(visitor.resume).to eq([:car, pea])
109
+ expect(visitor.resume).to eq([:cdr, NullList])
110
+ expect(visitor.resume).to eq([:cdr, NullList])
111
+ expect(visitor.resume).to eq([:cdr, pod])
112
+ end
99
113
  end # context
100
114
 
101
115
  context 'Skip visit of children of a ConsCell:' do
@@ -120,22 +134,24 @@ module MiniKraken
120
134
  # Tell to skip children by passing a true value to resume
121
135
  expect(visitor.resume(true)).to eq([:cdr, tree.cdr.cdr])
122
136
  expect(visitor.resume).to eq([:car, corn])
123
- expect(visitor.resume).to eq([:cdr, nil])
137
+ expect(visitor.resume).to eq([:cdr, NullList])
124
138
  expect(visitor.resume).to eq([:stop, nil])
125
139
  end
126
140
  end # context
127
141
 
128
142
  context 'Circular structures visiting:' do
129
143
  it 'should cope with a circular graph' do
130
- second_cell = ConsCell.new(pod)
144
+ second_cell = ConsCell.new(pea)
131
145
  first_cell = ConsCell.new(pea, second_cell)
132
- second_cell.instance_variable_set(:@car, first_cell) # Ugly!
146
+ second_cell.set_car!(first_cell)
133
147
 
134
148
  visitor = subject.df_visitor(first_cell)
135
149
  expect(visitor.resume).to eq([:car, first_cell])
136
150
  expect(visitor.resume).to eq([:car, pea])
137
151
  expect(visitor.resume).to eq([:cdr, second_cell])
138
- expect(visitor.resume).to eq([:cdr, nil]) # Skip car (was already visited)
152
+
153
+ # Skip car (was already visited)
154
+ expect(visitor.resume).to eq([:cdr, NullList])
139
155
  expect(visitor.resume).to eq([:stop, nil])
140
156
  end
141
157
  end # context