mini_kraken 0.2.03 → 0.3.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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +378 -333
  3. data/CHANGELOG.md +48 -0
  4. data/README.md +29 -21
  5. data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
  6. data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
  7. data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
  8. data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
  9. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  10. data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
  11. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  12. data/lib/mini_kraken/composite/composite_term.rb +27 -0
  13. data/lib/mini_kraken/composite/cons_cell.rb +301 -0
  14. data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
  15. data/lib/mini_kraken/composite/list.rb +32 -0
  16. data/lib/mini_kraken/core/all_core.rb +8 -0
  17. data/lib/mini_kraken/core/any_value.rb +31 -7
  18. data/lib/mini_kraken/core/arity.rb +69 -0
  19. data/lib/mini_kraken/core/association.rb +29 -4
  20. data/lib/mini_kraken/core/association_copy.rb +50 -0
  21. data/lib/mini_kraken/core/base_term.rb +13 -0
  22. data/lib/mini_kraken/core/blackboard.rb +315 -0
  23. data/lib/mini_kraken/core/bookmark.rb +46 -0
  24. data/lib/mini_kraken/core/context.rb +492 -0
  25. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  26. data/lib/mini_kraken/core/entry.rb +40 -0
  27. data/lib/mini_kraken/core/fail.rb +20 -18
  28. data/lib/mini_kraken/core/fusion.rb +29 -0
  29. data/lib/mini_kraken/core/goal.rb +20 -29
  30. data/lib/mini_kraken/core/log_var.rb +22 -0
  31. data/lib/mini_kraken/core/log_var_ref.rb +108 -0
  32. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  33. data/lib/mini_kraken/core/parametrized_term.rb +68 -0
  34. data/lib/mini_kraken/core/relation.rb +14 -28
  35. data/lib/mini_kraken/core/scope.rb +67 -0
  36. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  37. data/lib/mini_kraken/core/specification.rb +48 -0
  38. data/lib/mini_kraken/core/succeed.rb +21 -17
  39. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  40. data/lib/mini_kraken/core/term.rb +15 -4
  41. data/lib/mini_kraken/glue/dsl.rb +44 -88
  42. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  43. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  44. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  45. data/lib/mini_kraken/rela/conde.rb +143 -0
  46. data/lib/mini_kraken/rela/conj2.rb +65 -0
  47. data/lib/mini_kraken/rela/def_relation.rb +93 -0
  48. data/lib/mini_kraken/rela/disj2.rb +70 -0
  49. data/lib/mini_kraken/rela/fresh.rb +98 -0
  50. data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
  51. data/lib/mini_kraken/rela/unify.rb +265 -0
  52. data/lib/mini_kraken/version.rb +1 -1
  53. data/mini_kraken.gemspec +2 -2
  54. data/spec/.rubocop.yml +1 -1
  55. data/spec/atomic/atomic_term_spec.rb +98 -0
  56. data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
  57. data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
  58. data/spec/composite/cons_cell_spec.rb +225 -0
  59. data/spec/{core → composite}/cons_cell_visitor_spec.rb +36 -20
  60. data/spec/composite/list_spec.rb +50 -0
  61. data/spec/core/any_value_spec.rb +52 -0
  62. data/spec/core/arity_spec.rb +92 -0
  63. data/spec/core/association_copy_spec.rb +69 -0
  64. data/spec/core/association_spec.rb +31 -4
  65. data/spec/core/blackboard_spec.rb +287 -0
  66. data/spec/core/bookmark_spec.rb +40 -0
  67. data/spec/core/context_spec.rb +245 -0
  68. data/spec/core/core_spec.rb +40 -0
  69. data/spec/core/duck_fiber_spec.rb +16 -46
  70. data/spec/core/fail_spec.rb +5 -6
  71. data/spec/core/goal_spec.rb +22 -12
  72. data/spec/core/log_var_ref_spec.rb +105 -0
  73. data/spec/core/log_var_spec.rb +64 -0
  74. data/spec/core/nullary_relation_spec.rb +33 -0
  75. data/spec/core/parametrized_tem_spec.rb +39 -0
  76. data/spec/core/relation_spec.rb +33 -0
  77. data/spec/core/scope_spec.rb +73 -0
  78. data/spec/core/solver_adapter_spec.rb +70 -0
  79. data/spec/core/specification_spec.rb +43 -0
  80. data/spec/core/succeed_spec.rb +5 -5
  81. data/spec/core/symbol_table_spec.rb +142 -0
  82. data/spec/glue/dsl_chap1_spec.rb +88 -144
  83. data/spec/glue/dsl_chap2_spec.rb +454 -19
  84. data/spec/glue/run_star_expression_spec.rb +81 -906
  85. data/spec/rela/conde_spec.rb +153 -0
  86. data/spec/rela/conj2_spec.rb +123 -0
  87. data/spec/rela/def_relation_spec.rb +119 -0
  88. data/spec/rela/disj2_spec.rb +117 -0
  89. data/spec/rela/fresh_spec.rb +147 -0
  90. data/spec/rela/unify_spec.rb +369 -0
  91. data/spec/support/factory_atomic.rb +29 -0
  92. data/spec/support/factory_composite.rb +21 -0
  93. data/spec/support/factory_methods.rb +11 -26
  94. metadata +98 -70
  95. data/lib/mini_kraken/core/association_walker.rb +0 -183
  96. data/lib/mini_kraken/core/atomic_term.rb +0 -67
  97. data/lib/mini_kraken/core/base_arg.rb +0 -10
  98. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  99. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  100. data/lib/mini_kraken/core/composite_term.rb +0 -41
  101. data/lib/mini_kraken/core/conde.rb +0 -143
  102. data/lib/mini_kraken/core/conj2.rb +0 -79
  103. data/lib/mini_kraken/core/cons_cell.rb +0 -82
  104. data/lib/mini_kraken/core/cons_cell_visitor.rb +0 -102
  105. data/lib/mini_kraken/core/def_relation.rb +0 -53
  106. data/lib/mini_kraken/core/designation.rb +0 -55
  107. data/lib/mini_kraken/core/disj2.rb +0 -72
  108. data/lib/mini_kraken/core/environment.rb +0 -73
  109. data/lib/mini_kraken/core/equals.rb +0 -193
  110. data/lib/mini_kraken/core/formal_arg.rb +0 -22
  111. data/lib/mini_kraken/core/formal_ref.rb +0 -25
  112. data/lib/mini_kraken/core/freshness.rb +0 -45
  113. data/lib/mini_kraken/core/goal_arg.rb +0 -12
  114. data/lib/mini_kraken/core/goal_template.rb +0 -102
  115. data/lib/mini_kraken/core/k_boolean.rb +0 -35
  116. data/lib/mini_kraken/core/outcome.rb +0 -63
  117. data/lib/mini_kraken/core/variable.rb +0 -41
  118. data/lib/mini_kraken/core/variable_ref.rb +0 -84
  119. data/lib/mini_kraken/core/vocabulary.rb +0 -446
  120. data/lib/mini_kraken/glue/fresh_env.rb +0 -103
  121. data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
  122. data/spec/core/association_walker_spec.rb +0 -192
  123. data/spec/core/conde_spec.rb +0 -147
  124. data/spec/core/conj2_spec.rb +0 -114
  125. data/spec/core/cons_cell_spec.rb +0 -107
  126. data/spec/core/def_relation_spec.rb +0 -97
  127. data/spec/core/disj2_spec.rb +0 -99
  128. data/spec/core/environment_spec.rb +0 -142
  129. data/spec/core/equals_spec.rb +0 -317
  130. data/spec/core/goal_template_spec.rb +0 -74
  131. data/spec/core/outcome_spec.rb +0 -56
  132. data/spec/core/variable_ref_spec.rb +0 -30
  133. data/spec/core/variable_spec.rb +0 -35
  134. data/spec/core/vocabulary_spec.rb +0 -219
  135. data/spec/glue/fresh_env_factory_spec.rb +0 -97
  136. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -12,36 +12,66 @@ module MiniKraken
12
12
  include DSL
13
13
 
14
14
  context 'Chapter 2 examples:' do
15
+ # ((:a) (:b) (:c))
16
+ let(:abc) { cons(cons(:a), cons(cons(:b), cons(cons(:c)))) }
17
+
18
+ # '(:a :c :o :r :n)
15
19
  let(:acorn) { cons(:a, cons(:c, cons(:o, cons(:r, cons(:n))))) }
16
20
 
21
+ # '(:c :o :r :n)
22
+ let(:corn) { cons(:c, cons(:o, cons(:r, cons(:n)))) }
23
+
24
+ # '(:grape :raisin :pear)'
25
+ let(:fruits) { cons(:grape, cons(:raisin, cons(:pear))) }
26
+
27
+ let(:uuid_pattern) do
28
+ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
29
+ end
30
+
17
31
  it 'accepts caro definition inspired from frame 2:6' do
18
32
  # Reasoned S2, frame 2:6
19
33
  # (defrel (caro p a)
20
34
  # (fresh (d)
21
35
  # (== (cons a d) p)))
22
36
 
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
37
+ # As 'p' has a special meaning in Ruby, the argument has been renamed to 'r'
38
+ caro_rel = defrel('caro', %w[r a], fresh('d', unify(cons(a, d), r)))
39
+
40
+ # Check side-effect from DSL
41
+ expect(instance_variable_get(:@defrels)['caro']).to eq(caro_rel)
27
42
 
28
- expect(caro_rel).to be_kind_of(Core::DefRelation)
43
+ # Check results of defrel
44
+ expect(caro_rel).to be_kind_of(Rela::DefRelation)
29
45
  expect(caro_rel.name).to eq('caro')
30
46
  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')
47
+ expect(caro_rel.formals[0]).to match(/^r_/)
48
+ expect(caro_rel.formals[0]).to match(uuid_pattern)
49
+ expect(caro_rel.formals[1]).to match(/^a_/)
50
+ expect(caro_rel.formals[1]).to match(uuid_pattern)
51
+ g_template = caro_rel.expression
52
+
53
+ # Checking the 'fresh' part
54
+ expect(g_template).to be_kind_of(Core::Goal)
55
+ expect(g_template.relation).to be_kind_of(Rela::Fresh)
56
+ expect(g_template.actuals[0]).to eq('d')
57
+ fresh_2nd_actual = g_template.actuals[1]
58
+
59
+ # Checking the (== (cons a d) r) sub-expression
60
+ expect(fresh_2nd_actual).to be_kind_of(Core::Goal)
61
+ expect(fresh_2nd_actual.relation.name).to eq('unify')
62
+ expect(fresh_2nd_actual.actuals[0]).to be_kind_of(Composite::ConsCell)
63
+ expect(fresh_2nd_actual.actuals[0].to_s).to match(/^\(a_[-0-9a-f]+ \. d\)$/)
64
+ expect(fresh_2nd_actual.actuals[1]).to be_kind_of(Core::LogVarRef)
65
+ expect(fresh_2nd_actual.actuals[1].name).to match(/^r_[-0-9a-f]+$/)
36
66
  end
37
67
 
38
68
  # In Scheme:
39
69
  # (defrel (caro p a)
40
70
  # (fresh (d)
41
- # (== (cons a d) p)))
42
- # In Ruby, `p`is a stnadard Kernel method => replaced by `r`
71
+ # (== p (cons a d))))
72
+ # In Ruby, `p`is a standard Kernel method => replace it by `r`
43
73
  def defrel_caro
44
- defrel('caro', %w[r a]) { fresh('d', equals(cons(a, d), r)) }
74
+ defrel('caro', %w[r a], fresh('d', unify(r, cons(a, d))))
45
75
  end
46
76
 
47
77
  it 'passes frame 2:3' do
@@ -62,6 +92,7 @@ module MiniKraken
62
92
  expect(result.car).to eq(:_0)
63
93
  end
64
94
 
95
+ # IT FAILS
65
96
  it 'passes frame 2:5' do
66
97
  defrel_caro
67
98
 
@@ -71,7 +102,7 @@ module MiniKraken
71
102
  # (== 'pear x)));; r => (pear)
72
103
  result = run_star('r', fresh(%w[x y],
73
104
  [caro(cons(r, cons(y)), x),
74
- equals(:pear, x)]))
105
+ unify(:pear, x)]))
75
106
  expect(result.car).to eq(:pear)
76
107
  end
77
108
 
@@ -83,17 +114,421 @@ module MiniKraken
83
114
  # (caro '(grape raisin pear) x)
84
115
  # (caro '((a) (b) (c)) y)
85
116
  # (== (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
117
 
91
118
  result = run_star('r', fresh(%w[x y],
92
119
  [caro(fruits, x),
93
120
  caro(abc, y),
94
- equals(cons(x, y), r)]))
121
+ unify(cons(x, y), r)]))
95
122
  expect(result.car).to eq(cons(:grape, cons(:a)))
96
123
  end
124
+
125
+ it 'accepts cdro definition inspired from frame 2:13' do
126
+ # Reasoned S2, frame 2:13
127
+ # (defrel (cdro p d)
128
+ # (fresh (a)
129
+ # (== (cons a d) p)))
130
+
131
+ # As 'p' has a special meaning in Ruby, the argument has been remaned to 'r'
132
+ cdro_rel = defrel('cdro', %w[r d], fresh('a', unify(cons(a, d), r)))
133
+
134
+ expect(cdro_rel).to be_kind_of(Rela::DefRelation)
135
+ expect(cdro_rel.name).to eq('cdro')
136
+ expect(cdro_rel.arity).to eq(2)
137
+ expect(cdro_rel.formals[0]).to match(/^r_[-0-9a-f]+$/)
138
+ expect(cdro_rel.formals[1]).to match(/^d_[-0-9a-f]+$/)
139
+ g_template = cdro_rel.expression
140
+ expect(g_template.relation).to be_kind_of(Rela::Fresh)
141
+ expect(g_template.actuals).to include('a')
142
+ end
143
+
144
+ # In Scheme:
145
+ # (defrel (cdro p d)
146
+ # (fresh (a)
147
+ # (== p (cons a d))))
148
+ # In Ruby, `p`is a standard Kernel method => replace it by `r`
149
+ def defrel_cdro
150
+ defrel('cdro', %w[r d], fresh('a', unify(r, cons(a, d))))
151
+ end
152
+
153
+ it 'passes unnesting process in frame 2:12' do
154
+ defrel_caro
155
+ defrel_cdro
156
+
157
+ # (run* r
158
+ # (fresh (v)
159
+ # (cdro '(acorn) v)
160
+ # (fresh (w)
161
+ # (cdro v w)
162
+ # (caro w r))) ;; r => (o)
163
+
164
+ result = run_star('r', fresh('v',
165
+ [cdro(acorn, v),
166
+ fresh('w',
167
+ [cdro(v, w),
168
+ caro(w, r)])]))
169
+ expect(result.car).to eq(:o)
170
+ end
171
+
172
+ it 'passes frame 2:15' do
173
+ defrel_caro
174
+ defrel_cdro
175
+
176
+ # (run* r
177
+ # (fresh (x y)
178
+ # (cdro '(grape raisin pear) x)
179
+ # (caro '((a) (b) (c)) y)
180
+ # (== (cons x y) r))) ;; r => (((raisin pear) a))
181
+
182
+ result = run_star('r', fresh(%w[x y],
183
+ [cdro(fruits, x),
184
+ caro(abc, y),
185
+ unify(cons(x, y), r)]))
186
+ expect(result.to_s).to eq('(((:raisin :pear) :a))')
187
+ end
188
+
189
+ it 'passes frame 2:16' do
190
+ defrel_cdro
191
+
192
+ # (run* q
193
+ # (cdro '(a c o r n) '(c o r n))) ;; => (_0)
194
+ result = run_star('r', cdro(acorn, corn))
195
+ expect(result.car).to eq(:_0)
196
+ end
197
+
198
+ it 'passes frame 2:17' do
199
+ defrel_cdro
200
+
201
+ # (run* x
202
+ # (cdro '(c o r n) '(,x r n))) ;; => (o)
203
+ result = run_star('x', cdro(corn, cons(x, cons(:r, cons(:n)))))
204
+ expect(result.car).to eq(:o)
205
+ end
206
+
207
+ it 'passes frame 2:18' do
208
+ defrel_caro
209
+ defrel_cdro
210
+
211
+ # (run* l
212
+ # (fresh (x)
213
+ # (cdro l '(c o r n))
214
+ # (caro l x)
215
+ # (== 'a x))) ;; l => ('(a c o r n))
216
+
217
+ result = run_star('l', fresh('x',
218
+ [cdro(l, corn),
219
+ caro(l, x),
220
+ unify(:a, x)]))
221
+ expect(result.to_s).to eq('((:a :c :o :r :n))')
222
+ end
223
+
224
+ it 'accepts conso definition inspired from frame 2:25' do
225
+ defrel_caro
226
+ defrel_cdro
227
+
228
+ # Reasoned S2, frame 2:25
229
+ # (defrel (conso a p d)
230
+ # (caro p a)
231
+ # (cdro p d))
232
+
233
+ # As 'p' has a special meaning in Ruby, the argument has been renamed
234
+ # to 'r'
235
+ conso_rel = defrel('conso', %w[a d r], [caro(r, a), cdro(r, d)])
236
+
237
+ expect(conso_rel).to be_kind_of(Rela::DefRelation)
238
+ expect(conso_rel.name).to eq('conso')
239
+ expect(conso_rel.arity).to eq(3)
240
+ expect(conso_rel.formals[0]).to match(/^a_[-0-9a-f]+$/)
241
+ expect(conso_rel.formals[1]).to match(/^d_[-0-9a-f]+$/)
242
+ expect(conso_rel.formals[2]).to match(/^r_[-0-9a-f]+$/)
243
+ g_template = conso_rel.expression
244
+ expect(g_template.relation).to be_kind_of(Rela::Conj2)
245
+ g1 = g_template.actuals[0]
246
+ expect(g1).to be_kind_of(Core::Goal)
247
+ expect(g1.relation.name).to eq('caro')
248
+ expect(g1.actuals[0].name).to match(/^r_/)
249
+ expect(g1.actuals[1].name).to match(/^a_/)
250
+
251
+ g2 = g_template.actuals[1]
252
+ expect(g2).to be_kind_of(Core::Goal)
253
+ expect(g2.relation.name).to eq('cdro')
254
+ expect(g2.actuals[0].name).to match(/^r_/)
255
+ expect(g2.actuals[1].name).to match(/^d_/)
256
+ end
257
+
258
+
259
+ def defrel_conso
260
+ defrel_caro
261
+ defrel_cdro
262
+
263
+ # Definition derived from frame 2:25
264
+ # In Scheme:
265
+ # (defrel (conso a d p)
266
+ # (caro p a)
267
+ # (cdro p d))
268
+ # In Ruby, `p`is a standard Kernel method => replace it by `r`
269
+ # defrel('conso', %w[a d r], [caro(r, a), cdro(r, d)])
270
+
271
+ # Definition derived from frame 2:26
272
+ defrel('conso', %w[a d r], [unify(cons(a, d), r)])
273
+ end
274
+
275
+ it 'passes frame 2:19' do
276
+ defrel_conso
277
+
278
+ # (run* l
279
+ # (conso '(a b c) '(d e) l)) ;; => (((a b c) d e))
280
+
281
+ result = run_star('l', conso(list(:a, :b, :c), list(:d, :e), l))
282
+ expect(result.to_s).to eq('(((:a :b :c) :d :e))')
283
+ end
284
+
285
+ it 'passes frame 2:20' do
286
+ defrel_conso
287
+
288
+ # (run* x
289
+ # (conso x '(a b c) '(d a b c))) ;; => (d)
290
+
291
+ result = run_star('x', conso(x, list(:a, :b, :c), list(:d, :a, :b, :c)))
292
+ expect(result.to_s).to eq('(:d)')
293
+ end
294
+
295
+ it 'passes frame 2:21' do
296
+ defrel_conso
297
+
298
+ # (run* r
299
+ # (fresh (x y z)
300
+ # (== '(e a d ,x) r)
301
+ # (conso y '(a ,z c) r))) ;; => ((e a d c)
302
+
303
+ expr = fresh(%w[x y z],
304
+ [unify(list(:e, :a, :d, x), r),
305
+ conso(y, list(:a, z, :c), r)])
306
+ result = run_star('r', expr)
307
+ expect(result.to_s).to eq('((:e :a :d :c))')
308
+ end
309
+
310
+ it 'passes frame 2:22' do
311
+ defrel_conso
312
+
313
+ # (run* x
314
+ # (conso x '(a ,x c) '(d a ,x c))) ;; => (d)
315
+
316
+ result = run_star('x', conso(x, list(:a, x, :c), list(:d, :a, x, :c)))
317
+ expect(result.to_s).to eq('(:d)')
318
+ end
319
+
320
+ it 'passes frame 2:23' do
321
+ defrel_conso
322
+
323
+ # (run* l
324
+ # (fresh (x)
325
+ # (== '(d a ,x c) l)
326
+ # (conso x '(a ,x c) l))) ;; => ((d a d c)
327
+
328
+ expr = fresh(%w[x],
329
+ [unify(list(:d, :a, x, :c), l),
330
+ conso(x, list(:a, x, :c), l)])
331
+ result = run_star('l', expr)
332
+ expect(result.to_s).to eq('((:d :a :d :c))')
333
+ end
334
+
335
+ it 'passes frame 2:24' do
336
+ defrel_conso
337
+
338
+ # (run* l
339
+ # (fresh (x)
340
+ # (conso x '(a ,x c) l)))
341
+ # (== '(d a ,x c) l) ;; => ((d a d c)
342
+
343
+ expr = fresh(%w[x],
344
+ [conso(x, list(:a, x, :c), l),
345
+ unify(list(:d, :a, x, :c), l)])
346
+ result = run_star('l', expr)
347
+ expect(result.to_s).to eq('((:d :a :d :c))')
348
+ end
349
+
350
+ # it 'passes frame 2:25' do
351
+ # defrel_conso
352
+
353
+ # # (run* l
354
+ # # (fresh (d t x y w)
355
+ # # (conso w '(n u s) t)
356
+ # # (cdro l t)
357
+ # # (caro l x)
358
+ # # (== 'b x)
359
+ # # (cdro l d)
360
+ # # (caro d y)
361
+ # # (== 'o y))) ;; => ((b o n u s))
362
+
363
+ # expr = fresh(%w[d t x y w],
364
+ # [conso(w, list(:n, :u, :s), t),
365
+ # cdro(l, t),
366
+ # caro(l, x),
367
+ # unify(:b, x),
368
+ # cdro(l, d),
369
+ # caro(d, y),
370
+ # unify(:o, y)])
371
+ # result = run_star('l', expr)
372
+ # expect(result.to_s).to eq('((:b :o :n :u :s))')
373
+ # end
374
+
375
+ it 'accepts nullo definition inspired from frame 2:33' do
376
+ # Reasoned S2, frame 2:33
377
+ # (defrel (nullo x)
378
+ # (== '() x)
379
+
380
+ nullo_rel = defrel('nullo', %w[x], unify(null, x))
381
+
382
+ expect(nullo_rel).to be_kind_of(Rela::DefRelation)
383
+ expect(nullo_rel.name).to eq('nullo')
384
+ expect(nullo_rel.arity).to eq(1)
385
+ expect(nullo_rel.formals[0]).to match(/^x_[-0-9a-f]+$/)
386
+ g_template = nullo_rel.expression
387
+ expect(g_template.relation).to be_kind_of(Rela::Unify)
388
+ expect(g_template.actuals[0]).to be_null
389
+ expect(g_template.actuals[1]).to be_kind_of(Core::LogVarRef)
390
+ expect(g_template.actuals[1].name).to match(/^x_[-0-9a-f]+$/)
391
+ end
392
+
393
+ def defrel_nullo
394
+ # Definition derived from frame 2:33
395
+ defrel('nullo', %w[x], unify(null_list, x))
396
+ end
397
+
398
+ it 'passes frame 2:30' do
399
+ defrel_nullo
400
+
401
+ # (run* q
402
+ # (nullo '(grape raisin pear))) ;; => ()
403
+
404
+ result = run_star('q', nullo(list(:grape, :raisin, :pear)))
405
+ expect(result).to be_null
406
+ end
407
+
408
+ it 'passes frame 2:31' do
409
+ defrel_nullo
410
+
411
+ # (run* q
412
+ # (nullo '())) ;; => (_0)
413
+
414
+ result = run_star('q', nullo(null_list))
415
+ expect(result.to_s).to eq('(_0)')
416
+ end
417
+
418
+ it 'passes frame 2:32' do
419
+ defrel_nullo
420
+
421
+ # (run* x
422
+ # (nullo x)) ;; => (())
423
+
424
+ result = run_star('x', nullo(x))
425
+ expect(result.to_s).to eq('(())')
426
+ end
427
+
428
+ it 'passes frame 2:35' do
429
+ defrel_nullo
430
+
431
+ # (run* r
432
+ # (fresh (x y)
433
+ # (== (cons x (cons y 'salad)) r))) ;; => ((_0 _1 . salad))
434
+
435
+ result = run_star('r', fresh(%w[x y],
436
+ unify(cons(x, cons(y, :salad)), r)))
437
+ expect(result.to_s).to eq('((_0 _1 . :salad))')
438
+ end
439
+
440
+ it 'passes frame 2:45' do
441
+ defrel_nullo
442
+
443
+ # (run* r
444
+ # (fresh (x y)
445
+ # (== (cons x (cons y 'salad)) r))) ;; => ((_0 _1 . salad))
446
+
447
+ result = run_star('r', fresh(%w[x y],
448
+ unify(cons(x, cons(y, :salad)), r)))
449
+ expect(result.to_s).to eq('((_0 _1 . :salad))')
450
+ end
451
+
452
+ it 'accepts pairo definition inspired from frame 2:46' do
453
+ defrel_conso
454
+
455
+ # Reasoned S2, frame 2:46
456
+ # (defrel (pairo r)
457
+ # (fresh (a d)
458
+ # (conso a d r)))
459
+
460
+ pairo_rel = defrel('pairo', %w[r],fresh(%w[a d], conso(a, d, r)))
461
+
462
+ expect(pairo_rel).to be_kind_of(Rela::DefRelation)
463
+ expect(pairo_rel.name).to eq('pairo')
464
+ expect(pairo_rel.arity).to eq(1)
465
+ expect(pairo_rel.formals[0]).to match(/^r_[-0-9a-f]+$/)
466
+ g_template = pairo_rel.expression
467
+ expect(g_template.relation).to be_kind_of(Rela::Fresh)
468
+ expect(g_template.actuals[0]).to eq(%w[a d])
469
+ expect(g_template.actuals[1]).to be_kind_of(Core::Goal)
470
+ expect(g_template.actuals[1].relation.name).to eq('conso')
471
+ expect(g_template.actuals[1].actuals[0].name).to eq('a')
472
+ expect(g_template.actuals[1].actuals[1].name).to eq('d')
473
+ expect(g_template.actuals[1].actuals[2].name).to match(/^r_[-0-9a-f]+$/)
474
+ end
475
+
476
+ def defrel_pairo
477
+ defrel_conso
478
+
479
+ # Definition derived from frame 2:46
480
+ defrel('pairo', %w[r],fresh(%w[a d], conso(a, d, r)))
481
+ end
482
+
483
+ it 'passes frame 2:47' do
484
+ defrel_pairo
485
+
486
+ # (run* q
487
+ # (pairo (cons q q))) ;; => (_0)
488
+
489
+ result = run_star('q', pairo(cons(q, q)))
490
+ expect(result.to_s).to eq('(_0)')
491
+ end
492
+
493
+ it 'passes frame 2:48' do
494
+ defrel_pairo
495
+
496
+ # (run* q
497
+ # (pairo '())) ;; => ()
498
+
499
+ result = run_star('q', pairo(null_list))
500
+ expect(result.to_s).to eq('()')
501
+ end
502
+
503
+ it 'passes frame 2:49' do
504
+ defrel_pairo
505
+
506
+ # (run* q
507
+ # (pairo 'pair)) ;; => ()
508
+
509
+ result = run_star('q', pairo(:pair))
510
+ expect(result.to_s).to eq('()')
511
+ end
512
+
513
+ it 'passes frame 2:50' do
514
+ defrel_pairo
515
+
516
+ # (run* x
517
+ # (pairo x)) ;; => ((_0 . _1))
518
+
519
+ result = run_star('x', pairo(x))
520
+ expect(result.to_s).to eq('((_0 . _1))')
521
+ end
522
+
523
+ it 'passes frame 2:51' do
524
+ defrel_pairo
525
+
526
+ # (run* r
527
+ # (pairo (cons r '()))) ;; => (_0)
528
+
529
+ result = run_star('r', pairo(cons(r, null_list)))
530
+ expect(result.to_s).to eq('(_0)')
531
+ end
97
532
  end # context
98
533
  end # describe
99
534
  end # module