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
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ # Load the class under test
6
+ require_relative '../../lib/mini_kraken/core/bookmark'
7
+
8
+ module MiniKraken
9
+ module Core
10
+ describe Bookmark do
11
+ let(:one_ser_num) { 42 }
12
+ let(:a_kind) { :scope }
13
+ subject { Bookmark.new(a_kind, one_ser_num) }
14
+
15
+ context 'Initialization:' do
16
+ it 'should be initialized with a Symbol and an Integer' do
17
+ expect { Bookmark.new(a_kind, one_ser_num) }.not_to raise_error
18
+ end
19
+
20
+ it 'should know its kind' do
21
+ expect(subject.kind).to eq(a_kind)
22
+ end
23
+
24
+ it 'should know its serial number' do
25
+ expect(subject.ser_num).to eq(one_ser_num)
26
+ end
27
+ end # context
28
+
29
+ context 'Provided services:' do
30
+ it 'should compare to another instance' do
31
+ same = Bookmark.new(a_kind, one_ser_num)
32
+ expect(subject).to eq(same)
33
+
34
+ distinct = Bookmark.new(a_kind, 3)
35
+ expect(subject).not_to eq(distinct)
36
+ end
37
+ end # context
38
+ end # describe
39
+ end # module
40
+ end # module
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+ require_relative '../../lib/mini_kraken/core/association'
5
+ require_relative '../../lib/mini_kraken/core/log_var'
6
+ require_relative '../../lib/mini_kraken/composite/all_composite'
7
+
8
+ require_relative '../support/factory_atomic'
9
+ require_relative '../support/factory_methods'
10
+
11
+ # Load the class under test
12
+ require_relative '../../lib/mini_kraken/core/context'
13
+
14
+ module MiniKraken
15
+ module Core
16
+ describe Context do
17
+ include MiniKraken::FactoryAtomic # Use mix-in module
18
+ subject { Context.new }
19
+
20
+ context 'Initialization:' do
21
+ it 'should be initialized without argument' do
22
+ expect { Context.new }.not_to raise_error
23
+ end
24
+
25
+ it 'should have an empty symbol table' do
26
+ expect(subject.symbol_table).to be_empty
27
+ end
28
+
29
+ it 'should have an empty blackboard' do
30
+ expect(subject.blackboard).to be_empty
31
+ end
32
+ end # context
33
+
34
+ context 'Provided services:' do
35
+ def var(aName)
36
+ LogVar.new(aName)
37
+ end
38
+
39
+ def cons(term1, term2 = nil)
40
+ Composite::ConsCell.new(term1, term2)
41
+ end
42
+
43
+ it 'should accept the addition of an entry in symbol table' do
44
+ subject.insert(var('x'))
45
+ expect(subject.symbol_table).not_to be_empty
46
+ expect(subject.symbol_table.current_scope.defns['x']).to be_kind_of(LogVar)
47
+ end
48
+
49
+ it 'should create one or more variables from name(s)' do
50
+ # Case: single name
51
+ subject.add_vars('x')
52
+ expect(subject.symbol_table).not_to be_empty
53
+ expect(subject.symbol_table.current_scope.defns['x']).to be_kind_of(LogVar)
54
+
55
+ # Case: multiple names
56
+ subject.add_vars(%w[y z])
57
+ expect(subject.symbol_table.current_scope.defns['y']).to be_kind_of(LogVar)
58
+ expect(subject.symbol_table.current_scope.defns['z']).to be_kind_of(LogVar)
59
+ end
60
+
61
+ it 'should accept the addition of an association to a given i_name' do
62
+ i_name_x = subject.insert(var('x'))
63
+ i_name_y = subject.insert(var('y'))
64
+
65
+ expect(subject.associations_for('x')).to be_empty
66
+ something = double('something')
67
+ assoc_x = subject.associate('x', something)
68
+ expect(subject.associations_for('x')).to eq([assoc_x])
69
+
70
+ thing = double('thing')
71
+ assoc_y = Association.new(i_name_y, thing)
72
+ subject.enqueue_association(assoc_y)
73
+ expect(subject.associations_for('y')).to eq([assoc_y])
74
+
75
+ blob = double('blob')
76
+ assoc2_x = Association.new(i_name_x, blob)
77
+ subject.enqueue_association(assoc2_x)
78
+ expect(subject.associations_for('x')).to eq([assoc_x, assoc2_x])
79
+
80
+ var_y = subject.lookup('y')
81
+ foo = double('bar')
82
+ assoc2_y = subject.associate(var_y, foo)
83
+ expect(subject.associations_for('y')).to eq([assoc_y, assoc2_y])
84
+ end
85
+
86
+ it 'should allow the fusion of two variables' do
87
+ symb_tbl = subject.symbol_table
88
+ i_name_q = subject.insert(var('q'))
89
+ symb_tbl.enter_scope(Core::Scope.new)
90
+ i_name_x = subject.insert(var('x'))
91
+
92
+ expect(subject.associations_for('q')).to be_empty
93
+ something = double('something')
94
+ assoc_x = subject.associate('x', something)
95
+ expect(subject.associations_for('x')).to eq([assoc_x])
96
+ pre_queue_size = subject.blackboard.move_queue.size
97
+ fusion = subject.fuse(%w[q x])
98
+
99
+ expect(fusion).to be_kind_of(Fusion)
100
+ expect(fusion.elements).to eq(%w[q x].map { |e| subject.lookup(e).i_name })
101
+ expect(subject.blackboard.move_queue.size).to eq(pre_queue_size + 2)
102
+ expect(subject.cv2vars).to be_include(fusion.i_name)
103
+ expect(subject.cv2vars[fusion.i_name]).to eq(fusion.elements)
104
+ expect(subject.blackboard.vars2cv[i_name_q]).to eq(fusion.i_name)
105
+ expect(subject.blackboard.vars2cv[i_name_x]).to eq(fusion.i_name)
106
+ expect(subject.associations_for('q')).not_to be_empty
107
+ end
108
+
109
+ it 'should allow the search of an entry based on its name' do
110
+ symb_tbl = subject.symbol_table
111
+ subject.add_vars(%w[q x])
112
+ symb_tbl.enter_scope(Core::Scope.new)
113
+ subject.add_vars(%w[q y])
114
+
115
+ # Search for unknown name
116
+ expect(subject.lookup('z')).to be_nil
117
+
118
+ # Search for existing unique names
119
+ expect(subject.lookup('y')).to eq(symb_tbl.current_scope.defns['y'])
120
+ expect(subject.lookup('x')).to eq(symb_tbl.root.defns['x'])
121
+
122
+ # Search for redefined name
123
+ expect(subject.lookup('q')).to eq(symb_tbl.current_scope.defns['q'])
124
+ end
125
+
126
+ it 'should determine the ranks of fresh variables' do
127
+ subject.add_vars(%w[x y z])
128
+
129
+ ref_y = LogVarRef.new('y')
130
+ subject.associate('x', ref_y)
131
+ subject.send(:calc_ranking)
132
+ expect(subject.ranking.size).to eq(2)
133
+ i_name_y = subject.lookup('y').i_name
134
+ expect(subject.ranking[i_name_y]).to eq(0)
135
+ i_name_z = subject.lookup('z').i_name
136
+ expect(subject.ranking[i_name_z]).to eq(1)
137
+ end
138
+
139
+ it 'should allow entering in a new scope' do
140
+ new_scope = Scope.new
141
+ expect { subject.enter_scope(new_scope) }.not_to raise_error
142
+ expect(subject.symbol_table.current_scope).to eq(new_scope)
143
+ end
144
+
145
+ it 'should allow leaving out current scope' do
146
+ subject.add_vars(%w[q x])
147
+ x_val = k_symbol(:foo)
148
+ assoc_x = subject.associate('x', x_val) # x => :foo
149
+ expect(subject.blackboard.move_queue.size).to eq(1)
150
+ new_scope = Scope.new
151
+ subject.enter_scope(new_scope) # Adds one bookmark
152
+ expect(subject.blackboard.move_queue.size).to eq(2)
153
+ subject.add_vars(%w[w x y z])
154
+
155
+ q_val = LogVarRef.new('x')
156
+ assoc_q = subject.associate('q', q_val)
157
+ w_val = k_symbol(:bar)
158
+ subject.associate('w', w_val)
159
+ x2_val = LogVarRef.new('z')
160
+ assoc2_x = subject.associate('x', x2_val)
161
+ y_val = k_symbol(:foobar)
162
+ subject.associate('y', y_val)
163
+ # x => :foo
164
+ # ------
165
+ # q => x
166
+ # w => :bar
167
+ # x => z
168
+ # y => :foobar
169
+ expect(subject.blackboard.i_name2moves.keys.size).to eq(5)
170
+ expect(subject.blackboard.move_queue.size).to eq(6)
171
+ # require 'debug'
172
+ expect { subject.leave_scope }.not_to raise_error
173
+ # Expected state:
174
+ # x => :foo
175
+ # q => x'
176
+ # x' => z
177
+ expect(subject.blackboard.move_queue.size).to eq(3)
178
+ symb_table = subject.symbol_table
179
+ expect(symb_table.current_scope).to eq(symb_table.root)
180
+ expect(subject.blackboard.i_name2moves.keys.size).to eq(3)
181
+ expect(subject.blackboard.move_queue).to eq([assoc_x, assoc_q, assoc2_x])
182
+ end
183
+
184
+ it 'should substitute values of associations (if needed)' do
185
+ subject.add_vars(%w[q x y z])
186
+
187
+ x_ref = LogVarRef.new('x')
188
+ foobar = Composite::ConsCell.new(k_symbol(:foo), k_symbol(:bar))
189
+ q_val = Composite::ConsCell.new(x_ref, foobar)
190
+ assoc_q = subject.associate('q', q_val)
191
+ subject.send(:calc_ranking)
192
+
193
+ expect(subject.send(:substitute, assoc_q).to_s).to eq('(_0 :foo . :bar)')
194
+ end
195
+
196
+ it 'should build a solution (atomic terms)' do
197
+ subject.add_vars(%w[x y z])
198
+
199
+ subject.succeeded!
200
+ sol = subject.build_solution
201
+ expect(sol.size).to eq(3)
202
+ expect(sol['x']).to eq(:_0)
203
+ expect(sol['y']).to eq(:_1)
204
+ expect(sol['z']).to eq(:_2)
205
+
206
+ foo = k_symbol(:foo)
207
+ subject.associate('x', foo)
208
+ sol = subject.build_solution
209
+ expect(sol.size).to eq(3)
210
+ expect(sol['x']).to eq(foo)
211
+ expect(sol['y']).to eq(:_0)
212
+ expect(sol['z']).to eq(:_1)
213
+
214
+ bar = k_symbol(:bar)
215
+ subject.associate('y', bar)
216
+ sol = subject.build_solution
217
+ expect(sol.size).to eq(3)
218
+ expect(sol['x']).to eq(foo)
219
+ expect(sol['y']).to eq(bar)
220
+ expect(sol['z']).to eq(:_0)
221
+ end
222
+
223
+ it 'should build a solution (composite terms)' do
224
+ subject.add_vars(['l'])
225
+ new_scope = Scope.new
226
+ subject.enter_scope(new_scope)
227
+ a = k_symbol(:a)
228
+ b = k_symbol(:b)
229
+ c = k_symbol(:c)
230
+ subject.add_vars(['d'])
231
+ d_ref = LogVarRef.new('d')
232
+ subject.associate('l', cons(cons(a, cons(b)), d_ref))
233
+ subject.associate('d', cons(c))
234
+
235
+ subject.succeeded!
236
+ sol = subject.build_solution
237
+ expect(sol.size).to eq(1)
238
+
239
+ # TODO: fix next line. Actual is: ((a :c))
240
+ expect(sol['l'].to_s).to eq('((:a :b) :c)')
241
+ end
242
+ end
243
+ end # describe
244
+ end # module
245
+ end # module
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ require_relative '../../lib/mini_kraken/core/all_core'
6
+
7
+ module MiniKraken
8
+ module Core
9
+ # Integration-in-the-small testing
10
+ describe 'Core Classes' do
11
+ let(:ctx) { Context.new }
12
+
13
+ context 'Executing nullary goals:' do
14
+ def var(aName)
15
+ LogVar.new(aName)
16
+ end
17
+
18
+ it 'should execute nullary fail goal' do
19
+ # Equivalent to frame 1:7
20
+ goal = Goal.new(Fail.instance, [])
21
+ ctx.insert(var('q'))
22
+ result = goal.achieve(ctx)
23
+ expect(result.resume).to eq(ctx)
24
+ expect(ctx).to be_failure
25
+ expect(ctx.associations_for('q')).to be_empty
26
+ end
27
+
28
+ it 'should execute nullary succeed goal' do
29
+ # Equivalent to frame 1:17
30
+ goal = Goal.new(Succeed.instance, [])
31
+ ctx.insert(var('q'))
32
+ result = goal.achieve(ctx)
33
+ expect(result.resume).to eq(ctx)
34
+ expect(ctx).to be_success
35
+ expect(ctx.associations_for('q')).to be_empty # RS: (_0)
36
+ end
37
+ end # context
38
+ end # describe
39
+ end # module
40
+ end # module
@@ -1,7 +1,6 @@
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/environment'
5
4
 
6
5
  # Load the class under test
7
6
  require_relative '../../lib/mini_kraken/core/duck_fiber'
@@ -9,62 +8,33 @@ require_relative '../../lib/mini_kraken/core/duck_fiber'
9
8
  module MiniKraken
10
9
  module Core
11
10
  describe DuckFiber do
12
- subject { DuckFiber.new(:failure) }
11
+ let(:ctx) { Core::Context.new }
12
+ let(:callable) { -> { ctx.failed! } }
13
+ subject { DuckFiber.new(callable) }
13
14
 
14
15
  context 'Initialization:' do
15
- it 'should be initialized with a symbol and an optional block' do
16
- expect { DuckFiber.new(:failure) }.not_to raise_error
16
+ it 'could be initialized with a Proc' do
17
+ expect { DuckFiber.new(-> { ctx.failed }) }.not_to raise_error
18
+ end
17
19
 
18
- expect { DuckFiber.new(:custom) { Outcome.new(:"#s") } }.not_to raise_error
20
+ it "could be initialized with an object that responds to 'call'" do
21
+ expect { DuckFiber.new(callable) }.not_to raise_error
19
22
  end
20
23
 
21
- it 'should know its outcome' do
22
- expect(subject.outcome).to eq(Failure)
24
+ it 'should know its callable object' do
25
+ expect(subject.callable).to eq(callable)
23
26
  end
24
27
  end # context
25
28
 
26
29
  context 'Provided services:' do
27
- let(:parent) { Environment.new }
28
-
29
- it 'should behave like a Fiber yielding a failure' do
30
- failing = DuckFiber.new(:failure)
31
- outcome = nil
32
- expect { outcome = failing.resume }.not_to raise_error
33
- expect(outcome).to eq(Failure)
34
-
35
- # Only one result should be yielded
36
- expect(failing.resume).to be_nil
37
- end
38
-
39
- it 'should behave like a Fiber yielding a basic success' do
40
- succeeding = DuckFiber.new(:success)
41
- outcome = nil
42
- expect { outcome = succeeding.resume }.not_to raise_error
43
- expect(outcome).to be_success
44
- expect(outcome.parent).to be_nil
45
-
46
- # Only one result should be yielded
47
- expect(succeeding.resume).to be_nil
48
- end
49
-
50
- it 'should yield a distinct success object' do
51
- instance1 = DuckFiber.new(:success)
52
- outcome1 = instance1.resume
53
-
54
- instance2 = DuckFiber.new(:success)
55
- outcome2 = instance2.resume
56
-
57
- expect(outcome1).not_to be_equal(outcome2)
58
- end
59
-
60
- it 'should behave like a Fiber yielding a custom outcome' do
61
- tailored = DuckFiber.new(:custom) { Outcome.new(:"#s", parent) }
62
- outcome = nil
63
- expect { outcome = tailored.resume }.not_to raise_error
64
- expect(outcome).to eq(Outcome.new(:"#s", parent))
30
+ it 'should behave like a Fiber yielding the given Context' do
31
+ result = nil
32
+ expect { result = subject.resume }.not_to raise_error
33
+ expect(result).to eq(ctx)
34
+ expect(ctx).to be_failure
65
35
 
66
36
  # Only one result should be yielded
67
- expect(tailored.resume).to be_nil
37
+ expect(subject.resume).to be_nil
68
38
  end
69
39
  end # context
70
40
  end # describe
@@ -21,17 +21,16 @@ module MiniKraken
21
21
  end # context
22
22
 
23
23
  context 'Provided services:' do
24
- it 'should unconditionally return a failure result' do
25
- args = double('fake-args')
26
- env = double('fake-env')
24
+ let(:ctx) { Context.new }
27
25
 
26
+ it 'should unconditionally return a failure result' do
28
27
  solver = nil
29
- expect { solver = subject.solver_for(args, env) }.not_to raise_error
28
+ expect { solver = subject.solver_for([], ctx) }.not_to raise_error
30
29
 
31
- # Solver should quack like a Fiber
30
+ # Solver quacks like a Fiber
32
31
  dummy_arg = double('dummy-stuff')
33
32
  result = solver.resume(dummy_arg)
34
- expect(result).to eq(Failure)
33
+ expect(result).to be_failure
35
34
 
36
35
  # Only one "solution", next 'resume' call should return nil
37
36
  result = solver.resume(dummy_arg)
@@ -1,22 +1,31 @@
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/environment'
5
- require_relative '../../lib/mini_kraken/core/equals'
6
4
  require_relative '../../lib/mini_kraken/core/fail'
7
- require_relative '../../lib/mini_kraken/core/k_symbol'
5
+ require_relative '../../lib/mini_kraken/atomic/k_symbol'
6
+
8
7
 
9
8
  # Load the class under test
10
9
  require_relative '../../lib/mini_kraken/core/goal'
11
10
 
12
11
  module MiniKraken
13
12
  module Core
13
+ class DummyRelation < Relation
14
+ def initialize
15
+ super('dummy', 2)
16
+ end
17
+
18
+ def solver_for(_actuals, ctx)
19
+ DuckFiber.new(-> { ctx.succeeded! })
20
+ end
21
+ end
22
+
14
23
  describe Goal do
15
24
  let(:nullary_relation) { Fail.instance }
16
- subject { Goal.new(nullary_relation, []) }
17
- let(:binary_relation) { Equals.instance }
18
- let(:env) { Environment.new }
19
- subject { Goal.new(binary_relation, [KSymbol.new(:pea), KSymbol.new(:pod)]) }
25
+ let(:binary_relation) { DummyRelation.new }
26
+ let(:ctx) { Context.new }
27
+ let(:actuals) { [Atomic::KSymbol.new(:pea), Atomic::KSymbol.new(:pod)] }
28
+ subject { Goal.new(binary_relation, actuals) }
20
29
 
21
30
  context 'Initialization:' do
22
31
  it 'should accept one nullary relation and empty argument array' do
@@ -24,7 +33,7 @@ module MiniKraken
24
33
  end
25
34
 
26
35
  it 'should accept one binary relation and 2-elements array' do
27
- expect { Goal.new(binary_relation, [KSymbol.new(:pea), KSymbol.new(:pod)]) }.not_to raise_error
36
+ expect { Goal.new(binary_relation, [Term.new, Term.new]) }.not_to raise_error
28
37
  end
29
38
 
30
39
  it 'should know its relation' do
@@ -32,14 +41,15 @@ module MiniKraken
32
41
  end
33
42
 
34
43
  it 'should know its actual arguments' do
35
- expectations = [KSymbol.new(:pea), KSymbol.new(:pod)]
44
+ expectations = [Atomic::KSymbol.new(:pea), Atomic::KSymbol.new(:pod)]
36
45
  expect(subject.actuals).to eq(expectations)
37
46
  end
38
47
  end # context
39
48
 
40
49
  context 'Provided services:' do
41
50
  it 'should fail if relation does not succeed' do
42
- solver = subject.attain(env)
51
+ instance = Goal.new(nullary_relation, [])
52
+ solver = instance.achieve(ctx)
43
53
  expect(solver.resume).not_to be_success
44
54
 
45
55
  # No more solution...
@@ -47,9 +57,9 @@ module MiniKraken
47
57
  end
48
58
 
49
59
  it 'should succeed if relation succeeds' do
50
- instance = Goal.new(binary_relation, [KSymbol.new(:pea), KSymbol.new(:pea)])
60
+ instance = Goal.new(binary_relation, actuals)
51
61
 
52
- solver = instance.attain(env)
62
+ solver = instance.achieve(ctx)
53
63
  expect(solver.resume).to be_success
54
64
 
55
65
  # No more solution...