mini_kraken 0.2.04 → 0.3.00

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +16 -16
  4. data/lib/mini_kraken/atomic/all_atomic.rb +1 -0
  5. data/lib/mini_kraken/atomic/atomic_term.rb +32 -17
  6. data/lib/mini_kraken/atomic/k_integer.rb +0 -4
  7. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  8. data/lib/mini_kraken/atomic/k_symbol.rb +0 -6
  9. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  10. data/lib/mini_kraken/composite/composite_term.rb +2 -18
  11. data/lib/mini_kraken/composite/cons_cell.rb +178 -11
  12. data/lib/mini_kraken/composite/cons_cell_visitor.rb +12 -64
  13. data/lib/mini_kraken/composite/list.rb +32 -0
  14. data/lib/mini_kraken/core/all_core.rb +8 -0
  15. data/lib/mini_kraken/core/any_value.rb +31 -7
  16. data/lib/mini_kraken/core/arity.rb +69 -0
  17. data/lib/mini_kraken/core/association.rb +29 -4
  18. data/lib/mini_kraken/core/association_copy.rb +50 -0
  19. data/lib/mini_kraken/core/base_term.rb +13 -0
  20. data/lib/mini_kraken/core/blackboard.rb +315 -0
  21. data/lib/mini_kraken/core/bookmark.rb +46 -0
  22. data/lib/mini_kraken/core/context.rb +624 -0
  23. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  24. data/lib/mini_kraken/core/entry.rb +40 -0
  25. data/lib/mini_kraken/core/fail.rb +20 -18
  26. data/lib/mini_kraken/core/fusion.rb +29 -0
  27. data/lib/mini_kraken/core/goal.rb +20 -29
  28. data/lib/mini_kraken/core/log_var.rb +4 -30
  29. data/lib/mini_kraken/core/log_var_ref.rb +72 -48
  30. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  31. data/lib/mini_kraken/core/parametrized_term.rb +61 -0
  32. data/lib/mini_kraken/core/relation.rb +14 -28
  33. data/lib/mini_kraken/core/scope.rb +67 -0
  34. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  35. data/lib/mini_kraken/core/specification.rb +48 -0
  36. data/lib/mini_kraken/core/succeed.rb +21 -17
  37. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  38. data/lib/mini_kraken/core/term.rb +15 -4
  39. data/lib/mini_kraken/glue/dsl.rb +35 -69
  40. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  41. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  42. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  43. data/lib/mini_kraken/rela/conde.rb +146 -0
  44. data/lib/mini_kraken/rela/conj2.rb +65 -0
  45. data/lib/mini_kraken/rela/def_relation.rb +64 -0
  46. data/lib/mini_kraken/rela/disj2.rb +70 -0
  47. data/lib/mini_kraken/rela/fresh.rb +98 -0
  48. data/lib/mini_kraken/{core → rela}/goal_relation.rb +6 -8
  49. data/lib/mini_kraken/rela/unify.rb +258 -0
  50. data/lib/mini_kraken/version.rb +1 -1
  51. data/spec/atomic/atomic_term_spec.rb +23 -20
  52. data/spec/atomic/k_symbol_spec.rb +0 -5
  53. data/spec/composite/cons_cell_spec.rb +116 -0
  54. data/spec/composite/cons_cell_visitor_spec.rb +16 -3
  55. data/spec/composite/list_spec.rb +50 -0
  56. data/spec/core/any_value_spec.rb +52 -0
  57. data/spec/core/arity_spec.rb +91 -0
  58. data/spec/core/association_copy_spec.rb +69 -0
  59. data/spec/core/association_spec.rb +25 -0
  60. data/spec/core/blackboard_spec.rb +287 -0
  61. data/spec/core/bookmark_spec.rb +40 -0
  62. data/spec/core/context_spec.rb +221 -0
  63. data/spec/core/core_spec.rb +40 -0
  64. data/spec/core/duck_fiber_spec.rb +22 -46
  65. data/spec/core/fail_spec.rb +5 -6
  66. data/spec/core/goal_spec.rb +20 -11
  67. data/spec/core/log_var_ref_spec.rb +80 -5
  68. data/spec/core/log_var_spec.rb +35 -6
  69. data/spec/core/nullary_relation_spec.rb +33 -0
  70. data/spec/core/parametrized_tem_spec.rb +39 -0
  71. data/spec/core/relation_spec.rb +33 -0
  72. data/spec/core/scope_spec.rb +73 -0
  73. data/spec/core/solver_adapter_spec.rb +70 -0
  74. data/spec/core/specification_spec.rb +43 -0
  75. data/spec/core/succeed_spec.rb +5 -5
  76. data/spec/core/symbol_table_spec.rb +142 -0
  77. data/spec/glue/dsl_chap1_spec.rb +88 -99
  78. data/spec/glue/dsl_chap2_spec.rb +59 -41
  79. data/spec/glue/run_star_expression_spec.rb +69 -896
  80. data/spec/{core → rela}/conde_spec.rb +50 -46
  81. data/spec/rela/conj2_spec.rb +123 -0
  82. data/spec/rela/def_relation_spec.rb +119 -0
  83. data/spec/rela/disj2_spec.rb +117 -0
  84. data/spec/rela/fresh_spec.rb +147 -0
  85. data/spec/rela/unify_spec.rb +369 -0
  86. data/spec/support/factory_atomic.rb +7 -0
  87. data/spec/support/factory_composite.rb +21 -0
  88. metadata +71 -48
  89. data/lib/mini_kraken/core/association_walker.rb +0 -183
  90. data/lib/mini_kraken/core/base_arg.rb +0 -10
  91. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  92. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  93. data/lib/mini_kraken/core/conde.rb +0 -143
  94. data/lib/mini_kraken/core/conj2.rb +0 -79
  95. data/lib/mini_kraken/core/def_relation.rb +0 -53
  96. data/lib/mini_kraken/core/designation.rb +0 -55
  97. data/lib/mini_kraken/core/disj2.rb +0 -72
  98. data/lib/mini_kraken/core/environment.rb +0 -73
  99. data/lib/mini_kraken/core/equals.rb +0 -191
  100. data/lib/mini_kraken/core/formal_arg.rb +0 -22
  101. data/lib/mini_kraken/core/formal_ref.rb +0 -25
  102. data/lib/mini_kraken/core/freshness.rb +0 -45
  103. data/lib/mini_kraken/core/goal_arg.rb +0 -12
  104. data/lib/mini_kraken/core/goal_template.rb +0 -102
  105. data/lib/mini_kraken/core/outcome.rb +0 -63
  106. data/lib/mini_kraken/core/tap.rb +0 -46
  107. data/lib/mini_kraken/core/vocabulary.rb +0 -446
  108. data/lib/mini_kraken/glue/fresh_env.rb +0 -108
  109. data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
  110. data/spec/core/association_walker_spec.rb +0 -194
  111. data/spec/core/conj2_spec.rb +0 -116
  112. data/spec/core/def_relation_spec.rb +0 -99
  113. data/spec/core/disj2_spec.rb +0 -100
  114. data/spec/core/environment_spec.rb +0 -144
  115. data/spec/core/equals_spec.rb +0 -319
  116. data/spec/core/goal_template_spec.rb +0 -74
  117. data/spec/core/outcome_spec.rb +0 -56
  118. data/spec/core/vocabulary_spec.rb +0 -220
  119. data/spec/glue/fresh_env_factory_spec.rb +0 -99
  120. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ # Load the class under test
6
+ require_relative '../../lib/mini_kraken/core/relation'
7
+
8
+
9
+ module MiniKraken
10
+ module Core
11
+ describe Relation do
12
+ subject { Relation.new('caro', 2) }
13
+
14
+ context 'Initialization:' do
15
+ it 'should be initialized with a name and an arity' do
16
+ expect { Relation.new('caro', Arity.new(2, 2)) }.not_to raise_error
17
+ end
18
+
19
+ it 'should be initialized with a name and an integer' do
20
+ expect { Relation.new('caro', 2) }.not_to raise_error
21
+ end
22
+
23
+ it 'should know its name' do
24
+ expect(subject.name).to eq('caro')
25
+ end
26
+
27
+ it 'should know its arity' do
28
+ expect(subject.arity).to eq(Arity.new(2, 2))
29
+ end
30
+ end # context
31
+ end # describe
32
+ end # module
33
+ end # module
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+ require_relative '../support/factory_atomic'
5
+
6
+ # Load the class under test
7
+ require_relative '../../lib/mini_kraken/core/scope'
8
+
9
+ module MiniKraken
10
+ module Core
11
+ describe Scope do
12
+ include MiniKraken::FactoryAtomic # Use mix-in module
13
+ let(:mother) { Scope.new }
14
+ subject { Scope.new(mother) }
15
+
16
+ def var(aName)
17
+ LogVar.new(aName)
18
+ end
19
+
20
+ context 'Initialization:' do
21
+ it 'could be initialized without argument' do
22
+ expect { Scope.new }.not_to raise_error
23
+ end
24
+
25
+ it 'could be initialized with a parent scope' do
26
+ expect { Scope.new(mother) }.not_to raise_error
27
+ end
28
+
29
+ it "shouldn't have definitions by default" do
30
+ expect(subject.defns).to be_empty
31
+ end
32
+
33
+ it 'should know its parent (if any)' do
34
+ expect(subject.parent).to eq(mother)
35
+ end
36
+ end # context
37
+
38
+ context 'Provided services:' do
39
+ it 'should accept the addition of a variable' do
40
+ subject.insert(var('a'))
41
+ expect(subject.defns).not_to be_empty
42
+ var_a = subject.defns['a']
43
+ expect(var_a).to be_kind_of(Core::LogVar)
44
+ expect(var_a.label).to eq('a')
45
+ end
46
+
47
+ it 'should accept the addition of multiple variables' do
48
+ subject.insert(var('a'))
49
+ expect(subject.defns).not_to be_empty
50
+
51
+ subject.insert(var('b'))
52
+ var_b = subject.defns['b']
53
+ expect(var_b).to be_kind_of(Core::LogVar)
54
+ expect(var_b.label).to eq('b')
55
+ end
56
+
57
+ it 'should set the suffix of just created variable' do
58
+ subject.insert(var('a'))
59
+ var_a = subject.defns['a']
60
+ expect(var_a.suffix).to eq("_#{subject.object_id.to_s(16)}")
61
+ end
62
+
63
+ it 'should complain when variable names collide' do
64
+ subject.insert(var('c'))
65
+ expect(subject.defns['c']).to be_kind_of(Core::LogVar)
66
+ err = StandardError
67
+ err_msg = "Variable with name 'c' already exists."
68
+ expect { subject.insert(var('c')) }.to raise_error(err, err_msg)
69
+ end
70
+ end # context
71
+ end # describe
72
+ end # module
73
+ end # module
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+ require 'singleton'
5
+
6
+ require_relative '../../lib/mini_kraken/core/context'
7
+
8
+ # Load the class under test
9
+ require_relative '../../lib/mini_kraken/core/solver_adapter'
10
+
11
+
12
+ module MiniKraken
13
+ module Core
14
+ describe SolverAdapter do
15
+ let(:ctx) { Context.new }
16
+ let(:fib) { make_fiber(ctx, true, true, false, nil) }
17
+ let(:blk) do
18
+ lambda do |adapter, _context|
19
+ adapter.adaptee.resume
20
+ end
21
+ end
22
+ subject { SolverAdapter.new(fib, &blk) }
23
+
24
+ # Factory method.
25
+ def make_fiber(ctx, *args)
26
+ Fiber.new do
27
+ signature = *args
28
+ signature.each do |outcome|
29
+ if outcome
30
+ Fiber.yield ctx.succeeded!
31
+ next
32
+ elsif outcome.nil?
33
+ Fiber.yield nil
34
+ break
35
+ else
36
+ Fiber.yield ctx.failed!
37
+ next
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'Initialization:' do
44
+ it 'should be initialized with a Fiber-like object' do
45
+ expect { SolverAdapter.new(fib, &blk) }.not_to raise_error
46
+ end
47
+
48
+ it 'should know its adaptee' do
49
+ expect(subject.adaptee).to eq(fib)
50
+ end
51
+ end # context
52
+
53
+ context 'Provided services:' do
54
+ it 'should respond to the resume message' do
55
+ result = subject.resume(ctx)
56
+ expect(result).to be_success
57
+
58
+ result = subject.resume(ctx)
59
+ expect(result).to be_success
60
+
61
+ result = subject.resume(ctx)
62
+ expect(result).to be_failure
63
+
64
+ result = subject.resume(ctx)
65
+ expect(result).to be_nil
66
+ end
67
+ end # context
68
+ end # describe
69
+ end # module
70
+ end # module
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ # Load the class under test
6
+ require_relative '../../lib/mini_kraken/core/specification'
7
+
8
+
9
+ module MiniKraken
10
+ module Core
11
+ describe Specification do
12
+ subject { Specification.new('cons', 2) }
13
+
14
+ context 'Initialization:' do
15
+ it 'should be initialized with a name and an arity' do
16
+ expect { Specification.new('cons', Arity.new(2, 2)) }.not_to raise_error
17
+ end
18
+
19
+ it 'should be initialized with a name and an integer' do
20
+ expect { Specification.new('cons', 2) }.not_to raise_error
21
+ end
22
+
23
+ it 'should know its name' do
24
+ expect(subject.name).to eq('cons')
25
+ end
26
+
27
+ it 'should know its arity' do
28
+ expect(subject.arity).to be_binary
29
+ end
30
+ end # context
31
+
32
+ context 'Provided services:' do
33
+ it "should complain when number of arguments does't fit arity" do
34
+ dummy_arg = double('dummy-stuff')
35
+
36
+ err = StandardError
37
+ err_msg = 'Count of arguments (1) is out of allowed range (2, 2).'
38
+ expect { subject.check_arity([dummy_arg]) }.to raise_error(err, err_msg)
39
+ end
40
+ end
41
+ end # describe
42
+ end # module
43
+ end # module
@@ -21,17 +21,17 @@ module MiniKraken
21
21
  end # context
22
22
 
23
23
  context 'Provided services:' do
24
- it 'should unconditionally return a success result' do
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(args, env) }.not_to raise_error
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(BasicSuccess)
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
@@ -22,14 +22,14 @@ module MiniKraken
22
22
  it 'passes frame 1:10' do
23
23
  # (run* q (== 'pea 'pod) ;; => ()
24
24
 
25
- result = run_star('q', equals(:pea, :pod))
25
+ result = run_star('q', unify(:pea, :pod))
26
26
  expect(result).to be_null
27
27
  end
28
28
 
29
29
  it 'passes frame 1:11' do
30
30
  # (run* q (== q 'pea) ;; => (pea)
31
31
 
32
- result = run_star('q', equals(q, :pea))
32
+ result = run_star('q', unify(q, :pea))
33
33
  expect(result.car).to eq(:pea)
34
34
  end
35
35
 
@@ -37,7 +37,7 @@ module MiniKraken
37
37
  # Reasoned S2, frame 1:12
38
38
  # (run* q (== 'pea q) ;; => (pea)
39
39
 
40
- result = run_star('q', equals(:pea, q))
40
+ result = run_star('q', unify(:pea, q))
41
41
  expect(result.car).to eq(:pea)
42
42
  end
43
43
 
@@ -52,14 +52,14 @@ module MiniKraken
52
52
  # Reasoned S2, frame 1:19
53
53
  # (run* q (== 'pea 'pea)) ;; => (_0)
54
54
 
55
- result = run_star('q', equals(:pea, :pea))
55
+ result = run_star('q', unify(:pea, :pea))
56
56
  expect(result.car).to eq(:_0)
57
57
  end
58
58
 
59
59
  it 'passes frame 1:20' do
60
60
  # (run* q (== q q)) ;; => (_0)
61
61
 
62
- result = run_star('q', equals(q, q))
62
+ result = run_star('q', unify(q, q))
63
63
  expect(result.car).to eq(:_0)
64
64
  end
65
65
 
@@ -67,28 +67,30 @@ module MiniKraken
67
67
  # Reasoned S2, frame 1:21
68
68
  # (run* q (fresh (x) (== 'pea q))) ;; => (pea)
69
69
 
70
- result = run_star('q', fresh('x', equals(:pea, q)))
70
+ result = run_star('q', fresh('x', unify(:pea, q)))
71
71
  expect(result.car).to eq(:pea)
72
72
  end
73
73
 
74
74
  it 'passes frame 1:25' do
75
- # (run* q (fresh (x) (== (cons x '()) q))) ;; => ((_0))
76
- # require 'debug' Invalid goal argument
77
- result = run_star('q', fresh('x', equals(cons(x, null), q)))
78
- expect(result.car).to eq(cons(:_0))
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)')
79
81
  end
80
82
 
81
83
  it 'passes frame 1:31' do
82
84
  # (run* q (fresh (x) (== x q))) ;; => (_0)
83
85
 
84
- result = run_star('q', fresh('x', equals(x, q)))
86
+ result = run_star('q', fresh('x', unify(x, q)))
85
87
  expect(result.car).to eq(:_0)
86
88
  end
87
89
 
88
90
  it 'passes frame 1:32' do
89
91
  # (run* q (== '(((pea)) pod) '(((pea)) pod))) ;; => (_0)
90
92
 
91
- result = run_star('q', equals(cons(cons(:pea), :pod), cons(cons(:pea), :pod)))
93
+ result = run_star('q', unify(cons(cons(:pea), :pod), cons(cons(:pea), :pod)))
92
94
  expect(result.car).to eq(:_0)
93
95
  end
94
96
 
@@ -96,7 +98,7 @@ module MiniKraken
96
98
  # Beware: quasiquoting
97
99
  # (run* q (== '(((pea)) pod) '(((pea)) ,q))) ;; => ('pod)
98
100
 
99
- result = run_star('q', equals(cons(cons(:pea), :pod), cons(cons(:pea), q)))
101
+ result = run_star('q', unify(cons(cons(:pea), :pod), cons(cons(:pea), q)))
100
102
  expect(result.car).to eq(:pod)
101
103
  end
102
104
 
@@ -107,14 +109,14 @@ module MiniKraken
107
109
  expect(expr1.to_s).to eq('(((q)) :pod)')
108
110
  expr2 = cons(cons(cons(:pea)), cons(:pod))
109
111
  expect(expr2.to_s).to eq('(((:pea)) :pod)')
110
- result = run_star('q', equals(expr1, expr2))
112
+ result = run_star('q', unify(expr1, expr2))
111
113
  expect(result.car).to eq(:pea)
112
114
  end
113
115
 
114
116
  it 'passes frame 1:35' do
115
117
  # (run* q (fresh (x) (== '(((,q)) pod) `(((,x)) pod)))) ;; => (_0)
116
118
 
117
- result = run_star('q', fresh('x', equals(cons(cons(q), :pod), cons(cons(x), :pod))))
119
+ result = run_star('q', fresh('x', unify(cons(cons(q), :pod), cons(cons(x), :pod))))
118
120
  expect(result.car).to eq(:_0)
119
121
  end
120
122
 
@@ -125,21 +127,21 @@ module MiniKraken
125
127
  expect(expr1.to_s).to eq('(((q)) x)')
126
128
  expr2 = cons(cons(cons(x)), cons(:pod))
127
129
  expect(expr2.to_s).to eq('(((x)) :pod)')
128
- result = run_star('q', fresh('x', equals(expr1, expr2)))
130
+ result = run_star('q', fresh('x', unify(expr1, expr2)))
129
131
  expect(result.car).to eq(:pod)
130
132
  end
131
133
 
132
134
  it 'passes frame 1:37' do
133
135
  # (run* q (fresh (x) (== '( ,x ,x) q))) ;; => (_0 _0)
134
136
 
135
- result = run_star('q', fresh('x', equals(cons(x, cons(x)), q)))
137
+ result = run_star('q', fresh('x', unify(cons(x, cons(x)), q)))
136
138
  expect(result.car).to eq(cons(:_0, cons(:_0)))
137
139
  end
138
140
 
139
141
  it 'passes frame 1:38' do
140
142
  # (run* q (fresh (x) (fresh (y) (== '( ,q ,y) '((,x ,y) ,x))))) ;; => (_0 _0)
141
143
 
142
- result = run_star('q', fresh('x', fresh('y', equals(cons(q, cons(y)), cons(cons(x, cons(y)), cons(x))))))
144
+ result = run_star('q', fresh('x', fresh('y', unify(cons(q, cons(y)), cons(cons(x, cons(y)), cons(x))))))
143
145
  expect(result.car).to eq(cons(:_0, cons(:_0)))
144
146
  end
145
147
 
@@ -147,7 +149,7 @@ module MiniKraken
147
149
  # Reasoned S2, frame 1:41
148
150
  # (run* q (fresh (x) (fresh (y) (== '( ,x ,y) q)))) ;; => (_0 _1)
149
151
 
150
- result = run_star('q', fresh('x', fresh('y', equals(cons(x, cons(y)), q))))
152
+ result = run_star('q', fresh('x', fresh('y', unify(cons(x, cons(y)), q))))
151
153
  # q should be bound to '(,x ,y)
152
154
  expect(result.car).to eq(cons(:_0, cons(:_1)))
153
155
  end
@@ -155,7 +157,7 @@ module MiniKraken
155
157
  it 'passes frame 1:42' do
156
158
  # (run* s (fresh (t) (fresh (u) (== '( ,t ,u) s)))) ;; => (_0 _1)
157
159
 
158
- result = run_star('s', fresh('t', fresh('u', equals(cons(t, cons(u)), s))))
160
+ result = run_star('s', fresh('t', fresh('u', unify(cons(t, cons(u)), s))))
159
161
  # s should be bound to '(,t ,u)
160
162
  expect(result.car).to eq(cons(:_0, cons(:_1)))
161
163
  end
@@ -163,7 +165,7 @@ module MiniKraken
163
165
  it 'passes frame 1:43' do
164
166
  # (run* q (fresh (x) (fresh (y) (== '( ,x ,y ,x) q)))) ;; => (_0 _1 _0)
165
167
 
166
- result = run_star('q', fresh('x', fresh('y', equals(cons(x, cons(y, cons(x))), q))))
168
+ result = run_star('q', fresh('x', fresh('y', unify(cons(x, cons(y, cons(x))), q))))
167
169
  # q should be bound to '(,x ,y, ,x)
168
170
  expect(result.car).to eq(cons(:_0, cons(:_1, cons(:_0))))
169
171
  end
@@ -179,14 +181,14 @@ module MiniKraken
179
181
  it 'passes frame 1:51' do
180
182
  # (run* q (conj2 succeed (== 'corn q)) ;; => ('corn)
181
183
 
182
- result = run_star('q', conj2(succeed, equals(:corn, q)))
184
+ result = run_star('q', conj2(succeed, unify(:corn, q)))
183
185
  expect(result.car).to eq(:corn)
184
186
  end
185
187
 
186
188
  it 'passes frame 1:52' do
187
189
  # (run* q (conj2 fail (== 'corn q)) ;; => ()
188
190
 
189
- result = run_star('q', conj2(_fail, equals(:corn, q)))
191
+ result = run_star('q', conj2(_fail, unify(:corn, q)))
190
192
  expect(result).to be_null
191
193
  end
192
194
 
@@ -194,14 +196,14 @@ module MiniKraken
194
196
  # Reasoned S2, frame 1:53
195
197
  # (run* q (conj2 (== 'corn q)(== 'meal q)) ;; => ()
196
198
 
197
- result = run_star('q', conj2(equals(:corn, q), equals(:meal, q)))
199
+ result = run_star('q', conj2(unify(:corn, q), unify(:meal, q)))
198
200
  expect(result).to be_null
199
201
  end
200
202
 
201
203
  it 'passes frame 1:54' do
202
204
  # (run* q (conj2 (== 'corn q)(== 'corn q)) ;; => ('corn)
203
205
 
204
- result = run_star('q', conj2(equals(:corn, q), equals(:corn, q)))
206
+ result = run_star('q', conj2(unify(:corn, q), unify(:corn, q)))
205
207
  expect(result.car).to eq(:corn)
206
208
  end
207
209
 
@@ -215,21 +217,21 @@ module MiniKraken
215
217
  it 'passes frame 1:56' do
216
218
  # (run* q (disj2 (== 'olive q) fail)) ;; => ('olive)
217
219
 
218
- result = run_star('q', disj2(equals(:olive, q), _fail))
220
+ result = run_star('q', disj2(unify(:olive, q), _fail))
219
221
  expect(result.car).to eq(:olive)
220
222
  end
221
223
 
222
224
  it 'passes frame 1:57' do
223
225
  # (run* q (disj2 fail (== 'oil q))) ;; => (oil)
224
226
 
225
- result = run_star('q', disj2(_fail, equals(:oil, q)))
227
+ result = run_star('q', disj2(_fail, unify(:oil, q)))
226
228
  expect(result.car).to eq(:oil)
227
229
  end
228
230
 
229
231
  it 'passes frame 1:58' do
230
232
  # (run* q (disj2 (== 'olive q) (== 'oil q))) ;; => (olive oil)
231
233
 
232
- result = run_star('q', disj2(equals(:olive, q), equals(:oil, q)))
234
+ result = run_star('q', disj2(unify(:olive, q), unify(:oil, q)))
233
235
  expect(result.car).to eq(:olive)
234
236
  expect(result.cdr.car).to eq(:oil)
235
237
  end
@@ -238,7 +240,7 @@ module MiniKraken
238
240
  # (run* q (fresh (x) (fresh (y) (disj2 (== '( ,x ,y ) q) (== '( ,x ,y ) q)))))
239
241
  # ;; => ((_0 _1) (_0 _1))
240
242
 
241
- result = run_star('q', fresh('x', (fresh 'y', disj2(equals(cons(x, cons(y)), q), equals(cons(x, cons(y)), q)))))
243
+ result = run_star('q', fresh('x', (fresh 'y', disj2(unify(cons(x, cons(y)), q), unify(cons(x, cons(y)), q)))))
242
244
  # q should be bound to '(,x ,y), then to '(,y ,x)
243
245
  expect(result.car).to eq(cons(:_0, cons(:_1)))
244
246
  expect(result.cdr.car).to eq(cons(:_0, cons(:_1)))
@@ -249,7 +251,7 @@ module MiniKraken
249
251
  # (conj2 (== 'olive x) fail)
250
252
  # (== 'oil x))) ;; => (oil)
251
253
 
252
- result = run_star('x', disj2(conj2(equals(:olive, x), _fail), equals(:oil, x)))
254
+ result = run_star('x', disj2(conj2(unify(:olive, x), _fail), unify(:oil, x)))
253
255
  expect(result.car).to eq(:oil)
254
256
  end
255
257
 
@@ -258,7 +260,7 @@ module MiniKraken
258
260
  # (conj2 (== 'olive x) succeed)
259
261
  # ('oil x))) ;; => (olive oil)
260
262
 
261
- result = run_star('x', disj2(conj2(equals(:olive, x), succeed), equals(:oil, x)))
263
+ result = run_star('x', disj2(conj2(unify(:olive, x), succeed), unify(:oil, x)))
262
264
  expect(result).to eq(cons(:olive, cons(:oil)))
263
265
  end
264
266
 
@@ -267,7 +269,7 @@ module MiniKraken
267
269
  # (== 'oil x)
268
270
  # (conj2 (== 'olive x) succeed))) ;; => (oil olive)
269
271
 
270
- result = run_star('x', disj2(equals(:oil, x), conj2(equals(:olive, x), succeed)))
272
+ result = run_star('x', disj2(unify(:oil, x), conj2(unify(:olive, x), succeed)))
271
273
  expect(result).to eq(cons(:oil, cons(:olive)))
272
274
  end
273
275
 
@@ -280,9 +282,10 @@ module MiniKraken
280
282
  # succeed
281
283
  # (== 'oil x))))) ;; => (olive _0 oil)
282
284
 
283
- result = run_star('x', disj2(conj2(equals(:virgin, x), _fail),
284
- disj2(equals(:olive, x), disj2(succeed, equals(:oil, x)))))
285
+ result = run_star('x', disj2(conj2(unify(:virgin, x), _fail),
286
+ disj2(unify(:olive, x), disj2(succeed, unify(:oil, x)))))
285
287
  expect(result).to eq(cons(:olive, cons(:_0, cons(:oil))))
288
+ expect(result.to_s).to eq('(:olive _0 :oil)')
286
289
  end
287
290
 
288
291
  it 'passes frame 1:67' do
@@ -296,9 +299,9 @@ module MiniKraken
296
299
  # (== '(,x ,y) r)))))) ;; => ((split pea))
297
300
 
298
301
  result = run_star('r', fresh('x', fresh('y',
299
- conj2(equals(:split, x),
300
- conj2(equals(:pea, y), equals(cons(x, cons(y)), r))))))
301
- expect(result).to eq(cons(cons(:split, cons(:pea))))
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))')
302
305
  end
303
306
 
304
307
  it 'passes frame 1:68' do
@@ -312,9 +315,9 @@ module MiniKraken
312
315
  # (== '(,x ,y) r)))))) ;; => ((split pea))
313
316
 
314
317
  result = run_star('r', fresh('x', fresh('y',
315
- conj2(conj2(equals(:split, x), equals(:pea, y)),
316
- equals(cons(x, cons(y)), r)))))
317
- expect(result).to eq(cons(cons(:split, cons(:pea))))
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))')
318
321
  end
319
322
 
320
323
  it 'passes frame 1:70' do
@@ -327,9 +330,9 @@ module MiniKraken
327
330
  # (== '(,x ,y) r))))) ;; => ((split pea))
328
331
 
329
332
  result = run_star('r', fresh(%w[x y], conj2(
330
- conj2(equals(:split, x), equals(:pea, y)),
331
- equals(cons(x, cons(y)), r))))
332
- expect(result).to eq(cons(cons(:split, cons(:pea))))
333
+ conj2(unify(:split, x), unify(:pea, y)),
334
+ unify(cons(x, cons(y)), r))))
335
+ expect(result.to_s).to eq('((:split :pea))')
333
336
  end
334
337
 
335
338
  it 'passes frame 1:72' do
@@ -354,14 +357,15 @@ module MiniKraken
354
357
  # pea nil pea nil
355
358
 
356
359
  result = run_star(%w[r x y], conj2(
357
- conj2(equals(:split, x), equals(:pea, y)),
358
- equals(cons(x, cons(y)), r)))
360
+ conj2(unify(:split, x), unify(:pea, y)),
361
+ unify(cons(x, cons(y)), r)))
359
362
  expect(result.car.car.car).to eq(:split)
360
363
  expect(result.car.car.cdr.car).to eq(:pea)
361
364
  expect(result.car.car.cdr.cdr).to be_nil
362
365
  expect(result.car.cdr.car).to eq(:split)
363
366
  expect(result.car.cdr.cdr.car).to eq(:pea)
364
367
  expect(result.car.cdr.cdr.cdr).to be_nil
368
+ expect(result.to_s).to eq('(((:split :pea) :split :pea))')
365
369
  end
366
370
 
367
371
  it 'passes frame 1:75' do
@@ -370,8 +374,8 @@ module MiniKraken
370
374
  # (== 'split x)
371
375
  # (== 'pea y))) ;; => ((split pea))
372
376
 
373
- result = run_star(%w[x y], conj2(equals(:split, x), equals(:pea, y)))
374
- expect(result.car).to eq(list(:split, :pea))
377
+ result = run_star(%w[x y], conj2(unify(:split, x), unify(:pea, y)))
378
+ expect(result.to_s).to eq('((:split :pea))')
375
379
  end
376
380
 
377
381
  it 'passes frame 1:76' do
@@ -381,8 +385,9 @@ module MiniKraken
381
385
  # (conj2 (== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
382
386
 
383
387
  result = run_star(%w[x y], disj2(
384
- conj2(equals(:split, x), equals(:pea, y)),
385
- conj2(equals(:red, x), equals(:bean, y))))
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))')
386
391
  expect(result.car).to eq(list(:split, :pea))
387
392
  expect(result.cdr.car).to eq(list(:red, :bean))
388
393
  end
@@ -399,9 +404,10 @@ module MiniKraken
399
404
  result = run_star('r',
400
405
  fresh(%w[x y], conj2(
401
406
  disj2(
402
- conj2(equals(:split, x), equals(:pea, y)),
403
- conj2(equals(:red, x), equals(:bean, y))),
404
- equals(cons(x, cons(y, cons(:soup))), r))))
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))')
405
411
  expect(result.car).to eq(list(:split, :pea, :soup))
406
412
  expect(result.cdr.car).to eq(list(:red, :bean, :soup))
407
413
  end
@@ -416,11 +422,10 @@ module MiniKraken
416
422
 
417
423
  result = run_star('r',
418
424
  fresh(%w[x y], [disj2(
419
- conj2(equals(:split, x), equals(:pea, y)),
420
- conj2(equals(:red, x), equals(:bean, y))),
421
- equals(cons(x, cons(y, cons(:soup))), r)]))
422
- expect(result.car).to eq(list(:split, :pea, :soup))
423
- 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))')
424
429
  end
425
430
 
426
431
  it 'passes frame 1:80' do
@@ -431,9 +436,9 @@ module MiniKraken
431
436
  # (== 'soup z)) ;; => ((split pea soup) (red bean soup))
432
437
 
433
438
  result = run_star(%w[x y z], [disj2(
434
- conj2(equals(:split, x), equals(:pea, y)),
435
- conj2(equals(:red, x), equals(:bean, y))),
436
- equals(:soup, z)])
439
+ conj2(unify(:split, x), unify(:pea, y)),
440
+ conj2(unify(:red, x), unify(:bean, y))),
441
+ unify(:soup, z)])
437
442
  expect(result.car).to eq(list(:split, :pea, :soup))
438
443
  expect(result.cdr.car).to eq(list(:red, :bean, :soup))
439
444
  end
@@ -443,42 +448,26 @@ module MiniKraken
443
448
  # (== 'split x)
444
449
  # (== 'pea y)) ;; => ((split pea))
445
450
 
446
- result = run_star(%w[x y], [equals(:split, x), equals(:pea, y)])
451
+ result = run_star(%w[x y], [unify(:split, x), unify(:pea, y)])
447
452
  expect(result.car).to eq(list(:split, :pea))
448
453
  end
449
454
 
450
455
  it "supports 'defrel' and passes frame 1:82" do
451
456
  # (defrel (teacupo t)
452
457
  # (disj2 (== 'tea t) (== 'cup t)))
453
-
454
- result = defrel('teacupo', 't') do
455
- disj2(equals(:tea, t), equals(:cup, t))
456
- end
457
-
458
- 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)
459
461
  expect(result.name).to eq('teacupo')
460
462
  expect(result.formals.size).to eq(1)
461
- expect(result.formals[0].name).to eq('t')
462
- g_template = result.goal_template
463
- expect(g_template).to be_kind_of(Core::GoalTemplate)
464
- expect(g_template.relation).to eq(Core::Disj2.instance)
465
-
466
- first_arg = g_template.args[0]
467
- expect(first_arg).to be_kind_of(Core::GoalTemplate)
468
- expect(first_arg.relation).to eq(Core::Equals.instance)
469
- expect(first_arg.args[0]).to eq(:tea)
470
- expect(first_arg.args[1]).to be_kind_of(Core::FormalRef)
471
- expect(first_arg.args[1].name).to eq('t')
472
- second_arg = g_template.args[1]
473
- expect(second_arg).to be_kind_of(Core::GoalTemplate)
474
- expect(second_arg.relation).to eq(Core::Equals.instance)
475
- expect(second_arg.args[0]).to eq(:cup)
476
- expect(second_arg.args[1]).to be_kind_of(Core::FormalRef)
477
- 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)
478
467
  end
479
468
 
480
- def defrel_teacupo
481
- defrel('teacupo', 't') { disj2(equals(:tea, t), equals(:cup, t)) }
469
+ let(:defrel_teacupo) do
470
+ defrel('teacupo', ['t'], disj2(unify(:tea, t), unify(:cup, t)))
482
471
  end
483
472
 
484
473
  it "supports the invokation of a 'defrel' and passes frame 1:83" do
@@ -502,8 +491,8 @@ module MiniKraken
502
491
  defrel_teacupo
503
492
  result = run_star(%w[x y],
504
493
  disj2(
505
- conj2(teacupo(x), equals('#t', y)),
506
- conj2(equals('#f', x), equals('#t', y))))
494
+ conj2(teacupo(x), unify('#t', y)),
495
+ conj2(unify('#f', x), unify('#t', y))))
507
496
 
508
497
  # Order of solutions differs from RS book
509
498
  expect(result.car).to eq(cons(:tea, cons(true)))
@@ -544,7 +533,7 @@ module MiniKraken
544
533
  defrel_teacupo
545
534
  result = run_star(%w[x y], disj2(
546
535
  conj2(teacupo(x), teacupo(x)),
547
- conj2(equals('#f', x), teacupo(y))))
536
+ conj2(unify('#f', x), teacupo(y))))
548
537
 
549
538
  # Order of solutions differs from RS book
550
539
  expected = '((:tea _0) (:cup _0) (false :tea) (false :cup))'
@@ -564,7 +553,7 @@ module MiniKraken
564
553
  defrel_teacupo
565
554
  result = run_star(%w[x y], conde(
566
555
  [teacupo(x), teacupo(x)],
567
- [equals('#f', x), teacupo(y)]))
556
+ [unify('#f', x), teacupo(y)]))
568
557
 
569
558
  # Order of solutions differs from RS book
570
559
  expected = '((:tea _0) (:cup _0) (false :tea) (false :cup))'
@@ -578,8 +567,8 @@ module MiniKraken
578
567
  # ((== 'split x) (== 'pea y))
579
568
  # ((== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
580
569
  result = run_star(%w[x y], conde(
581
- [equals(:split, x), equals(:pea, y)],
582
- [equals(:red, x), equals(:bean, y)]))
570
+ [unify(:split, x), unify(:pea, y)],
571
+ [unify(:red, x), unify(:bean, y)]))
583
572
 
584
573
  expected = '((:split :pea) (:red :bean))'
585
574
  expect(result.to_s).to eq(expected)
@@ -593,8 +582,8 @@ module MiniKraken
593
582
  # ('oil x))) ;; => (oil)
594
583
 
595
584
  result = run_star('x', conde(
596
- [equals(:olive, x), _fail],
597
- equals(:oil, x)))
585
+ [unify(:olive, x), _fail],
586
+ unify(:oil, x)))
598
587
 
599
588
  expect(result.to_s).to eq('(:oil)')
600
589
  end
@@ -607,8 +596,8 @@ module MiniKraken
607
596
  # ((== x y)))) ;; => ((_0 _1)(_0 _0))
608
597
 
609
598
  result = run_star(%w[x y], conde(
610
- [fresh(%w[z], equals(:lentil, z))],
611
- [equals(x, y)]))
599
+ [fresh(%w[z], unify(:lentil, z))],
600
+ [unify(x, y)]))
612
601
 
613
602
  expect(result.to_s).to eq('((_0 _1) (_0 _0))')
614
603
  end
@@ -621,9 +610,9 @@ module MiniKraken
621
610
  # ((== 'green x) (== 'lentil y))))
622
611
  # ;; => ((split pea)(red bean)(green lentil))
623
612
  result = run_star(%w[x y], conde(
624
- [equals(:split, x), equals(:pea, y)],
625
- [equals(:red, x), equals(:bean, y)],
626
- [equals(:green, x), equals(:lentil, y)]))
613
+ [unify(:split, x), unify(:pea, y)],
614
+ [unify(:red, x), unify(:bean, y)],
615
+ [unify(:green, x), unify(:lentil, y)]))
627
616
 
628
617
  expected = '((:split :pea) (:red :bean) (:green :lentil))'
629
618
  expect(result.to_s).to eq(expected)