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 +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +14 -6
- data/lib/mini_kraken/composite/cons_cell.rb +46 -44
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +1 -1
- data/lib/mini_kraken/core/parametrized_term.rb +8 -1
- data/lib/mini_kraken/glue/dsl.rb +1 -0
- data/lib/mini_kraken/rela/unify.rb +10 -3
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/composite/cons_cell_spec.rb +3 -3
- data/spec/composite/cons_cell_visitor_spec.rb +11 -9
- data/spec/glue/dsl_chap2_spec.rb +191 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0c4ccbb33a59eddd02ccbb56c5ad942002cb131e834b345a35c47a81985f999
|
4
|
+
data.tar.gz: ed3aba64c03d87c7f56b9516a0a8fa78aa6bbd39eb1bb39e6ece7b68f6226cd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13890c7b650bb8d83ac660c5e9c0d33cf87094f286a1e8d349095ee98dd8ec66652f16e5cc89928fb593c5dd921c9e612dc2d8f8ec565754baa4cb36c93e1256
|
7
|
+
data.tar.gz: 2358ff17fc9f2982675ff10d17761bf909db4fe38acc8f6f16389b3a31ea286ce4ad20cc1240147886baac98fb5ea047012ffc191ce58f1cf45cea0ca2e2341f
|
data/CHANGELOG.md
CHANGED
@@ -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
|
-
- [ ]
|
37
|
-
|
38
|
-
-
|
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 =
|
55
|
+
def initialize(obj1, obj2 = NullList)
|
56
56
|
super()
|
57
57
|
@car = obj1
|
58
58
|
if obj2.kind_of?(ConsCell) && obj2.null?
|
59
|
-
@cdr =
|
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
|
125
|
+
# Does the cons cell have a definite value?
|
97
126
|
# @return [Boolean]
|
98
127
|
def pinned?(ctx)
|
99
|
-
|
100
|
-
|
128
|
+
pinned_car = car.nil? || car.pinned?(ctx)
|
129
|
+
pinned_cdr = cdr.nil? || cdr.pinned?(ctx)
|
101
130
|
|
102
|
-
|
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)
|
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
|
|
@@ -34,7 +34,14 @@ module MiniKraken
|
|
34
34
|
# @return [Term]
|
35
35
|
def dup_cond(substitutions)
|
36
36
|
duplicate = dup
|
37
|
-
|
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
|
data/lib/mini_kraken/glue/dsl.rb
CHANGED
@@ -156,11 +156,11 @@ module MiniKraken
|
|
156
156
|
skip_children1 = skip_children2 = false
|
157
157
|
|
158
158
|
loop do
|
159
|
-
# side
|
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
|
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)
|
data/lib/mini_kraken/version.rb
CHANGED
@@ -53,10 +53,10 @@ module MiniKraken
|
|
53
53
|
expect(NullList).to be_null
|
54
54
|
end
|
55
55
|
|
56
|
-
it '
|
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
|
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
|
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
|
-
|
36
|
-
|
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,
|
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,
|
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,
|
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,
|
110
|
-
expect(visitor.resume).to eq([:cdr,
|
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,
|
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
|
-
|
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
|
data/spec/glue/dsl_chap2_spec.rb
CHANGED
@@ -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
|
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
|
-
|
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.
|
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-
|
11
|
+
date: 2020-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|