mini_kraken 0.1.04 → 0.1.09
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 -0
- data/Gemfile +3 -1
- data/README.md +8 -6
- 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 +76 -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 +127 -188
- 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 +44 -6
- data/lib/mini_kraken/glue/run_star_expression.rb +49 -23
- 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 +28 -2
- data/spec/glue/run_star_expression_spec.rb +370 -59
- 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/spec/core/succeed_spec.rb
CHANGED
@@ -24,18 +24,18 @@ module MiniKraken
|
|
24
24
|
it 'should unconditionally return a success result' do
|
25
25
|
args = double('fake-args')
|
26
26
|
env = double('fake-env')
|
27
|
-
|
27
|
+
|
28
28
|
solver = nil
|
29
29
|
expect { solver = subject.solver_for(args, env) }.not_to raise_error
|
30
|
-
|
30
|
+
|
31
31
|
# Solver should quack like a Fiber
|
32
32
|
dummy_arg = double('dummy-stuff')
|
33
33
|
result = solver.resume(dummy_arg)
|
34
34
|
expect(result).to eq(BasicSuccess)
|
35
|
-
|
35
|
+
|
36
36
|
# Only one "solution", next 'resume' call should return nil
|
37
37
|
result = solver.resume(dummy_arg)
|
38
|
-
expect(result).to be_nil
|
38
|
+
expect(result).to be_nil
|
39
39
|
end
|
40
40
|
end # context
|
41
41
|
end # describe
|
@@ -1,18 +1,18 @@
|
|
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/association'
|
5
4
|
require_relative '../../lib/mini_kraken/core/k_symbol'
|
5
|
+
require_relative '../../lib/mini_kraken/core/variable'
|
6
6
|
require_relative '../../lib/mini_kraken/core/variable_ref'
|
7
7
|
require_relative '../support/factory_methods'
|
8
8
|
|
9
9
|
# Load the class under test
|
10
|
-
|
10
|
+
# frozen_string_literal: true
|
11
11
|
|
12
|
+
require_relative '../../lib/mini_kraken/core/vocabulary'
|
12
13
|
|
13
14
|
module MiniKraken
|
14
15
|
module Core
|
15
|
-
|
16
16
|
class TestVocabulary
|
17
17
|
include Vocabulary
|
18
18
|
|
@@ -21,16 +21,20 @@ module MiniKraken
|
|
21
21
|
end
|
22
22
|
end # class
|
23
23
|
|
24
|
+
# Helper module that simulates an environment-like object.
|
24
25
|
module VariableBearer
|
25
26
|
attr_reader :vars
|
27
|
+
attr_accessor :ivars
|
26
28
|
|
27
29
|
def init_var_bearer
|
28
30
|
@vars = {}
|
31
|
+
@ivars = {}
|
29
32
|
self
|
30
33
|
end
|
31
34
|
|
32
35
|
def add_var(aVarName)
|
33
|
-
vars[aVarName] = aVarName
|
36
|
+
vars[aVarName] = Variable.new(aVarName)
|
37
|
+
ivars[aVarName] = Set.new([aVarName])
|
34
38
|
end
|
35
39
|
end # module
|
36
40
|
|
@@ -75,11 +79,11 @@ module MiniKraken
|
|
75
79
|
|
76
80
|
it 'should provide a walker over ancestors' do
|
77
81
|
walker = subject.ancestor_walker
|
78
|
-
expect(walker).to be_kind_of(
|
79
|
-
expect(walker.
|
80
|
-
expect(walker.
|
81
|
-
expect(walker.
|
82
|
-
expect(walker.
|
82
|
+
expect(walker).to be_kind_of(Enumerator)
|
83
|
+
expect(walker.next).to eq(subject)
|
84
|
+
expect(walker.next).to eq(mother)
|
85
|
+
expect(walker.next).to eq(grandma)
|
86
|
+
expect(walker.next).to be_nil
|
83
87
|
end
|
84
88
|
|
85
89
|
it 'should know if a variable is defined' do
|
@@ -99,11 +103,12 @@ module MiniKraken
|
|
99
103
|
it 'should allow the addition of associations' do
|
100
104
|
grandma.add_var('q')
|
101
105
|
expect(subject['q']).to be_empty
|
102
|
-
mother.add_assoc(
|
106
|
+
res_add = mother.add_assoc('q', pea)
|
107
|
+
expect(res_add).to be_kind_of(Association)
|
103
108
|
expect(subject['q'].size).to eq(1)
|
104
109
|
expect(subject['q'].first.value).to eq(pea)
|
105
110
|
|
106
|
-
subject.add_assoc(
|
111
|
+
subject.add_assoc('q', ref_x)
|
107
112
|
expect(subject['q'].size).to eq(2)
|
108
113
|
expect(subject['q'].first.value).to eq(ref_x)
|
109
114
|
expect(subject['q'].last.value).to eq(pea)
|
@@ -111,8 +116,8 @@ module MiniKraken
|
|
111
116
|
|
112
117
|
it 'should allow the deletion of associations' do
|
113
118
|
grandma.add_var('q')
|
114
|
-
mother.add_assoc(
|
115
|
-
subject.add_assoc(
|
119
|
+
mother.add_assoc('q', pea)
|
120
|
+
subject.add_assoc('q', ref_x)
|
116
121
|
expect(mother.associations.size).to eq(1)
|
117
122
|
expect(subject.associations.size).to eq(1)
|
118
123
|
|
@@ -127,18 +132,18 @@ module MiniKraken
|
|
127
132
|
grandma.add_var('q')
|
128
133
|
grandma.add_var('x')
|
129
134
|
expect(subject.fresh?(ref_q)).to be_truthy
|
130
|
-
subject.add_assoc(
|
135
|
+
subject.add_assoc('q', ref_x) # Dependency: q --> x
|
131
136
|
expect(subject.fresh?(ref_x)).to be_truthy
|
132
137
|
end
|
133
138
|
|
134
139
|
it 'should say not fresh when variable --> atomic value' do
|
135
140
|
grandma.add_var('q')
|
136
141
|
grandma.add_var('x')
|
137
|
-
subject.add_assoc(
|
142
|
+
subject.add_assoc('q', ref_x) # Dependency: q --> x
|
138
143
|
expect(subject.fresh?(ref_q)).to be_truthy
|
139
144
|
|
140
145
|
# Associate with an atomic term
|
141
|
-
subject.add_assoc(
|
146
|
+
subject.add_assoc('q', pea)
|
142
147
|
expect(subject.fresh?(ref_q)).to be_falsey
|
143
148
|
end
|
144
149
|
|
@@ -147,16 +152,16 @@ module MiniKraken
|
|
147
152
|
|
148
153
|
# Composite having only atomic terms as leaf elements
|
149
154
|
expr = cons(pea, cons(pod))
|
150
|
-
subject.add_assoc(
|
155
|
+
subject.add_assoc('q', expr)
|
151
156
|
expect(subject.fresh?(ref_q)).to be_falsey
|
152
157
|
end
|
153
158
|
|
154
159
|
it 'say not fresh when variable --> composite of atomics & bound var' do
|
155
160
|
grandma.add_var('q')
|
156
161
|
grandma.add_var('x')
|
157
|
-
subject.add_assoc(
|
162
|
+
subject.add_assoc('x', pea) # Dependency: x --> pea
|
158
163
|
expr = cons(pea, cons(pod, cons(ref_x)))
|
159
|
-
subject.add_assoc(
|
164
|
+
subject.add_assoc('q', expr)
|
160
165
|
expect(subject.fresh?(ref_q)).to be_falsey
|
161
166
|
end
|
162
167
|
|
@@ -164,7 +169,7 @@ module MiniKraken
|
|
164
169
|
grandma.add_var('q')
|
165
170
|
grandma.add_var('x')
|
166
171
|
expr = cons(pea, cons(pod, cons(ref_x)))
|
167
|
-
subject.add_assoc(
|
172
|
+
subject.add_assoc('q', expr)
|
168
173
|
expect(subject.fresh?(ref_q)).to be_truthy
|
169
174
|
end
|
170
175
|
|
@@ -173,13 +178,14 @@ module MiniKraken
|
|
173
178
|
grandma.add_var('x')
|
174
179
|
|
175
180
|
# Beware of cyclic structure
|
176
|
-
subject.add_assoc(
|
177
|
-
subject.add_assoc(
|
181
|
+
subject.add_assoc('q', ref_x) # Dependency: q --> x
|
182
|
+
subject.add_assoc('x', ref_q) # Dependency: x --> q
|
178
183
|
expect(subject.fresh?(ref_x)).to be_truthy
|
179
184
|
expect(subject.fresh?(ref_q)).to be_truthy
|
185
|
+
expect(subject.associations).to be_empty
|
180
186
|
|
181
187
|
# Associate with an atomic term
|
182
|
-
subject.add_assoc(
|
188
|
+
subject.add_assoc('x', pea)
|
183
189
|
expect(subject.fresh?(ref_q)).to be_falsey
|
184
190
|
end
|
185
191
|
|
@@ -190,16 +196,16 @@ module MiniKraken
|
|
190
196
|
expect(subject.get_rank('c')).to eq(2)
|
191
197
|
end
|
192
198
|
end
|
193
|
-
|
199
|
+
|
194
200
|
it 'should clear the rankings' do
|
195
201
|
expect(subject.get_rank('a')).to eq(0)
|
196
202
|
expect(subject.get_rank('z')).to eq(1)
|
197
|
-
|
203
|
+
|
198
204
|
subject.clear_rankings
|
199
205
|
expect(grandma.rankings).to be_empty
|
200
206
|
|
201
|
-
expect(subject.get_rank('z')).to eq(0)
|
202
|
-
expect(subject.get_rank('a')).to eq(1)
|
207
|
+
expect(subject.get_rank('z')).to eq(0)
|
208
|
+
expect(subject.get_rank('a')).to eq(1)
|
203
209
|
end
|
204
210
|
end # context
|
205
211
|
end # describe
|
data/spec/glue/fresh_env_spec.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
4
|
require_relative '../../lib/mini_kraken/core/goal'
|
5
5
|
require_relative '../../lib/mini_kraken/core/equals'
|
6
|
+
require_relative '../../lib/mini_kraken/core/fail'
|
6
7
|
require_relative '../../lib/mini_kraken/core/k_symbol'
|
8
|
+
require_relative '../../lib/mini_kraken/core/succeed'
|
7
9
|
|
8
10
|
# Load the class under test
|
9
11
|
require_relative '../../lib/mini_kraken/glue/fresh_env'
|
@@ -15,17 +17,41 @@ module MiniKraken
|
|
15
17
|
let(:pea) { Core::KSymbol.new(:pea) }
|
16
18
|
let(:pod) { Core::KSymbol.new(:pod) }
|
17
19
|
let(:sample_goal) do
|
18
|
-
Core::Goal.new(Core::Equals.instance, [pea, pod])
|
20
|
+
Core::Goal.new(Core::Equals.instance, [pea, pod])
|
19
21
|
end
|
22
|
+
let(:pea_goal) do
|
23
|
+
Core::Goal.new(Core::Equals.instance, [pea, pea])
|
24
|
+
end
|
25
|
+
let(:goal_succeeds) { Core::Goal.new(Core::Succeed.instance, []) }
|
26
|
+
let(:goal_fails) { Core::Goal.new(Core::Fail.instance, []) }
|
20
27
|
subject { FreshEnv.new(['q'], sample_goal) }
|
21
28
|
|
22
29
|
context 'Initialization:' do
|
23
|
-
it '
|
30
|
+
it 'could be initialized with names and a goal' do
|
24
31
|
expect { FreshEnv.new(['q'], sample_goal) }.not_to raise_error
|
25
32
|
end
|
26
33
|
|
34
|
+
it 'could be initialized with names and goals' do
|
35
|
+
expect { FreshEnv.new(%w[x y], [pea_goal, goal_succeeds]) }.not_to raise_error
|
36
|
+
end
|
37
|
+
|
27
38
|
it 'should know its variables' do
|
28
39
|
expect(subject.vars['q']).not_to be_nil
|
40
|
+
|
41
|
+
instance = FreshEnv.new(%w[x y], sample_goal)
|
42
|
+
expect(instance.vars['x']).not_to be_nil
|
43
|
+
expect(instance.vars['y']).not_to be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should know its goal' do
|
47
|
+
# Single goal at initialization
|
48
|
+
expect(subject.goal).to eq(sample_goal)
|
49
|
+
|
50
|
+
# Multiple goals at initialization
|
51
|
+
instance = FreshEnv.new(['q'], [pea_goal, goal_succeeds])
|
52
|
+
expect(instance.goal.relation.name).to eq('conj2')
|
53
|
+
expect(instance.goal.actuals[0]).to eq(pea_goal)
|
54
|
+
expect(instance.goal.actuals[1]).to eq(goal_succeeds)
|
29
55
|
end
|
30
56
|
end # context
|
31
57
|
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
4
|
require_relative '../../lib/mini_kraken/core/goal'
|
5
|
+
require_relative '../../lib/mini_kraken/core/conj2'
|
6
|
+
require_relative '../../lib/mini_kraken/core/disj2'
|
5
7
|
require_relative '../../lib/mini_kraken/core/equals'
|
6
8
|
require_relative '../../lib/mini_kraken/core/fail'
|
7
9
|
require_relative '../../lib/mini_kraken/core/succeed'
|
@@ -19,16 +21,26 @@ module MiniKraken
|
|
19
21
|
let(:pea) { k_symbol(:pea) }
|
20
22
|
let(:pod) { k_symbol(:pod) }
|
21
23
|
let(:sample_goal) { equals_goal(pea, pod) }
|
24
|
+
let(:fails) { Core::Goal.new(Core::Fail.instance, []) }
|
25
|
+
let(:succeeds) { Core::Goal.new(Core::Succeed.instance, []) }
|
22
26
|
subject { RunStarExpression.new('q', sample_goal) }
|
23
27
|
|
24
28
|
context 'Initialization:' do
|
25
|
-
it '
|
29
|
+
it 'could be initialized with a name and a goal' do
|
26
30
|
expect { RunStarExpression.new('q', sample_goal) }.not_to raise_error
|
27
31
|
end
|
28
32
|
|
33
|
+
it 'could be initialized with multiple names and a goal' do
|
34
|
+
expect { RunStarExpression.new(%w[r x y], sample_goal) }.not_to raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'could be initialized with multiple names and goals' do
|
38
|
+
expect { RunStarExpression.new(%w[r x y], [succeeds, succeeds]) }.not_to raise_error
|
39
|
+
end
|
40
|
+
|
29
41
|
it 'should know its variables' do
|
30
42
|
expect(subject.env.vars['q']).not_to be_nil
|
31
|
-
expect(subject.
|
43
|
+
expect(subject.env.vars.values[0].name).to eq('q')
|
32
44
|
end
|
33
45
|
|
34
46
|
it 'should know its goal' do
|
@@ -37,24 +49,33 @@ module MiniKraken
|
|
37
49
|
end # context
|
38
50
|
|
39
51
|
context 'Provided services:' do
|
52
|
+
let(:bean) { k_symbol(:bean) }
|
53
|
+
let(:corn) { k_symbol(:corn) }
|
54
|
+
let(:meal) { k_symbol(:meal) }
|
55
|
+
let(:oil) { k_symbol(:oil) }
|
56
|
+
let(:olive) { k_symbol(:olive) }
|
57
|
+
let(:red) { k_symbol(:red) }
|
58
|
+
let(:soup) { k_symbol(:soup) }
|
59
|
+
let(:split) { k_symbol(:split) }
|
60
|
+
let(:virgin) { k_symbol(:virgin) }
|
40
61
|
let(:ref_q) { Core::VariableRef.new('q') }
|
62
|
+
let(:ref_r) { Core::VariableRef.new('r') }
|
41
63
|
let(:ref_x) { Core::VariableRef.new('x') }
|
42
64
|
let(:ref_y) { Core::VariableRef.new('y') }
|
43
65
|
let(:ref_s) { Core::VariableRef.new('s') }
|
44
66
|
let(:ref_t) { Core::VariableRef.new('t') }
|
45
|
-
let(:ref_u) { Core::VariableRef.new('u') }
|
67
|
+
let(:ref_u) { Core::VariableRef.new('u') }
|
46
68
|
|
47
|
-
it
|
69
|
+
it 'should return a null list with the fail goal' do
|
48
70
|
# Reasoned S2, frame 1:7
|
49
71
|
# (run* q #u) ;; => ()
|
50
72
|
failing = Core::Goal.new(Core::Fail.instance, [])
|
51
73
|
instance = RunStarExpression.new('q', failing)
|
52
74
|
|
53
75
|
expect(instance.run).to be_null
|
54
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
55
76
|
end
|
56
77
|
|
57
|
-
it
|
78
|
+
it 'should return a null list when a goal fails' do
|
58
79
|
# Reasoned S2, frame 1:10
|
59
80
|
# (run* q (== 'pea 'pod) ;; => ()
|
60
81
|
|
@@ -69,7 +90,6 @@ module MiniKraken
|
|
69
90
|
# Reasoned S2, frame 1:11
|
70
91
|
# (run* q (== q 'pea) ;; => (pea)
|
71
92
|
expect(instance.run.car).to eq(pea)
|
72
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
73
93
|
end
|
74
94
|
|
75
95
|
it 'should unify the righthand variable(s)' do
|
@@ -79,19 +99,14 @@ module MiniKraken
|
|
79
99
|
# Reasoned S2, frame 1:12
|
80
100
|
# (run* q (== 'pea q) ;; => (pea)
|
81
101
|
expect(instance.run.car).to eq(pea)
|
82
|
-
|
83
|
-
# Reasoned S2, frame 1:15
|
84
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
85
102
|
end
|
86
103
|
|
87
104
|
it 'should return a null list with the succeed goal' do
|
88
|
-
|
89
|
-
instance = RunStarExpression.new('q', success)
|
105
|
+
instance = RunStarExpression.new('q', succeeds)
|
90
106
|
|
91
107
|
# (display (run* q succeed)) ;; => (_0)
|
92
108
|
# Reasoned S2, frame 1:16
|
93
109
|
result = instance.run
|
94
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
95
110
|
|
96
111
|
# Reasoned S2, frame 1:17
|
97
112
|
expect(result.car).to eq(any_value(0))
|
@@ -104,7 +119,6 @@ module MiniKraken
|
|
104
119
|
# (display (run* q (== 'pea 'pea))) ;; => (_0)
|
105
120
|
# Reasoned S2, frame 1:19
|
106
121
|
result = instance.run
|
107
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
108
122
|
expect(result.car).to eq(any_value(0))
|
109
123
|
end
|
110
124
|
|
@@ -117,7 +131,6 @@ module MiniKraken
|
|
117
131
|
# (display (run* q (== q q))) ;; => (_0)
|
118
132
|
# Reasoned S2, frame 1:20
|
119
133
|
result = instance.run
|
120
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
121
134
|
expect(result.car).to eq(any_value(0))
|
122
135
|
end
|
123
136
|
|
@@ -129,8 +142,6 @@ module MiniKraken
|
|
129
142
|
# Reasoned S2, frame 1:21..23
|
130
143
|
# (run* q (fresh (x) (== 'pea q))) ;; => (pea)
|
131
144
|
result = instance.run
|
132
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
133
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
134
145
|
|
135
146
|
# Reasoned S2, frame 1:40
|
136
147
|
expect(ref_q.different_from?(ref_x, fresh_env)).to be_truthy
|
@@ -145,8 +156,6 @@ module MiniKraken
|
|
145
156
|
# Reasoned S2, frame 1:24
|
146
157
|
# (run* q (fresh (x) (== 'pea x))) ;; => (_0)
|
147
158
|
result = instance.run
|
148
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
149
|
-
expect(ref_x.fresh?(fresh_env)).to be_falsey
|
150
159
|
expect(result.car).to eq(any_value(0))
|
151
160
|
end
|
152
161
|
|
@@ -158,8 +167,6 @@ module MiniKraken
|
|
158
167
|
# Reasoned S2, frame 1:25
|
159
168
|
# (run* q (fresh (x) (== (cons x '()) q))) ;; => ((_0))
|
160
169
|
result = instance.run
|
161
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
162
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
163
170
|
expect(result.car).to eq(cons(any_value(0)))
|
164
171
|
end
|
165
172
|
|
@@ -190,7 +197,6 @@ module MiniKraken
|
|
190
197
|
# Reasoned S2, frame 1:32
|
191
198
|
# (run* q (== '(((pea)) pod) '(((pea)) pod))) ;; => (_0)
|
192
199
|
result = instance.run
|
193
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
194
200
|
expect(result.car).to eq(any_value(0))
|
195
201
|
end
|
196
202
|
|
@@ -204,7 +210,6 @@ module MiniKraken
|
|
204
210
|
# Reasoned S2, frame 1:33
|
205
211
|
# (run* q (== '(((pea)) pod) `(((pea)) ,q))) ;; => ('pod)
|
206
212
|
result = instance.run
|
207
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
208
213
|
expect(result.car).to eq(pod)
|
209
214
|
end
|
210
215
|
|
@@ -217,7 +222,6 @@ module MiniKraken
|
|
217
222
|
# Reasoned S2, frame 1:34
|
218
223
|
# (run* q (== '(((,q)) pod) `(((pea)) pod))) ;; => ('pod)
|
219
224
|
result = instance.run
|
220
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
221
225
|
expect(result.car).to eq(pea)
|
222
226
|
end
|
223
227
|
|
@@ -231,8 +235,6 @@ module MiniKraken
|
|
231
235
|
# Reasoned S2, frame 1:35
|
232
236
|
# (run* q (fresh (x) (== '(((,q)) pod) `(((,x)) pod)))) ;; => (_0)
|
233
237
|
result = instance.run
|
234
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
235
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
236
238
|
expect(result.car).to eq(any_value(0))
|
237
239
|
end
|
238
240
|
|
@@ -246,11 +248,6 @@ module MiniKraken
|
|
246
248
|
instance = RunStarExpression.new('q', fresh_env)
|
247
249
|
|
248
250
|
result = instance.run
|
249
|
-
|
250
|
-
# Does propagate work correctly?
|
251
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy # x isn't defined here
|
252
|
-
expect(ref_q.fresh?(fresh_env)).to be_falsey
|
253
|
-
expect(ref_x.fresh?(fresh_env)).to be_falsey
|
254
251
|
expect(result.car).to eq(pod)
|
255
252
|
end
|
256
253
|
|
@@ -263,9 +260,6 @@ module MiniKraken
|
|
263
260
|
instance = RunStarExpression.new('q', fresh_env)
|
264
261
|
|
265
262
|
result = instance.run
|
266
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy # x isn't defined here
|
267
|
-
expect(ref_q.fresh?(fresh_env)).to be_truthy
|
268
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
269
263
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(0))))
|
270
264
|
end
|
271
265
|
|
@@ -280,17 +274,16 @@ module MiniKraken
|
|
280
274
|
instance = RunStarExpression.new('q', fresh_env_x)
|
281
275
|
|
282
276
|
result = instance.run
|
283
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
284
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
285
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
286
|
-
expect(ref_x.bound?(fresh_env_y)).to be_truthy
|
287
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
288
|
-
expect(ref_y.bound?(fresh_env_y)).to be_truthy
|
289
277
|
|
290
278
|
# y should be fused with x...
|
279
|
+
var_x = fresh_env_y.name2var('x')
|
280
|
+
var_y = fresh_env_y.name2var('y')
|
281
|
+
expect(var_x.i_name).to eq(var_y.i_name)
|
291
282
|
expect(ref_y.fused_with?(ref_x, fresh_env_y)).to be_truthy
|
292
283
|
expect(ref_x.names_fused(fresh_env_y)).to eq(['y'])
|
293
284
|
expect(ref_y.names_fused(fresh_env_y)).to eq(['x'])
|
285
|
+
|
286
|
+
# q should be bound to '(,x ,x)
|
294
287
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(0))))
|
295
288
|
end
|
296
289
|
|
@@ -304,16 +297,10 @@ module MiniKraken
|
|
304
297
|
instance = RunStarExpression.new('q', fresh_env_x)
|
305
298
|
|
306
299
|
result = instance.run
|
307
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
308
300
|
# q should be bound to '(,x ,y)
|
309
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
310
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
311
|
-
expect(ref_x.bound?(fresh_env_y)).to be_falsey
|
312
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
313
|
-
expect(ref_y.bound?(fresh_env_y)).to be_falsey
|
314
301
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
315
302
|
end
|
316
|
-
|
303
|
+
|
317
304
|
it 'should work with variable names' do
|
318
305
|
# Reasoned S2, frame 1:42
|
319
306
|
# (run* s (fresh (t) (fresh (u) (== '( ,t ,u) s)))) ;; => (_0 _1)
|
@@ -324,15 +311,9 @@ module MiniKraken
|
|
324
311
|
instance = RunStarExpression.new('s', fresh_env_t)
|
325
312
|
|
326
313
|
result = instance.run
|
327
|
-
expect(ref_s.fresh?(fresh_env_u)).to be_truthy
|
328
314
|
# s should be bound to '(,t ,u)
|
329
|
-
expect(ref_s.bound?(fresh_env_u)).to be_truthy
|
330
|
-
expect(ref_t.fresh?(fresh_env_u)).to be_truthy
|
331
|
-
expect(ref_t.bound?(fresh_env_u)).to be_falsey
|
332
|
-
expect(ref_u.fresh?(fresh_env_u)).to be_truthy
|
333
|
-
expect(ref_u.bound?(fresh_env_u)).to be_falsey
|
334
315
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
335
|
-
end
|
316
|
+
end
|
336
317
|
|
337
318
|
it 'should support repeated variables' do
|
338
319
|
# Reasoned S2, frame 1:43
|
@@ -344,13 +325,343 @@ module MiniKraken
|
|
344
325
|
instance = RunStarExpression.new('q', fresh_env_x)
|
345
326
|
|
346
327
|
result = instance.run
|
347
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
348
328
|
# q should be bound to '(,x ,y, ,x)
|
349
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
350
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
351
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
352
329
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1), cons(any_value(0)))))
|
353
|
-
end
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'should support conjunction of two succeed' do
|
333
|
+
goal = conj2_goal(succeeds, succeeds)
|
334
|
+
instance = RunStarExpression.new('q', goal)
|
335
|
+
|
336
|
+
# Reasoned S2, frame 1:50
|
337
|
+
# (run* q (conj2 succeed succeed)) ;; => (_0)
|
338
|
+
result = instance.run
|
339
|
+
expect(result.car).to eq(any_value(0))
|
340
|
+
end
|
341
|
+
|
342
|
+
# TODO: fix erratic RSpec failure
|
343
|
+
it 'should support conjunction of one succeed and a successful goal' do
|
344
|
+
subgoal = equals_goal(corn, ref_q)
|
345
|
+
goal = conj2_goal(succeeds, subgoal)
|
346
|
+
instance = RunStarExpression.new('q', goal)
|
347
|
+
|
348
|
+
# Reasoned S2, frame 1:51
|
349
|
+
# (run* q (conj2 succeed (== 'corn q)) ;; => ('corn)
|
350
|
+
result = instance.run
|
351
|
+
expect(result.car).to eq(corn)
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'should support conjunction of one fail and a successful goal' do
|
355
|
+
subgoal = equals_goal(corn, ref_q)
|
356
|
+
goal = conj2_goal(fails, subgoal)
|
357
|
+
instance = RunStarExpression.new('q', goal)
|
358
|
+
|
359
|
+
# Reasoned S2, frame 1:52
|
360
|
+
# (run* q (conj2 fail (== 'corn q)) ;; => ()
|
361
|
+
expect(instance.run).to be_null
|
362
|
+
end
|
363
|
+
|
364
|
+
it 'should support conjunction of two contradictory goals' do
|
365
|
+
subgoal1 = equals_goal(corn, ref_q)
|
366
|
+
subgoal2 = equals_goal(meal, ref_q)
|
367
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
368
|
+
instance = RunStarExpression.new('q', goal)
|
369
|
+
|
370
|
+
# Reasoned S2, frame 1:53
|
371
|
+
# (run* q (conj2 (== 'corn q)(== 'meal q)) ;; => ()
|
372
|
+
expect(instance.run).to be_null
|
373
|
+
end
|
374
|
+
|
375
|
+
it 'should succeed the conjunction of two identical goals' do
|
376
|
+
subgoal1 = equals_goal(corn, ref_q)
|
377
|
+
subgoal2 = equals_goal(corn, ref_q)
|
378
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
379
|
+
instance = RunStarExpression.new('q', goal)
|
380
|
+
|
381
|
+
# Reasoned S2, frame 1:54
|
382
|
+
# (run* q (conj2 (== 'corn q)(== 'corn q)) ;; => ('corn)
|
383
|
+
result = instance.run
|
384
|
+
expect(result.car).to eq(corn)
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'should not yield solution when both disjunction arguments fail' do
|
388
|
+
goal = disj2_goal(fails, fails)
|
389
|
+
instance = RunStarExpression.new('q', goal)
|
390
|
+
|
391
|
+
# Reasoned S2, frame 1:55
|
392
|
+
# (run* q (disj2 fail fail)) ;; => ()
|
393
|
+
expect(instance.run).to be_null
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'should yield solution when first argument succeed' do
|
397
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_q])
|
398
|
+
goal = disj2_goal(subgoal, fails)
|
399
|
+
instance = RunStarExpression.new('q', goal)
|
400
|
+
|
401
|
+
# Reasoned S2, frame 1:56
|
402
|
+
# (run* q (disj2 (== 'olive q) fail)) ;; => ('olive)
|
403
|
+
result = instance.run
|
404
|
+
expect(result.car).to eq(olive)
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'should yield solution when second argument succeed' do
|
408
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_q])
|
409
|
+
goal = disj2_goal(fails, subgoal)
|
410
|
+
instance = RunStarExpression.new('q', goal)
|
411
|
+
|
412
|
+
# Reasoned S2, frame 1:57
|
413
|
+
# (run* q (disj2 fail (== 'oil q))) ;; => (oil)
|
414
|
+
result = instance.run
|
415
|
+
expect(result.car).to eq(oil)
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'should yield solutions when both arguments succeed' do
|
419
|
+
subgoal1 = Core::Goal.new(Core::Equals.instance, [olive, ref_q])
|
420
|
+
subgoal2 = Core::Goal.new(Core::Equals.instance, [oil, ref_q])
|
421
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
422
|
+
instance = RunStarExpression.new('q', goal)
|
423
|
+
|
424
|
+
# Reasoned S2, frame 1:58
|
425
|
+
# (run* q (disj2 (== 'olive q) (== 'oil q))) ;; => (olive oil)
|
426
|
+
result = instance.run
|
427
|
+
expect(result.car).to eq(olive)
|
428
|
+
expect(result.cdr.car).to eq(oil)
|
429
|
+
end
|
430
|
+
|
431
|
+
it 'should support the nesting of variables and disjunction' do
|
432
|
+
# Reasoned S2, frame 1:59
|
433
|
+
# (run* q (fresh (x) (fresh (y) (disj2 (== '( ,x ,y ) q) (== '( ,x ,y ) q)))))
|
434
|
+
# ;; => ((_0 _1) (_0 _1))
|
435
|
+
expr1 = cons(ref_x, cons(ref_y))
|
436
|
+
subgoal1 = equals_goal(expr1, ref_q)
|
437
|
+
expr2 = cons(ref_y, cons(ref_x))
|
438
|
+
subgoal2 = equals_goal(expr2, ref_q)
|
439
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
440
|
+
fresh_env_y = FreshEnv.new(['y'], goal)
|
441
|
+
fresh_env_x = FreshEnv.new(['x'], fresh_env_y)
|
442
|
+
instance = RunStarExpression.new('q', fresh_env_x)
|
443
|
+
|
444
|
+
result = instance.run
|
445
|
+
# q should be bound to '(,x ,y), then to '(,y ,x)
|
446
|
+
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
447
|
+
expect(result.cdr.car).to eq(cons(any_value(0), cons(any_value(1))))
|
448
|
+
end
|
449
|
+
|
450
|
+
it 'should accept nesting of disj2 and conj2 (I)' do
|
451
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
452
|
+
conjunction = conj2_goal(conj_subgoal, fails)
|
453
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
454
|
+
goal = disj2_goal(conjunction, subgoal)
|
455
|
+
instance = RunStarExpression.new('x', goal)
|
456
|
+
|
457
|
+
# Reasoned S2, frame 1:62
|
458
|
+
# (run* x (disj2
|
459
|
+
# (conj2 (== 'olive x) fail)
|
460
|
+
# ('oil x))) ;; => (oil)
|
461
|
+
result = instance.run
|
462
|
+
expect(result.car).to eq(oil)
|
463
|
+
end
|
464
|
+
|
465
|
+
it 'should accept nesting of disj2 and conj2 (II)' do
|
466
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
467
|
+
conjunction = conj2_goal(conj_subgoal, succeeds)
|
468
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
469
|
+
goal = disj2_goal(conjunction, subgoal)
|
470
|
+
instance = RunStarExpression.new('x', goal)
|
471
|
+
|
472
|
+
# Reasoned S2, frame 1:63
|
473
|
+
# (run* x (disj2
|
474
|
+
# (conj2 (== 'olive x) succeed)
|
475
|
+
# ('oil x))) ;; => (olive oil)
|
476
|
+
result = instance.run
|
477
|
+
expect(result.car).to eq(olive)
|
478
|
+
expect(result.cdr.car).to eq(oil)
|
479
|
+
end
|
480
|
+
|
481
|
+
it 'should accept nesting of disj2 and conj2 (III)' do
|
482
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
483
|
+
conjunction = conj2_goal(conj_subgoal, succeeds)
|
484
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
485
|
+
goal = disj2_goal(subgoal, conjunction)
|
486
|
+
instance = RunStarExpression.new('x', goal)
|
487
|
+
|
488
|
+
# Reasoned S2, frame 1:64
|
489
|
+
# (run* x (disj2
|
490
|
+
# ('oil x)
|
491
|
+
# (conj2 (== 'olive x) succeed))) ;; => (oil olive)
|
492
|
+
result = instance.run
|
493
|
+
expect(result.car).to eq(oil)
|
494
|
+
expect(result.cdr.car).to eq(olive)
|
495
|
+
end
|
496
|
+
|
497
|
+
it 'should accept nesting of disj2 and conj2 (IV)' do
|
498
|
+
oil_goal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
499
|
+
disja = disj2_goal(succeeds, oil_goal)
|
500
|
+
olive_goal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
501
|
+
disjb = disj2_goal(olive_goal, disja)
|
502
|
+
virgin_goal = Core::Goal.new(Core::Equals.instance, [virgin, ref_x])
|
503
|
+
conjunction = conj2_goal(virgin_goal, fails)
|
504
|
+
goal = disj2_goal(conjunction, disjb)
|
505
|
+
instance = RunStarExpression.new('x', goal)
|
506
|
+
|
507
|
+
# Reasoned S2, frame 1:65
|
508
|
+
# (run* x (disj2
|
509
|
+
# (conj2(== 'virgin x) fails)
|
510
|
+
# (disj2
|
511
|
+
# (== 'olive x)
|
512
|
+
# (dis2
|
513
|
+
# succeeds
|
514
|
+
# (== 'oil x))))) ;; => (olive _0 oil)
|
515
|
+
result = instance.run
|
516
|
+
expect(result.car).to eq(olive)
|
517
|
+
expect(result.cdr.car).to eq(any_value(0))
|
518
|
+
expect(result.cdr.cdr.car).to eq(oil)
|
519
|
+
end
|
520
|
+
|
521
|
+
it 'should accept nesting fresh, disj2 and conj2 expressions (I)' do
|
522
|
+
subgoal1 = equals_goal(split, ref_x)
|
523
|
+
expr1 = equals_goal(pea, ref_y)
|
524
|
+
expr2 = equals_goal(cons(ref_x, cons(ref_y)), ref_r)
|
525
|
+
subgoal2 = conj2_goal(expr1, expr2)
|
526
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
527
|
+
fresh_env_y = FreshEnv.new(['y'], goal)
|
528
|
+
fresh_env_x = FreshEnv.new(['x'], fresh_env_y)
|
529
|
+
instance = RunStarExpression.new('r', fresh_env_x)
|
530
|
+
|
531
|
+
# Reasoned S2, frame 1:67
|
532
|
+
# (run* r
|
533
|
+
# (fresh x
|
534
|
+
# (fresh y
|
535
|
+
# (conj2
|
536
|
+
# (== 'split x)
|
537
|
+
# (conj2
|
538
|
+
# (== 'pea y)
|
539
|
+
# (== '(,x ,y) r)))))) ;; => ((split pea))
|
540
|
+
result = instance.run
|
541
|
+
expect(result.car.car).to eq(split)
|
542
|
+
expect(result.car.cdr.car).to eq(pea)
|
543
|
+
end
|
544
|
+
|
545
|
+
it 'should accept nesting fresh, disj2 and conj2 expressions (II)' do
|
546
|
+
expr1 = equals_goal(split, ref_x)
|
547
|
+
expr2 = equals_goal(pea, ref_y)
|
548
|
+
subgoal1 = conj2_goal(expr1, expr2)
|
549
|
+
subgoal2 = equals_goal(cons(ref_x, cons(ref_y)), ref_r)
|
550
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
551
|
+
fresh_env_y = FreshEnv.new(['y'], goal)
|
552
|
+
fresh_env_x = FreshEnv.new(['x'], fresh_env_y)
|
553
|
+
instance = RunStarExpression.new('r', fresh_env_x)
|
554
|
+
|
555
|
+
# Reasoned S2, frame 1:68
|
556
|
+
# (run* r
|
557
|
+
# (fresh x
|
558
|
+
# (fresh y
|
559
|
+
# (conj2
|
560
|
+
# (conj2
|
561
|
+
# (== 'split x)
|
562
|
+
# (== 'pea y)
|
563
|
+
# (== '(,x ,y) r)))))) ;; => ((split pea))
|
564
|
+
result = instance.run
|
565
|
+
expect(result.car.car).to eq(split)
|
566
|
+
expect(result.car.cdr.car).to eq(pea)
|
567
|
+
end
|
568
|
+
|
569
|
+
it 'should accept fresh with multiple variables' do
|
570
|
+
expr1 = equals_goal(split, ref_x)
|
571
|
+
expr2 = equals_goal(pea, ref_y)
|
572
|
+
subgoal1 = conj2_goal(expr1, expr2)
|
573
|
+
subgoal2 = equals_goal(cons(ref_x, cons(ref_y)), ref_r)
|
574
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
575
|
+
fresh_env = FreshEnv.new(%w[x y], goal)
|
576
|
+
instance = RunStarExpression.new('r', fresh_env)
|
577
|
+
|
578
|
+
# Reasoned S2, frame 1:70
|
579
|
+
# (run* r
|
580
|
+
# (fresh (x y)
|
581
|
+
# (conj2
|
582
|
+
# (conj2
|
583
|
+
# (== 'split x)
|
584
|
+
# (== 'pea y)
|
585
|
+
# (== '(,x ,y) r))))) ;; => ((split pea))
|
586
|
+
result = instance.run
|
587
|
+
expect(result.car.car).to eq(split)
|
588
|
+
expect(result.car.cdr.car).to eq(pea)
|
589
|
+
end
|
590
|
+
|
591
|
+
it 'should accept multiple variables' do
|
592
|
+
expr1 = equals_goal(split, ref_x)
|
593
|
+
expr2 = equals_goal(pea, ref_y)
|
594
|
+
subgoal1 = conj2_goal(expr1, expr2)
|
595
|
+
subgoal2 = equals_goal(cons(ref_x, cons(ref_y)), ref_r)
|
596
|
+
goal = conj2_goal(subgoal1, subgoal2)
|
597
|
+
instance = RunStarExpression.new(%w[r x y], goal)
|
598
|
+
|
599
|
+
# Reasoned S2, frame 1:72
|
600
|
+
# (run* (r x y)
|
601
|
+
# (conj2
|
602
|
+
# (conj2
|
603
|
+
# (== 'split x)
|
604
|
+
# (== 'pea y))
|
605
|
+
# (== '(,x ,y) r))) ;; => (((split pea) split pea))
|
606
|
+
# o
|
607
|
+
# / \
|
608
|
+
# o nil
|
609
|
+
# / \
|
610
|
+
# / \
|
611
|
+
# / \
|
612
|
+
# / \
|
613
|
+
# / \
|
614
|
+
# o o
|
615
|
+
# / \ / \
|
616
|
+
# split o split o
|
617
|
+
# / \ / \
|
618
|
+
# pea nil pea nil
|
619
|
+
result = instance.run
|
620
|
+
expect(result.car.car.car).to eq(split)
|
621
|
+
expect(result.car.car.cdr.car).to eq(pea)
|
622
|
+
expect(result.car.car.cdr.cdr).to be_nil
|
623
|
+
expect(result.car.cdr.car).to eq(split)
|
624
|
+
expect(result.car.cdr.cdr.car).to eq(pea)
|
625
|
+
expect(result.car.cdr.cdr.cdr).to be_nil
|
626
|
+
end
|
627
|
+
|
628
|
+
it 'should allow simplication of expressions' do
|
629
|
+
expr1 = equals_goal(split, ref_x)
|
630
|
+
expr2 = equals_goal(pea, ref_y)
|
631
|
+
goal = conj2_goal(expr1, expr2)
|
632
|
+
instance = RunStarExpression.new(%w[x y], goal)
|
633
|
+
|
634
|
+
# Reasoned S2, frame 1:75
|
635
|
+
# (run* (x y)
|
636
|
+
# (conj2
|
637
|
+
# (== 'split x)
|
638
|
+
# (== 'pea y))) ;; => ((split pea))
|
639
|
+
result = instance.run
|
640
|
+
expect(result.car.car).to eq(split)
|
641
|
+
expect(result.car.cdr.car).to eq(pea)
|
642
|
+
end
|
643
|
+
|
644
|
+
it 'should allow simplication of expressions' do
|
645
|
+
expr1 = equals_goal(split, ref_x)
|
646
|
+
expr2 = equals_goal(pea, ref_y)
|
647
|
+
subgoal1 = conj2_goal(expr1, expr2)
|
648
|
+
expr3 = equals_goal(red, ref_x)
|
649
|
+
expr4 = equals_goal(bean, ref_y)
|
650
|
+
subgoal2 = conj2_goal(expr3, expr4)
|
651
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
652
|
+
instance = RunStarExpression.new(%w[x y], goal)
|
653
|
+
|
654
|
+
# Reasoned S2, frame 1:76
|
655
|
+
# (run* (x y)
|
656
|
+
# (disj2
|
657
|
+
# (conj2 (== 'split x) (== 'pea y))
|
658
|
+
# (conj2 (== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
|
659
|
+
result = instance.run
|
660
|
+
expect(result.car.car).to eq(split)
|
661
|
+
expect(result.car.cdr.car).to eq(pea)
|
662
|
+
expect(result.cdr.car.car).to eq(red)
|
663
|
+
expect(result.cdr.car.cdr.car).to eq(bean)
|
664
|
+
end
|
354
665
|
end # context
|
355
666
|
end # describe
|
356
667
|
end # module
|