mini_kraken 0.1.06 → 0.1.07
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/.travis.yml +5 -1
- data/CHANGELOG.md +16 -1
- data/README.md +1 -1
- data/lib/mini_kraken/core/conj2.rb +0 -13
- data/lib/mini_kraken/core/cons_cell.rb +49 -43
- data/lib/mini_kraken/core/disj2.rb +67 -0
- data/lib/mini_kraken/core/environment.rb +1 -1
- data/lib/mini_kraken/core/goal_relation.rb +13 -0
- data/lib/mini_kraken/core/outcome.rb +28 -26
- data/lib/mini_kraken/core/vocabulary.rb +15 -13
- data/lib/mini_kraken/glue/run_star_expression.rb +11 -2
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/core/cons_cell_spec.rb +8 -0
- data/spec/core/disj2_spec.rb +144 -0
- data/spec/core/vocabulary_spec.rb +5 -5
- data/spec/glue/run_star_expression_spec.rb +113 -54
- data/spec/support/factory_methods.rb +9 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15536181da18de42e83ec948742a97c63338f2065841849de64d3537eeeb9bc1
|
4
|
+
data.tar.gz: bb25b2bfcab17da55d5dfa6845e699fa2a48e89e19956f3c63f2e755577d4ae7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a964e66c182fa2d834007c2003fa7b16b0e91d8cc80f8525de9c95df89d81523a9a2e93c7e57c2a96605ce6af5244324d5a7bf80c877d46a8a647726a3ac1e49
|
7
|
+
data.tar.gz: 6608b250a6949ce6d7f3fd4c548c7525595fc20c808b5fa327b2cdc1b48ac5b37dd05ee92ae4a8ea2e9a5f76477c24afd5b20e6d1851061afca43952f8d75949
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
|
+
## [0.1.07] - 2020-05-23
|
2
|
+
- Implementation of `disj2` (two arguments disjunction - or -)
|
3
|
+
|
4
|
+
### New
|
5
|
+
- Class `Disj2` as subclass of `GoalRelation` that implements the disjunction of two subgoals
|
6
|
+
|
7
|
+
### CHANGED
|
8
|
+
- Class `Disj2`: common code with `Conj2` class factored out to superclass `GoalRelation`
|
9
|
+
- File `cons_cell.rb`: prevent multiple inclusions via different requires
|
10
|
+
- Method `Vocabulary#ancestor_walker` now returns an `Enumerator` instead of a `Fiber`.
|
11
|
+
|
12
|
+
### FIXED
|
13
|
+
- Method `RunStarExpression#run` clear associations and rankings for second and consecutive solmutions
|
14
|
+
|
15
|
+
|
1
16
|
## [0.1.06] - 2020-05-20
|
2
|
-
- Implementation of `conj2` (two arguments conjunction)
|
17
|
+
- Implementation of `conj2` (two arguments conjunction - and -)
|
3
18
|
|
4
19
|
### New
|
5
20
|
- Class `CompositeGoal`
|
data/README.md
CHANGED
@@ -68,19 +68,6 @@ module MiniKraken
|
|
68
68
|
|
69
69
|
Fiber.yield nil
|
70
70
|
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def validated_args(actuals)
|
75
|
-
actuals.each do |arg|
|
76
|
-
unless arg.kind_of?(Goal)
|
77
|
-
prefix = 'conj2 expects goal as argument, found a '
|
78
|
-
raise StandardError, prefix + "'#{arg.class}'"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
actuals
|
83
|
-
end
|
84
71
|
end # class
|
85
72
|
end # module
|
86
73
|
end # module
|
@@ -2,47 +2,53 @@
|
|
2
2
|
|
3
3
|
require_relative 'composite_term'
|
4
4
|
|
5
|
-
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
5
|
+
unless MiniKraken::Core.constants(false).include? :ConsCell
|
6
|
+
module MiniKraken
|
7
|
+
module Core
|
8
|
+
class ConsCell < CompositeTerm
|
9
|
+
attr_reader :car
|
10
|
+
attr_reader :cdr
|
11
|
+
|
12
|
+
def initialize(obj1, obj2 = nil)
|
13
|
+
@car = obj1
|
14
|
+
@cdr = obj2
|
15
|
+
end
|
16
|
+
|
17
|
+
def children
|
18
|
+
[car, cdr]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return true if it is an empty list, otherwise false.
|
22
|
+
# A list is empty, when both car and cdr fields are nil.
|
23
|
+
def null?
|
24
|
+
car.nil? && cdr.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
return false unless other.respond_to?(:car)
|
29
|
+
|
30
|
+
(car == other.car) && (cdr == other.cdr)
|
31
|
+
end
|
32
|
+
|
33
|
+
def eql?(other)
|
34
|
+
(self.class == other.class) && car.eql?(other.car) && cdr.eql?(other.cdr)
|
35
|
+
end
|
36
|
+
|
37
|
+
def quote(anEnv)
|
38
|
+
return self if null?
|
39
|
+
|
40
|
+
new_car = car.nil? ? nil : car.quote(anEnv)
|
41
|
+
new_cdr = cdr.nil? ? nil : cdr.quote(anEnv)
|
42
|
+
ConsCell.new(new_car, new_cdr)
|
43
|
+
end
|
44
|
+
|
45
|
+
def append(another)
|
46
|
+
@cdr = another
|
47
|
+
end
|
48
|
+
end # class
|
49
|
+
|
50
|
+
# Constant representing the null (empty) list.
|
51
|
+
NullList = ConsCell.new(nil, nil).freeze
|
52
|
+
end # module
|
47
53
|
end # module
|
48
|
-
end #
|
54
|
+
end # defined
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require_relative 'duck_fiber'
|
5
|
+
require_relative 'goal'
|
6
|
+
require_relative 'goal_relation'
|
7
|
+
require_relative 'outcome'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
# The disjunction is a relation that accepts only goal(s) as its two
|
12
|
+
# arguments. It succeeds if at least one of its goal arguments succeeds.
|
13
|
+
class Disj2 < GoalRelation
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super('disj2', nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param actuals [Array<Term>] A two-elements array
|
21
|
+
# @param anEnv [Vocabulary] A vocabulary object
|
22
|
+
# @return [Fiber<Outcome>] A Fiber that yields Outcomes objects
|
23
|
+
def solver_for(actuals, anEnv)
|
24
|
+
g1, g2 = *validated_args(actuals)
|
25
|
+
Fiber.new { disjunction(g1, g2, anEnv) }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Yields [Outcome, NilClass] result of the disjunction
|
29
|
+
# @param g1 [Goal] First goal argument
|
30
|
+
# @param g2 [Goal] Second goal argument
|
31
|
+
# @param voc [Vocabulary] A vocabulary object
|
32
|
+
def disjunction(g1, g2, voc)
|
33
|
+
# require 'debug'
|
34
|
+
outcome1 = nil
|
35
|
+
outcome2 = nil
|
36
|
+
if g1.relation.kind_of?(Fail) && g2.relation.kind_of?(Fail)
|
37
|
+
Fiber.yield Outcome.new(:"#u", voc)
|
38
|
+
else
|
39
|
+
f1 = g1.attain(voc)
|
40
|
+
loop do
|
41
|
+
outcome1 = f1.resume
|
42
|
+
break unless outcome1
|
43
|
+
|
44
|
+
outcome1.parent = voc unless outcome1.parent
|
45
|
+
if outcome1.successful?
|
46
|
+
Fiber.yield outcome1
|
47
|
+
outcome1.clear
|
48
|
+
end
|
49
|
+
end
|
50
|
+
f2 = g2.attain(voc)
|
51
|
+
loop do
|
52
|
+
outcome2 = f2.resume
|
53
|
+
break unless outcome2
|
54
|
+
|
55
|
+
outcome2.parent = voc unless outcome2.parent
|
56
|
+
if outcome2.successful?
|
57
|
+
Fiber.yield outcome2
|
58
|
+
outcome2.clear
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Fiber.yield nil
|
64
|
+
end
|
65
|
+
end # class
|
66
|
+
end # module
|
67
|
+
end # module
|
@@ -10,6 +10,19 @@ module MiniKraken
|
|
10
10
|
def arity
|
11
11
|
2
|
12
12
|
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def validated_args(actuals)
|
17
|
+
actuals.each do |arg|
|
18
|
+
unless arg.kind_of?(Goal)
|
19
|
+
prefix = "#{name} expects goal as argument, found a "
|
20
|
+
raise StandardError, prefix + "'#{arg.class}'"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
actuals
|
25
|
+
end
|
13
26
|
end # class
|
14
27
|
end # module
|
15
28
|
end # module
|
@@ -2,36 +2,38 @@
|
|
2
2
|
|
3
3
|
require_relative 'vocabulary'
|
4
4
|
|
5
|
-
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
unless MiniKraken::Core.constants(false).include? :Outcome
|
6
|
+
module MiniKraken
|
7
|
+
module Core
|
8
|
+
class Outcome
|
9
|
+
include Vocabulary # Use mix-in module
|
10
|
+
|
11
|
+
# @return [Symbol] One of: :"#s" (success), :"#u" (failure)
|
12
|
+
attr_reader :resultant
|
13
|
+
|
14
|
+
def initialize(aResult, aParent = nil)
|
15
|
+
init_vocabulary(aParent)
|
16
|
+
@resultant = aResult
|
17
|
+
end
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
19
|
+
def successful?
|
20
|
+
resultant == :"#s"
|
21
|
+
end
|
17
22
|
|
18
|
-
|
19
|
-
|
20
|
-
end
|
23
|
+
def ==(other)
|
24
|
+
are_equal = false
|
21
25
|
|
22
|
-
|
23
|
-
|
26
|
+
if resultant == other.resultant && parent == other.parent &&
|
27
|
+
associations == other.associations
|
28
|
+
are_equal = true
|
29
|
+
end
|
24
30
|
|
25
|
-
|
26
|
-
associations == other.associations
|
27
|
-
are_equal = true
|
31
|
+
are_equal
|
28
32
|
end
|
33
|
+
end # class
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
end #
|
33
|
-
|
34
|
-
Failure = Outcome.new(:"#u")
|
35
|
-
BasicSuccess = Outcome.new(:"#s")
|
35
|
+
Failure = Outcome.new(:"#u")
|
36
|
+
BasicSuccess = Outcome.new(:"#s")
|
37
|
+
end # module
|
36
38
|
end # module
|
37
|
-
end #
|
39
|
+
end # defined
|
@@ -23,26 +23,28 @@ module MiniKraken
|
|
23
23
|
@rankings = {} unless aParent
|
24
24
|
end
|
25
25
|
|
26
|
-
# Return a
|
26
|
+
# Return a Enumerator object that can iterate over this vocabulary and
|
27
27
|
# all its direct and indirect parent(s).
|
28
|
-
# @return [
|
28
|
+
# @return [Enumerator<Vocabulary, NilClass>]
|
29
29
|
def ancestor_walker
|
30
|
-
|
30
|
+
unless @ancestors # Not yet in cache?...
|
31
|
+
@ancestors = []
|
31
32
|
relative = self
|
32
33
|
while relative
|
33
|
-
|
34
|
+
@ancestors << relative
|
34
35
|
relative = relative.parent
|
35
36
|
end
|
36
|
-
|
37
|
-
Fiber.yield nil # nil marks end of iteration...
|
37
|
+
@ancestors << nil # nil marks end of iteration...
|
38
38
|
end
|
39
|
+
|
40
|
+
@ancestors.to_enum
|
39
41
|
end
|
40
42
|
|
41
43
|
def clear_rankings
|
42
44
|
walker = ancestor_walker
|
43
45
|
orphan = nil
|
44
46
|
loop do
|
45
|
-
orphan_temp = walker.
|
47
|
+
orphan_temp = walker.next
|
46
48
|
break unless orphan_temp
|
47
49
|
|
48
50
|
orphan = orphan_temp
|
@@ -57,7 +59,7 @@ module MiniKraken
|
|
57
59
|
walker = ancestor_walker
|
58
60
|
orphan = nil
|
59
61
|
loop do
|
60
|
-
orphan_temp = walker.
|
62
|
+
orphan_temp = walker.next
|
61
63
|
break unless orphan_temp
|
62
64
|
|
63
65
|
orphan = orphan_temp
|
@@ -182,7 +184,7 @@ module MiniKraken
|
|
182
184
|
walker = ancestor_walker
|
183
185
|
|
184
186
|
loop do
|
185
|
-
voc = walker.
|
187
|
+
voc = walker.next
|
186
188
|
break unless voc
|
187
189
|
|
188
190
|
if voc.associations.include?(old_i_name)
|
@@ -277,7 +279,7 @@ module MiniKraken
|
|
277
279
|
walker = ancestor_walker
|
278
280
|
|
279
281
|
loop do
|
280
|
-
voc = walker.
|
282
|
+
voc = walker.next
|
281
283
|
if voc
|
282
284
|
next unless voc.respond_to?(:vars) && voc.vars.include?(aName)
|
283
285
|
|
@@ -299,7 +301,7 @@ module MiniKraken
|
|
299
301
|
walker = ancestor_walker
|
300
302
|
|
301
303
|
loop do
|
302
|
-
voc = walker.
|
304
|
+
voc = walker.next
|
303
305
|
if voc
|
304
306
|
next unless voc.respond_to?(:ivars) && voc.ivars.include?(i_name)
|
305
307
|
|
@@ -335,7 +337,7 @@ module MiniKraken
|
|
335
337
|
walker = ancestor_walker
|
336
338
|
|
337
339
|
loop do
|
338
|
-
voc = walker.
|
340
|
+
voc = walker.next
|
339
341
|
break unless voc
|
340
342
|
next unless voc.respond_to?(:ivars)
|
341
343
|
|
@@ -358,7 +360,7 @@ module MiniKraken
|
|
358
360
|
walker = ancestor_walker
|
359
361
|
|
360
362
|
loop do
|
361
|
-
voc = walker.
|
363
|
+
voc = walker.next
|
362
364
|
break unless voc
|
363
365
|
next unless voc.associations.include?(i_name)
|
364
366
|
|
@@ -21,20 +21,29 @@ module MiniKraken
|
|
21
21
|
|
22
22
|
def run
|
23
23
|
result = nil
|
24
|
+
next_result = nil
|
24
25
|
solver = env.goal.attain(env)
|
25
26
|
# require 'debug'
|
26
27
|
loop do
|
28
|
+
env.clear
|
29
|
+
env.clear_rankings
|
27
30
|
outcome = solver.resume
|
28
31
|
break if outcome.nil?
|
29
32
|
|
30
|
-
env.clear
|
31
33
|
if result # ... more than one result...
|
34
|
+
if outcome.successful?
|
35
|
+
next_result.append(Core::ConsCell.new(var.quote(outcome)))
|
36
|
+
else
|
37
|
+
next_result.append(Core::NullList)
|
38
|
+
end
|
39
|
+
next_result = next_result.cdr
|
32
40
|
elsif outcome.successful?
|
33
41
|
env.propagate(outcome)
|
34
42
|
result = Core::ConsCell.new(var.quote(outcome))
|
43
|
+
next_result = result
|
35
44
|
else
|
36
45
|
result = Core::NullList
|
37
|
-
|
46
|
+
next_result = result
|
38
47
|
end
|
39
48
|
end
|
40
49
|
|
data/lib/mini_kraken/version.rb
CHANGED
data/spec/core/cons_cell_spec.rb
CHANGED
@@ -58,6 +58,14 @@ module MiniKraken
|
|
58
58
|
different = ConsCell.new(pea)
|
59
59
|
expect(subject.eql?(different)).to be_falsey
|
60
60
|
end
|
61
|
+
|
62
|
+
it 'should append another cons cell' do
|
63
|
+
instance = ConsCell.new(pea)
|
64
|
+
trail = ConsCell.new(pod)
|
65
|
+
instance.append(trail)
|
66
|
+
expect(instance.car).to eq(pea)
|
67
|
+
expect(instance.cdr).to eq(trail)
|
68
|
+
end
|
61
69
|
end # context
|
62
70
|
end # describe
|
63
71
|
end # module
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../lib/mini_kraken/core/k_symbol'
|
5
|
+
require_relative '../../lib/mini_kraken/core/fail'
|
6
|
+
require_relative '../../lib/mini_kraken/core/succeed'
|
7
|
+
require_relative '../../lib/mini_kraken/core/equals'
|
8
|
+
require_relative '../../lib/mini_kraken/core/environment'
|
9
|
+
require_relative '../../lib/mini_kraken/core/variable'
|
10
|
+
require_relative '../../lib/mini_kraken/core/variable_ref'
|
11
|
+
|
12
|
+
# Load the class under test
|
13
|
+
require_relative '../../lib/mini_kraken/core/disj2'
|
14
|
+
|
15
|
+
module MiniKraken
|
16
|
+
module Core
|
17
|
+
describe Disj2 do
|
18
|
+
subject { Disj2.instance }
|
19
|
+
|
20
|
+
context 'Initialization:' do
|
21
|
+
it 'should be initialized without argument' do
|
22
|
+
expect { Disj2.instance }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should know its name' do
|
26
|
+
expect(subject.name).to eq('disj2')
|
27
|
+
end
|
28
|
+
end # context
|
29
|
+
|
30
|
+
context 'Provided services:' do
|
31
|
+
let(:corn) { KSymbol.new(:corn) }
|
32
|
+
let(:meal) { KSymbol.new(:meal) }
|
33
|
+
let(:oil) { KSymbol.new(:oil) }
|
34
|
+
let(:olive) { KSymbol.new(:olive) }
|
35
|
+
let(:pea) { KSymbol.new(:pea) }
|
36
|
+
let(:fails) { Goal.new(Fail.instance, []) }
|
37
|
+
let(:succeeds) { Goal.new(Succeed.instance, []) }
|
38
|
+
let(:var_q) { Variable.new('q') }
|
39
|
+
let(:ref_q) { VariableRef.new('q') }
|
40
|
+
let(:env) do
|
41
|
+
e = Environment.new
|
42
|
+
e.add_var(var_q)
|
43
|
+
e
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should complain when one of its argument is not a goal' do
|
47
|
+
err = StandardError
|
48
|
+
expect { subject.solver_for([succeeds, pea], env) }.to raise_error(err)
|
49
|
+
expect { subject.solver_for([pea, succeeds], env) }.to raise_error(err)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should fails if both arguments fail' do
|
53
|
+
# Covers frame 1:55
|
54
|
+
solver = subject.solver_for([fails, fails], env)
|
55
|
+
expect(solver.resume).not_to be_successful
|
56
|
+
expect(solver.resume).to be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'yield success if first argument succeeds' do
|
60
|
+
# Covers frame 1:56
|
61
|
+
subgoal = Goal.new(Equals.instance, [olive, ref_q])
|
62
|
+
solver = subject.solver_for([subgoal, fails], env)
|
63
|
+
outcome = solver.resume
|
64
|
+
expect(outcome).to be_successful
|
65
|
+
expect(outcome.associations['q'].first.value).to eq(olive)
|
66
|
+
expect(solver.resume).to be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'yield success if second argument succeeds' do
|
70
|
+
# Covers frame 1:57
|
71
|
+
subgoal = Goal.new(Equals.instance, [oil, ref_q])
|
72
|
+
solver = subject.solver_for([fails, subgoal], env)
|
73
|
+
outcome = solver.resume
|
74
|
+
expect(outcome).to be_successful
|
75
|
+
expect(outcome.associations['q'].first.value).to eq(oil)
|
76
|
+
expect(solver.resume).to be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'yield two solutions if both arguments succeed' do
|
80
|
+
# Covers frame 1:58
|
81
|
+
subgoal1 = Goal.new(Equals.instance, [olive, ref_q])
|
82
|
+
subgoal2 = Goal.new(Equals.instance, [oil, ref_q])
|
83
|
+
solver = subject.solver_for([subgoal1, subgoal2], env)
|
84
|
+
|
85
|
+
# First solution
|
86
|
+
outcome1 = solver.resume
|
87
|
+
expect(outcome1).to be_successful
|
88
|
+
expect(outcome1.associations['q'].first.value).to eq(olive)
|
89
|
+
|
90
|
+
# Second solution
|
91
|
+
outcome2 = solver.resume
|
92
|
+
expect(outcome2).to be_successful
|
93
|
+
expect(outcome2.associations['q'].first.value).to eq(oil)
|
94
|
+
expect(solver.resume).to be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should yield success and set associations' do
|
98
|
+
# # Weird: this example succeeds if run alone...
|
99
|
+
# # Covers frame 1-51
|
100
|
+
# env.add_var(var_q)
|
101
|
+
# sub_goal = Goal.new(Equals.instance, [corn, ref_q])
|
102
|
+
# solver = subject.solver_for([succeeds, sub_goal], env)
|
103
|
+
# outcome = solver.resume
|
104
|
+
# expect(outcome).to be_successful
|
105
|
+
# expect(outcome.associations).not_to be_empty
|
106
|
+
# expect(outcome.associations['q'].first.value).to eq(corn)
|
107
|
+
end
|
108
|
+
|
109
|
+
# it 'should yield fails and set no associations' do
|
110
|
+
# # Covers frame 1-52
|
111
|
+
# env.add_var(var_q)
|
112
|
+
# sub_goal = Goal.new(Equals.instance, [corn, ref_q])
|
113
|
+
# solver = subject.solver_for([fails, sub_goal], env)
|
114
|
+
# outcome = solver.resume
|
115
|
+
# expect(outcome).not_to be_successful
|
116
|
+
# expect(outcome.associations).to be_empty
|
117
|
+
# end
|
118
|
+
|
119
|
+
# it 'should yield fails when sub-goals are incompatible' do
|
120
|
+
# # Covers frame 1-53
|
121
|
+
# env.add_var(var_q)
|
122
|
+
# sub_goal1 = Goal.new(Equals.instance, [corn, ref_q])
|
123
|
+
# sub_goal2 = Goal.new(Equals.instance, [meal, ref_q])
|
124
|
+
# solver = subject.solver_for([sub_goal1, sub_goal2], env)
|
125
|
+
# outcome = solver.resume
|
126
|
+
# expect(outcome).not_to be_successful
|
127
|
+
# expect(outcome.associations).to be_empty
|
128
|
+
# end
|
129
|
+
|
130
|
+
# it 'should yield success when sub-goals are same and successful' do
|
131
|
+
# # Covers frame 1-54
|
132
|
+
# env.add_var(var_q)
|
133
|
+
# sub_goal1 = Goal.new(Equals.instance, [corn, ref_q])
|
134
|
+
# sub_goal2 = Goal.new(Equals.instance, [corn, ref_q])
|
135
|
+
# solver = subject.solver_for([sub_goal1, sub_goal2], env)
|
136
|
+
# outcome = solver.resume
|
137
|
+
# expect(outcome).to be_successful
|
138
|
+
# expect(outcome.associations).not_to be_empty
|
139
|
+
# expect(outcome.associations['q'].first.value).to eq(corn)
|
140
|
+
# end
|
141
|
+
end # context
|
142
|
+
end # describe
|
143
|
+
end # module
|
144
|
+
end # module
|
@@ -79,11 +79,11 @@ module MiniKraken
|
|
79
79
|
|
80
80
|
it 'should provide a walker over ancestors' do
|
81
81
|
walker = subject.ancestor_walker
|
82
|
-
expect(walker).to be_kind_of(
|
83
|
-
expect(walker.
|
84
|
-
expect(walker.
|
85
|
-
expect(walker.
|
86
|
-
expect(walker.
|
82
|
+
expect(walker).to be_kind_of(Enumerator)
|
83
|
+
expect(walker.next).to eq(subject)
|
84
|
+
expect(walker.next).to eq(mother)
|
85
|
+
expect(walker.next).to eq(grandma)
|
86
|
+
expect(walker.next).to be_nil
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'should know if a variable is defined' do
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
4
|
require_relative '../../lib/mini_kraken/core/goal'
|
5
5
|
require_relative '../../lib/mini_kraken/core/conj2'
|
6
|
+
require_relative '../../lib/mini_kraken/core/disj2'
|
6
7
|
require_relative '../../lib/mini_kraken/core/equals'
|
7
8
|
require_relative '../../lib/mini_kraken/core/fail'
|
8
9
|
require_relative '../../lib/mini_kraken/core/succeed'
|
@@ -40,6 +41,8 @@ module MiniKraken
|
|
40
41
|
context 'Provided services:' do
|
41
42
|
let(:corn) { k_symbol(:corn) }
|
42
43
|
let(:meal) { k_symbol(:meal) }
|
44
|
+
let(:oil) { k_symbol(:oil) }
|
45
|
+
let(:olive) { k_symbol(:olive) }
|
43
46
|
let(:ref_q) { Core::VariableRef.new('q') }
|
44
47
|
let(:ref_x) { Core::VariableRef.new('x') }
|
45
48
|
let(:ref_y) { Core::VariableRef.new('y') }
|
@@ -56,7 +59,6 @@ module MiniKraken
|
|
56
59
|
instance = RunStarExpression.new('q', failing)
|
57
60
|
|
58
61
|
expect(instance.run).to be_null
|
59
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
60
62
|
end
|
61
63
|
|
62
64
|
it 'should return a null list when a goal fails' do
|
@@ -74,7 +76,6 @@ module MiniKraken
|
|
74
76
|
# Reasoned S2, frame 1:11
|
75
77
|
# (run* q (== q 'pea) ;; => (pea)
|
76
78
|
expect(instance.run.car).to eq(pea)
|
77
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
78
79
|
end
|
79
80
|
|
80
81
|
it 'should unify the righthand variable(s)' do
|
@@ -84,9 +85,6 @@ module MiniKraken
|
|
84
85
|
# Reasoned S2, frame 1:12
|
85
86
|
# (run* q (== 'pea q) ;; => (pea)
|
86
87
|
expect(instance.run.car).to eq(pea)
|
87
|
-
|
88
|
-
# Reasoned S2, frame 1:15
|
89
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
90
88
|
end
|
91
89
|
|
92
90
|
it 'should return a null list with the succeed goal' do
|
@@ -96,7 +94,6 @@ module MiniKraken
|
|
96
94
|
# (display (run* q succeed)) ;; => (_0)
|
97
95
|
# Reasoned S2, frame 1:16
|
98
96
|
result = instance.run
|
99
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
100
97
|
|
101
98
|
# Reasoned S2, frame 1:17
|
102
99
|
expect(result.car).to eq(any_value(0))
|
@@ -109,7 +106,6 @@ module MiniKraken
|
|
109
106
|
# (display (run* q (== 'pea 'pea))) ;; => (_0)
|
110
107
|
# Reasoned S2, frame 1:19
|
111
108
|
result = instance.run
|
112
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
113
109
|
expect(result.car).to eq(any_value(0))
|
114
110
|
end
|
115
111
|
|
@@ -122,7 +118,6 @@ module MiniKraken
|
|
122
118
|
# (display (run* q (== q q))) ;; => (_0)
|
123
119
|
# Reasoned S2, frame 1:20
|
124
120
|
result = instance.run
|
125
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
126
121
|
expect(result.car).to eq(any_value(0))
|
127
122
|
end
|
128
123
|
|
@@ -134,8 +129,6 @@ module MiniKraken
|
|
134
129
|
# Reasoned S2, frame 1:21..23
|
135
130
|
# (run* q (fresh (x) (== 'pea q))) ;; => (pea)
|
136
131
|
result = instance.run
|
137
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
138
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
139
132
|
|
140
133
|
# Reasoned S2, frame 1:40
|
141
134
|
expect(ref_q.different_from?(ref_x, fresh_env)).to be_truthy
|
@@ -150,8 +143,6 @@ module MiniKraken
|
|
150
143
|
# Reasoned S2, frame 1:24
|
151
144
|
# (run* q (fresh (x) (== 'pea x))) ;; => (_0)
|
152
145
|
result = instance.run
|
153
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
154
|
-
expect(ref_x.fresh?(fresh_env)).to be_falsey
|
155
146
|
expect(result.car).to eq(any_value(0))
|
156
147
|
end
|
157
148
|
|
@@ -163,8 +154,6 @@ module MiniKraken
|
|
163
154
|
# Reasoned S2, frame 1:25
|
164
155
|
# (run* q (fresh (x) (== (cons x '()) q))) ;; => ((_0))
|
165
156
|
result = instance.run
|
166
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
167
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
168
157
|
expect(result.car).to eq(cons(any_value(0)))
|
169
158
|
end
|
170
159
|
|
@@ -195,7 +184,6 @@ module MiniKraken
|
|
195
184
|
# Reasoned S2, frame 1:32
|
196
185
|
# (run* q (== '(((pea)) pod) '(((pea)) pod))) ;; => (_0)
|
197
186
|
result = instance.run
|
198
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
199
187
|
expect(result.car).to eq(any_value(0))
|
200
188
|
end
|
201
189
|
|
@@ -209,7 +197,6 @@ module MiniKraken
|
|
209
197
|
# Reasoned S2, frame 1:33
|
210
198
|
# (run* q (== '(((pea)) pod) `(((pea)) ,q))) ;; => ('pod)
|
211
199
|
result = instance.run
|
212
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
213
200
|
expect(result.car).to eq(pod)
|
214
201
|
end
|
215
202
|
|
@@ -222,7 +209,6 @@ module MiniKraken
|
|
222
209
|
# Reasoned S2, frame 1:34
|
223
210
|
# (run* q (== '(((,q)) pod) `(((pea)) pod))) ;; => ('pod)
|
224
211
|
result = instance.run
|
225
|
-
expect(ref_q.fresh?(instance.env)).to be_falsey
|
226
212
|
expect(result.car).to eq(pea)
|
227
213
|
end
|
228
214
|
|
@@ -236,8 +222,6 @@ module MiniKraken
|
|
236
222
|
# Reasoned S2, frame 1:35
|
237
223
|
# (run* q (fresh (x) (== '(((,q)) pod) `(((,x)) pod)))) ;; => (_0)
|
238
224
|
result = instance.run
|
239
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
240
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
241
225
|
expect(result.car).to eq(any_value(0))
|
242
226
|
end
|
243
227
|
|
@@ -251,11 +235,6 @@ module MiniKraken
|
|
251
235
|
instance = RunStarExpression.new('q', fresh_env)
|
252
236
|
|
253
237
|
result = instance.run
|
254
|
-
|
255
|
-
# Does propagate work correctly?
|
256
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy # x isn't defined here
|
257
|
-
expect(ref_q.fresh?(fresh_env)).to be_falsey
|
258
|
-
expect(ref_x.fresh?(fresh_env)).to be_falsey
|
259
238
|
expect(result.car).to eq(pod)
|
260
239
|
end
|
261
240
|
|
@@ -268,9 +247,6 @@ module MiniKraken
|
|
268
247
|
instance = RunStarExpression.new('q', fresh_env)
|
269
248
|
|
270
249
|
result = instance.run
|
271
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy # x isn't defined here
|
272
|
-
expect(ref_q.fresh?(fresh_env)).to be_truthy
|
273
|
-
expect(ref_x.fresh?(fresh_env)).to be_truthy
|
274
250
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(0))))
|
275
251
|
end
|
276
252
|
|
@@ -285,12 +261,6 @@ module MiniKraken
|
|
285
261
|
instance = RunStarExpression.new('q', fresh_env_x)
|
286
262
|
|
287
263
|
result = instance.run
|
288
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
289
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
290
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
291
|
-
expect(ref_x.bound?(fresh_env_y)).to be_falsy
|
292
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
293
|
-
expect(ref_y.bound?(fresh_env_y)).to be_falsy
|
294
264
|
|
295
265
|
# y should be fused with x...
|
296
266
|
var_x = fresh_env_y.name2var('x')
|
@@ -314,13 +284,7 @@ module MiniKraken
|
|
314
284
|
instance = RunStarExpression.new('q', fresh_env_x)
|
315
285
|
|
316
286
|
result = instance.run
|
317
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
318
287
|
# q should be bound to '(,x ,y)
|
319
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
320
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
321
|
-
expect(ref_x.bound?(fresh_env_y)).to be_falsey
|
322
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
323
|
-
expect(ref_y.bound?(fresh_env_y)).to be_falsey
|
324
288
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
325
289
|
end
|
326
290
|
|
@@ -334,13 +298,7 @@ module MiniKraken
|
|
334
298
|
instance = RunStarExpression.new('s', fresh_env_t)
|
335
299
|
|
336
300
|
result = instance.run
|
337
|
-
expect(ref_s.fresh?(fresh_env_u)).to be_truthy
|
338
301
|
# s should be bound to '(,t ,u)
|
339
|
-
expect(ref_s.bound?(fresh_env_u)).to be_truthy
|
340
|
-
expect(ref_t.fresh?(fresh_env_u)).to be_truthy
|
341
|
-
expect(ref_t.bound?(fresh_env_u)).to be_falsey
|
342
|
-
expect(ref_u.fresh?(fresh_env_u)).to be_truthy
|
343
|
-
expect(ref_u.bound?(fresh_env_u)).to be_falsey
|
344
302
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
345
303
|
end
|
346
304
|
|
@@ -354,11 +312,7 @@ module MiniKraken
|
|
354
312
|
instance = RunStarExpression.new('q', fresh_env_x)
|
355
313
|
|
356
314
|
result = instance.run
|
357
|
-
expect(ref_q.fresh?(fresh_env_y)).to be_truthy
|
358
315
|
# q should be bound to '(,x ,y, ,x)
|
359
|
-
expect(ref_q.bound?(fresh_env_y)).to be_truthy
|
360
|
-
expect(ref_x.fresh?(fresh_env_y)).to be_truthy
|
361
|
-
expect(ref_y.fresh?(fresh_env_y)).to be_truthy
|
362
316
|
expect(result.car).to eq(cons(any_value(0), cons(any_value(1), cons(any_value(0)))))
|
363
317
|
end
|
364
318
|
|
@@ -369,7 +323,6 @@ module MiniKraken
|
|
369
323
|
# Reasoned S2, frame 1:50
|
370
324
|
# (run* q (conj2 succeed succeed)) ;; => (_0)
|
371
325
|
result = instance.run
|
372
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
373
326
|
expect(result.car).to eq(any_value(0))
|
374
327
|
end
|
375
328
|
|
@@ -382,7 +335,6 @@ module MiniKraken
|
|
382
335
|
# # Reasoned S2, frame 1:51
|
383
336
|
# # (run* q (conj2 succeed (== 'corn q)) ;; => ('corn)
|
384
337
|
# result = instance.run
|
385
|
-
# expect(ref_q.fresh?(instance.env)).to be_falsy
|
386
338
|
# expect(result.car).to eq(corn)
|
387
339
|
# end
|
388
340
|
|
@@ -394,7 +346,6 @@ module MiniKraken
|
|
394
346
|
# Reasoned S2, frame 1:52
|
395
347
|
# (run* q (conj2 fail (== 'corn q)) ;; => ()
|
396
348
|
expect(instance.run).to be_null
|
397
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
398
349
|
end
|
399
350
|
|
400
351
|
it 'should support conjunction of two contradictory goals' do
|
@@ -406,7 +357,6 @@ module MiniKraken
|
|
406
357
|
# Reasoned S2, frame 1:53
|
407
358
|
# (run* q (conj2 (== 'corn q)(== 'meal q)) ;; => ()
|
408
359
|
expect(instance.run).to be_null
|
409
|
-
expect(ref_q.fresh?(instance.env)).to be_truthy
|
410
360
|
end
|
411
361
|
|
412
362
|
it 'should succeed the conjunction of two identical goals' do
|
@@ -418,9 +368,118 @@ module MiniKraken
|
|
418
368
|
# Reasoned S2, frame 1:54
|
419
369
|
# (run* q (conj2 (== 'corn q)(== 'corn q)) ;; => ('corn)
|
420
370
|
result = instance.run
|
421
|
-
expect(ref_q.fresh?(instance.env)).to be_falsy
|
422
371
|
expect(result.car).to eq(corn)
|
423
372
|
end
|
373
|
+
|
374
|
+
it 'should not yield solution when both disjunction arguments fail' do
|
375
|
+
goal = disj2_goal(fails, fails)
|
376
|
+
instance = RunStarExpression.new('q', goal)
|
377
|
+
|
378
|
+
# Reasoned S2, frame 1:55
|
379
|
+
# (run* q (disj2 fail fail)) ;; => ()
|
380
|
+
expect(instance.run).to be_null
|
381
|
+
end
|
382
|
+
|
383
|
+
it 'should yield solution when first argument succeed' do
|
384
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_q])
|
385
|
+
goal = disj2_goal(subgoal, fails)
|
386
|
+
instance = RunStarExpression.new('q', goal)
|
387
|
+
|
388
|
+
# Reasoned S2, frame 1:56
|
389
|
+
# (run* q (disj2 (equals 'olive q) fail)) ;; => ('olive)
|
390
|
+
result = instance.run
|
391
|
+
expect(result.car).to eq(olive)
|
392
|
+
end
|
393
|
+
|
394
|
+
it 'should yield solution when second argument succeed' do
|
395
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_q])
|
396
|
+
goal = disj2_goal(fails, subgoal)
|
397
|
+
instance = RunStarExpression.new('q', goal)
|
398
|
+
|
399
|
+
# Reasoned S2, frame 1:57
|
400
|
+
# (run* q (disj2 fail (equals 'oil q)) ;; => (oil)
|
401
|
+
result = instance.run
|
402
|
+
expect(result.car).to eq(oil)
|
403
|
+
end
|
404
|
+
|
405
|
+
it 'should yield solutions when both arguments succeed' do
|
406
|
+
subgoal1 = Core::Goal.new(Core::Equals.instance, [olive, ref_q])
|
407
|
+
subgoal2 = Core::Goal.new(Core::Equals.instance, [oil, ref_q])
|
408
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
409
|
+
instance = RunStarExpression.new('q', goal)
|
410
|
+
|
411
|
+
# Reasoned S2, frame 1:58
|
412
|
+
# (run* q (disj2 (equals 'olive q) (equals 'oil q)) ;; => (olive oil)
|
413
|
+
result = instance.run
|
414
|
+
expect(result.car).to eq(olive)
|
415
|
+
expect(result.cdr.car).to eq(oil)
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'should support the nesting of variables and disjunction' do
|
419
|
+
# Reasoned S2, frame 1:59
|
420
|
+
# (run* q (fresh (x) (fresh (y) (disj2 (== '( ,x ,y ) q) (== '( ,x ,y ) q)))))
|
421
|
+
# ;; => ((_0 _1) (_0 _1))
|
422
|
+
expr1 = cons(ref_x, cons(ref_y))
|
423
|
+
subgoal1 = equals_goal(expr1, ref_q)
|
424
|
+
expr2 = cons(ref_y, cons(ref_x))
|
425
|
+
subgoal2 = equals_goal(expr2, ref_q)
|
426
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
427
|
+
fresh_env_y = FreshEnv.new(['y'], goal)
|
428
|
+
fresh_env_x = FreshEnv.new(['x'], fresh_env_y)
|
429
|
+
instance = RunStarExpression.new('q', fresh_env_x)
|
430
|
+
|
431
|
+
result = instance.run
|
432
|
+
# q should be bound to '(,x ,y), then to '(,y ,x)
|
433
|
+
expect(result.car).to eq(cons(any_value(0), cons(any_value(1))))
|
434
|
+
expect(result.cdr.car).to eq(cons(any_value(0), cons(any_value(1))))
|
435
|
+
end
|
436
|
+
|
437
|
+
it 'should accept nesting of disj2 and conj2 (I)' do
|
438
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
439
|
+
conjunction = conj2_goal(conj_subgoal, fails)
|
440
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
441
|
+
goal = disj2_goal(conjunction, subgoal)
|
442
|
+
instance = RunStarExpression.new('x', goal)
|
443
|
+
|
444
|
+
# Reasoned S2, frame 1:62
|
445
|
+
# (run* x (disj2
|
446
|
+
# (conj2 (== 'olive x) fail)
|
447
|
+
# ('oil x))) ;; => (oil)
|
448
|
+
result = instance.run
|
449
|
+
expect(result.car).to eq(oil)
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'should accept nesting of disj2 and conj2 (II)' do
|
453
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
454
|
+
conjunction = conj2_goal(conj_subgoal, succeeds)
|
455
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
456
|
+
goal = disj2_goal(conjunction, subgoal)
|
457
|
+
instance = RunStarExpression.new('x', goal)
|
458
|
+
|
459
|
+
# Reasoned S2, frame 1:63
|
460
|
+
# (run* x (disj2
|
461
|
+
# (conj2 (== 'olive x) succeed)
|
462
|
+
# ('oil x))) ;; => (olive oil)
|
463
|
+
result = instance.run
|
464
|
+
expect(result.car).to eq(olive)
|
465
|
+
expect(result.cdr.car).to eq(oil)
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'should accept nesting of disj2 and conj2 (III)' do
|
469
|
+
conj_subgoal = Core::Goal.new(Core::Equals.instance, [olive, ref_x])
|
470
|
+
conjunction = conj2_goal(conj_subgoal, succeeds)
|
471
|
+
subgoal = Core::Goal.new(Core::Equals.instance, [oil, ref_x])
|
472
|
+
goal = disj2_goal(subgoal, conjunction)
|
473
|
+
instance = RunStarExpression.new('x', goal)
|
474
|
+
|
475
|
+
# Reasoned S2, frame 1:64
|
476
|
+
# (run* x (disj2
|
477
|
+
# ('oil x)
|
478
|
+
# (conj2 (== 'olive x) succeed))) ;; => (oil olive)
|
479
|
+
result = instance.run
|
480
|
+
expect(result.car).to eq(oil)
|
481
|
+
expect(result.cdr.car).to eq(olive)
|
482
|
+
end
|
424
483
|
end # context
|
425
484
|
end # describe
|
426
485
|
end # module
|
@@ -34,7 +34,7 @@ module MiniKraken
|
|
34
34
|
Core::Goal.new(Core::Equals.instance, [arg1, arg2])
|
35
35
|
end
|
36
36
|
|
37
|
-
# Factory method for constructing a goal using the
|
37
|
+
# Factory method for constructing a goal using the conjunction relation.
|
38
38
|
# @param g1 [Core::Goal]
|
39
39
|
# @param g2 [Core::Goal]
|
40
40
|
# @return [Core::Goal]
|
@@ -42,6 +42,14 @@ module MiniKraken
|
|
42
42
|
Core::Goal.new(Core::Conj2.instance, [g1, g2])
|
43
43
|
end
|
44
44
|
|
45
|
+
# Factory method for constructing a goal using the disjunction relation.
|
46
|
+
# @param g1 [Core::Goal]
|
47
|
+
# @param g2 [Core::Goal]
|
48
|
+
# @return [Core::Goal]
|
49
|
+
def disj2_goal(g1, g2)
|
50
|
+
Core::Goal.new(Core::Disj2.instance, [g1, g2])
|
51
|
+
end
|
52
|
+
|
45
53
|
# Factory method for constructing a KSymbol instance
|
46
54
|
# @param aSymbol [Symbol]
|
47
55
|
# @return [Core::KSymbol]
|
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.1.
|
4
|
+
version: 0.1.07
|
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-05-
|
11
|
+
date: 2020-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- lib/mini_kraken/core/conj2.rb
|
79
79
|
- lib/mini_kraken/core/cons_cell.rb
|
80
80
|
- lib/mini_kraken/core/designation.rb
|
81
|
+
- lib/mini_kraken/core/disj2.rb
|
81
82
|
- lib/mini_kraken/core/duck_fiber.rb
|
82
83
|
- lib/mini_kraken/core/environment.rb
|
83
84
|
- lib/mini_kraken/core/equals.rb
|
@@ -104,6 +105,7 @@ files:
|
|
104
105
|
- spec/core/association_walker_spec.rb
|
105
106
|
- spec/core/conj2_spec.rb
|
106
107
|
- spec/core/cons_cell_spec.rb
|
108
|
+
- spec/core/disj2_spec.rb
|
107
109
|
- spec/core/duck_fiber_spec.rb
|
108
110
|
- spec/core/environment_spec.rb
|
109
111
|
- spec/core/equals_spec.rb
|
@@ -148,6 +150,7 @@ test_files:
|
|
148
150
|
- spec/core/association_walker_spec.rb
|
149
151
|
- spec/core/conj2_spec.rb
|
150
152
|
- spec/core/cons_cell_spec.rb
|
153
|
+
- spec/core/disj2_spec.rb
|
151
154
|
- spec/core/duck_fiber_spec.rb
|
152
155
|
- spec/core/environment_spec.rb
|
153
156
|
- spec/core/equals_spec.rb
|