mini_kraken 0.1.01 → 0.1.02
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +0 -3
- data/lib/mini_kraken/core/any_value.rb +29 -0
- data/lib/mini_kraken/core/association.rb +21 -0
- data/lib/mini_kraken/core/association_walker.rb +179 -0
- data/lib/mini_kraken/core/atomic_term.rb +64 -0
- data/lib/mini_kraken/core/binary_relation.rb +61 -0
- data/lib/mini_kraken/core/composite_term.rb +54 -0
- data/lib/mini_kraken/core/cons_cell.rb +44 -0
- data/lib/mini_kraken/core/duck_fiber.rb +44 -0
- data/lib/mini_kraken/core/environment.rb +59 -0
- data/lib/mini_kraken/core/equals.rb +216 -0
- data/lib/mini_kraken/core/fail.rb +8 -5
- data/lib/mini_kraken/core/freshness.rb +42 -0
- data/lib/mini_kraken/core/goal.rb +31 -6
- data/lib/mini_kraken/core/k_integer.rb +15 -0
- data/lib/mini_kraken/core/k_symbol.rb +15 -0
- data/lib/mini_kraken/core/nullary_relation.rb +11 -3
- data/lib/mini_kraken/core/outcome.rb +35 -0
- data/lib/mini_kraken/core/relation.rb +31 -4
- data/lib/mini_kraken/core/succeed.rb +13 -1
- data/lib/mini_kraken/core/term.rb +7 -0
- data/lib/mini_kraken/core/variable.rb +45 -3
- data/lib/mini_kraken/core/variable_ref.rb +76 -0
- data/lib/mini_kraken/core/vocabulary.rb +161 -0
- data/lib/mini_kraken/glue/fresh_env.rb +31 -0
- data/lib/mini_kraken/glue/run_star_expression.rb +43 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/core/association_spec.rb +38 -0
- data/spec/core/association_walker_spec.rb +191 -0
- data/spec/core/cons_cell_spec.rb +63 -0
- data/spec/core/duck_fiber_spec.rb +62 -0
- data/spec/core/environment_spec.rb +154 -0
- data/spec/core/equals_spec.rb +289 -0
- data/spec/core/fail_spec.rb +16 -0
- data/spec/core/goal_spec.rb +36 -10
- data/spec/core/k_symbol_spec.rb +72 -0
- data/spec/core/succeed_spec.rb +43 -0
- data/spec/core/variable_ref_spec.rb +31 -0
- data/spec/core/variable_spec.rb +11 -3
- data/spec/core/vocabulary_spec.rb +188 -0
- data/spec/glue/fresh_env_spec.rb +36 -0
- data/spec/glue/run_star_expression_spec.rb +247 -0
- data/spec/support/factory_methods.rb +54 -0
- metadata +46 -13
- data/lib/mini_kraken/core/facade.rb +0 -45
- data/lib/mini_kraken/core/formal_arg.rb +0 -6
- data/lib/mini_kraken/core/publisher.rb +0 -27
- data/lib/mini_kraken/core/run_star_expression.rb +0 -34
- data/lib/mini_kraken/dsl/kraken_dsl.rb +0 -12
- data/spec/core/facade_spec.rb +0 -38
- data/spec/core/run_star_expression_spec.rb +0 -43
- data/spec/dsl/kraken_dsl_spec.rb +0 -31
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative '../core/environment'
|
2
|
+
require_relative '../core/variable'
|
3
|
+
|
4
|
+
module MiniKraken
|
5
|
+
module Glue
|
6
|
+
# (fresh (x) (== 'pea q))
|
7
|
+
# Introduces the new variable 'x'
|
8
|
+
# Takes a list of names and a goal-like object
|
9
|
+
# Must respond to message attain(aPublisher, vars) and must return an Outcome
|
10
|
+
class FreshEnv < Core::Environment
|
11
|
+
# @return [Goal]
|
12
|
+
attr_reader :goal
|
13
|
+
|
14
|
+
# @param theNames [Array<String>]
|
15
|
+
# @param aGoal [Goal]
|
16
|
+
def initialize(theNames, aGoal)
|
17
|
+
super()
|
18
|
+
@goal = aGoal
|
19
|
+
theNames.each { |nm| add_var(Core::Variable.new(nm)) }
|
20
|
+
end
|
21
|
+
|
22
|
+
# Attempt to achieve the goal given this environment
|
23
|
+
# @param aParent [Environment]
|
24
|
+
# @return [Fiber<Outcome>] A Fiber object that will generate the results.
|
25
|
+
def attain(aParent)
|
26
|
+
self.parent = aParent
|
27
|
+
goal.attain(self)
|
28
|
+
end
|
29
|
+
end # class
|
30
|
+
end # module
|
31
|
+
end # module
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../core/any_value'
|
2
|
+
require_relative '../core/cons_cell'
|
3
|
+
require_relative 'fresh_env'
|
4
|
+
|
5
|
+
module MiniKraken
|
6
|
+
module Glue
|
7
|
+
class RunStarExpression
|
8
|
+
attr_reader :env
|
9
|
+
|
10
|
+
# @param var_name [String]
|
11
|
+
# @param goal [Core::Goal]
|
12
|
+
def initialize(var_name, goal)
|
13
|
+
@env = FreshEnv.new([var_name], goal)
|
14
|
+
end
|
15
|
+
|
16
|
+
def var
|
17
|
+
env.vars.values.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
result = nil
|
22
|
+
solver = env.goal.attain(env)
|
23
|
+
# require 'debug'
|
24
|
+
loop do
|
25
|
+
outcome = solver.resume
|
26
|
+
break if outcome.nil?
|
27
|
+
env.clear
|
28
|
+
if result # ... more than one result...
|
29
|
+
else
|
30
|
+
if outcome.successful?
|
31
|
+
env.propagate(outcome)
|
32
|
+
result = Core::ConsCell.new(var.quote(outcome))
|
33
|
+
else
|
34
|
+
result = Core::NullList
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end # class
|
42
|
+
end # module
|
43
|
+
end # module
|
data/lib/mini_kraken/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
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/variable'
|
6
|
+
|
7
|
+
# Load the class under test
|
8
|
+
require_relative '../../lib/mini_kraken/core/association'
|
9
|
+
|
10
|
+
module MiniKraken
|
11
|
+
module Core
|
12
|
+
describe Association do
|
13
|
+
let(:pea) {KSymbol.new(:pea) }
|
14
|
+
subject { Association.new('q', pea) }
|
15
|
+
|
16
|
+
context 'Initialization:' do
|
17
|
+
it 'should be initialized with a name and a value' do
|
18
|
+
expect { Association.new('q', pea) }.not_to raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be initialized with a variable and a value' do
|
22
|
+
expect { Association.new(Variable.new('p'), pea) }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should know the variable name' do
|
26
|
+
expect(subject.var_name).to eq('q')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should know the associated value' do
|
30
|
+
expect(subject.value).to eq(pea)
|
31
|
+
end
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context 'Provided services:' do
|
35
|
+
end # context
|
36
|
+
end # describe
|
37
|
+
end # module
|
38
|
+
end # module
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../lib/mini_kraken/core/environment'
|
5
|
+
require_relative '../support/factory_methods'
|
6
|
+
|
7
|
+
# Load the class under test
|
8
|
+
require_relative '../../lib/mini_kraken/core/association_walker'
|
9
|
+
|
10
|
+
|
11
|
+
module MiniKraken
|
12
|
+
module Core
|
13
|
+
describe AssociationWalker do
|
14
|
+
include FactoryMethods
|
15
|
+
|
16
|
+
subject { AssociationWalker.new }
|
17
|
+
|
18
|
+
context 'Initialization:' do
|
19
|
+
it 'should be initialized without argument' do
|
20
|
+
expect { AssociationWalker.new }.not_to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it "shouldn't have any visitee at initialization" do
|
24
|
+
expect(subject.visitees.size).to eq(0)
|
25
|
+
end
|
26
|
+
end # context
|
27
|
+
|
28
|
+
context 'Provided services:' do
|
29
|
+
let(:pea) { KSymbol.new(:pea) }
|
30
|
+
let(:pod) { KSymbol.new(:pod) }
|
31
|
+
let(:var_q) { Variable.new('q') }
|
32
|
+
let(:ref_q) { VariableRef.new('q') }
|
33
|
+
let(:var_x) { Variable.new('x') }
|
34
|
+
let(:ref_x) { VariableRef.new('x') }
|
35
|
+
let(:env) { Environment.new }
|
36
|
+
|
37
|
+
it 'should return composite when it has only atomic term(s)' do
|
38
|
+
expr1 = cons(pea)
|
39
|
+
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
40
|
+
|
41
|
+
expr2 = cons(pea, pod)
|
42
|
+
expect(subject.walk_value(expr2, env)).to eq(expr2)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should return composite when it has ground composite term(s)' do
|
46
|
+
expr1 = cons(pea, cons(pod))
|
47
|
+
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
48
|
+
|
49
|
+
expr2 = cons(pea, cons(pod, cons(pea, cons(pod))))
|
50
|
+
expect(subject.walk_value(expr2, env)).to eq(expr2)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return nil when there is one fresh variable' do
|
54
|
+
env.add_var(var_q)
|
55
|
+
expr1 = cons(pea, cons(pod, ref_q))
|
56
|
+
expect(subject.walk_value(expr1, env)).to be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return composite when it has ground composite term(s)' do
|
60
|
+
env.add_var(var_q)
|
61
|
+
env.add_assoc(Association.new('q', pea))
|
62
|
+
expr1 = cons(pea, cons(pod, cons(ref_q)))
|
63
|
+
expect(subject.walk_value(expr1, env)).to eq(expr1)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should return nil when no assocation exists' do
|
67
|
+
env.add_var(var_q)
|
68
|
+
env.add_assoc(Association.new('q', pea))
|
69
|
+
env.add_var(var_x)
|
70
|
+
|
71
|
+
expect(subject.find_ground(var_x.name, env)).to be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should find an atomic term directly associated' do
|
75
|
+
env.add_var(var_q)
|
76
|
+
env.add_assoc(Association.new('q', pea))
|
77
|
+
|
78
|
+
result = subject.find_ground(var_q.name, env)
|
79
|
+
expect(result).to eq(pea)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should find an atomic term directly associated' do
|
83
|
+
env.add_var(var_q)
|
84
|
+
env.add_var(var_x)
|
85
|
+
env.add_assoc(Association.new('q', ref_x))
|
86
|
+
env.add_assoc(Association.new('x', pea))
|
87
|
+
expect(env['x']).not_to be_nil
|
88
|
+
|
89
|
+
result = subject.find_ground(var_q.name, env)
|
90
|
+
expect(result).to eq(pea)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should cope with cyclic structures' do
|
94
|
+
env.add_var(var_q)
|
95
|
+
env.add_var(var_x)
|
96
|
+
env.add_assoc(Association.new('q', ref_x))
|
97
|
+
env.add_assoc(Association.new('x', pea))
|
98
|
+
env.add_assoc(Association.new('x', ref_q))
|
99
|
+
|
100
|
+
result = subject.find_ground(var_q.name, env)
|
101
|
+
expect(result).to eq(pea)
|
102
|
+
|
103
|
+
result = subject.find_ground(var_x.name, env)
|
104
|
+
expect(result).to eq(pea)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should cope with a composite with atomic terms only' do
|
108
|
+
env.add_var(var_q)
|
109
|
+
expr = cons(pea, cons(pod, cons(pea)))
|
110
|
+
env.add_assoc(Association.new('q', expr))
|
111
|
+
|
112
|
+
result = subject.find_ground(var_q.name, env)
|
113
|
+
expect(result).to eq(expr)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should cope with a composite with one fresh variable' do
|
117
|
+
env.add_var(var_q)
|
118
|
+
env.add_var(var_x)
|
119
|
+
expr = cons(pea, cons(pod, cons(ref_x)))
|
120
|
+
env.add_assoc(Association.new('q', expr))
|
121
|
+
|
122
|
+
result = subject.find_ground(var_q.name, env)
|
123
|
+
expect(result).to be_nil
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should cope with a composite with one ground variable' do
|
127
|
+
env.add_var(var_q)
|
128
|
+
env.add_var(var_x)
|
129
|
+
expr = cons(pea, cons(pod, cons(ref_x)))
|
130
|
+
env.add_assoc(Association.new('q', expr))
|
131
|
+
env.add_assoc(Association.new('x', pod))
|
132
|
+
|
133
|
+
result = subject.find_ground(var_q.name, env)
|
134
|
+
expect(result).to eq(expr)
|
135
|
+
end
|
136
|
+
=begin
|
137
|
+
=end
|
138
|
+
it 'should categorize a variable without association as free' do
|
139
|
+
env.add_var(var_q)
|
140
|
+
result = subject.determine_freshness(ref_q, env)
|
141
|
+
expect(result).to be_fresh
|
142
|
+
expect(result.associated).to be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should categorize a variable related to fresh variable as bound' do
|
146
|
+
env.add_var(var_q)
|
147
|
+
env.add_var(var_x)
|
148
|
+
env.add_assoc(Association.new('q', ref_x))
|
149
|
+
|
150
|
+
result = subject.determine_freshness(ref_q, env)
|
151
|
+
expect(result).to be_bound
|
152
|
+
expect(result.associated).to eq(ref_x)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should categorize a variable even in presence of cycle(s)' do
|
156
|
+
env.add_var(var_q)
|
157
|
+
env.add_var(var_x)
|
158
|
+
env.add_assoc(Association.new('q', ref_x))
|
159
|
+
env.add_assoc(Association.new('x', ref_q))
|
160
|
+
|
161
|
+
result = subject.determine_freshness(ref_q, env)
|
162
|
+
expect(result).to be_bound
|
163
|
+
expect(result.associated).to eq(ref_x)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should categorize an atomic term as ground term' do
|
167
|
+
result = subject.determine_freshness(pea, env)
|
168
|
+
expect(result).to be_ground
|
169
|
+
expect(result.associated).to eq(pea)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should categorize a composite term as ground term' do
|
173
|
+
# Ground composite: a composite where all members are ground
|
174
|
+
composite = cons(pea, cons(pod))
|
175
|
+
result = subject.determine_freshness(composite, env)
|
176
|
+
expect(result).to be_ground
|
177
|
+
expect(result.associated).to eq(composite)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should categorize a composite term as bound term' do
|
181
|
+
# Bound composite: a composite where at least one member is fresh
|
182
|
+
env.add_var(var_q)
|
183
|
+
composite = cons(pea, cons(ref_q))
|
184
|
+
result = subject.determine_freshness(composite, env)
|
185
|
+
expect(result).to be_bound
|
186
|
+
expect(result.associated).to eq(composite)
|
187
|
+
end
|
188
|
+
end # context
|
189
|
+
end # describe
|
190
|
+
end # module
|
191
|
+
end # module
|
@@ -0,0 +1,63 @@
|
|
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
|
+
|
6
|
+
# Load the class under test
|
7
|
+
require_relative '../../lib/mini_kraken/core/cons_cell'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe ConsCell do
|
12
|
+
let(:pea) {KSymbol.new(:pea) }
|
13
|
+
let(:pod) {KSymbol.new(:pod) }
|
14
|
+
subject { ConsCell.new(pea, pod) }
|
15
|
+
|
16
|
+
context 'Initialization:' do
|
17
|
+
it 'could be initialized with one argument' do
|
18
|
+
expect { ConsCell.new(pea) }.not_to raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'could be initialized with a second optional argument' do
|
22
|
+
expect { ConsCell.new(pea, pod) }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should know its car child' do
|
26
|
+
expect(subject.car).to eq(pea)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should know its cdr child' do
|
30
|
+
expect(subject.cdr).to eq(pod)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should know its children' do
|
34
|
+
expect(subject.children).to eq([pea, pod])
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should know if it is empty (null)' do
|
38
|
+
expect(subject).not_to be_null
|
39
|
+
expect(ConsCell.new(nil, nil)).to be_null
|
40
|
+
expect(NullList).to be_null
|
41
|
+
end
|
42
|
+
end # context
|
43
|
+
|
44
|
+
context 'Provided services:' do
|
45
|
+
it 'should compare to itself' do
|
46
|
+
expect(subject.eql?(subject)).to be_truthy
|
47
|
+
expect(subject == subject).to be_truthy
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should compare to another instance' do
|
51
|
+
same = ConsCell.new(pea, pod)
|
52
|
+
expect(subject.eql?(same)).to be_truthy
|
53
|
+
|
54
|
+
different = ConsCell.new(pod, pea)
|
55
|
+
expect(subject.eql?(different)).to be_falsey
|
56
|
+
|
57
|
+
different = ConsCell.new(pea)
|
58
|
+
expect(subject.eql?(different)).to be_falsey
|
59
|
+
end
|
60
|
+
end # context
|
61
|
+
end # describe
|
62
|
+
end # module
|
63
|
+
end # module
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../lib/mini_kraken/core/environment'
|
5
|
+
|
6
|
+
# Load the class under test
|
7
|
+
require_relative '../../lib/mini_kraken/core/duck_fiber'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe DuckFiber do
|
12
|
+
subject { DuckFiber.new(:failure) }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'should be initialized with a symbol and an optional block' do
|
16
|
+
expect { DuckFiber.new(:failure) }.not_to raise_error
|
17
|
+
|
18
|
+
expect { DuckFiber.new(:custom) { Outcome.new(:"#s") } }.not_to raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should know its outcome' do
|
22
|
+
expect(subject.outcome).to eq(Failure)
|
23
|
+
end
|
24
|
+
end # context
|
25
|
+
|
26
|
+
context 'Provided services:' do
|
27
|
+
let(:parent) { Environment.new }
|
28
|
+
|
29
|
+
it 'should behave like a Fiber yielding a failure' do
|
30
|
+
failing = DuckFiber.new(:failure)
|
31
|
+
outcome = nil
|
32
|
+
expect { outcome = failing.resume }.not_to raise_error
|
33
|
+
expect(outcome).to eq(Failure)
|
34
|
+
|
35
|
+
# Only one result should be yielded
|
36
|
+
expect(failing.resume).to be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should behave like a Fiber yielding a basic success' do
|
40
|
+
succeeding = DuckFiber.new(:success)
|
41
|
+
outcome = nil
|
42
|
+
expect { outcome = succeeding.resume }.not_to raise_error
|
43
|
+
expect(outcome).to eq(BasicSuccess)
|
44
|
+
|
45
|
+
# Only one result should be yielded
|
46
|
+
expect(succeeding.resume).to be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should behave like a Fiber yielding a custom outcome' do
|
50
|
+
|
51
|
+
tailored = DuckFiber.new(:custom) { Outcome.new(:"#s", parent) }
|
52
|
+
outcome = nil
|
53
|
+
expect { outcome = tailored.resume }.not_to raise_error
|
54
|
+
expect(outcome).to eq(Outcome.new(:"#s", parent))
|
55
|
+
|
56
|
+
# Only one result should be yielded
|
57
|
+
expect(tailored.resume).to be_nil
|
58
|
+
end
|
59
|
+
end # context
|
60
|
+
end # describe
|
61
|
+
end # module
|
62
|
+
end # module
|
@@ -0,0 +1,154 @@
|
|
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/variable'
|
6
|
+
require_relative '../../lib/mini_kraken/core/variable_ref'
|
7
|
+
require_relative '../../lib/mini_kraken/core/association'
|
8
|
+
require_relative '../../lib/mini_kraken/core/outcome'
|
9
|
+
|
10
|
+
# Load the class under test
|
11
|
+
require_relative '../../lib/mini_kraken/core/environment'
|
12
|
+
|
13
|
+
module MiniKraken
|
14
|
+
module Core
|
15
|
+
describe Environment do
|
16
|
+
subject { Environment.new }
|
17
|
+
|
18
|
+
context 'Initialization:' do
|
19
|
+
it 'should be initialized with an optional parent' do
|
20
|
+
expect { Environment.new }.not_to raise_error
|
21
|
+
parent = Environment.new
|
22
|
+
expect { Environment.new(parent) }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it "shouldn't have variable by default" do
|
26
|
+
expect(subject.vars).to be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it "shouldn't have associations by default" do
|
30
|
+
expect(subject.associations).to be_empty
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'shold know its parent (if any)' do
|
34
|
+
# Case: no parent
|
35
|
+
expect(subject.parent).to be_nil
|
36
|
+
|
37
|
+
# Case: there is a parent
|
38
|
+
child = Environment.new(subject)
|
39
|
+
expect(child.parent).to eq(subject)
|
40
|
+
end
|
41
|
+
|
42
|
+
end # context
|
43
|
+
|
44
|
+
context 'Provided services:' do
|
45
|
+
let(:var_a) { Variable.new('a') }
|
46
|
+
let(:var_b) { Variable.new('b') }
|
47
|
+
let(:var_c) { Variable.new('c') }
|
48
|
+
let(:var_c_bis) { Variable.new('c') }
|
49
|
+
let(:pea) { KSymbol.new(:pea) }
|
50
|
+
let(:pod) { KSymbol.new(:pod) }
|
51
|
+
let(:pad) { KSymbol.new(:pad) }
|
52
|
+
|
53
|
+
it 'should accept the addition of a variable' do
|
54
|
+
subject.add_var(var_a)
|
55
|
+
expect(subject.vars).not_to be_empty
|
56
|
+
expect(subject.vars['a']).to eq(var_a)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should accept the addition of multiple variables' do
|
60
|
+
subject.add_var(var_a)
|
61
|
+
expect(subject.vars).not_to be_empty
|
62
|
+
subject.add_var(var_b)
|
63
|
+
expect(subject.vars['a']).to eq(var_a)
|
64
|
+
expect(subject.vars['b']).to eq(var_b)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should accept the addition of an association' do
|
68
|
+
subject.add_var(var_a)
|
69
|
+
assoc = Association.new('a', pea)
|
70
|
+
subject.add_assoc(assoc)
|
71
|
+
expect(subject.associations.size).to eq(1)
|
72
|
+
expect(subject.associations['a']).to eq([assoc])
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should tell that a newborn variable is fresh' do
|
76
|
+
subject.add_var(var_a)
|
77
|
+
|
78
|
+
# By default, a variable is fresh...
|
79
|
+
expect(subject.fresh?(var_a)).to be_truthy
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should tell variable associated with a literal value isn't fresh" do
|
83
|
+
subject.add_var(var_a)
|
84
|
+
|
85
|
+
# Let's associate an atomic term...
|
86
|
+
assoc = Association.new('a', pea)
|
87
|
+
subject.add_assoc(assoc)
|
88
|
+
|
89
|
+
expect(subject.fresh?(var_a)).to be_falsey
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should cope with a variable associated with another variable" do
|
93
|
+
subject.add_var(var_a)
|
94
|
+
subject.add_var(var_b)
|
95
|
+
|
96
|
+
# Let's associate a with (fresh) b
|
97
|
+
assoc = Association.new(var_a, var_b)
|
98
|
+
subject.add_assoc(assoc)
|
99
|
+
|
100
|
+
expect(subject.fresh?(var_a)).to be_truthy
|
101
|
+
|
102
|
+
# Now associate b with something ground...
|
103
|
+
assoc_b = Association.new(var_b, pea)
|
104
|
+
subject.add_assoc(assoc_b)
|
105
|
+
|
106
|
+
# b is no more fresh, so is ... a
|
107
|
+
expect(subject.fresh?(var_b)).to be_falsey
|
108
|
+
expect(subject.fresh?(var_a)).to be_falsey
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should remove all associations' do
|
112
|
+
subject.add_var(var_a)
|
113
|
+
assoc = Association.new(var_a, pea)
|
114
|
+
subject.add_assoc(assoc)
|
115
|
+
|
116
|
+
subject.add_var(var_b)
|
117
|
+
assoc = Association.new(var_b, pod)
|
118
|
+
subject.add_assoc(assoc)
|
119
|
+
|
120
|
+
subject.clear
|
121
|
+
expect(subject.fresh?(var_a)).to be_truthy
|
122
|
+
expect(subject.fresh?(var_a)).to be_truthy
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should propagate associations up in the environment hierarchy' do
|
126
|
+
parent = Environment.new
|
127
|
+
parent.add_var(var_a)
|
128
|
+
# parent.add_var(var_c)
|
129
|
+
instance = Environment.new(parent)
|
130
|
+
instance.add_var(var_b)
|
131
|
+
# instance.add_var(var_c_bis) # Should shadow parent's c variable
|
132
|
+
|
133
|
+
outcome = Outcome.new(:"#s", instance)
|
134
|
+
outcome.add_assoc(Association.new(var_a, pea))
|
135
|
+
outcome.add_assoc(Association.new(var_b, pod))
|
136
|
+
# outcome.add_assoc(Association.new(var_c_bis, pad))
|
137
|
+
expect(outcome.associations.size).to eq(2)
|
138
|
+
|
139
|
+
# Propagate: outcome -> .. -> instance
|
140
|
+
instance.propagate(outcome)
|
141
|
+
expect(outcome.associations.size).to eq(1)
|
142
|
+
expect(instance.associations[var_b.name]).not_to be_nil
|
143
|
+
expect(parent.associations[var_a.name]).to be_nil
|
144
|
+
|
145
|
+
# Propagate: outcome -> .. -> parent
|
146
|
+
parent.propagate(outcome)
|
147
|
+
expect(outcome.associations).to be_empty
|
148
|
+
expect(parent.associations[var_b.name]).to be_nil
|
149
|
+
expect(parent.associations[var_a.name]).not_to be_nil
|
150
|
+
end
|
151
|
+
end # context
|
152
|
+
end # describe
|
153
|
+
end # module
|
154
|
+
end # module
|