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

Sign up to get free protection for your applications and to get access to all the features.
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