mini_kraken 0.1.03 → 0.1.08
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/.travis.yml +5 -1
- data/CHANGELOG.md +54 -3
- data/Gemfile +3 -1
- data/README.md +22 -1
- data/Rakefile +5 -3
- data/lib/mini_kraken.rb +3 -1
- data/lib/mini_kraken/core/any_value.rb +9 -7
- data/lib/mini_kraken/core/association.rb +20 -7
- data/lib/mini_kraken/core/association_walker.rb +5 -1
- data/lib/mini_kraken/core/atomic_term.rb +5 -3
- data/lib/mini_kraken/core/binary_relation.rb +8 -6
- data/lib/mini_kraken/core/composite_goal.rb +46 -0
- data/lib/mini_kraken/core/composite_term.rb +7 -20
- data/lib/mini_kraken/core/conj2.rb +77 -0
- data/lib/mini_kraken/core/cons_cell.rb +51 -41
- data/lib/mini_kraken/core/designation.rb +55 -0
- data/lib/mini_kraken/core/disj2.rb +71 -0
- data/lib/mini_kraken/core/duck_fiber.rb +4 -2
- data/lib/mini_kraken/core/environment.rb +25 -11
- data/lib/mini_kraken/core/equals.rb +128 -189
- data/lib/mini_kraken/core/fail.rb +20 -14
- data/lib/mini_kraken/core/freshness.rb +11 -8
- data/lib/mini_kraken/core/goal.rb +8 -4
- data/lib/mini_kraken/core/goal_arg.rb +10 -0
- data/lib/mini_kraken/core/goal_relation.rb +28 -0
- data/lib/mini_kraken/core/k_integer.rb +4 -3
- data/lib/mini_kraken/core/k_symbol.rb +4 -3
- data/lib/mini_kraken/core/nullary_relation.rb +3 -1
- data/lib/mini_kraken/core/outcome.rb +29 -25
- data/lib/mini_kraken/core/relation.rb +4 -18
- data/lib/mini_kraken/core/succeed.rb +20 -14
- data/lib/mini_kraken/core/term.rb +7 -2
- data/lib/mini_kraken/core/variable.rb +11 -25
- data/lib/mini_kraken/core/variable_ref.rb +12 -59
- data/lib/mini_kraken/core/vocabulary.rb +267 -48
- data/lib/mini_kraken/glue/fresh_env.rb +5 -3
- data/lib/mini_kraken/glue/run_star_expression.rb +18 -8
- data/lib/mini_kraken/version.rb +3 -1
- data/mini_kraken.gemspec +15 -13
- data/spec/core/association_spec.rb +4 -4
- data/spec/core/association_walker_spec.rb +25 -24
- data/spec/core/conj2_spec.rb +114 -0
- data/spec/core/cons_cell_spec.rb +12 -3
- data/spec/core/disj2_spec.rb +99 -0
- data/spec/core/duck_fiber_spec.rb +22 -12
- data/spec/core/environment_spec.rb +16 -28
- data/spec/core/equals_spec.rb +7 -7
- data/spec/core/fail_spec.rb +7 -7
- data/spec/core/goal_spec.rb +10 -10
- data/spec/core/k_symbol_spec.rb +5 -6
- data/spec/core/succeed_spec.rb +4 -4
- data/spec/core/variable_ref_spec.rb +0 -4
- data/spec/core/vocabulary_spec.rb +33 -27
- data/spec/glue/fresh_env_spec.rb +1 -1
- data/spec/glue/run_star_expression_spec.rb +213 -60
- data/spec/mini_kraken_spec.rb +4 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/support/factory_methods.rb +20 -2
- metadata +12 -2
data/lib/mini_kraken/version.rb
CHANGED
data/mini_kraken.gemspec
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
5
|
+
require 'mini_kraken/version'
|
4
6
|
|
5
7
|
# Implementation module
|
6
8
|
module PkgExtending
|
@@ -10,7 +12,7 @@ module PkgExtending
|
|
10
12
|
'.travis.yml',
|
11
13
|
'Gemfile',
|
12
14
|
'Rakefile',
|
13
|
-
'CHANGELOG.md',
|
15
|
+
'CHANGELOG.md',
|
14
16
|
'LICENSE.txt',
|
15
17
|
'README.md',
|
16
18
|
'mini_kraken.gemspec',
|
@@ -31,25 +33,25 @@ module PkgExtending
|
|
31
33
|
end # module
|
32
34
|
|
33
35
|
Gem::Specification.new do |spec|
|
34
|
-
spec.name =
|
36
|
+
spec.name = 'mini_kraken'
|
35
37
|
spec.version = MiniKraken::VERSION
|
36
38
|
spec.authors = ['Dimitri Geshef']
|
37
39
|
spec.email = ['famished.tiger@yahoo.com']
|
38
40
|
|
39
41
|
spec.summary = %q{Implementation of Minikanren language in Ruby. WIP}
|
40
42
|
spec.description = %q{Implementation of Minikanren language in Ruby. WIP}
|
41
|
-
spec.homepage =
|
42
|
-
spec.license =
|
43
|
+
spec.homepage = 'https://github.com/famished-tiger/mini_kraken'
|
44
|
+
spec.license = 'MIT'
|
43
45
|
|
44
46
|
# Specify which files should be added to the gem when it is released.
|
45
|
-
spec.bindir =
|
47
|
+
spec.bindir = 'exe'
|
46
48
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
47
|
-
spec.require_paths = [
|
48
|
-
|
49
|
+
spec.require_paths = ['lib']
|
50
|
+
|
49
51
|
PkgExtending.pkg_files(spec)
|
50
|
-
PkgExtending.pkg_documentation(spec)
|
52
|
+
PkgExtending.pkg_documentation(spec)
|
51
53
|
|
52
|
-
spec.add_development_dependency
|
53
|
-
spec.add_development_dependency
|
54
|
-
spec.add_development_dependency
|
54
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
55
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
56
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
55
57
|
end
|
@@ -10,20 +10,20 @@ require_relative '../../lib/mini_kraken/core/association'
|
|
10
10
|
module MiniKraken
|
11
11
|
module Core
|
12
12
|
describe Association do
|
13
|
-
let(:pea) {KSymbol.new(:pea) }
|
13
|
+
let(:pea) { KSymbol.new(:pea) }
|
14
14
|
subject { Association.new('q', pea) }
|
15
15
|
|
16
16
|
context 'Initialization:' do
|
17
17
|
it 'should be initialized with a name and a value' do
|
18
18
|
expect { Association.new('q', pea) }.not_to raise_error
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
it 'should be initialized with a variable and a value' do
|
22
22
|
expect { Association.new(Variable.new('p'), pea) }.not_to raise_error
|
23
|
-
end
|
23
|
+
end
|
24
24
|
|
25
25
|
it 'should know the variable name' do
|
26
|
-
expect(subject.
|
26
|
+
expect(subject.i_name).to eq('q')
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'should know the associated value' do
|
@@ -58,14 +58,14 @@ module MiniKraken
|
|
58
58
|
|
59
59
|
it 'should return composite when it has ground composite term(s)' do
|
60
60
|
env.add_var(var_q)
|
61
|
-
env.add_assoc(
|
61
|
+
env.add_assoc('q', pea)
|
62
62
|
expr1 = cons(pea, cons(pod, cons(ref_q)))
|
63
63
|
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'should return nil when no assocation exists' do
|
67
67
|
env.add_var(var_q)
|
68
|
-
env.add_assoc(
|
68
|
+
env.add_assoc('q', pea)
|
69
69
|
env.add_var(var_x)
|
70
70
|
|
71
71
|
expect(subject.find_ground(var_x.name, env)).to be_nil
|
@@ -73,7 +73,7 @@ module MiniKraken
|
|
73
73
|
|
74
74
|
it 'should find an atomic term directly associated' do
|
75
75
|
env.add_var(var_q)
|
76
|
-
env.add_assoc(
|
76
|
+
env.add_assoc('q', pea)
|
77
77
|
|
78
78
|
result = subject.find_ground(var_q.name, env)
|
79
79
|
expect(result).to eq(pea)
|
@@ -82,8 +82,8 @@ module MiniKraken
|
|
82
82
|
it 'should find an atomic term directly associated' do
|
83
83
|
env.add_var(var_q)
|
84
84
|
env.add_var(var_x)
|
85
|
-
env.add_assoc(
|
86
|
-
env.add_assoc(
|
85
|
+
env.add_assoc('q', ref_x)
|
86
|
+
env.add_assoc('x', pea)
|
87
87
|
expect(env['x']).not_to be_nil
|
88
88
|
|
89
89
|
result = subject.find_ground(var_q.name, env)
|
@@ -93,9 +93,9 @@ module MiniKraken
|
|
93
93
|
it 'should cope with cyclic structures' do
|
94
94
|
env.add_var(var_q)
|
95
95
|
env.add_var(var_x)
|
96
|
-
env.add_assoc(
|
97
|
-
env.add_assoc(
|
98
|
-
env.add_assoc(
|
96
|
+
env.add_assoc('q', ref_x)
|
97
|
+
env.add_assoc('x', pea)
|
98
|
+
env.add_assoc('x', ref_q)
|
99
99
|
|
100
100
|
result = subject.find_ground(var_q.name, env)
|
101
101
|
expect(result).to eq(pea)
|
@@ -107,7 +107,7 @@ module MiniKraken
|
|
107
107
|
it 'should cope with a composite with atomic terms only' do
|
108
108
|
env.add_var(var_q)
|
109
109
|
expr = cons(pea, cons(pod, cons(pea)))
|
110
|
-
env.add_assoc(
|
110
|
+
env.add_assoc('q', expr)
|
111
111
|
|
112
112
|
result = subject.find_ground(var_q.name, env)
|
113
113
|
expect(result).to eq(expr)
|
@@ -117,7 +117,7 @@ module MiniKraken
|
|
117
117
|
env.add_var(var_q)
|
118
118
|
env.add_var(var_x)
|
119
119
|
expr = cons(pea, cons(pod, cons(ref_x)))
|
120
|
-
env.add_assoc(
|
120
|
+
env.add_assoc('q', expr)
|
121
121
|
|
122
122
|
result = subject.find_ground(var_q.name, env)
|
123
123
|
expect(result).to be_nil
|
@@ -127,14 +127,13 @@ module MiniKraken
|
|
127
127
|
env.add_var(var_q)
|
128
128
|
env.add_var(var_x)
|
129
129
|
expr = cons(pea, cons(pod, cons(ref_x)))
|
130
|
-
env.add_assoc(
|
131
|
-
env.add_assoc(
|
130
|
+
env.add_assoc('q', expr)
|
131
|
+
env.add_assoc('x', pod)
|
132
132
|
|
133
133
|
result = subject.find_ground(var_q.name, env)
|
134
134
|
expect(result).to eq(expr)
|
135
135
|
end
|
136
|
-
|
137
|
-
=end
|
136
|
+
|
138
137
|
it 'should categorize a variable without association as free' do
|
139
138
|
env.add_var(var_q)
|
140
139
|
result = subject.determine_freshness(ref_q, env)
|
@@ -145,22 +144,24 @@ module MiniKraken
|
|
145
144
|
it 'should categorize a variable related to fresh variable as bound' do
|
146
145
|
env.add_var(var_q)
|
147
146
|
env.add_var(var_x)
|
148
|
-
env.add_assoc(
|
147
|
+
env.add_assoc('q', ref_x)
|
149
148
|
|
150
149
|
result = subject.determine_freshness(ref_q, env)
|
151
150
|
expect(result).to be_bound
|
152
151
|
expect(result.associated).to eq(ref_x)
|
153
152
|
end
|
154
153
|
|
155
|
-
it 'should categorize a variable even in presence of
|
154
|
+
it 'should categorize a variable even in presence of fused var(s)' do
|
156
155
|
env.add_var(var_q)
|
157
156
|
env.add_var(var_x)
|
158
|
-
env.add_assoc(
|
159
|
-
env.add_assoc(
|
157
|
+
env.add_assoc('q', ref_x)
|
158
|
+
env.add_assoc('x', ref_q)
|
159
|
+
# q and x are fused...
|
160
160
|
|
161
161
|
result = subject.determine_freshness(ref_q, env)
|
162
|
-
expect(result).to
|
163
|
-
expect(
|
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
|
164
165
|
end
|
165
166
|
|
166
167
|
it 'should categorize an atomic term as ground term' do
|
@@ -176,15 +177,15 @@ module MiniKraken
|
|
176
177
|
expect(result).to be_ground
|
177
178
|
expect(result.associated).to eq(composite)
|
178
179
|
end
|
179
|
-
|
180
|
+
|
180
181
|
it 'should categorize a composite term as bound term' do
|
181
|
-
# Bound composite: a composite where at least one member is fresh
|
182
|
-
env.add_var(var_q)
|
182
|
+
# Bound composite: a composite where at least one member is fresh
|
183
|
+
env.add_var(var_q)
|
183
184
|
composite = cons(pea, cons(ref_q))
|
184
185
|
result = subject.determine_freshness(composite, env)
|
185
186
|
expect(result).to be_bound
|
186
187
|
expect(result.associated).to eq(composite)
|
187
|
-
end
|
188
|
+
end
|
188
189
|
end # context
|
189
190
|
end # describe
|
190
191
|
end # module
|
@@ -0,0 +1,114 @@
|
|
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
|
data/spec/core/cons_cell_spec.rb
CHANGED
@@ -9,8 +9,8 @@ require_relative '../../lib/mini_kraken/core/cons_cell'
|
|
9
9
|
module MiniKraken
|
10
10
|
module Core
|
11
11
|
describe ConsCell do
|
12
|
-
let(:pea) {KSymbol.new(:pea) }
|
13
|
-
let(:pod) {KSymbol.new(:pod) }
|
12
|
+
let(:pea) { KSymbol.new(:pea) }
|
13
|
+
let(:pod) { KSymbol.new(:pod) }
|
14
14
|
subject { ConsCell.new(pea, pod) }
|
15
15
|
|
16
16
|
context 'Initialization:' do
|
@@ -44,7 +44,8 @@ module MiniKraken
|
|
44
44
|
context 'Provided services:' do
|
45
45
|
it 'should compare to itself' do
|
46
46
|
expect(subject.eql?(subject)).to be_truthy
|
47
|
-
|
47
|
+
synonym = subject
|
48
|
+
expect(subject == synonym).to be_truthy
|
48
49
|
end
|
49
50
|
|
50
51
|
it 'should compare to another instance' do
|
@@ -57,6 +58,14 @@ module MiniKraken
|
|
57
58
|
different = ConsCell.new(pea)
|
58
59
|
expect(subject.eql?(different)).to be_falsey
|
59
60
|
end
|
61
|
+
|
62
|
+
it 'should append another cons cell' do
|
63
|
+
instance = ConsCell.new(pea)
|
64
|
+
trail = ConsCell.new(pod)
|
65
|
+
instance.append(trail)
|
66
|
+
expect(instance.car).to eq(pea)
|
67
|
+
expect(instance.cdr).to eq(trail)
|
68
|
+
end
|
60
69
|
end # context
|
61
70
|
end # describe
|
62
71
|
end # module
|
@@ -0,0 +1,99 @@
|
|
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/disj2'
|
14
|
+
|
15
|
+
module MiniKraken
|
16
|
+
module Core
|
17
|
+
describe Disj2 do
|
18
|
+
subject { Disj2.instance }
|
19
|
+
|
20
|
+
context 'Initialization:' do
|
21
|
+
it 'should be initialized without argument' do
|
22
|
+
expect { Disj2.instance }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should know its name' do
|
26
|
+
expect(subject.name).to eq('disj2')
|
27
|
+
end
|
28
|
+
end # context
|
29
|
+
|
30
|
+
context 'Provided services:' do
|
31
|
+
let(:corn) { KSymbol.new(:corn) }
|
32
|
+
let(:meal) { KSymbol.new(:meal) }
|
33
|
+
let(:oil) { KSymbol.new(:oil) }
|
34
|
+
let(:olive) { KSymbol.new(:olive) }
|
35
|
+
let(:pea) { KSymbol.new(:pea) }
|
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
|
+
let(:env) do
|
41
|
+
e = Environment.new
|
42
|
+
e.add_var(var_q)
|
43
|
+
e
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should complain when one of its argument is not a goal' do
|
47
|
+
err = StandardError
|
48
|
+
expect { subject.solver_for([succeeds, pea], env) }.to raise_error(err)
|
49
|
+
expect { subject.solver_for([pea, succeeds], env) }.to raise_error(err)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should fails if both arguments fail' do
|
53
|
+
# Covers frame 1:55
|
54
|
+
solver = subject.solver_for([fails, 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 first argument succeeds' do
|
60
|
+
# Covers frame 1:56
|
61
|
+
subgoal = Goal.new(Equals.instance, [olive, ref_q])
|
62
|
+
solver = subject.solver_for([subgoal, fails], env)
|
63
|
+
outcome = solver.resume
|
64
|
+
expect(outcome).to be_successful
|
65
|
+
expect(outcome.associations['q'].first.value).to eq(olive)
|
66
|
+
expect(solver.resume).to be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'yield success if second argument succeeds' do
|
70
|
+
# Covers frame 1:57
|
71
|
+
subgoal = Goal.new(Equals.instance, [oil, ref_q])
|
72
|
+
solver = subject.solver_for([fails, subgoal], env)
|
73
|
+
outcome = solver.resume
|
74
|
+
expect(outcome).to be_successful
|
75
|
+
expect(outcome.associations['q'].first.value).to eq(oil)
|
76
|
+
expect(solver.resume).to be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'yield two solutions if both arguments succeed' do
|
80
|
+
# Covers frame 1:58
|
81
|
+
subgoal1 = Goal.new(Equals.instance, [olive, ref_q])
|
82
|
+
subgoal2 = Goal.new(Equals.instance, [oil, ref_q])
|
83
|
+
solver = subject.solver_for([subgoal1, subgoal2], env)
|
84
|
+
|
85
|
+
# First solution
|
86
|
+
outcome1 = solver.resume
|
87
|
+
expect(outcome1).to be_successful
|
88
|
+
expect(outcome1.associations['q'].first.value).to eq(olive)
|
89
|
+
|
90
|
+
# Second solution
|
91
|
+
outcome2 = solver.resume
|
92
|
+
expect(outcome2).to be_successful
|
93
|
+
expect(outcome2.associations['q'].first.value).to eq(oil)
|
94
|
+
expect(solver.resume).to be_nil
|
95
|
+
end
|
96
|
+
end # context
|
97
|
+
end # describe
|
98
|
+
end # module
|
99
|
+
end # module
|