mini_kraken 0.3.02 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aef8d438d839320f5a38af687cfef1e4018a687d5a9b3d071f5a485fa03cab3d
4
- data.tar.gz: a8aefa5c850913634dbe5b28bec9c605782ef2ef7e8791632a9f7b504937442d
3
+ metadata.gz: b0c4ccbb33a59eddd02ccbb56c5ad942002cb131e834b345a35c47a81985f999
4
+ data.tar.gz: ed3aba64c03d87c7f56b9516a0a8fa78aa6bbd39eb1bb39e6ece7b68f6226cd9
5
5
  SHA512:
6
- metadata.gz: 521fefadf00ba08606646afdd5f881a1a7bd4626221085c69adc2e822a2c2777b6fa28d71ea5f6541c614e0b8e9ca8470cab2301683d1c9f235bb1e3535f20f3
7
- data.tar.gz: 99478f83ad99813aa29d82cef6cc5b8ad3d5df376d56819151ecc508d62f0a0fd23a62a1fb3553f8aa231e8c317ad5aa6930503b2cd8ff2951b6d94ca8b3480c
6
+ metadata.gz: 13890c7b650bb8d83ac660c5e9c0d33cf87094f286a1e8d349095ee98dd8ec66652f16e5cc89928fb593c5dd921c9e612dc2d8f8ec565754baa4cb36c93e1256
7
+ data.tar.gz: 2358ff17fc9f2982675ff10d17761bf909db4fe38acc8f6f16389b3a31ea286ce4ad20cc1240147886baac98fb5ea047012ffc191ce58f1cf45cea0ca2e2341f
@@ -1,5 +1,19 @@
1
+ ## [0.3.03] - 2020-12-20
2
+ - `mini_kraken` now implements the `nullo`, `pairo` relations.
3
+ - Passes all examples from 2:1 up to 2:51 but 2:37
4
+
5
+ ### CHANGED
6
+ - Class `ConsCell`: default value for cdr is NullList instead of nil.
7
+ - Method `ConsCellVisitor#df_visitor`: no visit of car and cdr fiels of a null ConsCell
8
+ - Method `Unify#unify_references` now supports the unification of of floating references
9
+
10
+ ### FIXED
11
+ - Method `ParametrizedTerm#dup_cond` now performs replacement of Array elements.
12
+ - Method `Unify#unify_composite_terms` fixed typo in a method call
13
+ - Method `Unify#unify_references` fixed typo of exception class
14
+
1
15
  ## [0.3.02] - 2020-12-19
2
- - `mini_kraken` now implements `conso` relation.
16
+ - `mini_kraken` now implements the `conso` relation.
3
17
 
4
18
  ### CHANGED
5
19
  - Method `Context#build_solution` old source code (redundant) removed.
data/README.md CHANGED
@@ -11,10 +11,10 @@ Daniel P. Friedman, William E. Byrd, Oleg Kiselyov, and Jason Hemann: "The Reaso
11
11
  ISBN: 9780262535519, (2018), MIT Press.
12
12
 
13
13
  ### Features
14
+ - Test suite patterned on examples from the reference book
14
15
  - Pure Ruby implementation, not a port from another language
15
16
  - Object-Oriented design
16
17
  - No runtime dependencies
17
- - Test suite patterned on examples from the reference book.
18
18
 
19
19
  ### miniKanren Features
20
20
  - [X] ( == ) unify
@@ -26,16 +26,24 @@ ISBN: 9780262535519, (2018), MIT Press.
26
26
  - [X] defrel
27
27
  - [X] caro
28
28
  - [X] cdro
29
- - [X] conso
29
+ - [X] conso
30
+ - [X] nullo
31
+ - [X] pairo
30
32
 
31
33
  ### TODO
32
34
 
33
35
  - [ ] Occurs check
34
36
 
35
- Pair-centric relations from Chapter 2
36
- - [ ] nullo
37
- - [ ] pairo
38
- - [ ] singletono
37
+ Pair-centric relations from Chapter 2
38
+ - [ ] singletono
39
+
40
+ List-centric relations from Chapter 3
41
+ - [ ] listo
42
+ - [ ] lolo
43
+ - [ ] loso
44
+ - [ ] membero
45
+ - [ ] proper_membero
46
+
39
47
 
40
48
  ## Installation
41
49
 
@@ -52,11 +52,11 @@ module MiniKraken
52
52
  # will silently replace the null list by a nil.
53
53
  # @param obj1 [Term, NilClass]
54
54
  # @param obj2 [Term, NilClass]
55
- def initialize(obj1, obj2 = nil)
55
+ def initialize(obj1, obj2 = NullList)
56
56
  super()
57
57
  @car = obj1
58
58
  if obj2.kind_of?(ConsCell) && obj2.null?
59
- @cdr = nil
59
+ @cdr = NullList
60
60
  else
61
61
  @cdr = obj2
62
62
  end
@@ -68,6 +68,35 @@ module MiniKraken
68
68
  new(nil, nil)
69
69
  end
70
70
 
71
+ # Set one element of the pair
72
+ # @param member [Symbol]
73
+ # @param element [Term]
74
+ def set!(member, element)
75
+ case member
76
+ when :car
77
+ set_car!(element)
78
+ when :cdr
79
+ set_cdr!(element)
80
+ else
81
+ raise StandardError, "Undefined cons cell member #{member}"
82
+ end
83
+ end
84
+
85
+ # Change the car of ConsCell to 'element'.
86
+ # Analogue of set-car! procedure in Scheme.
87
+ # @param element [Term]
88
+ def set_car!(element)
89
+ @cdr = NullList if null?
90
+ @car = element
91
+ end
92
+
93
+ # Change the cdr of ConsCell to 'element'.
94
+ # Analogue of set-cdr! procedure in Scheme.
95
+ # @param element [Term]
96
+ def set_cdr!(element)
97
+ @cdr = element
98
+ end
99
+
71
100
  def children
72
101
  [car, cdr]
73
102
  end
@@ -93,13 +122,13 @@ module MiniKraken
93
122
  !pinned?(ctx)
94
123
  end
95
124
 
96
- # Does the composite have a definite value?
125
+ # Does the cons cell have a definite value?
97
126
  # @return [Boolean]
98
127
  def pinned?(ctx)
99
- @pinned_car ||= car.nil? || car.pinned?(ctx)
100
- @pinned_cdr ||= cdr.nil? || cdr.pinned?(ctx)
128
+ pinned_car = car.nil? || car.pinned?(ctx)
129
+ pinned_cdr = cdr.nil? || cdr.pinned?(ctx)
101
130
 
102
- @pinned_car && @pinned_cdr
131
+ pinned_car && pinned_cdr
103
132
  end
104
133
 
105
134
  # Return true if car and cdr fields have the same values as the other
@@ -166,7 +195,7 @@ module MiniKraken
166
195
  head = curr_cell = nil
167
196
  path = []
168
197
 
169
- visitor = ConsCellVisitor.df_visitor(self) # Breadth-first!
198
+ visitor = ConsCellVisitor.df_visitor(self)
170
199
  skip_children = false
171
200
 
172
201
  loop do
@@ -180,9 +209,15 @@ module MiniKraken
180
209
  if curr_cell
181
210
  curr_cell.set!(side, new_cell)
182
211
  path.push(curr_cell) unless side == :cdr
212
+ else
213
+ head = new_cell
214
+ path.push(new_cell)
215
+ end
216
+ if side == :cdr && cell.null?
217
+ curr_cell = path.pop
218
+ else
219
+ curr_cell = new_cell
183
220
  end
184
- curr_cell = new_cell
185
- head ||= new_cell
186
221
 
187
222
  when Core::LogVarRef
188
223
  # Is this robust?
@@ -194,7 +229,6 @@ module MiniKraken
194
229
  expanded = ctx.expand_value_of(i_name, theSubstitutions)
195
230
  curr_cell.set!(side, expanded)
196
231
  curr_cell = path.pop if side == :cdr
197
-
198
232
  else
199
233
  curr_cell.set!(side, cell)
200
234
  curr_cell = path.pop if side == :cdr
@@ -245,47 +279,15 @@ module MiniKraken
245
279
  head
246
280
  end
247
281
 
248
- # Set one element of the pair
249
- # @param member [Symbol]
250
- # @param element [Term]
251
- def set!(member, element)
252
- case member
253
- when :car
254
- set_car!(element)
255
- when :cdr
256
- @pinned_cdr = nil
257
- @cdr = element
258
- else
259
- raise StandardError, "Undefined cons cell member #{member}"
260
- end
261
- end
262
-
263
- # Change the car of ConsCell to 'element'.
264
- # Analogue of set-car! procedure in Scheme.
265
- # @param element [Term]
266
- def set_car!(element)
267
- @pinned_car = nil # To force re-evaluation
268
- @car = element
269
- end
270
-
271
- # Change the cdr of ConsCell to 'element'.
272
- # Analogue of set-cdr! procedure in Scheme.
273
- # @param element [Term]
274
- def set_cdr!(element)
275
- @pinned_cdr = nil # To force re-evaluation
276
- @cdr = (element.kind_of?(ConsCell) && element.null?) ? nil : element
277
- end
278
-
279
282
  protected
280
283
 
281
284
  def pair_to_s
282
285
  result = +car.to_s
283
286
  if cdr
284
- result << ' '
285
287
  if cdr.kind_of?(ConsCell)
286
- result << cdr.pair_to_s
288
+ result << " #{cdr.pair_to_s}" unless cdr.null?
287
289
  else
288
- result << ". #{cdr}"
290
+ result << " . #{cdr}"
289
291
  end
290
292
  end
291
293
 
@@ -33,7 +33,7 @@ module MiniKraken
33
33
  next if skip_children || skipping
34
34
 
35
35
  skipping = false
36
- if cell.is_a?(ConsCell)
36
+ if cell.is_a?(ConsCell) && !cell.null?
37
37
  visit_stack.push([:cdr, cell.cdr])
38
38
  visit_stack.push([:car, cell.car])
39
39
  end
@@ -34,7 +34,14 @@ module MiniKraken
34
34
  # @return [Term]
35
35
  def dup_cond(substitutions)
36
36
  duplicate = dup
37
- updated_actuals = actuals.map { |e| e.dup_cond(substitutions) }
37
+
38
+ updated_actuals = actuals.map do |e|
39
+ if e.is_a?(Array)
40
+ e.map {|item| item.dup_cond(substitutions) }
41
+ else
42
+ e.dup_cond(substitutions)
43
+ end
44
+ end
38
45
  duplicate.actuals.concat(updated_actuals)
39
46
 
40
47
  duplicate
@@ -60,6 +60,7 @@ module MiniKraken
60
60
  when Array
61
61
  formals = theFormals
62
62
  end
63
+
63
64
  rela = Rela::DefRelation.new(relationName, aGoalExpr, formals)
64
65
  add_defrel(rela)
65
66
  end
@@ -156,11 +156,11 @@ module MiniKraken
156
156
  skip_children1 = skip_children2 = false
157
157
 
158
158
  loop do
159
- # side.. can be: :car, :cdr, :stop
159
+ # side can be: :car, :cdr, :stop
160
160
  side1, cell1 = visitor1.resume(skip_children1)
161
161
  side2, cell2 = visitor2.resume(skip_children2)
162
162
  if side1 != side2
163
- ctx.failed
163
+ ctx.failed!
164
164
  elsif side1 == :stop
165
165
  break
166
166
  else
@@ -244,8 +244,15 @@ module MiniKraken
244
244
  if ref1.unbound?(ctx) || ref2.unbound?(ctx)
245
245
  ctx.fuse([ref1.name, ref2.name])
246
246
  ctx.succeeded!
247
+ elsif ref1.floating?(ctx) && ref2.floating?(ctx)
248
+ raise StandarrError if ctx.associations_for(ref1.name).size > 1
249
+ val1 = ctx.associations_for(ref1.name)[0].value
250
+ raise StandarrError if ctx.associations_for(ref2.name).size > 1
251
+ val2 = ctx.associations_for(ref2.name)[0].value
252
+ unification(val1, val2, ctx)
253
+ ctx.fuse([ref1.name, ref2.name]) if ctx.success?
247
254
  else
248
- raise NotImplentedError
255
+ raise NotImplementedError
249
256
  end
250
257
  # if both refs are fresh, fuse them
251
258
  # if one ref is fresh & the other one isn't then bind fresh one (occurs check)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniKraken
4
- VERSION = '0.3.02'
4
+ VERSION = '0.3.03'
5
5
  end
@@ -53,10 +53,10 @@ module MiniKraken
53
53
  expect(NullList).to be_null
54
54
  end
55
55
 
56
- it 'simplifies cdr if its referencing a null list' do
56
+ it 'initialize cdr if its referencing the null list' do
57
57
  instance = ConsCell.new(pea, NullList)
58
58
  expect(instance.car).to eq(pea)
59
- expect(instance.cdr).to be_nil
59
+ expect(instance.cdr).to be_null
60
60
  end
61
61
  end # context
62
62
 
@@ -83,7 +83,7 @@ module MiniKraken
83
83
  head = ConsCell.new(pod)
84
84
  instance.set_car!(head)
85
85
  expect(instance.car).to eq(head)
86
- expect(instance.cdr).to be_nil
86
+ expect(instance.cdr).to be_null
87
87
  end
88
88
 
89
89
  it 'should set_cdr! another cons cell' do
@@ -32,8 +32,8 @@ module MiniKraken
32
32
  null_list = ConsCell.null
33
33
  visitor = subject.df_visitor(null_list)
34
34
  expect(visitor.resume).to eq([:car, null_list])
35
- expect(visitor.resume).to eq([:car, nil])
36
- expect(visitor.resume).to eq([:cdr, nil])
35
+
36
+ # The car and cdr fields aren't visited
37
37
  expect(visitor.resume).to eq([:stop, nil])
38
38
  end
39
39
 
@@ -41,7 +41,7 @@ module MiniKraken
41
41
  visitor = subject.df_visitor(l_pea)
42
42
  expect(visitor.resume).to eq([:car, l_pea])
43
43
  expect(visitor.resume).to eq([:car, pea])
44
- expect(visitor.resume).to eq([:cdr, nil])
44
+ expect(visitor.resume).to eq([:cdr, NullList])
45
45
  expect(visitor.resume).to eq([:stop, nil])
46
46
  end
47
47
 
@@ -51,7 +51,7 @@ module MiniKraken
51
51
  expect(visitor.resume).to eq([:car, pea])
52
52
  expect(visitor.resume).to eq([:cdr, l_pea_pod.cdr])
53
53
  expect(visitor.resume).to eq([:car, pod])
54
- expect(visitor.resume).to eq([:cdr, nil])
54
+ expect(visitor.resume).to eq([:cdr, NullList])
55
55
  expect(visitor.resume).to eq([:stop, nil])
56
56
  end
57
57
 
@@ -63,7 +63,7 @@ module MiniKraken
63
63
  expect(visitor.resume).to eq([:car, pod])
64
64
  expect(visitor.resume).to eq([:cdr, l_pea_pod_corn.cdr.cdr])
65
65
  expect(visitor.resume).to eq([:car, corn])
66
- expect(visitor.resume).to eq([:cdr, nil])
66
+ expect(visitor.resume).to eq([:cdr, NullList])
67
67
  expect(visitor.resume).to eq([:stop, nil])
68
68
  end
69
69
  end # context
@@ -106,8 +106,8 @@ module MiniKraken
106
106
  expect(visitor.resume).to eq([:car, composite.car])
107
107
  expect(visitor.resume).to eq([:car, composite.car.car])
108
108
  expect(visitor.resume).to eq([:car, pea])
109
- expect(visitor.resume).to eq([:cdr, nil])
110
- expect(visitor.resume).to eq([:cdr, nil])
109
+ expect(visitor.resume).to eq([:cdr, NullList])
110
+ expect(visitor.resume).to eq([:cdr, NullList])
111
111
  expect(visitor.resume).to eq([:cdr, pod])
112
112
  end
113
113
  end # context
@@ -134,7 +134,7 @@ module MiniKraken
134
134
  # Tell to skip children by passing a true value to resume
135
135
  expect(visitor.resume(true)).to eq([:cdr, tree.cdr.cdr])
136
136
  expect(visitor.resume).to eq([:car, corn])
137
- expect(visitor.resume).to eq([:cdr, nil])
137
+ expect(visitor.resume).to eq([:cdr, NullList])
138
138
  expect(visitor.resume).to eq([:stop, nil])
139
139
  end
140
140
  end # context
@@ -149,7 +149,9 @@ module MiniKraken
149
149
  expect(visitor.resume).to eq([:car, first_cell])
150
150
  expect(visitor.resume).to eq([:car, pea])
151
151
  expect(visitor.resume).to eq([:cdr, second_cell])
152
- expect(visitor.resume).to eq([:cdr, nil]) # Skip car (was already visited)
152
+
153
+ # Skip car (was already visited)
154
+ expect(visitor.resume).to eq([:cdr, NullList])
153
155
  expect(visitor.resume).to eq([:stop, nil])
154
156
  end
155
157
  end # context
@@ -230,7 +230,8 @@ module MiniKraken
230
230
  # (caro p a)
231
231
  # (cdro p d))
232
232
 
233
- # As 'p' has a special meaning in Ruby, the argument has been remaned to 'r'
233
+ # As 'p' has a special meaning in Ruby, the argument has been renamed
234
+ # to 'r'
234
235
  conso_rel = defrel('conso', %w[a d r], [caro(r, a), cdro(r, d)])
235
236
 
236
237
  expect(conso_rel).to be_kind_of(Rela::DefRelation)
@@ -254,16 +255,17 @@ module MiniKraken
254
255
  expect(g2.actuals[1].name).to match(/^d_/)
255
256
  end
256
257
 
257
- # In Scheme:
258
- # (defrel (conso a d p)
259
- # (caro p a)
260
- # (cdro p d))
261
- # In Ruby, `p`is a standard Kernel method => replace it by `r`
258
+
262
259
  def defrel_conso
263
260
  defrel_caro
264
261
  defrel_cdro
265
262
 
266
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`
267
269
  # defrel('conso', %w[a d r], [caro(r, a), cdro(r, d)])
268
270
 
269
271
  # Definition derived from frame 2:26
@@ -344,6 +346,189 @@ module MiniKraken
344
346
  result = run_star('l', expr)
345
347
  expect(result.to_s).to eq('((:d :a :d :c))')
346
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
347
532
  end # context
348
533
  end # describe
349
534
  end # module
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_kraken
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.02
4
+ version: 0.3.03
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-19 00:00:00.000000000 Z
11
+ date: 2020-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler