mini_kraken 0.2.03 → 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/.rubocop.yml +378 -333
- data/CHANGELOG.md +48 -0
- data/README.md +29 -21
- data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
- data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
- data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
- data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
- data/lib/mini_kraken/atomic/k_string.rb +17 -0
- data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
- data/lib/mini_kraken/composite/all_composite.rb +4 -0
- data/lib/mini_kraken/composite/composite_term.rb +27 -0
- data/lib/mini_kraken/composite/cons_cell.rb +301 -0
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
- data/lib/mini_kraken/composite/list.rb +32 -0
- data/lib/mini_kraken/core/all_core.rb +8 -0
- data/lib/mini_kraken/core/any_value.rb +31 -7
- data/lib/mini_kraken/core/arity.rb +69 -0
- data/lib/mini_kraken/core/association.rb +29 -4
- data/lib/mini_kraken/core/association_copy.rb +50 -0
- data/lib/mini_kraken/core/base_term.rb +13 -0
- data/lib/mini_kraken/core/blackboard.rb +315 -0
- data/lib/mini_kraken/core/bookmark.rb +46 -0
- data/lib/mini_kraken/core/context.rb +492 -0
- data/lib/mini_kraken/core/duck_fiber.rb +21 -19
- data/lib/mini_kraken/core/entry.rb +40 -0
- data/lib/mini_kraken/core/fail.rb +20 -18
- data/lib/mini_kraken/core/fusion.rb +29 -0
- data/lib/mini_kraken/core/goal.rb +20 -29
- data/lib/mini_kraken/core/log_var.rb +22 -0
- data/lib/mini_kraken/core/log_var_ref.rb +108 -0
- data/lib/mini_kraken/core/nullary_relation.rb +2 -9
- data/lib/mini_kraken/core/parametrized_term.rb +68 -0
- data/lib/mini_kraken/core/relation.rb +14 -28
- data/lib/mini_kraken/core/scope.rb +67 -0
- data/lib/mini_kraken/core/solver_adapter.rb +58 -0
- data/lib/mini_kraken/core/specification.rb +48 -0
- data/lib/mini_kraken/core/succeed.rb +21 -17
- data/lib/mini_kraken/core/symbol_table.rb +137 -0
- data/lib/mini_kraken/core/term.rb +15 -4
- data/lib/mini_kraken/glue/dsl.rb +44 -88
- data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
- data/lib/mini_kraken/rela/all_rela.rb +8 -0
- data/lib/mini_kraken/rela/binary_relation.rb +30 -0
- data/lib/mini_kraken/rela/conde.rb +143 -0
- data/lib/mini_kraken/rela/conj2.rb +65 -0
- data/lib/mini_kraken/rela/def_relation.rb +93 -0
- data/lib/mini_kraken/rela/disj2.rb +70 -0
- data/lib/mini_kraken/rela/fresh.rb +98 -0
- data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
- data/lib/mini_kraken/rela/unify.rb +265 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/mini_kraken.gemspec +2 -2
- data/spec/.rubocop.yml +1 -1
- data/spec/atomic/atomic_term_spec.rb +98 -0
- data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
- data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
- data/spec/composite/cons_cell_spec.rb +225 -0
- data/spec/{core → composite}/cons_cell_visitor_spec.rb +36 -20
- data/spec/composite/list_spec.rb +50 -0
- data/spec/core/any_value_spec.rb +52 -0
- data/spec/core/arity_spec.rb +92 -0
- data/spec/core/association_copy_spec.rb +69 -0
- data/spec/core/association_spec.rb +31 -4
- data/spec/core/blackboard_spec.rb +287 -0
- data/spec/core/bookmark_spec.rb +40 -0
- data/spec/core/context_spec.rb +245 -0
- data/spec/core/core_spec.rb +40 -0
- data/spec/core/duck_fiber_spec.rb +16 -46
- data/spec/core/fail_spec.rb +5 -6
- data/spec/core/goal_spec.rb +22 -12
- data/spec/core/log_var_ref_spec.rb +105 -0
- data/spec/core/log_var_spec.rb +64 -0
- data/spec/core/nullary_relation_spec.rb +33 -0
- data/spec/core/parametrized_tem_spec.rb +39 -0
- data/spec/core/relation_spec.rb +33 -0
- data/spec/core/scope_spec.rb +73 -0
- data/spec/core/solver_adapter_spec.rb +70 -0
- data/spec/core/specification_spec.rb +43 -0
- data/spec/core/succeed_spec.rb +5 -5
- data/spec/core/symbol_table_spec.rb +142 -0
- data/spec/glue/dsl_chap1_spec.rb +88 -144
- data/spec/glue/dsl_chap2_spec.rb +454 -19
- data/spec/glue/run_star_expression_spec.rb +81 -906
- data/spec/rela/conde_spec.rb +153 -0
- data/spec/rela/conj2_spec.rb +123 -0
- data/spec/rela/def_relation_spec.rb +119 -0
- data/spec/rela/disj2_spec.rb +117 -0
- data/spec/rela/fresh_spec.rb +147 -0
- data/spec/rela/unify_spec.rb +369 -0
- data/spec/support/factory_atomic.rb +29 -0
- data/spec/support/factory_composite.rb +21 -0
- data/spec/support/factory_methods.rb +11 -26
- metadata +98 -70
- data/lib/mini_kraken/core/association_walker.rb +0 -183
- data/lib/mini_kraken/core/atomic_term.rb +0 -67
- data/lib/mini_kraken/core/base_arg.rb +0 -10
- data/lib/mini_kraken/core/binary_relation.rb +0 -63
- data/lib/mini_kraken/core/composite_goal.rb +0 -46
- data/lib/mini_kraken/core/composite_term.rb +0 -41
- data/lib/mini_kraken/core/conde.rb +0 -143
- data/lib/mini_kraken/core/conj2.rb +0 -79
- data/lib/mini_kraken/core/cons_cell.rb +0 -82
- data/lib/mini_kraken/core/cons_cell_visitor.rb +0 -102
- data/lib/mini_kraken/core/def_relation.rb +0 -53
- data/lib/mini_kraken/core/designation.rb +0 -55
- data/lib/mini_kraken/core/disj2.rb +0 -72
- data/lib/mini_kraken/core/environment.rb +0 -73
- data/lib/mini_kraken/core/equals.rb +0 -193
- data/lib/mini_kraken/core/formal_arg.rb +0 -22
- data/lib/mini_kraken/core/formal_ref.rb +0 -25
- data/lib/mini_kraken/core/freshness.rb +0 -45
- data/lib/mini_kraken/core/goal_arg.rb +0 -12
- data/lib/mini_kraken/core/goal_template.rb +0 -102
- data/lib/mini_kraken/core/k_boolean.rb +0 -35
- data/lib/mini_kraken/core/outcome.rb +0 -63
- data/lib/mini_kraken/core/variable.rb +0 -41
- data/lib/mini_kraken/core/variable_ref.rb +0 -84
- data/lib/mini_kraken/core/vocabulary.rb +0 -446
- data/lib/mini_kraken/glue/fresh_env.rb +0 -103
- data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
- data/spec/core/association_walker_spec.rb +0 -192
- data/spec/core/conde_spec.rb +0 -147
- data/spec/core/conj2_spec.rb +0 -114
- data/spec/core/cons_cell_spec.rb +0 -107
- data/spec/core/def_relation_spec.rb +0 -97
- data/spec/core/disj2_spec.rb +0 -99
- data/spec/core/environment_spec.rb +0 -142
- data/spec/core/equals_spec.rb +0 -317
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -56
- data/spec/core/variable_ref_spec.rb +0 -30
- data/spec/core/variable_spec.rb +0 -35
- data/spec/core/vocabulary_spec.rb +0 -219
- data/spec/glue/fresh_env_factory_spec.rb +0 -97
- data/spec/glue/fresh_env_spec.rb +0 -62
@@ -4,10 +4,10 @@ require_relative '../spec_helper' # Use the RSpec framework
|
|
4
4
|
require 'ostruct'
|
5
5
|
|
6
6
|
# Load the class under test
|
7
|
-
require_relative '../../lib/mini_kraken/
|
7
|
+
require_relative '../../lib/mini_kraken/atomic/k_boolean'
|
8
8
|
|
9
9
|
module MiniKraken
|
10
|
-
module
|
10
|
+
module Atomic
|
11
11
|
describe KBoolean do
|
12
12
|
subject { KBoolean.new('#t') }
|
13
13
|
|
@@ -28,12 +28,23 @@ module MiniKraken
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'should know its value' do
|
31
|
-
|
32
|
-
|
31
|
+
other = KBoolean.new(true)
|
32
|
+
expect(other.value).to eq(true)
|
33
|
+
|
34
|
+
other = KBoolean.new('#t')
|
35
|
+
expect(other.value).to eq(true)
|
36
|
+
|
37
|
+
other = KBoolean.new(:"#t")
|
38
|
+
expect(other.value).to eq(true)
|
39
|
+
|
40
|
+
other = KBoolean.new(false)
|
41
|
+
expect(other.value).to eq(false)
|
42
|
+
|
43
|
+
other = KBoolean.new('#f')
|
44
|
+
expect(other.value).to eq(false)
|
33
45
|
|
34
|
-
|
35
|
-
|
36
|
-
expect(subject.ground?(env)).to be_truthy
|
46
|
+
other = KBoolean.new(:"#f")
|
47
|
+
expect(other.value).to eq(false)
|
37
48
|
end
|
38
49
|
end # context
|
39
50
|
|
@@ -43,27 +54,13 @@ module MiniKraken
|
|
43
54
|
other = KBoolean.new(true)
|
44
55
|
expect(subject).to be_eql(other)
|
45
56
|
|
46
|
-
other = KBoolean.new(:"#t")
|
47
|
-
expect(subject).to be_eql(other)
|
48
|
-
|
49
|
-
other = KBoolean.new('#t')
|
50
|
-
expect(subject).to be_eql(other)
|
51
|
-
|
52
57
|
# Same type, other value
|
53
58
|
another = KBoolean.new(false)
|
54
59
|
expect(subject).not_to be_eql(another)
|
55
60
|
|
56
|
-
# Same type, other value
|
57
|
-
another = KBoolean.new(:"#f")
|
58
|
-
expect(subject).not_to be_eql(another)
|
59
|
-
|
60
61
|
# Same type, other value
|
61
62
|
another = KBoolean.new('#f')
|
62
63
|
expect(subject).not_to be_eql(another)
|
63
|
-
|
64
|
-
# Different type, same value
|
65
|
-
yet_another = OpenStruct.new(value: true)
|
66
|
-
expect(subject).not_to be_eql(yet_another)
|
67
64
|
end
|
68
65
|
|
69
66
|
it 'should know whether it has same value than other object' do
|
@@ -71,27 +68,15 @@ module MiniKraken
|
|
71
68
|
other = KBoolean.new(true)
|
72
69
|
expect(subject == other).to be_truthy
|
73
70
|
|
74
|
-
other = KBoolean.new(:"#t")
|
75
|
-
expect(subject == other).to be_truthy
|
76
|
-
|
77
|
-
other = KBoolean.new('#t')
|
78
|
-
expect(subject == other).to be_truthy
|
79
|
-
|
80
71
|
# Same type, other value
|
81
72
|
another = KBoolean.new(false)
|
82
73
|
expect(subject == another).to be_falsy
|
83
74
|
|
84
|
-
another = KBoolean.new(:"#f")
|
85
|
-
expect(subject == another).to be_falsy
|
86
|
-
|
87
|
-
another = KBoolean.new('#f')
|
88
|
-
expect(subject == another).to be_falsy
|
89
|
-
|
90
75
|
# Same duck type, same value
|
91
76
|
yet_another = OpenStruct.new(value: true)
|
92
77
|
expect(subject == yet_another).to be_truthy
|
93
78
|
|
94
|
-
#
|
79
|
+
# Same duck type, different value
|
95
80
|
still_another = OpenStruct.new(value: false)
|
96
81
|
expect(subject == still_another).to be_falsy
|
97
82
|
|
@@ -4,10 +4,10 @@ require_relative '../spec_helper' # Use the RSpec framework
|
|
4
4
|
require 'ostruct'
|
5
5
|
|
6
6
|
# Load the class under test
|
7
|
-
require_relative '../../lib/mini_kraken/
|
7
|
+
require_relative '../../lib/mini_kraken/atomic/k_symbol'
|
8
8
|
|
9
9
|
module MiniKraken
|
10
|
-
module
|
10
|
+
module Atomic
|
11
11
|
describe KSymbol do
|
12
12
|
let(:a_value) { :pea }
|
13
13
|
subject { KSymbol.new(a_value) }
|
@@ -20,11 +20,6 @@ module MiniKraken
|
|
20
20
|
it 'should know its value' do
|
21
21
|
expect(subject.value).to eq(a_value)
|
22
22
|
end
|
23
|
-
|
24
|
-
it 'should know that it is a ground term' do
|
25
|
-
env = double('mock-env')
|
26
|
-
expect(subject.ground?(env)).to be_truthy
|
27
|
-
end
|
28
23
|
end # context
|
29
24
|
|
30
25
|
context 'Provided services:' do
|
@@ -37,7 +32,7 @@ module MiniKraken
|
|
37
32
|
another = KSymbol.new(:pod)
|
38
33
|
expect(subject).not_to be_eql(another)
|
39
34
|
|
40
|
-
# Different type, same value
|
35
|
+
# Different duck type, same value
|
41
36
|
yet_another = OpenStruct.new(value: :pea)
|
42
37
|
expect(subject).not_to be_eql(yet_another)
|
43
38
|
end
|
@@ -51,14 +46,6 @@ module MiniKraken
|
|
51
46
|
another = KSymbol.new(:pod)
|
52
47
|
expect(subject == another).to be_falsy
|
53
48
|
|
54
|
-
# Same duck type, same value
|
55
|
-
yet_another = OpenStruct.new(value: :pea)
|
56
|
-
expect(subject == yet_another).to be_truthy
|
57
|
-
|
58
|
-
# Different duck type, different value
|
59
|
-
still_another = OpenStruct.new(value: :pod)
|
60
|
-
expect(subject == still_another).to be_falsy
|
61
|
-
|
62
49
|
# Default Ruby representation, same value
|
63
50
|
expect(subject == :pea).to be_truthy
|
64
51
|
|
@@ -0,0 +1,225 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../support/factory_atomic'
|
5
|
+
require_relative '../../lib/mini_kraken/core/context'
|
6
|
+
require_relative '../../lib/mini_kraken/core/log_var'
|
7
|
+
require_relative '../../lib/mini_kraken/core/log_var_ref'
|
8
|
+
|
9
|
+
# Load the class under test
|
10
|
+
require_relative '../../lib/mini_kraken/composite/cons_cell'
|
11
|
+
|
12
|
+
module MiniKraken
|
13
|
+
module Composite
|
14
|
+
describe ConsCell do
|
15
|
+
include MiniKraken::FactoryAtomic # Use mix-in module
|
16
|
+
|
17
|
+
let(:pea) { k_symbol(:pea) }
|
18
|
+
let(:pod) { k_symbol(:pod) }
|
19
|
+
let(:corn) { k_symbol(:corn) }
|
20
|
+
let(:ctx) { Core::Context.new }
|
21
|
+
subject { ConsCell.new(pea, pod) }
|
22
|
+
|
23
|
+
context 'Initialization:' do
|
24
|
+
it 'could be initialized with one argument' do
|
25
|
+
expect { ConsCell.new(pea) }.not_to raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'could be initialized with a second optional argument' do
|
29
|
+
expect { ConsCell.new(pea, pod) }.not_to raise_error
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'could be initialized as null list' do
|
33
|
+
expect { ConsCell.null }.not_to raise_error
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should know its car child' do
|
37
|
+
expect(subject.car).to eq(pea)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should know its cdr child' do
|
41
|
+
expect(subject.cdr).to eq(pod)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it 'should know its children' do
|
46
|
+
expect(subject.children).to eq([pea, pod])
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should know if it is empty (null)' do
|
50
|
+
expect(subject).not_to be_null
|
51
|
+
expect(ConsCell.new(nil, nil)).to be_null
|
52
|
+
expect(ConsCell.null).to be_null
|
53
|
+
expect(NullList).to be_null
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'initialize cdr if its referencing the null list' do
|
57
|
+
instance = ConsCell.new(pea, NullList)
|
58
|
+
expect(instance.car).to eq(pea)
|
59
|
+
expect(instance.cdr).to be_null
|
60
|
+
end
|
61
|
+
end # context
|
62
|
+
|
63
|
+
context 'Provided services:' do
|
64
|
+
it 'should compare to itself' do
|
65
|
+
expect(subject.eql?(subject)).to be_truthy
|
66
|
+
synonym = subject
|
67
|
+
expect(subject == synonym).to be_truthy
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should compare to another instance' do
|
71
|
+
same = ConsCell.new(pea, pod)
|
72
|
+
expect(subject.eql?(same)).to be_truthy
|
73
|
+
|
74
|
+
different = ConsCell.new(pod, pea)
|
75
|
+
expect(subject.eql?(different)).to be_falsey
|
76
|
+
|
77
|
+
different = ConsCell.new(pea)
|
78
|
+
expect(subject.eql?(different)).to be_falsey
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should set_car! another cons cell' do
|
82
|
+
instance = ConsCell.new(pea)
|
83
|
+
head = ConsCell.new(pod)
|
84
|
+
instance.set_car!(head)
|
85
|
+
expect(instance.car).to eq(head)
|
86
|
+
expect(instance.cdr).to be_null
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should set_cdr! another cons cell' do
|
90
|
+
instance = ConsCell.new(pea)
|
91
|
+
trail = ConsCell.new(pod)
|
92
|
+
instance.set_cdr!(trail)
|
93
|
+
expect(instance.car).to eq(pea)
|
94
|
+
expect(instance.cdr).to eq(trail)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should set a member to some term' do
|
98
|
+
instance = ConsCell.null
|
99
|
+
head = ConsCell.new(pea)
|
100
|
+
trail = ConsCell.new(pod)
|
101
|
+
instance.set!(:car, head)
|
102
|
+
instance.set!(:cdr, trail)
|
103
|
+
expect(instance.car).to eq(head)
|
104
|
+
expect(instance.cdr).to eq(trail)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should know whether it is pinned or not' do
|
108
|
+
# Case: all pair members are atomic items
|
109
|
+
expect(subject).to be_pinned(ctx)
|
110
|
+
|
111
|
+
# Case: cdr is nil
|
112
|
+
instance = ConsCell.new(pea)
|
113
|
+
expect(instance).to be_pinned(ctx)
|
114
|
+
|
115
|
+
# Case: embedded composite
|
116
|
+
nested = ConsCell.new(ConsCell.new(pod, pea), ConsCell.new(pea))
|
117
|
+
expect(nested).to be_pinned(ctx)
|
118
|
+
|
119
|
+
ctx.add_vars('q')
|
120
|
+
nested.set_cdr!(Core::LogVarRef.new('q'))
|
121
|
+
expect(nested).not_to be_pinned(ctx)
|
122
|
+
expect(nested).to be_floating(ctx)
|
123
|
+
|
124
|
+
ctx.associate('q', ConsCell.new(pea))
|
125
|
+
expect(nested).to be_pinned(ctx)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should provide a list representation of itself' do
|
129
|
+
# Case of null list
|
130
|
+
expect(NullList.to_s).to eq '()'
|
131
|
+
|
132
|
+
# Case of one element proper list
|
133
|
+
cell = ConsCell.new(pea)
|
134
|
+
expect(cell.to_s).to eq '(:pea)'
|
135
|
+
|
136
|
+
# Case of two elements proper list
|
137
|
+
cell = ConsCell.new(pea, ConsCell.new(pod))
|
138
|
+
expect(cell.to_s).to eq '(:pea :pod)'
|
139
|
+
|
140
|
+
# Case of two elements improper list
|
141
|
+
expect(subject.to_s).to eq '(:pea . :pod)'
|
142
|
+
|
143
|
+
# Case of one element plus null list
|
144
|
+
cell = ConsCell.new(pea)
|
145
|
+
cell.set_cdr!(ConsCell.null)
|
146
|
+
expect(cell.to_s).to eq '(:pea)'
|
147
|
+
|
148
|
+
# Case of three elements proper list
|
149
|
+
cell = ConsCell.new(pea, ConsCell.new(pod, ConsCell.new(corn)))
|
150
|
+
expect(cell.to_s).to eq '(:pea :pod :corn)'
|
151
|
+
|
152
|
+
# Case of three elements improper list
|
153
|
+
cell = ConsCell.new(pea, ConsCell.new(pod, corn))
|
154
|
+
expect(cell.to_s).to eq '(:pea :pod . :corn)'
|
155
|
+
|
156
|
+
# Case of a nested list
|
157
|
+
cell = ConsCell.new(ConsCell.new(pea), ConsCell.new(pod))
|
158
|
+
expect(cell.to_s).to eq '((:pea) :pod)'
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should know its dependencies' do
|
162
|
+
# Case: no var ref...
|
163
|
+
lst = ConsCell.new(ConsCell.new(pod, pea), ConsCell.new(pea))
|
164
|
+
expect(lst.dependencies(ctx)).to be_empty
|
165
|
+
|
166
|
+
# Case: multiple var refs
|
167
|
+
ctx.add_vars(%w[q x])
|
168
|
+
q_ref = Core::LogVarRef.new('q')
|
169
|
+
x_ref = Core::LogVarRef.new('x')
|
170
|
+
list2 = ConsCell.new(ConsCell.new(q_ref, pea), ConsCell.new(x_ref))
|
171
|
+
expect(list2.dependencies(ctx).size).to eq(2)
|
172
|
+
q_var = ctx.lookup('q')
|
173
|
+
x_var = ctx.lookup('x')
|
174
|
+
predicted = Set.new([q_var.i_name, x_var.i_name])
|
175
|
+
expect(list2.dependencies(ctx)).to eq(predicted)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should, as list with atomic terms, provide an expanded copy' do
|
179
|
+
# Case of a list of atomic terms
|
180
|
+
lst = ConsCell.new(ConsCell.new(ConsCell.new(pea), pod))
|
181
|
+
representation = lst.to_s
|
182
|
+
|
183
|
+
copy = lst.expand(ctx, {})
|
184
|
+
expect(copy.to_s).to eq(representation)
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should, as list with variable refs, provide an expanded copy' do
|
188
|
+
# Case of a list of variable refs
|
189
|
+
ctx.add_vars(['x'])
|
190
|
+
x_ref = Core::LogVarRef.new('x')
|
191
|
+
x_var = ctx.lookup('x')
|
192
|
+
ctx.associate('x', Core::AnyValue.new(0))
|
193
|
+
lst = ConsCell.new(x_ref, ConsCell.new(x_ref))
|
194
|
+
substitutions = {}
|
195
|
+
substitutions[x_var.i_name] = Core::AnyValue.new(0)
|
196
|
+
|
197
|
+
copy = lst.expand(ctx, substitutions)
|
198
|
+
expect(copy.to_s).to eq('(_0 _0)')
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should provide a duplicate with variable replaced by their value' do
|
202
|
+
q_ref = Core::LogVarRef.new('q')
|
203
|
+
x_ref = Core::LogVarRef.new('x')
|
204
|
+
y_ref = Core::LogVarRef.new('y')
|
205
|
+
substitutions = {
|
206
|
+
'q' => ConsCell.new(pea, ConsCell.new(x_ref, y_ref)),
|
207
|
+
'x' => pod,
|
208
|
+
'y' => corn
|
209
|
+
}
|
210
|
+
|
211
|
+
# Basic case: variable ref points to an atomic value
|
212
|
+
expr = ConsCell.new(pea, x_ref)
|
213
|
+
duplicate = expr.dup_cond(substitutions)
|
214
|
+
expect(duplicate.to_s).to eq('(:pea . :pod)')
|
215
|
+
|
216
|
+
expr = ConsCell.new(pod, ConsCell.new(q_ref, y_ref))
|
217
|
+
duplicate = expr.dup_cond(substitutions)
|
218
|
+
expect(duplicate.car).to eq(pod)
|
219
|
+
expect(duplicate.cdr.car.to_s).to eq('(:pea :pod . :corn)')
|
220
|
+
expect(duplicate.to_s).to eq('(:pod (:pea :pod . :corn) . :corn)')
|
221
|
+
end
|
222
|
+
end # context
|
223
|
+
end # describe
|
224
|
+
end # module
|
225
|
+
end # module
|
@@ -1,38 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '
|
5
|
-
require_relative '../../lib/mini_kraken/core/
|
4
|
+
require_relative '../support/factory_atomic'
|
5
|
+
require_relative '../../lib/mini_kraken/core/log_var_ref'
|
6
6
|
|
7
7
|
# Load the class under test
|
8
|
-
require_relative '../../lib/mini_kraken/
|
9
|
-
|
8
|
+
require_relative '../../lib/mini_kraken/composite/cons_cell_visitor'
|
10
9
|
|
11
10
|
module MiniKraken
|
12
|
-
module
|
11
|
+
module Composite
|
13
12
|
describe ConsCellVisitor do
|
14
|
-
|
15
|
-
|
16
|
-
let(:
|
17
|
-
let(:
|
13
|
+
include MiniKraken::FactoryAtomic # Use mix-in module
|
14
|
+
|
15
|
+
let(:pea) { k_symbol(:pea) }
|
16
|
+
let(:pod) { k_symbol(:pod) }
|
17
|
+
let(:corn) { k_symbol(:corn) }
|
18
|
+
let(:ref_q) { LogVarRef.new('q') }
|
18
19
|
let(:l_pea) { ConsCell.new(pea) }
|
19
20
|
let(:l_pea_pod) { ConsCell.new(pea, ConsCell.new(pod)) }
|
20
21
|
let(:l_pea_pod_corn) { ConsCell.new(pea, ConsCell.new(pod, ConsCell.new(corn))) }
|
21
22
|
subject { ConsCellVisitor }
|
22
23
|
|
23
24
|
context 'Provided services:' do
|
24
|
-
it 'acts as a factory of
|
25
|
+
it 'acts as a factory of Fiber objects' do
|
25
26
|
expect(subject.df_visitor(l_pea)).to be_kind_of(Fiber)
|
26
27
|
end
|
27
28
|
end # context
|
28
29
|
|
29
30
|
context 'proper list visiting:' do
|
30
31
|
it 'can visit a null list' do
|
31
|
-
null_list = ConsCell.
|
32
|
+
null_list = ConsCell.null
|
32
33
|
visitor = subject.df_visitor(null_list)
|
33
34
|
expect(visitor.resume).to eq([:car, null_list])
|
34
|
-
|
35
|
-
|
35
|
+
|
36
|
+
# The car and cdr fields aren't visited
|
36
37
|
expect(visitor.resume).to eq([:stop, nil])
|
37
38
|
end
|
38
39
|
|
@@ -40,7 +41,7 @@ module MiniKraken
|
|
40
41
|
visitor = subject.df_visitor(l_pea)
|
41
42
|
expect(visitor.resume).to eq([:car, l_pea])
|
42
43
|
expect(visitor.resume).to eq([:car, pea])
|
43
|
-
expect(visitor.resume).to eq([:cdr,
|
44
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
44
45
|
expect(visitor.resume).to eq([:stop, nil])
|
45
46
|
end
|
46
47
|
|
@@ -50,7 +51,7 @@ module MiniKraken
|
|
50
51
|
expect(visitor.resume).to eq([:car, pea])
|
51
52
|
expect(visitor.resume).to eq([:cdr, l_pea_pod.cdr])
|
52
53
|
expect(visitor.resume).to eq([:car, pod])
|
53
|
-
expect(visitor.resume).to eq([:cdr,
|
54
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
54
55
|
expect(visitor.resume).to eq([:stop, nil])
|
55
56
|
end
|
56
57
|
|
@@ -62,7 +63,7 @@ module MiniKraken
|
|
62
63
|
expect(visitor.resume).to eq([:car, pod])
|
63
64
|
expect(visitor.resume).to eq([:cdr, l_pea_pod_corn.cdr.cdr])
|
64
65
|
expect(visitor.resume).to eq([:car, corn])
|
65
|
-
expect(visitor.resume).to eq([:cdr,
|
66
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
66
67
|
expect(visitor.resume).to eq([:stop, nil])
|
67
68
|
end
|
68
69
|
end # context
|
@@ -88,6 +89,7 @@ module MiniKraken
|
|
88
89
|
|
89
90
|
it 'can visit a three elements improper list' do
|
90
91
|
l_improper = ConsCell.new(pea, ConsCell.new(pod, corn))
|
92
|
+
expect(l_improper.to_s).to eq('(:pea :pod . :corn)')
|
91
93
|
visitor = subject.df_visitor(l_improper)
|
92
94
|
expect(visitor.resume).to eq([:car, l_improper])
|
93
95
|
expect(visitor.resume).to eq([:car, pea])
|
@@ -96,6 +98,18 @@ module MiniKraken
|
|
96
98
|
expect(visitor.resume).to eq([:cdr, corn])
|
97
99
|
expect(visitor.resume).to eq([:stop, nil])
|
98
100
|
end
|
101
|
+
|
102
|
+
it 'smurch' do
|
103
|
+
composite = ConsCell.new(ConsCell.new(ConsCell.new(pea)), pod)
|
104
|
+
visitor = subject.df_visitor(composite)
|
105
|
+
expect(visitor.resume).to eq([:car, composite])
|
106
|
+
expect(visitor.resume).to eq([:car, composite.car])
|
107
|
+
expect(visitor.resume).to eq([:car, composite.car.car])
|
108
|
+
expect(visitor.resume).to eq([:car, pea])
|
109
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
110
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
111
|
+
expect(visitor.resume).to eq([:cdr, pod])
|
112
|
+
end
|
99
113
|
end # context
|
100
114
|
|
101
115
|
context 'Skip visit of children of a ConsCell:' do
|
@@ -120,22 +134,24 @@ module MiniKraken
|
|
120
134
|
# Tell to skip children by passing a true value to resume
|
121
135
|
expect(visitor.resume(true)).to eq([:cdr, tree.cdr.cdr])
|
122
136
|
expect(visitor.resume).to eq([:car, corn])
|
123
|
-
expect(visitor.resume).to eq([:cdr,
|
137
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
124
138
|
expect(visitor.resume).to eq([:stop, nil])
|
125
139
|
end
|
126
140
|
end # context
|
127
141
|
|
128
142
|
context 'Circular structures visiting:' do
|
129
143
|
it 'should cope with a circular graph' do
|
130
|
-
second_cell = ConsCell.new(
|
144
|
+
second_cell = ConsCell.new(pea)
|
131
145
|
first_cell = ConsCell.new(pea, second_cell)
|
132
|
-
second_cell.
|
146
|
+
second_cell.set_car!(first_cell)
|
133
147
|
|
134
148
|
visitor = subject.df_visitor(first_cell)
|
135
149
|
expect(visitor.resume).to eq([:car, first_cell])
|
136
150
|
expect(visitor.resume).to eq([:car, pea])
|
137
151
|
expect(visitor.resume).to eq([:cdr, second_cell])
|
138
|
-
|
152
|
+
|
153
|
+
# Skip car (was already visited)
|
154
|
+
expect(visitor.resume).to eq([:cdr, NullList])
|
139
155
|
expect(visitor.resume).to eq([:stop, nil])
|
140
156
|
end
|
141
157
|
end # context
|