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
data/spec/core/succeed_spec.rb
CHANGED
@@ -21,17 +21,17 @@ module MiniKraken
|
|
21
21
|
end # context
|
22
22
|
|
23
23
|
context 'Provided services:' do
|
24
|
-
|
25
|
-
args = double('fake-args')
|
26
|
-
env = double('fake-env')
|
24
|
+
let(:ctx) { Context.new }
|
27
25
|
|
26
|
+
it 'should unconditionally return a success result' do
|
28
27
|
solver = nil
|
29
|
-
expect { solver = subject.solver_for(
|
28
|
+
expect { solver = subject.solver_for([], ctx) }.not_to raise_error
|
30
29
|
|
31
30
|
# Solver should quack like a Fiber
|
32
31
|
dummy_arg = double('dummy-stuff')
|
33
32
|
result = solver.resume(dummy_arg)
|
34
|
-
expect(result).to eq(
|
33
|
+
expect(result).to eq(ctx)
|
34
|
+
expect(result).to be_success
|
35
35
|
|
36
36
|
# Only one "solution", next 'resume' call should return nil
|
37
37
|
result = solver.resume(dummy_arg)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../lib/mini_kraken/core/log_var'
|
5
|
+
|
6
|
+
# Load the class under test
|
7
|
+
require_relative '../../lib/mini_kraken/core/symbol_table'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe SymbolTable do
|
12
|
+
subject { SymbolTable.new }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'should be initialized without argument' do
|
16
|
+
expect { SymbolTable.new }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have a root scope' do
|
20
|
+
expect(subject.root).not_to be_nil
|
21
|
+
expect(subject.current_scope).to eq(subject.root)
|
22
|
+
expect(subject.root).to be_kind_of(Core::Scope)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "shouldn't have names at initialization" do
|
26
|
+
expect(subject.name2scopes).to be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be empty at initialization' do
|
30
|
+
expect(subject).to be_empty
|
31
|
+
end
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context 'Provided services:' do
|
35
|
+
def var(aName)
|
36
|
+
LogVar.new(aName)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should allow the addition of a variable' do
|
40
|
+
expect { subject.insert(var('q')) }.not_to raise_error
|
41
|
+
expect(subject).not_to be_empty
|
42
|
+
expect(subject.name2scopes['q']).to be_kind_of(Array)
|
43
|
+
expect(subject.name2scopes['q'].size).to eq(1)
|
44
|
+
expect(subject.name2scopes['q'].first).to eq(subject.current_scope)
|
45
|
+
expect(subject.current_scope.defns['q']).to be_kind_of(Core::LogVar)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should allow the addition of several labels for same env' do
|
49
|
+
i_name = subject.insert(var('q'))
|
50
|
+
expect(i_name).to match(/^q_[0-9a-z]+$/)
|
51
|
+
|
52
|
+
expect { subject.insert(var('x')) }.not_to raise_error
|
53
|
+
expect(subject.name2scopes['x']).to be_kind_of(Array)
|
54
|
+
expect(subject.name2scopes['x'].first).to eq(subject.current_scope)
|
55
|
+
expect(subject.current_scope.defns['x']).to be_kind_of(Core::LogVar)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should allow the entry into a new scope' do
|
59
|
+
subject.insert(var('q'))
|
60
|
+
new_scope = Core::Scope.new
|
61
|
+
expect { subject.enter_scope(new_scope) }.not_to raise_error
|
62
|
+
expect(subject.current_scope).to eq(new_scope)
|
63
|
+
expect(subject.current_scope.parent).to eq(subject.root)
|
64
|
+
expect(subject.name2scopes['q']).to eq([subject.root])
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should allow the addition of same name in different scopes' do
|
68
|
+
subject.insert(var('q'))
|
69
|
+
subject.enter_scope(Core::Scope.new)
|
70
|
+
subject.insert(var('q'))
|
71
|
+
expect(subject.name2scopes['q']).to be_kind_of(Array)
|
72
|
+
expect(subject.name2scopes['q'].size).to eq(2)
|
73
|
+
expect(subject.name2scopes['q'].first).to eq(subject.root)
|
74
|
+
expect(subject.name2scopes['q'].last).to eq(subject.current_scope)
|
75
|
+
expect(subject.current_scope.defns['q']).to be_kind_of(Core::LogVar)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should allow the removal of a scope' do
|
79
|
+
subject.insert(var('q'))
|
80
|
+
new_scope = Core::Scope.new
|
81
|
+
subject.enter_scope(new_scope)
|
82
|
+
subject.insert(var('q'))
|
83
|
+
expect(subject.name2scopes['q'].size).to eq(2)
|
84
|
+
|
85
|
+
expect { subject.leave_scope }.not_to raise_error
|
86
|
+
expect(subject.current_scope).to eq(subject.root)
|
87
|
+
expect(subject.name2scopes['q'].size).to eq(1)
|
88
|
+
expect(subject.name2scopes['q']).to eq([subject.root])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should allow the search of an entry based on its name' do
|
92
|
+
subject.insert(var('q'))
|
93
|
+
subject.insert(var('x'))
|
94
|
+
subject.enter_scope(Core::Scope.new)
|
95
|
+
subject.insert(var('q'))
|
96
|
+
subject.insert(var('y'))
|
97
|
+
|
98
|
+
# Search for unknown name
|
99
|
+
expect(subject.lookup('z')).to be_nil
|
100
|
+
|
101
|
+
# Search for existing unique names
|
102
|
+
expect(subject.lookup('y')).to eq(subject.current_scope.defns['y'])
|
103
|
+
expect(subject.lookup('x')).to eq(subject.root.defns['x'])
|
104
|
+
|
105
|
+
# Search for redefined name
|
106
|
+
expect(subject.lookup('q')).to eq(subject.current_scope.defns['q'])
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should allow the search of an entry based on its i_name' do
|
110
|
+
subject.insert(var('q'))
|
111
|
+
i_name_x = subject.insert(var('x'))
|
112
|
+
subject.enter_scope(Core::Scope.new)
|
113
|
+
i_name_q2 = subject.insert(var('q'))
|
114
|
+
i_name_y = subject.insert(var('y'))
|
115
|
+
|
116
|
+
# Search for unknown i_name
|
117
|
+
expect(subject.lookup_i_name('dummy')).to be_nil
|
118
|
+
|
119
|
+
curr_scope = subject.current_scope
|
120
|
+
# # Search for existing unique names
|
121
|
+
expect(subject.lookup_i_name(i_name_y)).to eq(curr_scope.defns['y'])
|
122
|
+
expect(subject.lookup_i_name(i_name_x)).to eq(subject.root.defns['x'])
|
123
|
+
|
124
|
+
# Search for redefined name
|
125
|
+
expect(subject.lookup_i_name(i_name_q2)).to eq(curr_scope.defns['q'])
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should list all the variables defined in all the szcope chain' do
|
129
|
+
subject.insert(var('q'))
|
130
|
+
subject.enter_scope(Core::Scope.new)
|
131
|
+
subject.insert(var('x'))
|
132
|
+
subject.enter_scope(Core::Scope.new)
|
133
|
+
subject.insert(var('y'))
|
134
|
+
subject.insert(var('x'))
|
135
|
+
|
136
|
+
vars = subject.all_variables
|
137
|
+
expect(vars.map(&:name)).to eq(%w[q x y x])
|
138
|
+
end
|
139
|
+
end # context
|
140
|
+
end # describe
|
141
|
+
end # module
|
142
|
+
end # module
|
data/spec/glue/dsl_chap1_spec.rb
CHANGED
@@ -13,7 +13,6 @@ module MiniKraken
|
|
13
13
|
|
14
14
|
context 'Chapter 1 examples:' do
|
15
15
|
it 'passes frame 1:7' do
|
16
|
-
# Reasoned S2, frame 1:7
|
17
16
|
# (run* q #u) ;; => ()
|
18
17
|
|
19
18
|
result = run_star('q', _fail)
|
@@ -21,18 +20,16 @@ module MiniKraken
|
|
21
20
|
end
|
22
21
|
|
23
22
|
it 'passes frame 1:10' do
|
24
|
-
# Reasoned S2, frame 1:10
|
25
23
|
# (run* q (== 'pea 'pod) ;; => ()
|
26
24
|
|
27
|
-
result = run_star('q',
|
25
|
+
result = run_star('q', unify(:pea, :pod))
|
28
26
|
expect(result).to be_null
|
29
27
|
end
|
30
28
|
|
31
29
|
it 'passes frame 1:11' do
|
32
|
-
# Reasoned S2, frame 1:11
|
33
30
|
# (run* q (== q 'pea) ;; => (pea)
|
34
31
|
|
35
|
-
result = run_star('q',
|
32
|
+
result = run_star('q', unify(q, :pea))
|
36
33
|
expect(result.car).to eq(:pea)
|
37
34
|
end
|
38
35
|
|
@@ -40,12 +37,11 @@ module MiniKraken
|
|
40
37
|
# Reasoned S2, frame 1:12
|
41
38
|
# (run* q (== 'pea q) ;; => (pea)
|
42
39
|
|
43
|
-
result = run_star('q',
|
40
|
+
result = run_star('q', unify(:pea, q))
|
44
41
|
expect(result.car).to eq(:pea)
|
45
42
|
end
|
46
43
|
|
47
44
|
it 'passes frame 1:17' do
|
48
|
-
# Reasoned S2, frame 1:17
|
49
45
|
# (run* q succeed) ;; => (_0)
|
50
46
|
|
51
47
|
result = run_star('q', succeed)
|
@@ -56,15 +52,14 @@ module MiniKraken
|
|
56
52
|
# Reasoned S2, frame 1:19
|
57
53
|
# (run* q (== 'pea 'pea)) ;; => (_0)
|
58
54
|
|
59
|
-
result = run_star('q',
|
55
|
+
result = run_star('q', unify(:pea, :pea))
|
60
56
|
expect(result.car).to eq(:_0)
|
61
57
|
end
|
62
58
|
|
63
59
|
it 'passes frame 1:20' do
|
64
|
-
# Reasoned S2, frame 1:20
|
65
60
|
# (run* q (== q q)) ;; => (_0)
|
66
61
|
|
67
|
-
result = run_star('q',
|
62
|
+
result = run_star('q', unify(q, q))
|
68
63
|
expect(result.car).to eq(:_0)
|
69
64
|
end
|
70
65
|
|
@@ -72,80 +67,81 @@ module MiniKraken
|
|
72
67
|
# Reasoned S2, frame 1:21
|
73
68
|
# (run* q (fresh (x) (== 'pea q))) ;; => (pea)
|
74
69
|
|
75
|
-
result = run_star('q', fresh('x',
|
70
|
+
result = run_star('q', fresh('x', unify(:pea, q)))
|
76
71
|
expect(result.car).to eq(:pea)
|
77
72
|
end
|
78
73
|
|
79
74
|
it 'passes frame 1:25' do
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
|
84
|
-
|
75
|
+
# (run* q
|
76
|
+
# (fresh (x)
|
77
|
+
# (== (cons x '()) q))) ;; => ((_0))
|
78
|
+
|
79
|
+
result = run_star('q', fresh('x', unify(cons(x, null_list), q)))
|
80
|
+
expect(result.car.to_s).to eq('(_0)')
|
85
81
|
end
|
86
82
|
|
87
83
|
it 'passes frame 1:31' do
|
88
|
-
# Reasoned S2, frame 1:31
|
89
84
|
# (run* q (fresh (x) (== x q))) ;; => (_0)
|
90
85
|
|
91
|
-
result = run_star('q', fresh('x',
|
86
|
+
result = run_star('q', fresh('x', unify(x, q)))
|
92
87
|
expect(result.car).to eq(:_0)
|
93
88
|
end
|
94
89
|
|
95
90
|
it 'passes frame 1:32' do
|
96
|
-
# Reasoned S2, frame 1:32
|
97
91
|
# (run* q (== '(((pea)) pod) '(((pea)) pod))) ;; => (_0)
|
98
92
|
|
99
|
-
result = run_star('q',
|
93
|
+
result = run_star('q', unify(cons(cons(:pea), :pod), cons(cons(:pea), :pod)))
|
100
94
|
expect(result.car).to eq(:_0)
|
101
95
|
end
|
102
96
|
|
103
97
|
it 'passes frame 1:33' do
|
104
98
|
# Beware: quasiquoting
|
105
|
-
# Reasoned S2, frame 1:33
|
106
99
|
# (run* q (== '(((pea)) pod) '(((pea)) ,q))) ;; => ('pod)
|
107
100
|
|
108
|
-
result = run_star('q',
|
101
|
+
result = run_star('q', unify(cons(cons(:pea), :pod), cons(cons(:pea), q)))
|
109
102
|
expect(result.car).to eq(:pod)
|
110
103
|
end
|
111
104
|
|
112
105
|
it 'passes frame 1:34' do
|
113
|
-
# Reasoned S2, frame 1:34
|
114
106
|
# (run* q (== '(((,q)) pod) `(((pea)) pod))) ;; => ('pea)
|
115
107
|
|
116
|
-
|
108
|
+
expr1 = cons(cons(cons(q)), cons(:pod))
|
109
|
+
expect(expr1.to_s).to eq('(((q)) :pod)')
|
110
|
+
expr2 = cons(cons(cons(:pea)), cons(:pod))
|
111
|
+
expect(expr2.to_s).to eq('(((:pea)) :pod)')
|
112
|
+
result = run_star('q', unify(expr1, expr2))
|
117
113
|
expect(result.car).to eq(:pea)
|
118
114
|
end
|
119
115
|
|
120
116
|
it 'passes frame 1:35' do
|
121
|
-
# Reasoned S2, frame 1:35
|
122
117
|
# (run* q (fresh (x) (== '(((,q)) pod) `(((,x)) pod)))) ;; => (_0)
|
123
118
|
|
124
|
-
result = run_star('q', fresh('x',
|
119
|
+
result = run_star('q', fresh('x', unify(cons(cons(q), :pod), cons(cons(x), :pod))))
|
125
120
|
expect(result.car).to eq(:_0)
|
126
121
|
end
|
127
122
|
|
128
123
|
it 'passes frame 1:36' do
|
129
|
-
# Reasoned S2, frame 1:36
|
130
124
|
# (run* q (fresh (x) (== '(((,q)) ,x) `(((,x)) pod)))) ;; => ('pod)
|
131
125
|
|
132
|
-
|
126
|
+
expr1 = cons(cons(cons(q)), cons(x))
|
127
|
+
expect(expr1.to_s).to eq('(((q)) x)')
|
128
|
+
expr2 = cons(cons(cons(x)), cons(:pod))
|
129
|
+
expect(expr2.to_s).to eq('(((x)) :pod)')
|
130
|
+
result = run_star('q', fresh('x', unify(expr1, expr2)))
|
133
131
|
expect(result.car).to eq(:pod)
|
134
132
|
end
|
135
133
|
|
136
134
|
it 'passes frame 1:37' do
|
137
|
-
# Reasoned S2, frame 1:37
|
138
135
|
# (run* q (fresh (x) (== '( ,x ,x) q))) ;; => (_0 _0)
|
139
136
|
|
140
|
-
result = run_star('q', fresh('x',
|
137
|
+
result = run_star('q', fresh('x', unify(cons(x, cons(x)), q)))
|
141
138
|
expect(result.car).to eq(cons(:_0, cons(:_0)))
|
142
139
|
end
|
143
140
|
|
144
141
|
it 'passes frame 1:38' do
|
145
|
-
# Reasoned S2, frame 1:38
|
146
142
|
# (run* q (fresh (x) (fresh (y) (== '( ,q ,y) '((,x ,y) ,x))))) ;; => (_0 _0)
|
147
143
|
|
148
|
-
result = run_star('q', fresh('x', fresh('y',
|
144
|
+
result = run_star('q', fresh('x', fresh('y', unify(cons(q, cons(y)), cons(cons(x, cons(y)), cons(x))))))
|
149
145
|
expect(result.car).to eq(cons(:_0, cons(:_0)))
|
150
146
|
end
|
151
147
|
|
@@ -153,25 +149,23 @@ module MiniKraken
|
|
153
149
|
# Reasoned S2, frame 1:41
|
154
150
|
# (run* q (fresh (x) (fresh (y) (== '( ,x ,y) q)))) ;; => (_0 _1)
|
155
151
|
|
156
|
-
result = run_star('q', fresh('x', fresh('y',
|
152
|
+
result = run_star('q', fresh('x', fresh('y', unify(cons(x, cons(y)), q))))
|
157
153
|
# q should be bound to '(,x ,y)
|
158
154
|
expect(result.car).to eq(cons(:_0, cons(:_1)))
|
159
155
|
end
|
160
156
|
|
161
157
|
it 'passes frame 1:42' do
|
162
|
-
# Reasoned S2, frame 1:42
|
163
158
|
# (run* s (fresh (t) (fresh (u) (== '( ,t ,u) s)))) ;; => (_0 _1)
|
164
159
|
|
165
|
-
result = run_star('s', fresh('t', fresh('u',
|
160
|
+
result = run_star('s', fresh('t', fresh('u', unify(cons(t, cons(u)), s))))
|
166
161
|
# s should be bound to '(,t ,u)
|
167
162
|
expect(result.car).to eq(cons(:_0, cons(:_1)))
|
168
163
|
end
|
169
164
|
|
170
165
|
it 'passes frame 1:43' do
|
171
|
-
# Reasoned S2, frame 1:43
|
172
166
|
# (run* q (fresh (x) (fresh (y) (== '( ,x ,y ,x) q)))) ;; => (_0 _1 _0)
|
173
167
|
|
174
|
-
result = run_star('q', fresh('x', fresh('y',
|
168
|
+
result = run_star('q', fresh('x', fresh('y', unify(cons(x, cons(y, cons(x))), q))))
|
175
169
|
# q should be bound to '(,x ,y, ,x)
|
176
170
|
expect(result.car).to eq(cons(:_0, cons(:_1, cons(:_0))))
|
177
171
|
end
|
@@ -185,18 +179,16 @@ module MiniKraken
|
|
185
179
|
end
|
186
180
|
|
187
181
|
it 'passes frame 1:51' do
|
188
|
-
# Reasoned S2, frame 1:51
|
189
182
|
# (run* q (conj2 succeed (== 'corn q)) ;; => ('corn)
|
190
183
|
|
191
|
-
result = run_star('q', conj2(succeed,
|
184
|
+
result = run_star('q', conj2(succeed, unify(:corn, q)))
|
192
185
|
expect(result.car).to eq(:corn)
|
193
186
|
end
|
194
187
|
|
195
188
|
it 'passes frame 1:52' do
|
196
|
-
# Reasoned S2, frame 1:52
|
197
189
|
# (run* q (conj2 fail (== 'corn q)) ;; => ()
|
198
190
|
|
199
|
-
result = run_star('q', conj2(_fail,
|
191
|
+
result = run_star('q', conj2(_fail, unify(:corn, q)))
|
200
192
|
expect(result).to be_null
|
201
193
|
end
|
202
194
|
|
@@ -204,20 +196,18 @@ module MiniKraken
|
|
204
196
|
# Reasoned S2, frame 1:53
|
205
197
|
# (run* q (conj2 (== 'corn q)(== 'meal q)) ;; => ()
|
206
198
|
|
207
|
-
result = run_star('q', conj2(
|
199
|
+
result = run_star('q', conj2(unify(:corn, q), unify(:meal, q)))
|
208
200
|
expect(result).to be_null
|
209
201
|
end
|
210
202
|
|
211
203
|
it 'passes frame 1:54' do
|
212
|
-
# Reasoned S2, frame 1:54
|
213
204
|
# (run* q (conj2 (== 'corn q)(== 'corn q)) ;; => ('corn)
|
214
205
|
|
215
|
-
result = run_star('q', conj2(
|
206
|
+
result = run_star('q', conj2(unify(:corn, q), unify(:corn, q)))
|
216
207
|
expect(result.car).to eq(:corn)
|
217
208
|
end
|
218
209
|
|
219
210
|
it "supports 'disj2' and passes frame 1:55" do
|
220
|
-
# Reasoned S2, frame 1:55
|
221
211
|
# (run* q (disj2 fail fail)) ;; => ()
|
222
212
|
|
223
213
|
result = run_star('q', disj2(_fail, _fail))
|
@@ -225,73 +215,65 @@ module MiniKraken
|
|
225
215
|
end
|
226
216
|
|
227
217
|
it 'passes frame 1:56' do
|
228
|
-
# Reasoned S2, frame 1:56
|
229
218
|
# (run* q (disj2 (== 'olive q) fail)) ;; => ('olive)
|
230
219
|
|
231
|
-
result = run_star('q', disj2(
|
220
|
+
result = run_star('q', disj2(unify(:olive, q), _fail))
|
232
221
|
expect(result.car).to eq(:olive)
|
233
222
|
end
|
234
223
|
|
235
224
|
it 'passes frame 1:57' do
|
236
|
-
# Reasoned S2, frame 1:57
|
237
225
|
# (run* q (disj2 fail (== 'oil q))) ;; => (oil)
|
238
226
|
|
239
|
-
result = run_star('q', disj2(_fail,
|
227
|
+
result = run_star('q', disj2(_fail, unify(:oil, q)))
|
240
228
|
expect(result.car).to eq(:oil)
|
241
229
|
end
|
242
230
|
|
243
231
|
it 'passes frame 1:58' do
|
244
|
-
# Reasoned S2, frame 1:58
|
245
232
|
# (run* q (disj2 (== 'olive q) (== 'oil q))) ;; => (olive oil)
|
246
233
|
|
247
|
-
result = run_star('q', disj2(
|
234
|
+
result = run_star('q', disj2(unify(:olive, q), unify(:oil, q)))
|
248
235
|
expect(result.car).to eq(:olive)
|
249
236
|
expect(result.cdr.car).to eq(:oil)
|
250
237
|
end
|
251
238
|
|
252
239
|
it 'passes frame 1:59' do
|
253
|
-
# Reasoned S2, frame 1:59
|
254
240
|
# (run* q (fresh (x) (fresh (y) (disj2 (== '( ,x ,y ) q) (== '( ,x ,y ) q)))))
|
255
241
|
# ;; => ((_0 _1) (_0 _1))
|
256
242
|
|
257
|
-
result = run_star('q', fresh('x', (fresh 'y', disj2(
|
243
|
+
result = run_star('q', fresh('x', (fresh 'y', disj2(unify(cons(x, cons(y)), q), unify(cons(x, cons(y)), q)))))
|
258
244
|
# q should be bound to '(,x ,y), then to '(,y ,x)
|
259
245
|
expect(result.car).to eq(cons(:_0, cons(:_1)))
|
260
246
|
expect(result.cdr.car).to eq(cons(:_0, cons(:_1)))
|
261
247
|
end
|
262
248
|
|
263
249
|
it 'passes frame 1:62' do
|
264
|
-
# Reasoned S2, frame 1:62
|
265
250
|
# (run* x (disj2
|
266
251
|
# (conj2 (== 'olive x) fail)
|
267
252
|
# (== 'oil x))) ;; => (oil)
|
268
253
|
|
269
|
-
result = run_star('x', disj2(conj2(
|
254
|
+
result = run_star('x', disj2(conj2(unify(:olive, x), _fail), unify(:oil, x)))
|
270
255
|
expect(result.car).to eq(:oil)
|
271
256
|
end
|
272
257
|
|
273
258
|
it 'passes frame 1:63' do
|
274
|
-
# Reasoned S2, frame 1:63
|
275
259
|
# (run* x (disj2
|
276
260
|
# (conj2 (== 'olive x) succeed)
|
277
261
|
# ('oil x))) ;; => (olive oil)
|
278
262
|
|
279
|
-
result = run_star('x', disj2(conj2(
|
263
|
+
result = run_star('x', disj2(conj2(unify(:olive, x), succeed), unify(:oil, x)))
|
280
264
|
expect(result).to eq(cons(:olive, cons(:oil)))
|
281
265
|
end
|
282
266
|
|
283
267
|
it 'passes frame 1:64' do
|
284
|
-
# Reasoned S2, frame 1:64
|
285
268
|
# (run* x (disj2
|
286
269
|
# (== 'oil x)
|
287
270
|
# (conj2 (== 'olive x) succeed))) ;; => (oil olive)
|
288
271
|
|
289
|
-
result = run_star('x', disj2(
|
272
|
+
result = run_star('x', disj2(unify(:oil, x), conj2(unify(:olive, x), succeed)))
|
290
273
|
expect(result).to eq(cons(:oil, cons(:olive)))
|
291
274
|
end
|
292
275
|
|
293
276
|
it 'passes frame 1:65' do
|
294
|
-
# Reasoned S2, frame 1:65
|
295
277
|
# (run* x (disj2
|
296
278
|
# (conj2(== 'virgin x) fail)
|
297
279
|
# (disj2
|
@@ -300,13 +282,13 @@ module MiniKraken
|
|
300
282
|
# succeed
|
301
283
|
# (== 'oil x))))) ;; => (olive _0 oil)
|
302
284
|
|
303
|
-
result = run_star('x', disj2(conj2(
|
304
|
-
disj2(
|
285
|
+
result = run_star('x', disj2(conj2(unify(:virgin, x), _fail),
|
286
|
+
disj2(unify(:olive, x), disj2(succeed, unify(:oil, x)))))
|
305
287
|
expect(result).to eq(cons(:olive, cons(:_0, cons(:oil))))
|
288
|
+
expect(result.to_s).to eq('(:olive _0 :oil)')
|
306
289
|
end
|
307
290
|
|
308
291
|
it 'passes frame 1:67' do
|
309
|
-
# Reasoned S2, frame 1:67
|
310
292
|
# (run* r
|
311
293
|
# (fresh x
|
312
294
|
# (fresh y
|
@@ -317,13 +299,12 @@ module MiniKraken
|
|
317
299
|
# (== '(,x ,y) r)))))) ;; => ((split pea))
|
318
300
|
|
319
301
|
result = run_star('r', fresh('x', fresh('y',
|
320
|
-
conj2(
|
321
|
-
conj2(
|
322
|
-
expect(result).to eq(
|
302
|
+
conj2(unify(:split, x),
|
303
|
+
conj2(unify(:pea, y), unify(cons(x, cons(y)), r))))))
|
304
|
+
expect(result.to_s).to eq('((:split :pea))')
|
323
305
|
end
|
324
306
|
|
325
307
|
it 'passes frame 1:68' do
|
326
|
-
# Reasoned S2, frame 1:68
|
327
308
|
# (run* r
|
328
309
|
# (fresh x
|
329
310
|
# (fresh y
|
@@ -334,13 +315,12 @@ module MiniKraken
|
|
334
315
|
# (== '(,x ,y) r)))))) ;; => ((split pea))
|
335
316
|
|
336
317
|
result = run_star('r', fresh('x', fresh('y',
|
337
|
-
conj2(conj2(
|
338
|
-
|
339
|
-
expect(result).to eq(
|
318
|
+
conj2(conj2(unify(:split, x), unify(:pea, y)),
|
319
|
+
unify(cons(x, cons(y)), r)))))
|
320
|
+
expect(result.to_s).to eq('((:split :pea))')
|
340
321
|
end
|
341
322
|
|
342
323
|
it 'passes frame 1:70' do
|
343
|
-
# Reasoned S2, frame 1:70
|
344
324
|
# (run* r
|
345
325
|
# (fresh (x y)
|
346
326
|
# (conj2
|
@@ -350,13 +330,12 @@ module MiniKraken
|
|
350
330
|
# (== '(,x ,y) r))))) ;; => ((split pea))
|
351
331
|
|
352
332
|
result = run_star('r', fresh(%w[x y], conj2(
|
353
|
-
conj2(
|
354
|
-
|
355
|
-
expect(result).to eq(
|
333
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
334
|
+
unify(cons(x, cons(y)), r))))
|
335
|
+
expect(result.to_s).to eq('((:split :pea))')
|
356
336
|
end
|
357
337
|
|
358
338
|
it 'passes frame 1:72' do
|
359
|
-
# Reasoned S2, frame 1:72
|
360
339
|
# (run* (r x y)
|
361
340
|
# (conj2
|
362
341
|
# (conj2
|
@@ -378,43 +357,42 @@ module MiniKraken
|
|
378
357
|
# pea nil pea nil
|
379
358
|
|
380
359
|
result = run_star(%w[r x y], conj2(
|
381
|
-
conj2(
|
382
|
-
|
360
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
361
|
+
unify(cons(x, cons(y)), r)))
|
383
362
|
expect(result.car.car.car).to eq(:split)
|
384
363
|
expect(result.car.car.cdr.car).to eq(:pea)
|
385
364
|
expect(result.car.car.cdr.cdr).to be_nil
|
386
365
|
expect(result.car.cdr.car).to eq(:split)
|
387
366
|
expect(result.car.cdr.cdr.car).to eq(:pea)
|
388
367
|
expect(result.car.cdr.cdr.cdr).to be_nil
|
368
|
+
expect(result.to_s).to eq('(((:split :pea) :split :pea))')
|
389
369
|
end
|
390
370
|
|
391
371
|
it 'passes frame 1:75' do
|
392
|
-
# Reasoned S2, frame 1:75
|
393
372
|
# (run* (x y)
|
394
373
|
# (conj2
|
395
374
|
# (== 'split x)
|
396
375
|
# (== 'pea y))) ;; => ((split pea))
|
397
376
|
|
398
|
-
result = run_star(%w[x y], conj2(
|
399
|
-
expect(result.
|
377
|
+
result = run_star(%w[x y], conj2(unify(:split, x), unify(:pea, y)))
|
378
|
+
expect(result.to_s).to eq('((:split :pea))')
|
400
379
|
end
|
401
380
|
|
402
381
|
it 'passes frame 1:76' do
|
403
|
-
# Reasoned S2, frame 1:76
|
404
382
|
# (run* (x y)
|
405
383
|
# (disj2
|
406
384
|
# (conj2 (== 'split x) (== 'pea y))
|
407
385
|
# (conj2 (== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
|
408
386
|
|
409
387
|
result = run_star(%w[x y], disj2(
|
410
|
-
conj2(
|
411
|
-
conj2(
|
388
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
389
|
+
conj2(unify(:red, x), unify(:bean, y))))
|
390
|
+
expect(result.to_s).to eq('((:split :pea) (:red :bean))')
|
412
391
|
expect(result.car).to eq(list(:split, :pea))
|
413
392
|
expect(result.cdr.car).to eq(list(:red, :bean))
|
414
393
|
end
|
415
394
|
|
416
395
|
it 'passes frame 1:77' do
|
417
|
-
# Reasoned S2, frame 1:77
|
418
396
|
# (run* r
|
419
397
|
# (fresh (x y)
|
420
398
|
# (conj2
|
@@ -426,15 +404,15 @@ module MiniKraken
|
|
426
404
|
result = run_star('r',
|
427
405
|
fresh(%w[x y], conj2(
|
428
406
|
disj2(
|
429
|
-
conj2(
|
430
|
-
conj2(
|
431
|
-
|
407
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
408
|
+
conj2(unify(:red, x), unify(:bean, y))),
|
409
|
+
unify(cons(x, cons(y, cons(:soup))), r))))
|
410
|
+
expect(result.to_s).to eq('((:split :pea :soup) (:red :bean :soup))')
|
432
411
|
expect(result.car).to eq(list(:split, :pea, :soup))
|
433
412
|
expect(result.cdr.car).to eq(list(:red, :bean, :soup))
|
434
413
|
end
|
435
414
|
|
436
415
|
it 'passes frame 1:78' do
|
437
|
-
# Reasoned S2, frame 1:78
|
438
416
|
# (run* r
|
439
417
|
# (fresh (x y)
|
440
418
|
# (disj2
|
@@ -444,15 +422,13 @@ module MiniKraken
|
|
444
422
|
|
445
423
|
result = run_star('r',
|
446
424
|
fresh(%w[x y], [disj2(
|
447
|
-
conj2(
|
448
|
-
conj2(
|
449
|
-
|
450
|
-
expect(result.
|
451
|
-
expect(result.cdr.car).to eq(list(:red, :bean, :soup))
|
425
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
426
|
+
conj2(unify(:red, x), unify(:bean, y))),
|
427
|
+
unify(cons(x, cons(y, cons(:soup))), r)]))
|
428
|
+
expect(result.to_s).to eq('((:split :pea :soup) (:red :bean :soup))')
|
452
429
|
end
|
453
430
|
|
454
431
|
it 'passes frame 1:80' do
|
455
|
-
# Reasoned S2, frame 1:80
|
456
432
|
# (run* (x y z)
|
457
433
|
# (disj2
|
458
434
|
# (conj2 (== 'split x) (== 'pea y))
|
@@ -460,56 +436,38 @@ module MiniKraken
|
|
460
436
|
# (== 'soup z)) ;; => ((split pea soup) (red bean soup))
|
461
437
|
|
462
438
|
result = run_star(%w[x y z], [disj2(
|
463
|
-
conj2(
|
464
|
-
conj2(
|
465
|
-
|
439
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
440
|
+
conj2(unify(:red, x), unify(:bean, y))),
|
441
|
+
unify(:soup, z)])
|
466
442
|
expect(result.car).to eq(list(:split, :pea, :soup))
|
467
443
|
expect(result.cdr.car).to eq(list(:red, :bean, :soup))
|
468
444
|
end
|
469
445
|
|
470
446
|
it 'passes frame 1:81' do
|
471
|
-
# Reasoned S2, frame 1:81
|
472
447
|
# (run* (x y)
|
473
448
|
# (== 'split x)
|
474
449
|
# (== 'pea y)) ;; => ((split pea))
|
475
450
|
|
476
|
-
result = run_star(%w[x y], [
|
451
|
+
result = run_star(%w[x y], [unify(:split, x), unify(:pea, y)])
|
477
452
|
expect(result.car).to eq(list(:split, :pea))
|
478
453
|
end
|
479
454
|
|
480
455
|
it "supports 'defrel' and passes frame 1:82" do
|
481
|
-
# Reasoned S2, frame 1:82
|
482
456
|
# (defrel (teacupo t)
|
483
457
|
# (disj2 (== 'tea t) (== 'cup t)))
|
484
|
-
|
485
|
-
result = defrel('teacupo', 't')
|
486
|
-
|
487
|
-
end
|
488
|
-
|
489
|
-
expect(result).to be_kind_of(Core::DefRelation)
|
458
|
+
expr = disj2(unify(:tea, t), unify(:cup, t))
|
459
|
+
result = defrel('teacupo', ['t'], expr)
|
460
|
+
expect(result).to be_kind_of(Rela::DefRelation)
|
490
461
|
expect(result.name).to eq('teacupo')
|
491
462
|
expect(result.formals.size).to eq(1)
|
492
|
-
expect(result.formals[0]
|
493
|
-
|
494
|
-
expect(
|
495
|
-
expect(
|
496
|
-
|
497
|
-
first_arg = g_template.args[0]
|
498
|
-
expect(first_arg).to be_kind_of(Core::GoalTemplate)
|
499
|
-
expect(first_arg.relation).to eq(Core::Equals.instance)
|
500
|
-
expect(first_arg.args[0]).to eq(:tea)
|
501
|
-
expect(first_arg.args[1]).to be_kind_of(Core::FormalRef)
|
502
|
-
expect(first_arg.args[1].name).to eq('t')
|
503
|
-
second_arg = g_template.args[1]
|
504
|
-
expect(second_arg).to be_kind_of(Core::GoalTemplate)
|
505
|
-
expect(second_arg.relation).to eq(Core::Equals.instance)
|
506
|
-
expect(second_arg.args[0]).to eq(:cup)
|
507
|
-
expect(second_arg.args[1]).to be_kind_of(Core::FormalRef)
|
508
|
-
expect(second_arg.args[1].name).to eq('t')
|
463
|
+
expect(result.formals[0]).to match(/^t_/)
|
464
|
+
goal_expr = result.expression
|
465
|
+
expect(goal_expr).to be_kind_of(Core::Goal)
|
466
|
+
expect(goal_expr.relation).to eq(Rela::Disj2.instance)
|
509
467
|
end
|
510
468
|
|
511
|
-
|
512
|
-
defrel('teacupo', 't'
|
469
|
+
let(:defrel_teacupo) do
|
470
|
+
defrel('teacupo', ['t'], disj2(unify(:tea, t), unify(:cup, t)))
|
513
471
|
end
|
514
472
|
|
515
473
|
it "supports the invokation of a 'defrel' and passes frame 1:83" do
|
@@ -533,8 +491,8 @@ module MiniKraken
|
|
533
491
|
defrel_teacupo
|
534
492
|
result = run_star(%w[x y],
|
535
493
|
disj2(
|
536
|
-
conj2(teacupo(x),
|
537
|
-
conj2(
|
494
|
+
conj2(teacupo(x), unify('#t', y)),
|
495
|
+
conj2(unify('#f', x), unify('#t', y))))
|
538
496
|
|
539
497
|
# Order of solutions differs from RS book
|
540
498
|
expect(result.car).to eq(cons(:tea, cons(true)))
|
@@ -543,7 +501,6 @@ module MiniKraken
|
|
543
501
|
end
|
544
502
|
|
545
503
|
it 'passes frame 1:85' do
|
546
|
-
# Reasoned S2, frame 1:85
|
547
504
|
# (run* (x y)
|
548
505
|
# (teacupo x)
|
549
506
|
# (teacupo y)) ;; => ((tea tea)(tea cup)(cup tea)(cup c))
|
@@ -558,7 +515,6 @@ module MiniKraken
|
|
558
515
|
end
|
559
516
|
|
560
517
|
it 'passes frame 1:86' do
|
561
|
-
# Reasoned S2, frame 1:86
|
562
518
|
# (run* (x y)
|
563
519
|
# (teacupo x)
|
564
520
|
# (teacupo x)) ;; => ((tea _0)(cup _0))
|
@@ -569,7 +525,6 @@ module MiniKraken
|
|
569
525
|
end
|
570
526
|
|
571
527
|
it 'passes frame 1:87' do
|
572
|
-
# Reasoned S2, frame 1:87
|
573
528
|
# (run* (x y)
|
574
529
|
# (disj2
|
575
530
|
# (conj2 (teacupo x) (teacupo x))
|
@@ -578,7 +533,7 @@ module MiniKraken
|
|
578
533
|
defrel_teacupo
|
579
534
|
result = run_star(%w[x y], disj2(
|
580
535
|
conj2(teacupo(x), teacupo(x)),
|
581
|
-
conj2(
|
536
|
+
conj2(unify('#f', x), teacupo(y))))
|
582
537
|
|
583
538
|
# Order of solutions differs from RS book
|
584
539
|
expected = '((:tea _0) (:cup _0) (false :tea) (false :cup))'
|
@@ -590,7 +545,6 @@ module MiniKraken
|
|
590
545
|
end
|
591
546
|
|
592
547
|
it 'supports conde and passes frame 1:88 (i)' do
|
593
|
-
# Reasoned S2, frame 1:88
|
594
548
|
# (run* (x y)
|
595
549
|
# (conde
|
596
550
|
# ((teacupo x) (teacupo x))
|
@@ -599,7 +553,7 @@ module MiniKraken
|
|
599
553
|
defrel_teacupo
|
600
554
|
result = run_star(%w[x y], conde(
|
601
555
|
[teacupo(x), teacupo(x)],
|
602
|
-
[
|
556
|
+
[unify('#f', x), teacupo(y)]))
|
603
557
|
|
604
558
|
# Order of solutions differs from RS book
|
605
559
|
expected = '((:tea _0) (:cup _0) (false :tea) (false :cup))'
|
@@ -613,8 +567,8 @@ module MiniKraken
|
|
613
567
|
# ((== 'split x) (== 'pea y))
|
614
568
|
# ((== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
|
615
569
|
result = run_star(%w[x y], conde(
|
616
|
-
[
|
617
|
-
[
|
570
|
+
[unify(:split, x), unify(:pea, y)],
|
571
|
+
[unify(:red, x), unify(:bean, y)]))
|
618
572
|
|
619
573
|
expected = '((:split :pea) (:red :bean))'
|
620
574
|
expect(result.to_s).to eq(expected)
|
@@ -628,14 +582,13 @@ module MiniKraken
|
|
628
582
|
# ('oil x))) ;; => (oil)
|
629
583
|
|
630
584
|
result = run_star('x', conde(
|
631
|
-
[
|
632
|
-
|
585
|
+
[unify(:olive, x), _fail],
|
586
|
+
unify(:oil, x)))
|
633
587
|
|
634
588
|
expect(result.to_s).to eq('(:oil)')
|
635
589
|
end
|
636
590
|
|
637
591
|
it 'passes frame 1:90' do
|
638
|
-
# Reasoned S2, frame 1:90
|
639
592
|
# (run* (x y)
|
640
593
|
# (conde
|
641
594
|
# ((fresh (z)
|
@@ -643,14 +596,13 @@ module MiniKraken
|
|
643
596
|
# ((== x y)))) ;; => ((_0 _1)(_0 _0))
|
644
597
|
|
645
598
|
result = run_star(%w[x y], conde(
|
646
|
-
[fresh(%w[z],
|
647
|
-
[
|
599
|
+
[fresh(%w[z], unify(:lentil, z))],
|
600
|
+
[unify(x, y)]))
|
648
601
|
|
649
602
|
expect(result.to_s).to eq('((_0 _1) (_0 _0))')
|
650
603
|
end
|
651
604
|
|
652
605
|
it 'passes frame 1:91' do
|
653
|
-
# Reasoned S2, frame 1:91
|
654
606
|
# (run* (x y)
|
655
607
|
# (conde
|
656
608
|
# ((== 'split x) (== 'pea y))
|
@@ -658,9 +610,9 @@ module MiniKraken
|
|
658
610
|
# ((== 'green x) (== 'lentil y))))
|
659
611
|
# ;; => ((split pea)(red bean)(green lentil))
|
660
612
|
result = run_star(%w[x y], conde(
|
661
|
-
[
|
662
|
-
[
|
663
|
-
[
|
613
|
+
[unify(:split, x), unify(:pea, y)],
|
614
|
+
[unify(:red, x), unify(:bean, y)],
|
615
|
+
[unify(:green, x), unify(:lentil, y)]))
|
664
616
|
|
665
617
|
expected = '((:split :pea) (:red :bean) (:green :lentil))'
|
666
618
|
expect(result.to_s).to eq(expected)
|