mini_kraken 0.3.02 → 0.3.03

Sign up to get free protection for your applications and to get access to all the features.
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