mini_kraken 0.2.02 → 0.3.02

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +378 -333
  3. data/CHANGELOG.md +52 -0
  4. data/README.md +19 -19
  5. data/lib/mini_kraken.rb +0 -1
  6. data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
  7. data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
  8. data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
  9. data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
  10. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  11. data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
  12. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  13. data/lib/mini_kraken/composite/composite_term.rb +27 -0
  14. data/lib/mini_kraken/composite/cons_cell.rb +299 -0
  15. data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
  16. data/lib/mini_kraken/composite/list.rb +32 -0
  17. data/lib/mini_kraken/core/all_core.rb +8 -0
  18. data/lib/mini_kraken/core/any_value.rb +31 -7
  19. data/lib/mini_kraken/core/arity.rb +69 -0
  20. data/lib/mini_kraken/core/association.rb +29 -4
  21. data/lib/mini_kraken/core/association_copy.rb +50 -0
  22. data/lib/mini_kraken/core/base_term.rb +13 -0
  23. data/lib/mini_kraken/core/blackboard.rb +315 -0
  24. data/lib/mini_kraken/core/bookmark.rb +46 -0
  25. data/lib/mini_kraken/core/context.rb +492 -0
  26. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  27. data/lib/mini_kraken/core/entry.rb +40 -0
  28. data/lib/mini_kraken/core/fail.rb +20 -18
  29. data/lib/mini_kraken/core/fusion.rb +29 -0
  30. data/lib/mini_kraken/core/goal.rb +20 -29
  31. data/lib/mini_kraken/core/log_var.rb +22 -0
  32. data/lib/mini_kraken/core/log_var_ref.rb +108 -0
  33. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  34. data/lib/mini_kraken/core/parametrized_term.rb +61 -0
  35. data/lib/mini_kraken/core/relation.rb +14 -28
  36. data/lib/mini_kraken/core/scope.rb +67 -0
  37. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  38. data/lib/mini_kraken/core/specification.rb +48 -0
  39. data/lib/mini_kraken/core/succeed.rb +21 -17
  40. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  41. data/lib/mini_kraken/core/term.rb +15 -4
  42. data/lib/mini_kraken/glue/dsl.rb +45 -81
  43. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  44. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  45. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  46. data/lib/mini_kraken/rela/conde.rb +143 -0
  47. data/lib/mini_kraken/rela/conj2.rb +65 -0
  48. data/lib/mini_kraken/rela/def_relation.rb +93 -0
  49. data/lib/mini_kraken/rela/disj2.rb +70 -0
  50. data/lib/mini_kraken/rela/fresh.rb +98 -0
  51. data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
  52. data/lib/mini_kraken/rela/unify.rb +258 -0
  53. data/lib/mini_kraken/version.rb +1 -1
  54. data/mini_kraken.gemspec +2 -2
  55. data/spec/.rubocop.yml +1 -1
  56. data/spec/atomic/atomic_term_spec.rb +98 -0
  57. data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
  58. data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
  59. data/spec/composite/cons_cell_spec.rb +225 -0
  60. data/spec/composite/cons_cell_visitor_spec.rb +158 -0
  61. data/spec/composite/list_spec.rb +50 -0
  62. data/spec/core/any_value_spec.rb +52 -0
  63. data/spec/core/arity_spec.rb +92 -0
  64. data/spec/core/association_copy_spec.rb +69 -0
  65. data/spec/core/association_spec.rb +31 -4
  66. data/spec/core/blackboard_spec.rb +287 -0
  67. data/spec/core/bookmark_spec.rb +40 -0
  68. data/spec/core/context_spec.rb +245 -0
  69. data/spec/core/core_spec.rb +40 -0
  70. data/spec/core/duck_fiber_spec.rb +16 -46
  71. data/spec/core/fail_spec.rb +5 -6
  72. data/spec/core/goal_spec.rb +24 -14
  73. data/spec/core/log_var_ref_spec.rb +105 -0
  74. data/spec/core/log_var_spec.rb +64 -0
  75. data/spec/core/nullary_relation_spec.rb +33 -0
  76. data/spec/core/parametrized_tem_spec.rb +39 -0
  77. data/spec/core/relation_spec.rb +33 -0
  78. data/spec/core/scope_spec.rb +73 -0
  79. data/spec/core/solver_adapter_spec.rb +70 -0
  80. data/spec/core/specification_spec.rb +43 -0
  81. data/spec/core/succeed_spec.rb +5 -5
  82. data/spec/core/symbol_table_spec.rb +142 -0
  83. data/spec/glue/dsl_chap1_spec.rb +96 -144
  84. data/spec/glue/dsl_chap2_spec.rb +350 -0
  85. data/spec/glue/run_star_expression_spec.rb +82 -906
  86. data/spec/rela/conde_spec.rb +153 -0
  87. data/spec/rela/conj2_spec.rb +123 -0
  88. data/spec/rela/def_relation_spec.rb +119 -0
  89. data/spec/rela/disj2_spec.rb +117 -0
  90. data/spec/rela/fresh_spec.rb +147 -0
  91. data/spec/rela/unify_spec.rb +369 -0
  92. data/spec/support/factory_atomic.rb +29 -0
  93. data/spec/support/factory_composite.rb +21 -0
  94. data/spec/support/factory_methods.rb +11 -26
  95. metadata +100 -64
  96. data/lib/mini_kraken/core/association_walker.rb +0 -183
  97. data/lib/mini_kraken/core/atomic_term.rb +0 -67
  98. data/lib/mini_kraken/core/base_arg.rb +0 -10
  99. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  100. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  101. data/lib/mini_kraken/core/composite_term.rb +0 -41
  102. data/lib/mini_kraken/core/conde.rb +0 -143
  103. data/lib/mini_kraken/core/conj2.rb +0 -79
  104. data/lib/mini_kraken/core/cons_cell.rb +0 -82
  105. data/lib/mini_kraken/core/def_relation.rb +0 -50
  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 -156
  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 -62
  115. data/lib/mini_kraken/core/k_boolean.rb +0 -35
  116. data/lib/mini_kraken/core/outcome.rb +0 -53
  117. data/lib/mini_kraken/core/variable.rb +0 -41
  118. data/lib/mini_kraken/core/variable_ref.rb +0 -78
  119. data/lib/mini_kraken/core/vocabulary.rb +0 -442
  120. data/lib/mini_kraken/glue/fresh_env.rb +0 -75
  121. data/spec/core/association_walker_spec.rb +0 -192
  122. data/spec/core/conde_spec.rb +0 -147
  123. data/spec/core/conj2_spec.rb +0 -114
  124. data/spec/core/cons_cell_spec.rb +0 -107
  125. data/spec/core/def_relation_spec.rb +0 -96
  126. data/spec/core/disj2_spec.rb +0 -99
  127. data/spec/core/environment_spec.rb +0 -142
  128. data/spec/core/equals_spec.rb +0 -304
  129. data/spec/core/goal_template_spec.rb +0 -74
  130. data/spec/core/outcome_spec.rb +0 -48
  131. data/spec/core/variable_ref_spec.rb +0 -27
  132. data/spec/core/variable_spec.rb +0 -35
  133. data/spec/core/vocabulary_spec.rb +0 -219
  134. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../core/environment'
4
- require_relative '../core/conj2'
5
- require_relative '../core/variable'
6
-
7
- module MiniKraken
8
- module Glue
9
- # A combination of an Environment (= a scope for one or more variables)
10
- # and a goal. It quacks like a Goal object: when receiving the attain message,
11
- # it attempt to achieve its given goal.
12
- # (fresh (x) (== 'pea q))
13
- # Introduces the new variable 'x'
14
- # Takes a list of names and a goal-like object
15
- # Must respond to message attain(aPublisher, vars) and must return an Outcome
16
- class FreshEnv < Core::Environment
17
- # @return [Goal]
18
- attr_reader :goal
19
-
20
- # @param theNames [Array<String>] The variable names
21
- # @param aGoal [Goal, Array<Goal>] The goal to achieve or the conjunction of them.
22
- def initialize(theNames, aGoal)
23
- super()
24
- @goal = valid_goal(aGoal)
25
- theNames.each { |nm| add_var(Core::Variable.new(nm)) }
26
- end
27
-
28
- # Attempt to achieve the goal given this environment
29
- # @param aParent [Environment]
30
- # @return [Fiber<Outcome>] A Fiber object that will generate the results.
31
- def attain(aParent)
32
- self.parent = aParent
33
- goal.attain(self)
34
- end
35
-
36
- protected
37
-
38
- def introspect
39
- +", @vars=[#{vars.keys.join(', ')}]"
40
- end
41
-
42
- private
43
-
44
- def valid_goal(aGoal)
45
- result = nil
46
-
47
- case aGoal
48
- when Core::Goal
49
- result = aGoal
50
- when FreshEnv
51
- result = aGoal
52
- when Array # an Array of Goal?..
53
- goal_array = aGoal
54
- loop do
55
- conjunctions = []
56
- goal_array.each_slice(2) do |uno_duo|
57
- if uno_duo.size == 2
58
- conjunctions << Core::Goal.new(Core::Conj2.instance, uno_duo)
59
- else
60
- conjunctions << uno_duo[0]
61
- end
62
- end
63
- if conjunctions.size == 1
64
- result = conjunctions[0]
65
- break
66
- end
67
- goal_array = conjunctions
68
- end
69
- end
70
-
71
- result
72
- end
73
- end # class
74
- end # module
75
- end # module
@@ -1,192 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper' # Use the RSpec framework
4
- require_relative '../../lib/mini_kraken/core/environment'
5
- require_relative '../support/factory_methods'
6
-
7
- # Load the class under test
8
- require_relative '../../lib/mini_kraken/core/association_walker'
9
-
10
-
11
- module MiniKraken
12
- module Core
13
- describe AssociationWalker do
14
- include FactoryMethods
15
-
16
- subject { AssociationWalker.new }
17
-
18
- context 'Initialization:' do
19
- it 'should be initialized without argument' do
20
- expect { AssociationWalker.new }.not_to raise_error
21
- end
22
-
23
- it "shouldn't have any visitee at initialization" do
24
- expect(subject.visitees.size).to eq(0)
25
- end
26
- end # context
27
-
28
- context 'Provided services:' do
29
- let(:pea) { KSymbol.new(:pea) }
30
- let(:pod) { KSymbol.new(:pod) }
31
- let(:var_q) { Variable.new('q') }
32
- let(:ref_q) { VariableRef.new('q') }
33
- let(:var_x) { Variable.new('x') }
34
- let(:ref_x) { VariableRef.new('x') }
35
- let(:env) { Environment.new }
36
-
37
- it 'should return composite when it has only atomic term(s)' do
38
- expr1 = cons(pea)
39
- expect(subject.walk_value(expr1, env)).to eq(expr1)
40
-
41
- expr2 = cons(pea, pod)
42
- expect(subject.walk_value(expr2, env)).to eq(expr2)
43
- end
44
-
45
- it 'should return composite when it has ground composite term(s)' do
46
- expr1 = cons(pea, cons(pod))
47
- expect(subject.walk_value(expr1, env)).to eq(expr1)
48
-
49
- expr2 = cons(pea, cons(pod, cons(pea, cons(pod))))
50
- expect(subject.walk_value(expr2, env)).to eq(expr2)
51
- end
52
-
53
- it 'should return nil when there is one fresh variable' do
54
- env.add_var(var_q)
55
- expr1 = cons(pea, cons(pod, ref_q))
56
- expect(subject.walk_value(expr1, env)).to be_nil
57
- end
58
-
59
- it 'should return composite when it has ground composite term(s)' do
60
- env.add_var(var_q)
61
- env.add_assoc('q', pea)
62
- expr1 = cons(pea, cons(pod, cons(ref_q)))
63
- expect(subject.walk_value(expr1, env)).to eq(expr1)
64
- end
65
-
66
- it 'should return nil when no assocation exists' do
67
- env.add_var(var_q)
68
- env.add_assoc('q', pea)
69
- env.add_var(var_x)
70
-
71
- expect(subject.find_ground(var_x.name, env)).to be_nil
72
- end
73
-
74
- it 'should find an atomic term directly associated' do
75
- env.add_var(var_q)
76
- env.add_assoc('q', pea)
77
-
78
- result = subject.find_ground(var_q.name, env)
79
- expect(result).to eq(pea)
80
- end
81
-
82
- it 'should find an atomic term directly associated' do
83
- env.add_var(var_q)
84
- env.add_var(var_x)
85
- env.add_assoc('q', ref_x)
86
- env.add_assoc('x', pea)
87
- expect(env['x']).not_to be_nil
88
-
89
- result = subject.find_ground(var_q.name, env)
90
- expect(result).to eq(pea)
91
- end
92
-
93
- it 'should cope with cyclic structures' do
94
- env.add_var(var_q)
95
- env.add_var(var_x)
96
- env.add_assoc('q', ref_x)
97
- env.add_assoc('x', pea)
98
- env.add_assoc('x', ref_q)
99
-
100
- result = subject.find_ground(var_q.name, env)
101
- expect(result).to eq(pea)
102
-
103
- result = subject.find_ground(var_x.name, env)
104
- expect(result).to eq(pea)
105
- end
106
-
107
- it 'should cope with a composite with atomic terms only' do
108
- env.add_var(var_q)
109
- expr = cons(pea, cons(pod, cons(pea)))
110
- env.add_assoc('q', expr)
111
-
112
- result = subject.find_ground(var_q.name, env)
113
- expect(result).to eq(expr)
114
- end
115
-
116
- it 'should cope with a composite with one fresh variable' do
117
- env.add_var(var_q)
118
- env.add_var(var_x)
119
- expr = cons(pea, cons(pod, cons(ref_x)))
120
- env.add_assoc('q', expr)
121
-
122
- result = subject.find_ground(var_q.name, env)
123
- expect(result).to be_nil
124
- end
125
-
126
- it 'should cope with a composite with one ground variable' do
127
- env.add_var(var_q)
128
- env.add_var(var_x)
129
- expr = cons(pea, cons(pod, cons(ref_x)))
130
- env.add_assoc('q', expr)
131
- env.add_assoc('x', pod)
132
-
133
- result = subject.find_ground(var_q.name, env)
134
- expect(result).to eq(expr)
135
- end
136
-
137
- it 'should categorize a variable without association as free' do
138
- env.add_var(var_q)
139
- result = subject.determine_freshness(ref_q, env)
140
- expect(result).to be_fresh
141
- expect(result.associated).to be_nil
142
- end
143
-
144
- it 'should categorize a variable related to fresh variable as bound' do
145
- env.add_var(var_q)
146
- env.add_var(var_x)
147
- env.add_assoc('q', ref_x)
148
-
149
- result = subject.determine_freshness(ref_q, env)
150
- expect(result).to be_bound
151
- expect(result.associated).to eq(ref_x)
152
- end
153
-
154
- it 'should categorize a variable even in presence of fused var(s)' do
155
- env.add_var(var_q)
156
- env.add_var(var_x)
157
- env.add_assoc('q', ref_x)
158
- env.add_assoc('x', ref_q)
159
- # q and x are fused...
160
-
161
- result = subject.determine_freshness(ref_q, env)
162
- expect(result).to be_fresh
163
- expect(var_q.i_name).to eq(var_x.i_name)
164
- expect(env.associations).to be_empty
165
- end
166
-
167
- it 'should categorize an atomic term as ground term' do
168
- result = subject.determine_freshness(pea, env)
169
- expect(result).to be_ground
170
- expect(result.associated).to eq(pea)
171
- end
172
-
173
- it 'should categorize a composite term as ground term' do
174
- # Ground composite: a composite where all members are ground
175
- composite = cons(pea, cons(pod))
176
- result = subject.determine_freshness(composite, env)
177
- expect(result).to be_ground
178
- expect(result.associated).to eq(composite)
179
- end
180
-
181
- it 'should categorize a composite term as bound term' do
182
- # Bound composite: a composite where at least one member is fresh
183
- env.add_var(var_q)
184
- composite = cons(pea, cons(ref_q))
185
- result = subject.determine_freshness(composite, env)
186
- expect(result).to be_bound
187
- expect(result.associated).to eq(composite)
188
- end
189
- end # context
190
- end # describe
191
- end # module
192
- end # module
@@ -1,147 +0,0 @@
1
- # frozen_string_literal: true
2
-
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/fail'
6
- require_relative '../../lib/mini_kraken/core/succeed'
7
- require_relative '../../lib/mini_kraken/core/equals'
8
- require_relative '../../lib/mini_kraken/core/environment'
9
- require_relative '../../lib/mini_kraken/core/variable'
10
- require_relative '../../lib/mini_kraken/core/variable_ref'
11
-
12
- # Load the class under test
13
- require_relative '../../lib/mini_kraken/core/conde'
14
-
15
- module MiniKraken
16
- module Core
17
- describe Conde do
18
- subject { Conde.instance }
19
-
20
- context 'Initialization:' do
21
- it 'should be initialized without argument' do
22
- expect { Conde.instance }.not_to raise_error
23
- end
24
-
25
- it 'should know its name' do
26
- expect(subject.name).to eq('conde')
27
- end
28
- end # context
29
-
30
- context 'Provided services:' do
31
- let(:bean) { KSymbol.new(:bean) }
32
- let(:corn) { KSymbol.new(:corn) }
33
- let(:meal) { KSymbol.new(:meal) }
34
- let(:oil) { KSymbol.new(:oil) }
35
- let(:olive) { KSymbol.new(:olive) }
36
- let(:pea) { KSymbol.new(:pea) }
37
- let(:red) { KSymbol.new(:red) }
38
- let(:split) { KSymbol.new(:split) }
39
- let(:fails) { Goal.new(Fail.instance, []) }
40
- let(:succeeds) { Goal.new(Succeed.instance, []) }
41
- let(:var_q) { Variable.new('q') }
42
- let(:var_x) { Variable.new('x') }
43
- let(:var_y) { Variable.new('y') }
44
- let(:ref_q) { VariableRef.new('q') }
45
- let(:ref_x) { VariableRef.new('x') }
46
- let(:ref_y) { VariableRef.new('y') }
47
- let(:env) do
48
- e = Environment.new
49
- e.add_var(var_q)
50
- e.add_var(var_x)
51
- e.add_var(var_y)
52
- e
53
- end
54
-
55
- it 'should complain when one of its argument is not a goal' do
56
- err = StandardError
57
- expect { subject.solver_for([succeeds, pea], env) }.to raise_error(err)
58
- expect { subject.solver_for([pea, succeeds], env) }.to raise_error(err)
59
- end
60
-
61
- it 'should fail when all goals fail' do
62
- solver = subject.solver_for([fails, fails, fails], env)
63
- expect(solver.resume).not_to be_successful
64
- expect(solver.resume).to be_nil
65
- end
66
-
67
- it 'yield success if first argument succeeds' do
68
- subgoal = Goal.new(Equals.instance, [olive, ref_q])
69
- solver = subject.solver_for([subgoal, fails, fails], env)
70
- outcome = solver.resume
71
- expect(outcome).to be_successful
72
- expect(outcome.associations['q'].first.value).to eq(olive)
73
- expect(solver.resume).to be_nil
74
- end
75
-
76
- it 'yield success if second argument succeeds' do
77
- subgoal = Goal.new(Equals.instance, [oil, ref_q])
78
- solver = subject.solver_for([fails, subgoal, fails], env)
79
- outcome = solver.resume
80
- expect(outcome).to be_successful
81
- expect(outcome.associations['q'].first.value).to eq(oil)
82
- expect(solver.resume).to be_nil
83
- end
84
-
85
- it 'yield success if third argument succeeds' do
86
- subgoal = Goal.new(Equals.instance, [oil, ref_q])
87
- solver = subject.solver_for([fails, fails, subgoal], env)
88
- outcome = solver.resume
89
- expect(outcome).to be_successful
90
- expect(outcome.associations['q'].first.value).to eq(oil)
91
- expect(solver.resume).to be_nil
92
- end
93
-
94
- it 'yields three solutions if three goals succeed' do
95
- # Covers frame 1:58
96
- subgoal1 = Goal.new(Equals.instance, [olive, ref_q])
97
- subgoal2 = Goal.new(Equals.instance, [oil, ref_q])
98
- subgoal3 = Goal.new(Equals.instance, [pea, ref_q])
99
- solver = subject.solver_for([subgoal1, subgoal2, subgoal3, fails], env)
100
-
101
- # First solution
102
- outcome1 = solver.resume
103
- expect(outcome1).to be_successful
104
- expect(outcome1.associations['q'].first.value).to eq(olive)
105
-
106
- # Second solution
107
- outcome2 = solver.resume
108
- expect(outcome2).to be_successful
109
- expect(outcome2.associations['q'].first.value).to eq(oil)
110
-
111
- # Third solution
112
- outcome3 = solver.resume
113
- expect(outcome3).to be_successful
114
- expect(outcome3.associations['q'].first.value).to eq(pea)
115
-
116
- expect(solver.resume).to be_nil
117
- end
118
-
119
- it 'also use conjunctions for nested goals' do
120
- # Covers frame 1:88
121
- subgoal1 = Goal.new(Equals.instance, [split, ref_x])
122
- subgoal2 = Goal.new(Equals.instance, [pea, ref_y])
123
- combo1 = [subgoal1, subgoal2]
124
-
125
- subgoal3 = Goal.new(Equals.instance, [red, ref_x])
126
- subgoal4 = Goal.new(Equals.instance, [bean, ref_y])
127
- combo2 = [subgoal3, subgoal4]
128
- solver = subject.solver_for([combo1, combo2], env)
129
-
130
- # First solution
131
- outcome1 = solver.resume
132
- expect(outcome1).to be_successful
133
- expect(outcome1.associations['x'].first.value).to eq(split)
134
- expect(outcome1.associations['y'].first.value).to eq(pea)
135
-
136
- # Second solution
137
- outcome2 = solver.resume
138
- expect(outcome2).to be_successful
139
- expect(outcome2.associations['x'].first.value).to eq(red)
140
- expect(outcome2.associations['y'].first.value).to eq(bean)
141
-
142
- expect(solver.resume).to be_nil
143
- end
144
- end # context
145
- end # describe
146
- end # module
147
- end # module
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
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/fail'
6
- require_relative '../../lib/mini_kraken/core/succeed'
7
- require_relative '../../lib/mini_kraken/core/equals'
8
- require_relative '../../lib/mini_kraken/core/environment'
9
- require_relative '../../lib/mini_kraken/core/variable'
10
- require_relative '../../lib/mini_kraken/core/variable_ref'
11
-
12
- # Load the class under test
13
- require_relative '../../lib/mini_kraken/core/conj2'
14
-
15
-
16
- module MiniKraken
17
- module Core
18
- describe Conj2 do
19
- subject { Conj2.instance }
20
-
21
- context 'Initialization:' do
22
- it 'should be initialized without argument' do
23
- expect { Conj2.instance }.not_to raise_error
24
- end
25
-
26
- it 'should know its name' do
27
- expect(subject.name).to eq('conj2')
28
- end
29
- end # context
30
-
31
- context 'Provided services:' do
32
- let(:env) { Environment.new }
33
- let(:pea) { KSymbol.new(:pea) }
34
- let(:corn) { KSymbol.new(:corn) }
35
- let(:meal) { KSymbol.new(:meal) }
36
- let(:fails) { Goal.new(Fail.instance, []) }
37
- let(:succeeds) { Goal.new(Succeed.instance, []) }
38
- let(:var_q) { Variable.new('q') }
39
- let(:ref_q) { VariableRef.new('q') }
40
-
41
- it 'should complain when one of its argument is not a goal' do
42
- err = StandardError
43
- expect { subject.solver_for([succeeds, pea], env) }.to raise_error(err)
44
- expect { subject.solver_for([pea, succeeds], env) }.to raise_error(err)
45
- end
46
-
47
- it 'should yield one failure if one of the goal is fail' do
48
- # Fail as first argument
49
- solver = subject.solver_for([fails, succeeds], env)
50
- expect(solver.resume).not_to be_successful
51
- expect(solver.resume).to be_nil
52
-
53
- # Fail as second argument
54
- solver = subject.solver_for([succeeds, fails], env)
55
- expect(solver.resume).not_to be_successful
56
- expect(solver.resume).to be_nil
57
- end
58
-
59
- it 'yield success if both arguments are succeed goals' do
60
- # Covers frame 1-50
61
- solver = subject.solver_for([succeeds, succeeds], env)
62
- outcome = solver.resume
63
- expect(outcome).to be_successful
64
- expect(outcome.associations).to be_empty
65
- expect(solver.resume).to be_nil
66
- end
67
-
68
- it 'should yield success and set associations' do
69
- # Covers frame 1-51
70
- env.add_var(var_q)
71
- sub_goal = Goal.new(Equals.instance, [corn, ref_q])
72
- solver = subject.solver_for([succeeds, sub_goal], env)
73
- outcome = solver.resume
74
- expect(outcome).to be_successful
75
- expect(outcome.associations).not_to be_empty
76
- expect(outcome.associations['q'].first.value).to eq(corn)
77
- end
78
-
79
- it 'should yield fails and set no associations' do
80
- # Covers frame 1-52
81
- env.add_var(var_q)
82
- sub_goal = Goal.new(Equals.instance, [corn, ref_q])
83
- solver = subject.solver_for([fails, sub_goal], env)
84
- outcome = solver.resume
85
- expect(outcome).not_to be_successful
86
- expect(outcome.associations).to be_empty
87
- end
88
-
89
- it 'should yield fails when sub-goals are incompatible' do
90
- # Covers frame 1-53
91
- env.add_var(var_q)
92
- sub_goal1 = Goal.new(Equals.instance, [corn, ref_q])
93
- sub_goal2 = Goal.new(Equals.instance, [meal, ref_q])
94
- solver = subject.solver_for([sub_goal1, sub_goal2], env)
95
- outcome = solver.resume
96
- expect(outcome).not_to be_successful
97
- expect(outcome.associations).to be_empty
98
- end
99
-
100
- it 'should yield success when sub-goals are same and successful' do
101
- # Covers frame 1-54
102
- env.add_var(var_q)
103
- sub_goal1 = Goal.new(Equals.instance, [corn, ref_q])
104
- sub_goal2 = Goal.new(Equals.instance, [corn, ref_q])
105
- solver = subject.solver_for([sub_goal1, sub_goal2], env)
106
- outcome = solver.resume
107
- expect(outcome).to be_successful
108
- expect(outcome.associations).not_to be_empty
109
- expect(outcome.associations['q'].first.value).to eq(corn)
110
- end
111
- end # context
112
- end # describe
113
- end # module
114
- end # module