wongi-engine 0.4.0.pre.alpha10 → 0.4.0.pre.alpha12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0dc2418ab6ffabbb410e83db899bed0479fc5912ec24bc6bf5c01f40ca306aa1
4
- data.tar.gz: 4f22e6752c8dfe568eaae071cc7d10b062dee6ddaf8c8ddb2dc201773b7378a1
3
+ metadata.gz: 18bc1bfbc38b0ae08b505d3209fb6f0776c9abfa532d8c90b4ef8c6d26461c44
4
+ data.tar.gz: b10cc7b4fae950742ae4471d7385d745f23bb875d6436a80139c355e35c9370f
5
5
  SHA512:
6
- metadata.gz: 6f0d335b747ae2495a2cb259d4d538cb4b66f7f97fabb41ffd8c7dc78750df54c04990e60eea1913155388488d867e7090c71aee1ae647d0fdcf20447c455e00
7
- data.tar.gz: d1db63d17198447da1f6761897cda0e5db7af1dc880203146e0deae4c30de89fe0486049ece689e1394d773a9bac79c67cc85ecf45a2655eee84ec25eab7855a
6
+ metadata.gz: 2f480873ccb3c7292b143cfdff082829e8e52b9ab8424e86caa6a8929d544f1f6d0aa3bfbd266bf12d2c2cf1de42282a5183244db27a8d15e3e51d681f2a0bb6
7
+ data.tar.gz: 04dbbba150bbb6d01336fab7d041769d986e8602838ed79e4e321ebf2c9c914344377e5cf7e82a753d1324ac87daa730640006595ce645f259d572fe2fe5cd33
@@ -25,27 +25,6 @@ module Wongi::Engine
25
25
  index[hashed_key(wme)]
26
26
  end
27
27
 
28
- def collections_for_template(template)
29
- return nil unless template_matches_pattern?(template)
30
-
31
- # here we know that all fields on which we're indexing are concrete in the template
32
- collection_for_wme(template)
33
- end
34
-
35
- private def template_matches_pattern?(template)
36
- template_element_matches_pattern?(:subject, template.subject) &&
37
- template_element_matches_pattern?(:predicate, template.predicate) &&
38
- template_element_matches_pattern?(:object, template.object)
39
- end
40
-
41
- private def template_element_matches_pattern?(member, template_element)
42
- if Template.concrete?(template_element)
43
- pattern.include?(member)
44
- else
45
- !pattern.include?(member)
46
- end
47
- end
48
-
49
28
  private def key(wme)
50
29
  pattern.map { wme.public_send(_1) }
51
30
  end
@@ -61,12 +61,13 @@ module Wongi::Engine
61
61
  aggregated = aggregate.call(tokens.map(&map))
62
62
  assignment = { var => aggregated }
63
63
  children = child ? [child] : self.children
64
- tokens.each do |token|
65
- # TODO: optimize this to work with a diff of actual changes
66
- beta_deactivate_children(token: token, children: children)
67
- end
68
64
  children.each do |beta|
69
- beta.beta_activate(Token.new(beta, tokens, nil, assignment))
65
+ new_token = Token.new(beta, tokens, nil, assignment)
66
+ # nothing changed, skip useless traversal
67
+ next if beta.tokens.find { _1.duplicate?(new_token) }
68
+
69
+ beta.tokens.select { |child| tokens.any? { child.child_of?(_1) } }.each { beta.beta_deactivate(_1) }
70
+ beta.beta_activate(new_token)
70
71
  end
71
72
  end
72
73
  end
@@ -58,7 +58,8 @@ module Wongi::Engine
58
58
  end
59
59
 
60
60
  private def select_wmes(template)
61
- rete.current_overlay.select(template)
61
+ # capture the enumerator
62
+ rete.current_overlay.each(template).to_a
62
63
  end
63
64
 
64
65
  private def specialize(template, tests, token)
@@ -26,6 +26,8 @@ module Wongi::Engine
26
26
  end
27
27
 
28
28
  private def should_assert?(wme, token)
29
+ return true if rete.bypass_consistency_checks?
30
+
29
31
  considered_tokens = Set.new
30
32
  tokens_to_consider = [token]
31
33
  until tokens_to_consider.empty?
@@ -33,11 +35,17 @@ module Wongi::Engine
33
35
  considered_tokens.add(token)
34
36
 
35
37
  # self-affirming reasoning
36
- return false if token.wme == wme
38
+ if token.wme == wme
39
+ # puts "detected self-affirming"
40
+ return false
41
+ end
37
42
 
38
43
  # asserting this WME would invalidate the match
39
44
  # TODO: clean up
40
- return false if token.node.is_a?(NegNode) && wme =~ token.node.alpha.template && token.node.matches?(token, wme) # how much is actually necessary?
45
+ if token.node.is_a?(NegNode) && wme =~ token.node.alpha.template && token.node.matches?(token, wme) # how much is actually necessary?
46
+ # puts "detected self-negating"
47
+ return false
48
+ end
41
49
 
42
50
  token.parents.each { |parent| tokens_to_consider.push(parent) unless considered_tokens.include?(parent) }
43
51
 
@@ -0,0 +1,60 @@
1
+ module Wongi::Engine
2
+ class EntityIterator
3
+
4
+ attr_reader :entity, :collection
5
+ private :entity, :collection
6
+
7
+ def initialize(entity, collection)
8
+ @entity = entity
9
+ @collection = collection
10
+ end
11
+
12
+ def each
13
+ if block_given?
14
+ @collection.each do |wme|
15
+ yield wme.predicate, wme.object
16
+ end
17
+ else
18
+ Enumerator.new do |y|
19
+ @collection.each do |wme|
20
+ y << [wme.predicate, wme.object]
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def get(name)
27
+ each { |k, v| return v if k == name }
28
+ nil
29
+ end
30
+
31
+ def [](name)
32
+ get(name)
33
+ end
34
+
35
+ def get_all(name)
36
+ each.filter_map { |k, v| v if k == name }
37
+ end
38
+
39
+ def fetch(name, *args, &block)
40
+ each { |k, v| return v if k == name }
41
+ if args.first
42
+ args.first
43
+ elsif block
44
+ block.call(name)
45
+ else
46
+ raise KeyError
47
+ end
48
+ end
49
+
50
+ def method_missing(name)
51
+ each { |k, v| return v if k == name }
52
+ raise NoMethodError
53
+ end
54
+
55
+ def respond_to_missing?(name, _include_private)
56
+ each { |k, v| return true if k == name }
57
+ super
58
+ end
59
+ end
60
+ end
@@ -3,9 +3,12 @@ require 'wongi-engine/network/debug'
3
3
 
4
4
  module Wongi::Engine
5
5
  class Network
6
+ include CoreExt
6
7
  attr_accessor :alpha_top, :beta_top, :queries, :results, :alpha_hash
7
8
  attr_reader :productions, :overlays
8
9
 
10
+ attr_predicate :bypass_consistency_checks
11
+
9
12
  include NetworkParts::Collectable
10
13
  private :overlays
11
14
  private :alpha_hash, :alpha_hash=
@@ -106,6 +109,10 @@ module Wongi::Engine
106
109
  overlays.last
107
110
  end
108
111
 
112
+ def entity(subject)
113
+ current_overlay.entity(subject)
114
+ end
115
+
109
116
  def assert(wme)
110
117
  default_overlay.assert(wme)
111
118
  end
@@ -127,7 +134,7 @@ module Wongi::Engine
127
134
  end
128
135
 
129
136
  def wmes
130
- current_overlay.select(:_, :_, :_)
137
+ each.to_a
131
138
  end
132
139
 
133
140
  alias statements wmes
@@ -165,6 +172,7 @@ module Wongi::Engine
165
172
  else
166
173
  raise Error, "I don't know how to accept a #{something.class}"
167
174
  end
175
+ self
168
176
  end
169
177
  end
170
178
 
@@ -202,9 +210,8 @@ module Wongi::Engine
202
210
  compile_alpha Template.new(s, p, o)
203
211
  end
204
212
 
205
- # TODO: pick an alpha with fewer candidates to go through
206
213
  def initial_fill(alpha)
207
- default_overlay.select(:_, :_, :_).each do |wme|
214
+ default_overlay.each(:_, :_, :_).to_a.each do |wme|
208
215
  alpha.activate wme if wme =~ alpha.template
209
216
  end
210
217
  end
@@ -232,37 +239,19 @@ module Wongi::Engine
232
239
  end
233
240
 
234
241
  def exists?(wme)
235
- find(wme.subject, wme.predicate, wme.object)
242
+ !find(wme.subject, wme.predicate, wme.object).nil?
236
243
  end
237
244
 
238
245
  def each(*args, &block)
239
- template = case args.length
240
- when 0
241
- Template.new(:_, :_, :_)
242
- when 3
243
- Template.new(*args)
244
- else
245
- raise Error, "Network#each expect a template or nothing at all"
246
- end
247
- matching = current_overlay.select(template)
248
- if block_given?
249
- matching.each(&block)
250
- else
251
- matching.each
252
- end
246
+ current_overlay.each(*args, &block)
253
247
  end
254
248
 
255
- def select(s, p, o, &block)
256
- matching = current_overlay.select(s, p, o)
257
- if block_given?
258
- matching.each(&block)
259
- else
260
- matching.each
261
- end
249
+ def select(*args, &block)
250
+ each(*args, &block)
262
251
  end
263
252
 
264
- def find(s, p, o)
265
- current_overlay.select(s, p, o).first
253
+ def find(*args)
254
+ each(*args).first
266
255
  end
267
256
 
268
257
  protected
@@ -22,12 +22,14 @@ module Wongi::Engine
22
22
 
23
23
  @wmes = Set.new
24
24
  @indexes = [
25
- AlphaIndex.new(%i[subject]),
26
- AlphaIndex.new(%i[predicate]),
25
+ nil,
27
26
  AlphaIndex.new(%i[object]),
28
- AlphaIndex.new(%i[subject predicate]),
29
- AlphaIndex.new(%i[subject object]),
27
+ AlphaIndex.new(%i[predicate]),
30
28
  AlphaIndex.new(%i[predicate object]),
29
+ AlphaIndex.new(%i[subject]),
30
+ AlphaIndex.new(%i[subject object]),
31
+ AlphaIndex.new(%i[subject predicate]),
32
+ nil,
31
33
  ]
32
34
  @hidden_parent_wmes = {}
33
35
 
@@ -69,6 +71,8 @@ module Wongi::Engine
69
71
  else
70
72
  raise Error, "overlays can only accept data"
71
73
  end
74
+
75
+ self
72
76
  end
73
77
 
74
78
  def assert(wme, generator: nil)
@@ -76,6 +80,8 @@ module Wongi::Engine
76
80
  queue.push(operation)
77
81
 
78
82
  run_queue if queue.length == 1
83
+
84
+ self
79
85
  end
80
86
 
81
87
  def retract(wme, options = {})
@@ -87,9 +93,11 @@ module Wongi::Engine
87
93
  queue.push(operation)
88
94
 
89
95
  run_queue if queue.length == 1
96
+
97
+ self
90
98
  end
91
99
 
92
- def run_queue
100
+ private def run_queue
93
101
  until queue.empty?
94
102
  operation, wme, options = queue.shift
95
103
 
@@ -117,19 +125,6 @@ module Wongi::Engine
117
125
  self == rete.default_overlay
118
126
  end
119
127
 
120
- # TODO: this is inconsistent.
121
- # A WME retracted in-flight will be visible in active enumerators
122
- # but a token will not.
123
- # But this is how it works.
124
-
125
- # def wmes(template)
126
- # DuplicatingEnumerator.new(index(template))
127
- # end
128
-
129
- # def tokens(beta)
130
- # DeleteSafeEnumerator.new(raw_tokens(beta))
131
- # end
132
-
133
128
  def find(wme)
134
129
  if wme.is_a?(Array)
135
130
  wme = WME.new(*wme)
@@ -137,20 +132,35 @@ module Wongi::Engine
137
132
  find_wme(wme)
138
133
  end
139
134
 
140
- def select(*args)
135
+ def each(*args, &block)
136
+ template = nil
141
137
  case args.length
138
+ when 0
139
+ template = Template.new(:_, :_, :_)
142
140
  when 1
143
- case args.first
141
+ arg = args.first
142
+ case arg
143
+ when Array
144
+ template = Template.new(*arg)
144
145
  when Template
145
- select_by_template(args.first)
146
+ template = arg
147
+ when WME
148
+ template = Template.new(arg.subject, arg.predicate, arg.object)
146
149
  else
147
150
  raise ArgumentError
148
151
  end
149
152
  when 3
150
- select_by_template(Template.new(*args))
153
+ template = Template.new(*args)
151
154
  else
152
155
  raise ArgumentError
153
156
  end
157
+
158
+ each_by_template(template, &block)
159
+ end
160
+
161
+ def entity(subject)
162
+ # 4 is the bitmap for <s _ _>
163
+ EntityIterator.new(subject, indexes[4].collection_for_wme(Template.new(subject, :_, :_)))
154
164
  end
155
165
 
156
166
  def manual?(wme)
@@ -165,25 +175,21 @@ module Wongi::Engine
165
175
  end
166
176
 
167
177
  def generators(wme)
168
- own_generators = generator_tracker.for_wme(wme)
169
- parent_generators =
178
+ Enumerator.new do |y|
179
+ generator_tracker.for_wme(wme).each { y << _1 }
170
180
  if parent
171
- parent.generators(wme).reject { |t| hidden_token?(t) }.to_set
172
- else
173
- Set.new
181
+ parent.generators(wme).reject { hidden_token?(_1) }.each { y << _1 }
174
182
  end
175
- own_generators.union(parent_generators)
183
+ end
176
184
  end
177
185
 
178
186
  def generated_wmes(token)
179
- own_wmes = generator_tracker.for_token(token)
180
- parent_wmes =
187
+ Enumerator.new do |y|
188
+ generator_tracker.for_token(token).each { y << _1 }
181
189
  if parent && !hidden_token?(token)
182
- parent.generated_wmes(token).reject { hidden_wme?(_1) }.to_set
183
- else
184
- Set.new
190
+ parent.generated_wmes(token).reject { hidden_wme?(_1) }.each { y << _1 }
185
191
  end
186
- own_wmes.union(parent_wmes)
192
+ end
187
193
  end
188
194
 
189
195
  private def own_manual?(wme)
@@ -202,7 +208,9 @@ module Wongi::Engine
202
208
  has_own_wme?(wme) ? wme : nil
203
209
  end
204
210
 
205
- private def has_own_wme?(wme) = wmes.include?(wme)
211
+ private def has_own_wme?(wme)
212
+ wmes.include?(wme)
213
+ end
206
214
 
207
215
  private def find_parents_wme(wme)
208
216
  return unless parent
@@ -218,28 +226,27 @@ module Wongi::Engine
218
226
  end
219
227
  end
220
228
 
221
- private def select_by_template(template)
222
- select_parents_template(template) + select_own_template(template)
229
+ def each_by_template(template)
230
+ Enumerator.new do |y|
231
+ each_own_wme_by_template(template, y)
232
+ each_parent_wme_by_template(template, y)
233
+ end
223
234
  end
224
235
 
225
- private def select_own_template(template)
236
+ private def each_own_wme_by_template(template, y)
226
237
  if template.concrete?
227
238
  wme = find_own_wme(WME.from_concrete_template(template))
228
- wme ? [wme] : []
239
+ y << wme if wme
229
240
  elsif template.root?
230
- wmes
241
+ wmes.each { y << _1 }
231
242
  else
232
- indexes.map { |index|
233
- index.collections_for_template(template)
234
- }.compact.first
243
+ indexes[template.bitmap].collection_for_wme(template).each { y << _1 }
235
244
  end
236
245
  end
237
246
 
238
- private def select_parents_template(template)
247
+ private def each_parent_wme_by_template(template, y)
239
248
  if parent
240
- parent.select(template).reject { hidden_wme?(_1) }.to_set
241
- else
242
- Set.new
249
+ parent.each_by_template(template).reject { hidden_wme?(_1) }.each { y << _1 }
243
250
  end
244
251
  end
245
252
 
@@ -251,7 +258,7 @@ module Wongi::Engine
251
258
 
252
259
  unless has_own_wme?(wme)
253
260
  wmes.add(wme)
254
- indexes.each { _1.add(wme) }
261
+ indexes[1..6].each { _1.add(wme) }
255
262
  end
256
263
 
257
264
  if generator
@@ -271,7 +278,7 @@ module Wongi::Engine
271
278
  # no remaining reasons to keep this WME around
272
279
  if !own_generated?(wme) && !own_manual?(wme)
273
280
  wmes.delete(wme)
274
- indexes.each { _1.remove(wme) }
281
+ indexes[1..6].each { _1.remove(wme) }
275
282
  end
276
283
 
277
284
  neg_join_results.remove_wme(wme)
@@ -309,7 +316,8 @@ module Wongi::Engine
309
316
  def remove_token(token)
310
317
  # p remove_token: {token:}
311
318
 
312
- wmes = generated_wmes(token)
319
+ # capture the entire enumerated state
320
+ wmes = generated_wmes(token).to_a
313
321
 
314
322
  if own_node_tokens(token.node).find { _1.equal?(token) }.nil?
315
323
  if parents_node_tokens(token.node).find { _1.equal?(token) }
@@ -28,6 +28,10 @@ module Wongi::Engine
28
28
  Template.concrete?(subject) && Template.concrete?(predicate) && Template.concrete?(object)
29
29
  end
30
30
 
31
+ def bitmap
32
+ (Template.concrete?(subject) ? 4 : 0) | (Template.concrete?(predicate) ? 2 : 0) | (Template.concrete?(object) ? 1 : 0)
33
+ end
34
+
31
35
  def variables
32
36
  [].tap do |a|
33
37
  a << subject if Template.variable?(subject)
@@ -27,12 +27,18 @@ module Wongi::Engine
27
27
  @assignments[variable] = value
28
28
  end
29
29
 
30
+ def own_assignments
31
+ @assignments
32
+ end
33
+
30
34
  def assignments
31
- all_assignments
35
+ parents.each_with_object({}) do |parent, acc|
36
+ acc.merge!(parent.assignments)
37
+ end.merge(own_assignments)
32
38
  end
33
39
 
34
40
  def [](var)
35
- a = assignments[var]
41
+ a = assignment(var)
36
42
  a.respond_to?(:call) ? a.call(self) : a
37
43
  end
38
44
 
@@ -40,8 +46,23 @@ module Wongi::Engine
40
46
  vars.map { self[_1] }
41
47
  end
42
48
 
49
+ def assignment(x)
50
+ return @assignments[x] if has_own_var?(x)
51
+
52
+ parents.each do |parent|
53
+ a = parent.assignment(x)
54
+ return a if a
55
+ end
56
+
57
+ nil
58
+ end
59
+
43
60
  def has_var?(x)
44
- assignments.key? x
61
+ has_own_var?(x) || parents.any? { _1.has_var?(x) }
62
+ end
63
+
64
+ def has_own_var?(x)
65
+ @assignments.key?(x)
45
66
  end
46
67
 
47
68
  # TODO: ignore assignments?
@@ -49,12 +70,12 @@ module Wongi::Engine
49
70
  instance_of?(other.class) &&
50
71
  parents == other.parents &&
51
72
  wme == other.wme &&
52
- assignments == other.assignments
73
+ own_assignments == other.own_assignments
53
74
  end
54
75
 
55
76
  def to_s
56
77
  str = "TOKEN [ #{object_id} ancestors=#{ancestors.map(&:object_id).map(&:to_s).join('.')} "
57
- all_assignments.each_pair { |key, value| str << "#{key}=#{value.is_a?(TokenAssignment) ? "#{value.call} (#{value})" : value} " }
78
+ assignments.each_pair { |key, value| str << "#{key}=#{value.is_a?(TokenAssignment) ? "#{value.call} (#{value})" : value} " }
58
79
  str << "]"
59
80
  str
60
81
  end
@@ -62,13 +83,5 @@ module Wongi::Engine
62
83
  def inspect
63
84
  to_s
64
85
  end
65
-
66
- protected
67
-
68
- def all_assignments
69
- parents.each_with_object({}) do |parent, acc|
70
- acc.merge!(parent.assignments)
71
- end.merge(@assignments)
72
- end
73
86
  end
74
87
  end
@@ -1,5 +1,5 @@
1
1
  module Wongi
2
2
  module Engine
3
- VERSION = "0.4.0-alpha10".freeze
3
+ VERSION = "0.4.0-alpha12".freeze
4
4
  end
5
5
  end
data/lib/wongi-engine.rb CHANGED
@@ -31,6 +31,7 @@ require 'wongi-engine/compiler'
31
31
  require 'wongi-engine/join_results'
32
32
  require 'wongi-engine/generator_tracker'
33
33
  require 'wongi-engine/overlay'
34
+ require 'wongi-engine/entity_iterator'
34
35
  require 'wongi-engine/enumerators'
35
36
  require 'wongi-engine/network'
36
37
  require 'wongi-engine/graph'
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "issue 4" do
4
- it "correctlies retract pre-added items from within a rule" do
4
+ it "correctly retracts pre-added items from within a rule" do
5
5
  engine = Wongi::Engine.create
6
6
 
7
7
  10.times { |i| engine << [i, :is_number, true] }
@@ -22,11 +22,11 @@ describe "issue 4" do
22
22
  numbers = engine.select :_, :is_number, true
23
23
  evens = engine.select :_, :is_even, true
24
24
 
25
- expect(numbers.size).to eq(0)
26
- expect(evens.size).to eq(10)
25
+ expect(numbers.count).to eq(0)
26
+ expect(evens.count).to eq(10)
27
27
  end
28
28
 
29
- it "correctlies retract post-added items from within a rule" do
29
+ it "correctly retracts post-added items from within a rule" do
30
30
  engine = Wongi::Engine.create
31
31
 
32
32
  engine.rule 'segregate' do
@@ -47,8 +47,8 @@ describe "issue 4" do
47
47
  numbers = engine.select :_, :is_number, true
48
48
  evens = engine.select :_, :is_even, true
49
49
 
50
- expect(numbers.size).to eq(0)
51
- expect(evens.size).to eq(5)
50
+ expect(numbers.count).to eq(0)
51
+ expect(evens.count).to eq(5)
52
52
  end
53
53
 
54
54
  # cascaded processing affects this
@@ -80,9 +80,9 @@ describe "issue 4" do
80
80
  evens = engine.select :_, :is_even, true
81
81
  odds = engine.select :_, :is_odd, true
82
82
 
83
- expect(numbers.size).to eq(0)
84
- expect(evens.size).to eq(5)
85
- expect(odds.size).to eq(5)
83
+ expect(numbers.count).to eq(0)
84
+ expect(evens.count).to eq(5)
85
+ expect(odds.count).to eq(5)
86
86
  end
87
87
 
88
88
  it "does not lose track when another rule affects a set" do
@@ -126,8 +126,8 @@ describe "issue 4" do
126
126
  evens = engine.select :_, :is_even, true
127
127
  odds = engine.select :_, :is_odd, true
128
128
 
129
- expect(numbers.size).to eq(5)
130
- expect(evens.size).to eq(5)
131
- expect(odds.size).to eq(5)
129
+ expect(numbers.count).to eq(5)
130
+ expect(evens.count).to eq(5)
131
+ expect(odds.count).to eq(5)
132
132
  end
133
133
  end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe Wongi::Engine::EntityIterator do
4
+ let(:engine) { Wongi::Engine.create }
5
+ let(:x) { engine.entity(:x) }
6
+ let(:y) { engine.entity(:y) }
7
+
8
+ before do
9
+ engine << [:x, :prop1, 1]
10
+ engine << [:x, :prop1, 2]
11
+ engine << [:x, :prop2, :y]
12
+ engine << [:y, :prop3, 3]
13
+ end
14
+
15
+ describe "#each" do
16
+ it 'returns an enumerator' do
17
+ expect(x.each.to_h).to eq(prop1: 2, prop2: :y)
18
+ end
19
+
20
+ it 'iterates over properties' do
21
+ results = {}
22
+ x.each { |k, v| results[k] = v }
23
+ expect(results).to eq(prop1: 2, prop2: :y)
24
+ end
25
+ end
26
+
27
+ describe "#get" do
28
+ specify do
29
+ expect(x.get(:prop1)).to eq(1)
30
+ expect(x.get(:prop2)).to eq(:y)
31
+ expect(x.get(:prop3)).to eq(nil)
32
+
33
+ expect(y.get(:prop3)).to eq(3)
34
+ end
35
+ end
36
+
37
+ describe "#[]" do
38
+ specify do
39
+ expect(x[:prop1]).to eq(1)
40
+ expect(x[:prop2]).to eq(:y)
41
+ expect(x[:prop3]).to eq(nil)
42
+
43
+ expect(y[:prop3]).to eq(3)
44
+ end
45
+ end
46
+
47
+ describe "#fetch" do
48
+ specify do
49
+ expect(x.fetch(:prop1)).to eq(1)
50
+ expect(x.fetch(:prop2)).to eq(:y)
51
+ expect(x.fetch(:prop3, 42)).to eq(42)
52
+ expect(x.fetch(:prop3) { 42 }).to eq(42)
53
+ expect { x.fetch(:prop3) }.to raise_error(KeyError)
54
+
55
+ expect(y.fetch(:prop3)).to eq(3)
56
+ end
57
+ end
58
+
59
+ describe "#get_all" do
60
+ it 'returns all matching values' do
61
+ expect(x.get_all(:prop1)).to eq([1, 2])
62
+ expect(x.get_all(:prop2)).to eq([:y])
63
+ expect(x.get_all(:prop3)).to eq([])
64
+
65
+ expect(y.get_all(:prop3)).to eq([3])
66
+ end
67
+ end
68
+
69
+ describe "#method_missing" do
70
+ it 'can access properties directly' do
71
+ expect(x.prop1).to eq(1)
72
+ expect(x.prop2).to eq(:y)
73
+ expect { x.prop3 }.to raise_error(NoMethodError)
74
+
75
+ expect(y.prop3).to eq(3)
76
+ end
77
+ end
78
+
79
+ describe "#respond_to_missing?" do
80
+ specify do
81
+ expect(x.respond_to?(:prop1)).to be true
82
+ expect(x.respond_to?(:prop2)).to be true
83
+ expect(x.respond_to?(:prop3)).to be false
84
+
85
+ expect(y.respond_to?(:prop3)).to be true
86
+ end
87
+ end
88
+ end
@@ -115,10 +115,10 @@ describe Wongi::Engine::Network do
115
115
  engine << ["Bob", :age, 43]
116
116
 
117
117
  items = engine.select "Alice", :younger, "Bob"
118
- expect(items.size).to eq(1)
118
+ expect(items.count).to eq(1)
119
119
 
120
120
  items = engine.select "Bob", :older, "Alice"
121
- expect(items.size).to eq(1)
121
+ expect(items.count).to eq(1)
122
122
  end
123
123
 
124
124
  it 'uses collectors' do
data/spec/overlay_spec.rb CHANGED
@@ -52,21 +52,21 @@ describe Wongi::Engine::Overlay do
52
52
  ]
53
53
  wmes.each { overlay.assert(_1) }
54
54
 
55
- expect(overlay.select(1, :_, :_)).to have(5).items
56
- expect(overlay.select(2, :_, :_)).to have(4).items
57
- expect(overlay.select(3, :_, :_)).to have(3).items
58
- expect(overlay.select(1, 11, :_)).to have(3).items
59
- expect(overlay.select(:_, 11, :_)).to have(5).items
60
- expect(overlay.select(:_, :_, 113)).to have(2).items
61
- expect(overlay.select(:_, 22, :_)).to have(2).items
62
- expect(overlay.select(:_, 22, 222)).to have(1).items
63
- expect(overlay.select(:_, :_, 222)).to have(2).items
64
- expect(overlay.select(:_, :_, 223)).to have(1).items
65
-
66
- expect(overlay.select(:_, :_, :_)).to have(wmes.length).items
67
-
68
- expect(overlay.select(1, 11, 111)).to have(1).items
69
- expect(overlay.select(1, 11, 111).first).to eq(wmes.first)
55
+ expect(overlay.each(1, :_, :_)).to have(5).items
56
+ expect(overlay.each(2, :_, :_)).to have(4).items
57
+ expect(overlay.each(3, :_, :_)).to have(3).items
58
+ expect(overlay.each(1, 11, :_)).to have(3).items
59
+ expect(overlay.each(:_, 11, :_)).to have(5).items
60
+ expect(overlay.each(:_, :_, 113)).to have(2).items
61
+ expect(overlay.each(:_, 22, :_)).to have(2).items
62
+ expect(overlay.each(:_, 22, 222)).to have(1).items
63
+ expect(overlay.each(:_, :_, 222)).to have(2).items
64
+ expect(overlay.each(:_, :_, 223)).to have(1).items
65
+
66
+ expect(overlay.each(:_, :_, :_)).to have(wmes.length).items
67
+
68
+ expect(overlay.each(1, 11, 111)).to have(1).items
69
+ expect(overlay.each(1, 11, 111).first).to eq(wmes.first)
70
70
  end
71
71
  end
72
72
 
@@ -85,10 +85,10 @@ describe Wongi::Engine::Overlay do
85
85
  wme = Wongi::Engine::WME.new(1, 11, 111)
86
86
 
87
87
  overlay.assert(wme)
88
- expect(overlay.select(:_, :_, :_)).to have(1).items
88
+ expect(overlay.each(:_, :_, :_)).to have(1).items
89
89
 
90
90
  overlay.retract(wme)
91
- expect(overlay.select(:_, :_, :_)).to have(0).items
91
+ expect(overlay.each(:_, :_, :_)).to have(0).items
92
92
  end
93
93
  end
94
94
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wongi-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre.alpha10
4
+ version: 0.4.0.pre.alpha12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valeri Sokolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-05 00:00:00.000000000 Z
11
+ date: 2022-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -128,6 +128,7 @@ files:
128
128
  - lib/wongi-engine/dsl/ncc_subrule.rb
129
129
  - lib/wongi-engine/dsl/query.rb
130
130
  - lib/wongi-engine/dsl/rule.rb
131
+ - lib/wongi-engine/entity_iterator.rb
131
132
  - lib/wongi-engine/enumerators.rb
132
133
  - lib/wongi-engine/error.rb
133
134
  - lib/wongi-engine/filter.rb
@@ -163,6 +164,7 @@ files:
163
164
  - spec/beta_node_spec.rb
164
165
  - spec/bug_specs/issue_4_spec.rb
165
166
  - spec/dataset_spec.rb
167
+ - spec/entity_iterator_spec.rb
166
168
  - spec/generation_spec.rb
167
169
  - spec/greater_than_equality_test_spec.rb
168
170
  - spec/high_level_spec.rb