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.
- checksums.yaml +4 -4
- data/.rubocop.yml +378 -333
- data/CHANGELOG.md +52 -0
- data/README.md +19 -19
- data/lib/mini_kraken.rb +0 -1
- data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
- data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
- data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
- data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
- data/lib/mini_kraken/atomic/k_string.rb +17 -0
- data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
- data/lib/mini_kraken/composite/all_composite.rb +4 -0
- data/lib/mini_kraken/composite/composite_term.rb +27 -0
- data/lib/mini_kraken/composite/cons_cell.rb +299 -0
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
- data/lib/mini_kraken/composite/list.rb +32 -0
- data/lib/mini_kraken/core/all_core.rb +8 -0
- data/lib/mini_kraken/core/any_value.rb +31 -7
- data/lib/mini_kraken/core/arity.rb +69 -0
- data/lib/mini_kraken/core/association.rb +29 -4
- data/lib/mini_kraken/core/association_copy.rb +50 -0
- data/lib/mini_kraken/core/base_term.rb +13 -0
- data/lib/mini_kraken/core/blackboard.rb +315 -0
- data/lib/mini_kraken/core/bookmark.rb +46 -0
- data/lib/mini_kraken/core/context.rb +492 -0
- data/lib/mini_kraken/core/duck_fiber.rb +21 -19
- data/lib/mini_kraken/core/entry.rb +40 -0
- data/lib/mini_kraken/core/fail.rb +20 -18
- data/lib/mini_kraken/core/fusion.rb +29 -0
- data/lib/mini_kraken/core/goal.rb +20 -29
- data/lib/mini_kraken/core/log_var.rb +22 -0
- data/lib/mini_kraken/core/log_var_ref.rb +108 -0
- data/lib/mini_kraken/core/nullary_relation.rb +2 -9
- data/lib/mini_kraken/core/parametrized_term.rb +61 -0
- data/lib/mini_kraken/core/relation.rb +14 -28
- data/lib/mini_kraken/core/scope.rb +67 -0
- data/lib/mini_kraken/core/solver_adapter.rb +58 -0
- data/lib/mini_kraken/core/specification.rb +48 -0
- data/lib/mini_kraken/core/succeed.rb +21 -17
- data/lib/mini_kraken/core/symbol_table.rb +137 -0
- data/lib/mini_kraken/core/term.rb +15 -4
- data/lib/mini_kraken/glue/dsl.rb +45 -81
- data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
- data/lib/mini_kraken/rela/all_rela.rb +8 -0
- data/lib/mini_kraken/rela/binary_relation.rb +30 -0
- data/lib/mini_kraken/rela/conde.rb +143 -0
- data/lib/mini_kraken/rela/conj2.rb +65 -0
- data/lib/mini_kraken/rela/def_relation.rb +93 -0
- data/lib/mini_kraken/rela/disj2.rb +70 -0
- data/lib/mini_kraken/rela/fresh.rb +98 -0
- data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
- data/lib/mini_kraken/rela/unify.rb +258 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/mini_kraken.gemspec +2 -2
- data/spec/.rubocop.yml +1 -1
- data/spec/atomic/atomic_term_spec.rb +98 -0
- data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
- data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
- data/spec/composite/cons_cell_spec.rb +225 -0
- data/spec/composite/cons_cell_visitor_spec.rb +158 -0
- data/spec/composite/list_spec.rb +50 -0
- data/spec/core/any_value_spec.rb +52 -0
- data/spec/core/arity_spec.rb +92 -0
- data/spec/core/association_copy_spec.rb +69 -0
- data/spec/core/association_spec.rb +31 -4
- data/spec/core/blackboard_spec.rb +287 -0
- data/spec/core/bookmark_spec.rb +40 -0
- data/spec/core/context_spec.rb +245 -0
- data/spec/core/core_spec.rb +40 -0
- data/spec/core/duck_fiber_spec.rb +16 -46
- data/spec/core/fail_spec.rb +5 -6
- data/spec/core/goal_spec.rb +24 -14
- data/spec/core/log_var_ref_spec.rb +105 -0
- data/spec/core/log_var_spec.rb +64 -0
- data/spec/core/nullary_relation_spec.rb +33 -0
- data/spec/core/parametrized_tem_spec.rb +39 -0
- data/spec/core/relation_spec.rb +33 -0
- data/spec/core/scope_spec.rb +73 -0
- data/spec/core/solver_adapter_spec.rb +70 -0
- data/spec/core/specification_spec.rb +43 -0
- data/spec/core/succeed_spec.rb +5 -5
- data/spec/core/symbol_table_spec.rb +142 -0
- data/spec/glue/dsl_chap1_spec.rb +96 -144
- data/spec/glue/dsl_chap2_spec.rb +350 -0
- data/spec/glue/run_star_expression_spec.rb +82 -906
- data/spec/rela/conde_spec.rb +153 -0
- data/spec/rela/conj2_spec.rb +123 -0
- data/spec/rela/def_relation_spec.rb +119 -0
- data/spec/rela/disj2_spec.rb +117 -0
- data/spec/rela/fresh_spec.rb +147 -0
- data/spec/rela/unify_spec.rb +369 -0
- data/spec/support/factory_atomic.rb +29 -0
- data/spec/support/factory_composite.rb +21 -0
- data/spec/support/factory_methods.rb +11 -26
- metadata +100 -64
- data/lib/mini_kraken/core/association_walker.rb +0 -183
- data/lib/mini_kraken/core/atomic_term.rb +0 -67
- data/lib/mini_kraken/core/base_arg.rb +0 -10
- data/lib/mini_kraken/core/binary_relation.rb +0 -63
- data/lib/mini_kraken/core/composite_goal.rb +0 -46
- data/lib/mini_kraken/core/composite_term.rb +0 -41
- data/lib/mini_kraken/core/conde.rb +0 -143
- data/lib/mini_kraken/core/conj2.rb +0 -79
- data/lib/mini_kraken/core/cons_cell.rb +0 -82
- data/lib/mini_kraken/core/def_relation.rb +0 -50
- data/lib/mini_kraken/core/designation.rb +0 -55
- data/lib/mini_kraken/core/disj2.rb +0 -72
- data/lib/mini_kraken/core/environment.rb +0 -73
- data/lib/mini_kraken/core/equals.rb +0 -156
- data/lib/mini_kraken/core/formal_arg.rb +0 -22
- data/lib/mini_kraken/core/formal_ref.rb +0 -25
- data/lib/mini_kraken/core/freshness.rb +0 -45
- data/lib/mini_kraken/core/goal_arg.rb +0 -12
- data/lib/mini_kraken/core/goal_template.rb +0 -62
- data/lib/mini_kraken/core/k_boolean.rb +0 -35
- data/lib/mini_kraken/core/outcome.rb +0 -53
- data/lib/mini_kraken/core/variable.rb +0 -41
- data/lib/mini_kraken/core/variable_ref.rb +0 -78
- data/lib/mini_kraken/core/vocabulary.rb +0 -442
- data/lib/mini_kraken/glue/fresh_env.rb +0 -75
- data/spec/core/association_walker_spec.rb +0 -192
- data/spec/core/conde_spec.rb +0 -147
- data/spec/core/conj2_spec.rb +0 -114
- data/spec/core/cons_cell_spec.rb +0 -107
- data/spec/core/def_relation_spec.rb +0 -96
- data/spec/core/disj2_spec.rb +0 -99
- data/spec/core/environment_spec.rb +0 -142
- data/spec/core/equals_spec.rb +0 -304
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -48
- data/spec/core/variable_ref_spec.rb +0 -27
- data/spec/core/variable_spec.rb +0 -35
- data/spec/core/vocabulary_spec.rb +0 -219
- 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
|
data/spec/core/conde_spec.rb
DELETED
@@ -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
|
data/spec/core/conj2_spec.rb
DELETED
@@ -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
|