mini_kraken 0.2.04 → 0.3.00

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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +16 -16
  4. data/lib/mini_kraken/atomic/all_atomic.rb +1 -0
  5. data/lib/mini_kraken/atomic/atomic_term.rb +32 -17
  6. data/lib/mini_kraken/atomic/k_integer.rb +0 -4
  7. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  8. data/lib/mini_kraken/atomic/k_symbol.rb +0 -6
  9. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  10. data/lib/mini_kraken/composite/composite_term.rb +2 -18
  11. data/lib/mini_kraken/composite/cons_cell.rb +178 -11
  12. data/lib/mini_kraken/composite/cons_cell_visitor.rb +12 -64
  13. data/lib/mini_kraken/composite/list.rb +32 -0
  14. data/lib/mini_kraken/core/all_core.rb +8 -0
  15. data/lib/mini_kraken/core/any_value.rb +31 -7
  16. data/lib/mini_kraken/core/arity.rb +69 -0
  17. data/lib/mini_kraken/core/association.rb +29 -4
  18. data/lib/mini_kraken/core/association_copy.rb +50 -0
  19. data/lib/mini_kraken/core/base_term.rb +13 -0
  20. data/lib/mini_kraken/core/blackboard.rb +315 -0
  21. data/lib/mini_kraken/core/bookmark.rb +46 -0
  22. data/lib/mini_kraken/core/context.rb +624 -0
  23. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  24. data/lib/mini_kraken/core/entry.rb +40 -0
  25. data/lib/mini_kraken/core/fail.rb +20 -18
  26. data/lib/mini_kraken/core/fusion.rb +29 -0
  27. data/lib/mini_kraken/core/goal.rb +20 -29
  28. data/lib/mini_kraken/core/log_var.rb +4 -30
  29. data/lib/mini_kraken/core/log_var_ref.rb +72 -48
  30. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  31. data/lib/mini_kraken/core/parametrized_term.rb +61 -0
  32. data/lib/mini_kraken/core/relation.rb +14 -28
  33. data/lib/mini_kraken/core/scope.rb +67 -0
  34. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  35. data/lib/mini_kraken/core/specification.rb +48 -0
  36. data/lib/mini_kraken/core/succeed.rb +21 -17
  37. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  38. data/lib/mini_kraken/core/term.rb +15 -4
  39. data/lib/mini_kraken/glue/dsl.rb +35 -69
  40. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  41. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  42. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  43. data/lib/mini_kraken/rela/conde.rb +146 -0
  44. data/lib/mini_kraken/rela/conj2.rb +65 -0
  45. data/lib/mini_kraken/rela/def_relation.rb +64 -0
  46. data/lib/mini_kraken/rela/disj2.rb +70 -0
  47. data/lib/mini_kraken/rela/fresh.rb +98 -0
  48. data/lib/mini_kraken/{core → rela}/goal_relation.rb +6 -8
  49. data/lib/mini_kraken/rela/unify.rb +258 -0
  50. data/lib/mini_kraken/version.rb +1 -1
  51. data/spec/atomic/atomic_term_spec.rb +23 -20
  52. data/spec/atomic/k_symbol_spec.rb +0 -5
  53. data/spec/composite/cons_cell_spec.rb +116 -0
  54. data/spec/composite/cons_cell_visitor_spec.rb +16 -3
  55. data/spec/composite/list_spec.rb +50 -0
  56. data/spec/core/any_value_spec.rb +52 -0
  57. data/spec/core/arity_spec.rb +91 -0
  58. data/spec/core/association_copy_spec.rb +69 -0
  59. data/spec/core/association_spec.rb +25 -0
  60. data/spec/core/blackboard_spec.rb +287 -0
  61. data/spec/core/bookmark_spec.rb +40 -0
  62. data/spec/core/context_spec.rb +221 -0
  63. data/spec/core/core_spec.rb +40 -0
  64. data/spec/core/duck_fiber_spec.rb +22 -46
  65. data/spec/core/fail_spec.rb +5 -6
  66. data/spec/core/goal_spec.rb +20 -11
  67. data/spec/core/log_var_ref_spec.rb +80 -5
  68. data/spec/core/log_var_spec.rb +35 -6
  69. data/spec/core/nullary_relation_spec.rb +33 -0
  70. data/spec/core/parametrized_tem_spec.rb +39 -0
  71. data/spec/core/relation_spec.rb +33 -0
  72. data/spec/core/scope_spec.rb +73 -0
  73. data/spec/core/solver_adapter_spec.rb +70 -0
  74. data/spec/core/specification_spec.rb +43 -0
  75. data/spec/core/succeed_spec.rb +5 -5
  76. data/spec/core/symbol_table_spec.rb +142 -0
  77. data/spec/glue/dsl_chap1_spec.rb +88 -99
  78. data/spec/glue/dsl_chap2_spec.rb +59 -41
  79. data/spec/glue/run_star_expression_spec.rb +69 -896
  80. data/spec/{core → rela}/conde_spec.rb +50 -46
  81. data/spec/rela/conj2_spec.rb +123 -0
  82. data/spec/rela/def_relation_spec.rb +119 -0
  83. data/spec/rela/disj2_spec.rb +117 -0
  84. data/spec/rela/fresh_spec.rb +147 -0
  85. data/spec/rela/unify_spec.rb +369 -0
  86. data/spec/support/factory_atomic.rb +7 -0
  87. data/spec/support/factory_composite.rb +21 -0
  88. metadata +71 -48
  89. data/lib/mini_kraken/core/association_walker.rb +0 -183
  90. data/lib/mini_kraken/core/base_arg.rb +0 -10
  91. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  92. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  93. data/lib/mini_kraken/core/conde.rb +0 -143
  94. data/lib/mini_kraken/core/conj2.rb +0 -79
  95. data/lib/mini_kraken/core/def_relation.rb +0 -53
  96. data/lib/mini_kraken/core/designation.rb +0 -55
  97. data/lib/mini_kraken/core/disj2.rb +0 -72
  98. data/lib/mini_kraken/core/environment.rb +0 -73
  99. data/lib/mini_kraken/core/equals.rb +0 -191
  100. data/lib/mini_kraken/core/formal_arg.rb +0 -22
  101. data/lib/mini_kraken/core/formal_ref.rb +0 -25
  102. data/lib/mini_kraken/core/freshness.rb +0 -45
  103. data/lib/mini_kraken/core/goal_arg.rb +0 -12
  104. data/lib/mini_kraken/core/goal_template.rb +0 -102
  105. data/lib/mini_kraken/core/outcome.rb +0 -63
  106. data/lib/mini_kraken/core/tap.rb +0 -46
  107. data/lib/mini_kraken/core/vocabulary.rb +0 -446
  108. data/lib/mini_kraken/glue/fresh_env.rb +0 -108
  109. data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
  110. data/spec/core/association_walker_spec.rb +0 -194
  111. data/spec/core/conj2_spec.rb +0 -116
  112. data/spec/core/def_relation_spec.rb +0 -99
  113. data/spec/core/disj2_spec.rb +0 -100
  114. data/spec/core/environment_spec.rb +0 -144
  115. data/spec/core/equals_spec.rb +0 -319
  116. data/spec/core/goal_template_spec.rb +0 -74
  117. data/spec/core/outcome_spec.rb +0 -56
  118. data/spec/core/vocabulary_spec.rb +0 -220
  119. data/spec/glue/fresh_env_factory_spec.rb +0 -99
  120. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniKraken
4
- VERSION = '0.2.04'
4
+ VERSION = '0.3.00'
5
5
  end
@@ -28,19 +28,19 @@ module MiniKraken
28
28
  end # context
29
29
 
30
30
  context 'Provided services:' do
31
- it 'should know that it is a ground term' do
32
- env = double('mock-env')
33
- expect(subject.ground?(env)).to be_truthy
31
+ it 'should know that it is a pinned term' do
32
+ ctx = double('mock-ctx')
33
+ expect(subject.pinned?(ctx)).to be_truthy
34
34
  end
35
35
 
36
- it 'should know that it is not a fresh term' do
37
- env = double('mock-env')
38
- expect(subject.fresh?(env)).to be_falsy
36
+ it 'should know that it is not a floating term' do
37
+ ctx = double('mock-ctx')
38
+ expect(subject.floating?(ctx)).to be_falsy
39
39
  end
40
40
 
41
- it 'should know its freshness' do
42
- env = double('mock-env')
43
- expect(subject.freshness(env).degree).to eq(:ground)
41
+ it 'should know that it is not an unbound term' do
42
+ ctx = double('mock-ctx')
43
+ expect(subject.unbound?(ctx)).to be_falsy
44
44
  end
45
45
 
46
46
  it 'performs data value comparison' do
@@ -76,19 +76,22 @@ module MiniKraken
76
76
  end
77
77
 
78
78
  it 'returns itself when receiving quote message' do
79
- env = double('mock-env')
80
- expect(subject.quote(env)).to eq(subject)
79
+ ctx = double('mock-ctx')
80
+ expect(subject.quote(ctx)).to eq(subject)
81
+ end
82
+
83
+ it 'should know it has no dependency on variable(s)' do
84
+ ctx = double('mock-ctx')
85
+ expect(subject.dependencies(ctx)).to be_empty
86
+ end
87
+
88
+ it 'should dup itself' do
89
+ substitutions = double('fake-substitutions')
90
+ duplicate = subject.dup_cond(substitutions)
91
+ expect(duplicate).to eq(subject) # same value
92
+ expect(duplicate).not_to be_equal(subject) # different object ids
81
93
  end
82
94
  end # context
83
- =begin
84
- # An atomic term is by definition a ground term: since it doesn't contain
85
- # any bound variable (in Prolog sense).
86
- # @param _env [Vocabulary]
87
- # @return [Freshness]
88
- def freshness(_env)
89
- Freshness.new(:ground, self)
90
- end
91
- =end
92
95
  end # describe
93
96
  end # module
94
97
  end # module
@@ -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
@@ -2,6 +2,9 @@
2
2
 
3
3
  require_relative '../spec_helper' # Use the RSpec framework
4
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'
5
8
 
6
9
  # Load the class under test
7
10
  require_relative '../../lib/mini_kraken/composite/cons_cell'
@@ -14,6 +17,7 @@ module MiniKraken
14
17
  let(:pea) { k_symbol(:pea) }
15
18
  let(:pod) { k_symbol(:pod) }
16
19
  let(:corn) { k_symbol(:corn) }
20
+ let(:ctx) { Core::Context.new }
17
21
  subject { ConsCell.new(pea, pod) }
18
22
 
19
23
  context 'Initialization:' do
@@ -25,6 +29,10 @@ module MiniKraken
25
29
  expect { ConsCell.new(pea, pod) }.not_to raise_error
26
30
  end
27
31
 
32
+ it 'could be initialized as null list' do
33
+ expect { ConsCell.null }.not_to raise_error
34
+ end
35
+
28
36
  it 'should know its car child' do
29
37
  expect(subject.car).to eq(pea)
30
38
  end
@@ -33,6 +41,7 @@ module MiniKraken
33
41
  expect(subject.cdr).to eq(pod)
34
42
  end
35
43
 
44
+
36
45
  it 'should know its children' do
37
46
  expect(subject.children).to eq([pea, pod])
38
47
  end
@@ -40,6 +49,7 @@ module MiniKraken
40
49
  it 'should know if it is empty (null)' do
41
50
  expect(subject).not_to be_null
42
51
  expect(ConsCell.new(nil, nil)).to be_null
52
+ expect(ConsCell.null).to be_null
43
53
  expect(NullList).to be_null
44
54
  end
45
55
 
@@ -68,6 +78,14 @@ module MiniKraken
68
78
  expect(subject.eql?(different)).to be_falsey
69
79
  end
70
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_nil
87
+ end
88
+
71
89
  it 'should set_cdr! another cons cell' do
72
90
  instance = ConsCell.new(pea)
73
91
  trail = ConsCell.new(pod)
@@ -76,6 +94,37 @@ module MiniKraken
76
94
  expect(instance.cdr).to eq(trail)
77
95
  end
78
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
+
79
128
  it 'should provide a list representation of itself' do
80
129
  # Case of null list
81
130
  expect(NullList.to_s).to eq '()'
@@ -91,6 +140,11 @@ module MiniKraken
91
140
  # Case of two elements improper list
92
141
  expect(subject.to_s).to eq '(:pea . :pod)'
93
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
+
94
148
  # Case of three elements proper list
95
149
  cell = ConsCell.new(pea, ConsCell.new(pod, ConsCell.new(corn)))
96
150
  expect(cell.to_s).to eq '(:pea :pod :corn)'
@@ -103,6 +157,68 @@ module MiniKraken
103
157
  cell = ConsCell.new(ConsCell.new(pea), ConsCell.new(pod))
104
158
  expect(cell.to_s).to eq '((:pea) :pod)'
105
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
106
222
  end # context
107
223
  end # describe
108
224
  end # module
@@ -29,7 +29,7 @@ module MiniKraken
29
29
 
30
30
  context 'proper list visiting:' do
31
31
  it 'can visit a null list' do
32
- null_list = ConsCell.new(nil)
32
+ null_list = ConsCell.null
33
33
  visitor = subject.df_visitor(null_list)
34
34
  expect(visitor.resume).to eq([:car, null_list])
35
35
  expect(visitor.resume).to eq([:car, nil])
@@ -89,6 +89,7 @@ module MiniKraken
89
89
 
90
90
  it 'can visit a three elements improper list' do
91
91
  l_improper = ConsCell.new(pea, ConsCell.new(pod, corn))
92
+ expect(l_improper.to_s).to eq('(:pea :pod . :corn)')
92
93
  visitor = subject.df_visitor(l_improper)
93
94
  expect(visitor.resume).to eq([:car, l_improper])
94
95
  expect(visitor.resume).to eq([:car, pea])
@@ -97,6 +98,18 @@ module MiniKraken
97
98
  expect(visitor.resume).to eq([:cdr, corn])
98
99
  expect(visitor.resume).to eq([:stop, nil])
99
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, nil])
110
+ expect(visitor.resume).to eq([:cdr, nil])
111
+ expect(visitor.resume).to eq([:cdr, pod])
112
+ end
100
113
  end # context
101
114
 
102
115
  context 'Skip visit of children of a ConsCell:' do
@@ -128,9 +141,9 @@ module MiniKraken
128
141
 
129
142
  context 'Circular structures visiting:' do
130
143
  it 'should cope with a circular graph' do
131
- second_cell = ConsCell.new(pod)
144
+ second_cell = ConsCell.new(pea)
132
145
  first_cell = ConsCell.new(pea, second_cell)
133
- second_cell.instance_variable_set(:@car, first_cell) # Ugly!
146
+ second_cell.set_car!(first_cell)
134
147
 
135
148
  visitor = subject.df_visitor(first_cell)
136
149
  expect(visitor.resume).to eq([:car, first_cell])
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+ require_relative '../support/factory_atomic'
5
+
6
+ # Load the class under test
7
+ require_relative '../../lib/mini_kraken/composite/list'
8
+
9
+ module MiniKraken
10
+ module Composite
11
+ describe List do
12
+ include MiniKraken::FactoryAtomic # Use mix-in module
13
+
14
+ let(:pea) { k_symbol(:pea) }
15
+ let(:pod) { k_symbol(:pod) }
16
+ let(:corn) { k_symbol(:corn) }
17
+
18
+ context 'Module as a factory:' do
19
+ subject { List }
20
+
21
+ it 'builds a pair wiht one argument (= one element proper list)' do
22
+ pair = subject.cons(pea)
23
+ expect(pair.car).to eq(pea)
24
+ expect(pair.cdr).to be_nil
25
+ end
26
+
27
+ it 'builds a pair with two explicit arguments' do
28
+ pair = subject.cons(pea, pod)
29
+ expect(pair.car).to eq(pea)
30
+ expect(pair.cdr).to eq(pod)
31
+ end
32
+
33
+ it 'builds a null list from an empty array' do
34
+ l = subject.make_list([])
35
+ expect(l).to be_kind_of(ConsCell)
36
+ expect(l).to be_null
37
+ end
38
+
39
+ it 'builds a proper list from an non-empty array' do
40
+ l = subject.make_list([pea, pod, corn])
41
+
42
+ expect(l.car).to eq(pea)
43
+ expect(l.cdr.car).to eq(pod)
44
+ expect(l.cdr.cdr.car).to eq(corn)
45
+ expect(l.cdr.cdr.cdr).to be_nil
46
+ end
47
+ end # context
48
+ end # describz
49
+ end # module
50
+ end # module
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ # Load the class under test
6
+ require_relative '../../lib/mini_kraken/core/any_value'
7
+
8
+
9
+ module MiniKraken
10
+ module Core
11
+ describe AnyValue do
12
+ let(:some_rank) { 2 }
13
+ subject { AnyValue.new(some_rank) }
14
+
15
+ context 'Initialization:' do
16
+ it "should be initialized with a variable's rank" do
17
+ expect { AnyValue.new(0) }.not_to raise_error
18
+ end
19
+
20
+ it 'should know its rank' do
21
+ expect(subject.rank).to eq(some_rank)
22
+ end
23
+ end # context
24
+
25
+ context 'Provided services:' do
26
+ it 'should compare itself to another instance' do
27
+ expect(subject == AnyValue.new(some_rank)).to be_truthy
28
+ expect(subject == AnyValue.new(1)).to be_falsey
29
+ end
30
+
31
+ it 'should compare itself to an integer' do
32
+ expect(subject == some_rank).to be_truthy
33
+ expect(subject == 1).to be_falsey
34
+ end
35
+
36
+ it 'should compare itself to a symbol' do
37
+ expect(subject == :_2).to be_truthy
38
+ expect(subject == :_1).to be_falsey
39
+ end
40
+
41
+ it 'should know its text representation' do
42
+ expect(subject.to_s).to eq('_2')
43
+ end
44
+
45
+ it 'should know that it represents a non-pinned variable' do
46
+ ctx = double('dummy-context')
47
+ expect(subject).not_to be_pinned(ctx)
48
+ end
49
+ end
50
+ end # describe
51
+ end # module
52
+ end # module
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ # Load the class under test
6
+ require_relative '../../lib/mini_kraken/core/arity'
7
+
8
+ module MiniKraken
9
+ module Core
10
+ describe Arity do
11
+ subject { Arity.new(0, 1) }
12
+
13
+ context 'Initialization:' do
14
+ it 'should be initialized with two integers' do
15
+ expect { Arity.new(0, 1) }.not_to raise_error
16
+ end
17
+
18
+ it 'should know its lower bound' do
19
+ expect(subject.low).to eq(0)
20
+ end
21
+
22
+ it 'should know its upper bound' do
23
+ expect(subject.high).to eq(1)
24
+ end
25
+ end # context
26
+
27
+ context 'Initialization:' do
28
+ it 'should know whether is is nullary' do
29
+ expect(subject).not_to be_nullary
30
+
31
+ instance = Arity.new(0, '*')
32
+ expect(instance).not_to be_nullary
33
+
34
+ instance = Arity.new(0, 0)
35
+ expect(instance).to be_nullary
36
+ end
37
+
38
+ it 'should know whether is is unary' do
39
+ expect(subject).not_to be_unary
40
+
41
+ instance = Arity.new(1, 2)
42
+ expect(instance).not_to be_unary
43
+
44
+ instance = Arity.new(1, 1)
45
+ expect(instance).to be_unary
46
+ end
47
+
48
+ it 'should know whether is is binary' do
49
+ expect(subject).not_to be_binary
50
+
51
+ instance = Arity.new(1, 2)
52
+ expect(instance).not_to be_binary
53
+
54
+ instance = Arity.new(2, 2)
55
+ expect(instance).to be_binary
56
+ end
57
+
58
+ it 'should know whether is is variadic' do
59
+ expect(subject).not_to be_variadic
60
+
61
+ instance = Arity.new(1, '*')
62
+ expect(instance).to be_variadic
63
+ end
64
+
65
+ it 'should know whether an integer fits the arity range' do
66
+ expect(subject.match?(0)).to be_truthy
67
+ expect(subject.match?(1)).to be_truthy
68
+ expect(subject.match?(2)).to be_falsey
69
+
70
+ instance = Arity.new(2, '*')
71
+ expect(instance.match?(1)).to be_falsey
72
+ expect(instance.match?(2)).to be_truthy
73
+ expect(instance.match?(42)).to be_truthy
74
+ end
75
+
76
+ it 'should know whether is equal to another arity' do
77
+ expect(subject == subject).to be_truthy
78
+
79
+ same = Arity.new(0, 1)
80
+ expect(subject == same).to be_truthy
81
+
82
+ same_low = Arity.new(0, 2)
83
+ expect(subject == same_low).to be_falsey
84
+
85
+ same_high = Arity.new(1, 1)
86
+ expect(subject == same_high).to be_falsey
87
+ end
88
+ end # context
89
+ end # describe
90
+ end # module
91
+ end # module