mini_kraken 0.2.02 → 0.2.03

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.
@@ -17,6 +17,7 @@ require_relative '../../lib/mini_kraken/core/def_relation'
17
17
  module MiniKraken
18
18
  module Core
19
19
  describe DefRelation do
20
+ # (defrel (teao t) (== 'tea t))
20
21
  let(:tea) { KSymbol.new(:tea) }
21
22
  let(:formal_t) { FormalArg.new('t') }
22
23
  let(:t_ref) { FormalRef.new('t') }
@@ -53,13 +54,13 @@ module MiniKraken
53
54
  defrel = DefRelation.new('teao', equals_tea, [formal_t])
54
55
  solver = defrel.solver_for([tea], env)
55
56
  outcome = solver.resume
56
- expect(outcome).to be_successful
57
+ expect(outcome).to be_success
57
58
  outcome = solver.resume
58
59
  expect(outcome).to be_nil
59
60
 
60
61
  solver = defrel.solver_for([cup], env)
61
62
  outcome = solver.resume
62
- expect(outcome).not_to be_successful
63
+ expect(outcome).not_to be_success
63
64
  outcome = solver.resume
64
65
  expect(outcome).to be_nil
65
66
  end
@@ -69,7 +70,7 @@ module MiniKraken
69
70
  env.add_var(Variable.new('x'))
70
71
  solver = defrel.solver_for([ref_x], env)
71
72
  outcome = solver.resume
72
- expect(outcome).to be_successful
73
+ expect(outcome).to be_success
73
74
  expect(ref_x.value(outcome)).to eq(tea)
74
75
 
75
76
  outcome = solver.resume
@@ -80,11 +81,11 @@ module MiniKraken
80
81
  env.add_var(Variable.new('x'))
81
82
  solver = subject.solver_for([ref_x], env)
82
83
  outcome = solver.resume
83
- expect(outcome).to be_successful
84
+ expect(outcome).to be_success
84
85
  expect(ref_x.value(outcome)).to eq(tea)
85
86
 
86
87
  outcome = solver.resume
87
- expect(outcome).to be_successful
88
+ expect(outcome).to be_success
88
89
  expect(ref_x.value(outcome)).to eq(cup)
89
90
 
90
91
  outcome = solver.resume
@@ -52,7 +52,7 @@ module MiniKraken
52
52
  it 'should fails if both arguments fail' do
53
53
  # Covers frame 1:55
54
54
  solver = subject.solver_for([fails, fails], env)
55
- expect(solver.resume).not_to be_successful
55
+ expect(solver.resume).not_to be_success
56
56
  expect(solver.resume).to be_nil
57
57
  end
58
58
 
@@ -61,7 +61,7 @@ module MiniKraken
61
61
  subgoal = Goal.new(Equals.instance, [olive, ref_q])
62
62
  solver = subject.solver_for([subgoal, fails], env)
63
63
  outcome = solver.resume
64
- expect(outcome).to be_successful
64
+ expect(outcome).to be_success
65
65
  expect(outcome.associations['q'].first.value).to eq(olive)
66
66
  expect(solver.resume).to be_nil
67
67
  end
@@ -71,7 +71,7 @@ module MiniKraken
71
71
  subgoal = Goal.new(Equals.instance, [oil, ref_q])
72
72
  solver = subject.solver_for([fails, subgoal], env)
73
73
  outcome = solver.resume
74
- expect(outcome).to be_successful
74
+ expect(outcome).to be_success
75
75
  expect(outcome.associations['q'].first.value).to eq(oil)
76
76
  expect(solver.resume).to be_nil
77
77
  end
@@ -84,12 +84,12 @@ module MiniKraken
84
84
 
85
85
  # First solution
86
86
  outcome1 = solver.resume
87
- expect(outcome1).to be_successful
87
+ expect(outcome1).to be_success
88
88
  expect(outcome1.associations['q'].first.value).to eq(olive)
89
89
 
90
90
  # Second solution
91
91
  outcome2 = solver.resume
92
- expect(outcome2).to be_successful
92
+ expect(outcome2).to be_success
93
93
  expect(outcome2.associations['q'].first.value).to eq(oil)
94
94
  expect(solver.resume).to be_nil
95
95
  end
@@ -40,7 +40,7 @@ module MiniKraken
40
40
  succeeding = DuckFiber.new(:success)
41
41
  outcome = nil
42
42
  expect { outcome = succeeding.resume }.not_to raise_error
43
- expect(outcome).to be_successful
43
+ expect(outcome).to be_success
44
44
  expect(outcome.parent).to be_nil
45
45
 
46
46
  # Only one result should be yielded
@@ -106,7 +106,7 @@ module MiniKraken
106
106
  it 'should succeed for a right-handed fresh argument' do
107
107
  result = solve_for(pea, ref_q)
108
108
 
109
- expect(result).to be_successful
109
+ expect(result).to be_success
110
110
  expect(env.associations.size).to eq(1)
111
111
  expect(env.associations['q'].first.value).to eq(pea)
112
112
  expect(var_q.fresh?(result)).to be_falsey
@@ -116,7 +116,7 @@ module MiniKraken
116
116
  it 'should succeed for a left-handed fresh argument' do
117
117
  result = solve_for(ref_q, pea)
118
118
 
119
- expect(result).to be_successful
119
+ expect(result).to be_success
120
120
  expect(env.associations.size).to eq(1)
121
121
  expect(env.associations['q'].first.value).to eq(pea)
122
122
  expect(var_q.fresh?(result)).to be_falsey
@@ -127,7 +127,7 @@ module MiniKraken
127
127
  ref_q.associate(pod, env)
128
128
 
129
129
  result = solve_for(pod, ref_q)
130
- expect(result).to be_successful
130
+ expect(result).to be_success
131
131
  expect(env.associations.size).to eq(1) # No new association
132
132
  expect(ref_q.fresh?(result)).not_to be_truthy
133
133
  expect(ref_q.values(result).first).to eq(pod)
@@ -137,7 +137,7 @@ module MiniKraken
137
137
  ref_q.associate(pod, env)
138
138
 
139
139
  result = solve_for(ref_q, pod)
140
- expect(result).to be_successful
140
+ expect(result).to be_success
141
141
  expect(result.associations).to be_empty
142
142
  expect(ref_q.fresh?(result)).to be_falsey
143
143
  expect(ref_q.values(result).first).to eq(pod)
@@ -147,7 +147,7 @@ module MiniKraken
147
147
  ref_q.associate(pod, env)
148
148
 
149
149
  result = solve_for(pea, ref_q)
150
- expect(result).not_to be_successful
150
+ expect(result).not_to be_success
151
151
  expect(result.associations).to be_empty
152
152
  expect(ref_q.fresh?(result)).to be_falsey
153
153
  expect(ref_q.values(result).first).to eq(pod)
@@ -157,7 +157,7 @@ module MiniKraken
157
157
  ref_q.associate(pod, env)
158
158
 
159
159
  result = solve_for(ref_q, pea)
160
- expect(result).not_to be_successful
160
+ expect(result).not_to be_success
161
161
  expect(result.associations).to be_empty
162
162
  expect(ref_q.fresh?(result)).to be_falsey
163
163
  expect(ref_q.values(result).first).to eq(pod)
@@ -166,7 +166,7 @@ module MiniKraken
166
166
  it 'should succeed for a composite and right-handed fresh argument' do
167
167
  result = solve_for(sample_cons, ref_q)
168
168
 
169
- expect(result).to be_successful
169
+ expect(result).to be_success
170
170
  expect(env.associations.size).to eq(1)
171
171
  expect(ref_q.fresh?(result)).to be_falsey
172
172
  expect(ref_q.values(result).first).to eq(sample_cons)
@@ -175,7 +175,7 @@ module MiniKraken
175
175
  it 'should succeed for composite and left-handed fresh argument' do
176
176
  result = solve_for(ref_q, sample_cons)
177
177
 
178
- expect(result).to be_successful
178
+ expect(result).to be_success
179
179
  expect(env.associations.size).to eq(1)
180
180
  expect(ref_q.fresh?(result)).to be_falsey
181
181
  expect(ref_q.values(result).first).to eq(sample_cons)
@@ -186,7 +186,7 @@ module MiniKraken
186
186
  composite = ConsCell.new(pea)
187
187
  result = solve_for(composite, ref_q)
188
188
 
189
- expect(result).to be_successful
189
+ expect(result).to be_success
190
190
  expect(result.associations).to be_empty
191
191
  expect(ref_q.fresh?(result)).not_to be_truthy
192
192
  expect(ref_q.values(result).first).to eq(sample_cons)
@@ -197,7 +197,7 @@ module MiniKraken
197
197
  composite = ConsCell.new(pea)
198
198
  result = solve_for(ref_q, composite)
199
199
 
200
- expect(result).to be_successful
200
+ expect(result).to be_success
201
201
  expect(result.associations).to be_empty
202
202
  expect(ref_q.fresh?(result)).not_to be_truthy
203
203
  expect(ref_q.values(result).first).to eq(sample_cons)
@@ -208,7 +208,7 @@ module MiniKraken
208
208
  composite = ConsCell.new(pod)
209
209
  result = solve_for(composite, ref_q)
210
210
 
211
- expect(result).not_to be_successful
211
+ expect(result).to be_failure
212
212
  expect(result.associations).to be_empty
213
213
  expect(ref_q.fresh?(result)).not_to be_truthy
214
214
  expect(ref_q.values(result).first).to eq(sample_cons)
@@ -219,7 +219,7 @@ module MiniKraken
219
219
  composite = ConsCell.new(pod)
220
220
  result = solve_for(ref_q, composite)
221
221
 
222
- expect(result).not_to be_successful
222
+ expect(result).not_to be_success
223
223
  expect(result.associations).to be_empty
224
224
  expect(ref_q.fresh?(result)).not_to be_truthy
225
225
  expect(ref_q.values(result).first).to eq(sample_cons)
@@ -228,7 +228,7 @@ module MiniKraken
228
228
  it 'should succeed for both identical fresh arguments' do
229
229
  result = solve_for(ref_q, ref_q)
230
230
 
231
- expect(result).to be_successful
231
+ expect(result).to be_success
232
232
  expect(result.associations).to be_empty
233
233
  expect(ref_q.fresh?(result)).to be_truthy
234
234
  end
@@ -236,7 +236,7 @@ module MiniKraken
236
236
  it 'should succeed for both same fresh arguments' do
237
237
  result = solve_for(ref_q, ref_q_bis)
238
238
 
239
- expect(result).to be_successful
239
+ expect(result).to be_success
240
240
  expect(result.associations).to be_empty
241
241
  expect(ref_q.fresh?(result)).to be_truthy
242
242
  expect(ref_q_bis.fresh?(result)).to be_truthy
@@ -245,7 +245,7 @@ module MiniKraken
245
245
  it 'should succeed for both distinct fresh arguments' do
246
246
  result = solve_for(ref_x, ref_y)
247
247
 
248
- expect(result).to be_successful
248
+ expect(result).to be_success
249
249
  expect(env.associations).to be_empty # Symmetric association
250
250
  expect(ref_x.fresh?(result)).to be_truthy
251
251
  expect(ref_y.fresh?(result)).to be_truthy
@@ -258,7 +258,7 @@ module MiniKraken
258
258
  expect(ref_y.fresh?(env)).to be_falsey
259
259
 
260
260
  result = solve_for(ref_x, ref_y)
261
- expect(result).to be_successful
261
+ expect(result).to be_success
262
262
  expect(result.associations).to be_empty
263
263
  end
264
264
 
@@ -269,19 +269,20 @@ module MiniKraken
269
269
  expect(ref_y.fresh?(env)).to be_falsey
270
270
 
271
271
  result = solve_for(ref_x, ref_y)
272
- expect(result).not_to be_successful
272
+ expect(result).not_to be_success
273
273
  expect(result.associations).to be_empty
274
274
  end
275
275
 
276
276
  it 'should unify composite terms with variables' do
277
277
  # Reasoned S2, frame 1:36
278
278
  # (run* q (fresh (x) (== '(((,q)) ,x) `(((,x)) pod)))) ;; => ('pod)
279
- expr1 = cons(cons(cons(ref_q)), ref_x)
280
- expr2 = cons(cons(cons(ref_x)), pod)
279
+ expr1 = cons(cons(cons(ref_q)), cons(ref_x))
280
+ expect(expr1.to_s).to eq('(((q)) x)')
281
+ expr2 = cons(cons(cons(ref_x)), cons(pod))
282
+ expect(expr2.to_s).to eq('(((x)) :pod)')
281
283
 
282
284
  result = solve_for(expr1, expr2)
283
- # require 'debug'
284
- expect(result).to be_successful
285
+ expect(result).to be_success
285
286
  expect(ref_x.fresh?(env)).to be_falsey
286
287
  expect(ref_q.fresh?(env)).to be_falsey
287
288
  end
@@ -298,6 +299,18 @@ module MiniKraken
298
299
  expect(result.resultant).to eq(:"#u")
299
300
  expect(result.associations).to be_empty
300
301
  end
302
+
303
+ it 'should unify variables with a list' do
304
+ # Variant of Reasoned S2, frame 2:3
305
+ # (== (cons q x) '(a c o r n)) ;; q => :a, x => '(c o r n)
306
+ expr1 = cons(ref_q, ref_x)
307
+ acorn = cons(k_symbol(:a), cons(k_symbol(:c),
308
+ cons(k_symbol(:o), cons(k_symbol(:r), cons(k_symbol(:n))))))
309
+ result = solve_for(expr1, acorn)
310
+ expect(result.resultant).to eq(:"#s")
311
+ q_value = env.associations['q'].first.value
312
+ expect(q_value).to eq(:a)
313
+ end
301
314
  end # context
302
315
  end # describe
303
316
  end # module
@@ -40,7 +40,7 @@ module MiniKraken
40
40
  context 'Provided services:' do
41
41
  it 'should fail if relation does not succeed' do
42
42
  solver = subject.attain(env)
43
- expect(solver.resume).not_to be_successful
43
+ expect(solver.resume).not_to be_success
44
44
 
45
45
  # No more solution...
46
46
  expect(solver.resume).to be_nil
@@ -50,7 +50,7 @@ module MiniKraken
50
50
  instance = Goal.new(binary_relation, [KSymbol.new(:pea), KSymbol.new(:pea)])
51
51
 
52
52
  solver = instance.attain(env)
53
- expect(solver.resume).to be_successful
53
+ expect(solver.resume).to be_success
54
54
 
55
55
  # No more solution...
56
56
  expect(solver.resume).to be_nil
@@ -25,6 +25,14 @@ module MiniKraken
25
25
  expect(subject.resultant).to eq(:"#s")
26
26
  end
27
27
 
28
+ it 'should know whether it represents a failure' do
29
+ expect(Outcome.new(:"#u")).to be_failure
30
+ end
31
+
32
+ it 'should know whether it represents a success' do
33
+ expect(subject).to be_success
34
+ end
35
+
28
36
  it 'should know its parent' do
29
37
  expect(subject.parent).to eq(voc)
30
38
  end
@@ -21,6 +21,9 @@ module MiniKraken
21
21
  end # context
22
22
 
23
23
  context 'Provided services:' do
24
+ it 'knows its text representation' do
25
+ expect(subject.to_s).to eq('q')
26
+ end
24
27
  end # context
25
28
  end # describe
26
29
  end # module
@@ -113,7 +113,11 @@ module MiniKraken
113
113
  # Reasoned S2, frame 1:34
114
114
  # (run* q (== '(((,q)) pod) `(((pea)) pod))) ;; => ('pea)
115
115
 
116
- result = run_star('q', equals(cons(cons(q), :pod), cons(cons(:pea), q)))
116
+ expr1 = cons(cons(cons(q)), cons(:pod))
117
+ expect(expr1.to_s).to eq('(((q)) :pod)')
118
+ expr2 = cons(cons(cons(:pea)), cons(:pod))
119
+ expect(expr2.to_s).to eq('(((:pea)) :pod)')
120
+ result = run_star('q', equals(expr1, expr2))
117
121
  expect(result.car).to eq(:pea)
118
122
  end
119
123
 
@@ -129,7 +133,11 @@ module MiniKraken
129
133
  # Reasoned S2, frame 1:36
130
134
  # (run* q (fresh (x) (== '(((,q)) ,x) `(((,x)) pod)))) ;; => ('pod)
131
135
 
132
- result = run_star('q', fresh('x', equals(cons(cons(cons(q)), x), cons(cons(cons(x)), :pod))))
136
+ expr1 = cons(cons(cons(q)), cons(x))
137
+ expect(expr1.to_s).to eq('(((q)) x)')
138
+ expr2 = cons(cons(cons(x)), cons(:pod))
139
+ expect(expr2.to_s).to eq('(((x)) :pod)')
140
+ result = run_star('q', fresh('x', equals(expr1, expr2)))
133
141
  expect(result.car).to eq(:pod)
134
142
  end
135
143
 
@@ -0,0 +1,100 @@
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/glue/dsl'
7
+
8
+
9
+ module MiniKraken
10
+ module Glue
11
+ describe 'DSL (Chap 2)' do
12
+ include DSL
13
+
14
+ context 'Chapter 2 examples:' do
15
+ let(:acorn) { cons(:a, cons(:c, cons(:o, cons(:r, cons(:n))))) }
16
+
17
+ it 'accepts caro definition inspired from frame 2:6' do
18
+ # Reasoned S2, frame 2:6
19
+ # (defrel (caro p a)
20
+ # (fresh (d)
21
+ # (== (cons a d) p)))
22
+
23
+ # As 'p' has a special meaning in Ruby, the argument has been remaned to 'r'
24
+ caro_rel = defrel('caro', %w[r a]) do
25
+ fresh('d', equals(cons(a, d), r))
26
+ end
27
+
28
+ expect(caro_rel).to be_kind_of(Core::DefRelation)
29
+ expect(caro_rel.name).to eq('caro')
30
+ expect(caro_rel.arity).to eq(2)
31
+ expect(caro_rel.formals[0].name).to eq('r')
32
+ expect(caro_rel.formals[1].name).to eq('a')
33
+ g_template = caro_rel.goal_template
34
+ expect(g_template).to be_kind_of(FreshEnvFactory)
35
+ expect(g_template.names).to include('d')
36
+ end
37
+
38
+ # In Scheme:
39
+ # (defrel (caro p a)
40
+ # (fresh (d)
41
+ # (== (cons a d) p)))
42
+ # In Ruby, `p`is a stnadard Kernel method => replaced by `r`
43
+ def defrel_caro
44
+ defrel('caro', %w[r a]) { fresh('d', equals(cons(a, d), r)) }
45
+ end
46
+
47
+ it 'passes frame 2:3' do
48
+ defrel_caro
49
+
50
+ # (run* q
51
+ # (caro '(a c o r n) q)) ;; => (a)
52
+ result = run_star('q', caro(acorn, q))
53
+ expect(result.car).to eq(:a)
54
+ end
55
+
56
+ it 'passes frame 2:4' do
57
+ defrel_caro
58
+
59
+ # (run* q
60
+ # (caro '(a c o r n) 'a)) ;; => (_0)
61
+ result = run_star('q', caro(acorn, :a))
62
+ expect(result.car).to eq(:_0)
63
+ end
64
+
65
+ it 'passes frame 2:5' do
66
+ defrel_caro
67
+
68
+ # (run* r
69
+ # (fresh (x y)
70
+ # (caro '(,r ,y) x)
71
+ # (== 'pear x)));; r => (pear)
72
+ result = run_star('r', fresh(%w[x y],
73
+ [caro(cons(r, cons(y)), x),
74
+ equals(:pear, x)]))
75
+ expect(result.car).to eq(:pear)
76
+ end
77
+
78
+ it 'passes frame 2:8' do
79
+ defrel_caro
80
+
81
+ # (run* r
82
+ # (fresh (x y)
83
+ # (caro '(grape raisin pear) x)
84
+ # (caro '((a) (b) (c)) y)
85
+ # (== (cons x y) r))) ;; r => ((grape a))
86
+ fruits = cons(:grape, cons(:raisin, cons(:pear)))
87
+ expect(fruits.to_s).to eq('(:grape :raisin :pear)')
88
+ abc = cons(cons(:a), cons(cons(:b), cons(cons(:c))))
89
+ expect(abc.to_s).to eq('((:a) (:b) (:c))')
90
+
91
+ result = run_star('r', fresh(%w[x y],
92
+ [caro(fruits, x),
93
+ caro(abc, y),
94
+ equals(cons(x, y), r)]))
95
+ expect(result.car).to eq(cons(:grape, cons(:a)))
96
+ end
97
+ end # context
98
+ end # describe
99
+ end # module
100
+ end # module