wongi-engine 0.4.0.pre.alpha9 → 0.4.0.pre.alpha11

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: 8b8990e295e71589c0de4e5ab8ab947e4a88d6de25df75d15ea219532cd923e7
4
- data.tar.gz: ba314dbc0885f56c74b876d00f3b903836931a0b959b23708375c778692801c9
3
+ metadata.gz: c6618cdaae22d90fec75bb11bbfeb27477d9aca0661d0de91ab04ce3b434ce6e
4
+ data.tar.gz: c9973d3a202faa0882653e99a3db546af9b02f6d1e09af075e4749681903743b
5
5
  SHA512:
6
- metadata.gz: 34593896193fc9eb110f04794c2f33ae43f53e6061bf557e16320f980646999573002e186f4ef591388b16692419eb478aaab80e03250f500a64c407fc227333
7
- data.tar.gz: 97a14c3519ca53e3cbc665ff9d682ff41cc8b20a3d3e4f6de238c67c4a9ad6ac4d31dc90c605b83c205f5e469f8394a8d501377ea476c484291542fa6bd1c371
6
+ metadata.gz: 2ec734eba8278f9ed3b8571b67a5e7449c4d172143673953d568bc4299383dc60579c295457010a3e9160de5698ecd529713dad80940751fce6c8b599d05dc91
7
+ data.tar.gz: ead1a3405786c7be13882c24ce8457ff31efa003bd9a84722073ff543ddff028b201c5d769756a2fadadfa84bbf0d5289db810f4e06d574c6b5960cb3a55302e
@@ -57,17 +57,17 @@ module Wongi::Engine
57
57
  [tokens]
58
58
  end
59
59
 
60
-
61
60
  groups.each do |tokens|
62
- aggregated = self.aggregate.call(tokens.map(&self.map))
61
+ aggregated = aggregate.call(tokens.map(&map))
63
62
  assignment = { var => aggregated }
64
63
  children = child ? [child] : self.children
65
- tokens.each do |token|
66
- # TODO: optimize this to work with a diff of actual changes
67
- beta_deactivate_children(token: token, children: children)
68
- end
69
64
  children.each do |beta|
70
- 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)
71
71
  end
72
72
  end
73
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.select(template).to_a
62
63
  end
63
64
 
64
65
  private def specialize(template, tests, token)
@@ -3,8 +3,6 @@ require "set"
3
3
  module Wongi::Engine
4
4
  module DSL::Action
5
5
  class StatementGenerator < BaseAction
6
- GeneratorOrigin = Struct.new(:token, :action)
7
-
8
6
  attr_reader :template
9
7
  private :template
10
8
 
@@ -23,13 +21,13 @@ module Wongi::Engine
23
21
  production.tracer.trace(action: self, wme: wme) if production.tracer
24
22
 
25
23
  if should_assert?(wme, token)
26
- origin = GeneratorOrigin.new(token, self)
27
- token.generated_wmes << wme
28
- overlay.assert(wme, generator: origin)
24
+ overlay.assert(wme, generator: token)
29
25
  end
30
26
  end
31
27
 
32
28
  private def should_assert?(wme, token)
29
+ return true if rete.bypass_consistency_checks?
30
+
33
31
  considered_tokens = Set.new
34
32
  tokens_to_consider = [token]
35
33
  until tokens_to_consider.empty?
@@ -37,34 +35,30 @@ module Wongi::Engine
37
35
  considered_tokens.add(token)
38
36
 
39
37
  # self-affirming reasoning
40
- return false if token.wme == wme
38
+ if token.wme == wme
39
+ # puts "detected self-affirming"
40
+ return false
41
+ end
41
42
 
42
43
  # asserting this WME would invalidate the match
43
44
  # TODO: clean up
44
- 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
45
49
 
46
50
  token.parents.each { |parent| tokens_to_consider.push(parent) unless considered_tokens.include?(parent) }
47
51
 
48
52
  next unless token.wme
49
53
 
50
- overlay.generators(token.wme).each do |generator|
51
- tokens_to_consider.push(generator.token) unless considered_tokens.include?(generator.token)
54
+ overlay.generators(token.wme).each do |generating_token|
55
+ tokens_to_consider.push(generating_token) unless considered_tokens.include?(generating_token)
52
56
  end
53
57
  end
54
58
 
55
59
  # we could not prove that the new WME should not be asserted
56
60
  true
57
61
  end
58
-
59
- def deexecute(token)
60
- # p deexecute: {token:}
61
- origin = GeneratorOrigin.new(token, self)
62
-
63
- generated = token.generated_wmes.dup # select { overlay.generators(_1).include?(origin) }
64
- generated.each do |wme|
65
- overlay.retract wme, generator: origin
66
- end
67
- end
68
62
  end
69
63
  end
70
64
  end
@@ -0,0 +1,32 @@
1
+ module Wongi::Engine
2
+ class GeneratorTracker
3
+ def initialize
4
+ @by_wme = Hash.new { |h, k| h[k] = Set.new }
5
+ @by_token = Hash.new { |h, k| h[k] = Set.new }
6
+ end
7
+
8
+ def add(wme, token)
9
+ @by_wme[wme].add(token)
10
+ @by_token[token.object_id].add(wme)
11
+ end
12
+
13
+ def for_wme(wme)
14
+ @by_wme.has_key?(wme) ? @by_wme[wme] : Set.new
15
+ end
16
+
17
+ def for_token(token)
18
+ @by_token.has_key?(token.object_id) ? @by_token[token.object_id] : Set.new
19
+ end
20
+
21
+ def remove_token(token)
22
+ wmes = for_token(token)
23
+ @by_token.delete(token.object_id)
24
+ wmes.each do |wme|
25
+ next unless @by_wme.key?(wme)
26
+
27
+ @by_wme[wme].delete(token)
28
+ @by_wme.delete(wme) if @by_wme[wme].empty?
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,80 @@
1
+ module Wongi::Engine
2
+ class JoinResults
3
+ attr_reader :by_wme, :by_token, :hidden
4
+ private :by_wme, :by_token
5
+ private :hidden
6
+ def initialize
7
+ @by_wme = Hash.new { |h, k| h[k] = {} }
8
+ @by_token = Hash.new { |h, k| h[k] = {} }
9
+ @hidden = {}
10
+ end
11
+
12
+ def for(wme: nil, token: nil)
13
+ if wme
14
+ by_wme.key?(wme) ? by_wme[wme].keys : []
15
+ elsif token
16
+ by_token.key?(token.object_id) ? by_token[token.object_id].keys : []
17
+ else
18
+ []
19
+ end
20
+ end
21
+
22
+ def has?(jr)
23
+ by_wme.key?(jr.wme) && by_wme[jr.wme].key?(jr)
24
+ end
25
+
26
+ def hidden?(jr)
27
+ hidden.key?(jr)
28
+ end
29
+
30
+ def add(jr)
31
+ if hidden.key?(jr)
32
+ hidden.delete(jr)
33
+ else
34
+ by_wme[jr.wme][jr] = true
35
+ by_token[jr.token.object_id][jr] = true
36
+ end
37
+ end
38
+
39
+ def remove(jr)
40
+ unless has?(jr)
41
+ hide(jr)
42
+ return
43
+ end
44
+
45
+ if by_wme.key?(jr.wme)
46
+ by_wme[jr.wme].delete(jr)
47
+ if by_wme[jr.wme].empty?
48
+ by_wme.delete(jr.wme)
49
+ end
50
+ end
51
+
52
+ if by_token.key?(jr.token.object_id)
53
+ by_token[jr.token.object_id].delete(jr)
54
+ if by_token[jr.token.object_id].empty?
55
+ by_token.delete(jr.token.object_id)
56
+ end
57
+ end
58
+ end
59
+
60
+ def hide(jr)
61
+ hidden[jr] = true
62
+ end
63
+
64
+ def remove_token(token)
65
+ return unless by_token.key?(token.object_id)
66
+
67
+ by_token[token.object_id].keys.each do |jr|
68
+ remove(jr)
69
+ end
70
+ end
71
+
72
+ def remove_wme(wme)
73
+ return unless by_wme.key?(wme)
74
+
75
+ by_wme[wme].keys do |jr|
76
+ remove(jr)
77
+ end
78
+ end
79
+ end
80
+ 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=
@@ -67,7 +70,6 @@ module Wongi::Engine
67
70
  block.call(child)
68
71
  ensure
69
72
  remove_overlay(child)
70
- child.dispose!
71
73
  end
72
74
 
73
75
  def alphas
@@ -203,9 +205,8 @@ module Wongi::Engine
203
205
  compile_alpha Template.new(s, p, o)
204
206
  end
205
207
 
206
- # TODO: pick an alpha with fewer candidates to go through
207
208
  def initial_fill(alpha)
208
- default_overlay.select(:_, :_, :_).each do |wme|
209
+ default_overlay.select(:_, :_, :_).to_a.each do |wme|
209
210
  alpha.activate wme if wme =~ alpha.template
210
211
  end
211
212
  end
@@ -254,16 +255,11 @@ module Wongi::Engine
254
255
  end
255
256
 
256
257
  def select(s, p, o, &block)
257
- matching = current_overlay.select(s, p, o)
258
- if block_given?
259
- matching.each(&block)
260
- else
261
- matching.each
262
- end
258
+ current_overlay.select(s, p, o, &block)
263
259
  end
264
260
 
265
261
  def find(s, p, o)
266
- current_overlay.select(s, p, o).first
262
+ select(s, p, o).first
267
263
  end
268
264
 
269
265
  protected
@@ -1,92 +1,13 @@
1
1
  module Wongi::Engine
2
2
  class Overlay
3
- class JoinResults
4
- attr_reader :by_wme, :by_token, :hidden
5
- private :by_wme, :by_token
6
- private :hidden
7
- def initialize
8
- @by_wme = Hash.new { |h, k| h[k] = {} }
9
- @by_token = Hash.new { |h, k| h[k] = {} }
10
- @hidden = {}
11
- end
12
-
13
- def for(wme: nil, token: nil)
14
- if wme
15
- by_wme.key?(wme) ? by_wme[wme].keys : []
16
- elsif token
17
- by_token.key?(token.object_id) ? by_token[token.object_id].keys : []
18
- else
19
- []
20
- end
21
- end
22
-
23
- def has?(jr)
24
- by_wme.key?(jr.wme) && by_wme[jr.wme].key?(jr)
25
- end
26
-
27
- def hidden?(jr)
28
- hidden.key?(jr)
29
- end
30
3
 
31
- def add(jr)
32
- if hidden.key?(jr)
33
- hidden.delete(jr)
34
- else
35
- by_wme[jr.wme][jr] = true
36
- by_token[jr.token.object_id][jr] = true
37
- end
38
- end
39
-
40
- def remove(jr)
41
- unless has?(jr)
42
- hide(jr)
43
- return
44
- end
45
-
46
- if by_wme.key?(jr.wme)
47
- by_wme[jr.wme].delete(jr)
48
- if by_wme[jr.wme].empty?
49
- by_wme.delete(jr.wme)
50
- end
51
- end
52
-
53
- if by_token.key?(jr.token.object_id)
54
- by_token[jr.token.object_id].delete(jr)
55
- if by_token[jr.token.object_id].empty?
56
- by_token.delete(jr.token.object_id)
57
- end
58
- end
59
- end
60
-
61
- def hide(jr)
62
- hidden[jr] = true
63
- end
64
-
65
- def remove_token(token)
66
- return unless by_token.key?(token.object_id)
67
-
68
- by_token[token.object_id].keys.each do |jr|
69
- remove(jr)
70
- end
71
- end
72
-
73
- def remove_wme(wme)
74
- return unless by_wme.key?(wme)
75
-
76
- by_wme[wme].keys do |jr|
77
- remove(jr)
78
- end
79
- end
80
- end
81
-
82
- attr_reader :rete, :parent, :wmes, :tokens, :indexes, :queue, :hidden_parent_wmes, :hidden_parent_tokens, :wme_generators, :hidden_parent_wme_generators, :wme_manual, :hidden_parent_wme_manual, :neg_join_results, :opt_join_results, :ncc_tokens, :ncc_tokens_owner, :hidden_ncc_tokens
4
+ attr_reader :rete, :parent, :wmes, :tokens, :indexes, :queue, :hidden_parent_wmes, :hidden_parent_tokens, :generator_tracker, :wme_manual, :hidden_parent_wme_manual, :neg_join_results, :opt_join_results, :ncc_tokens, :ncc_tokens_owner, :hidden_ncc_tokens
83
5
  private :wmes, :tokens
84
6
  private :indexes
85
7
  private :queue
86
8
  private :hidden_parent_wmes
87
9
  private :hidden_parent_tokens
88
- private :wme_generators
89
- private :hidden_parent_wme_generators
10
+ private :generator_tracker
90
11
  private :wme_manual
91
12
  private :hidden_parent_wme_manual
92
13
  private :neg_join_results
@@ -111,10 +32,9 @@ module Wongi::Engine
111
32
  @hidden_parent_wmes = {}
112
33
 
113
34
  @tokens = Hash.new { |h, k| h[k] = [] }
114
- @hidden_parent_tokens = {}
35
+ @hidden_parent_tokens = Set.new
115
36
 
116
- @wme_generators = Hash.new { |h, k| h[k] = [] }
117
- @hidden_parent_wme_generators = {}
37
+ @generator_tracker = GeneratorTracker.new
118
38
 
119
39
  @wme_manual = {}
120
40
  @hidden_parent_wme_manual = {}
@@ -140,14 +60,6 @@ module Wongi::Engine
140
60
  parent.ancestor?(other)
141
61
  end
142
62
 
143
- def dispose!
144
- return if default?
145
-
146
- tokens.each do |_node, tokens|
147
- tokens.each(&:dispose!)
148
- end
149
- end
150
-
151
63
  def <<(thing)
152
64
  case thing
153
65
  when Array
@@ -180,19 +92,23 @@ module Wongi::Engine
180
92
  def run_queue
181
93
  until queue.empty?
182
94
  operation, wme, options = queue.shift
95
+
183
96
  case operation
184
97
  when :assert
185
- wme = find_ignoring_hidden(wme) || wme
98
+ existing_wme = find_ignoring_hidden(wme)
99
+ wme = existing_wme || wme
186
100
  visible = !find(wme).nil?
187
101
  add_wme(wme, **options)
188
102
  rete.real_assert(wme) unless visible
103
+
189
104
  when :retract
190
105
  wme = find_ignoring_hidden(wme)
191
- return if wme.nil? # it's perhaps better to return quietly, because complicated cascades may delete a WME while we're going through the queue
106
+ if wme # it's perhaps better to return quietly, because complicated cascades may delete a WME while we're going through the queue
107
+ visible = !find(wme).nil?
108
+ remove_wme(wme, **options)
109
+ rete.real_retract(wme) if visible
110
+ end
192
111
 
193
- visible = !find(wme).nil?
194
- remove_wme(wme, **options)
195
- rete.real_retract(wme) if visible
196
112
  end
197
113
  end
198
114
  end
@@ -226,12 +142,12 @@ module Wongi::Engine
226
142
  when 1
227
143
  case args.first
228
144
  when Template
229
- select_by_template(args.first)
145
+ each_by_template(args.first)
230
146
  else
231
147
  raise ArgumentError
232
148
  end
233
149
  when 3
234
- select_by_template(Template.new(*args))
150
+ each_by_template(Template.new(*args))
235
151
  else
236
152
  raise ArgumentError
237
153
  end
@@ -248,28 +164,22 @@ module Wongi::Engine
248
164
  generators(wme).any?
249
165
  end
250
166
 
251
- def generated_by?(wme, gen)
252
- own_generated_by?(wme, gen) ||
167
+ def generators(wme)
168
+ Enumerator.new do |y|
169
+ generator_tracker.for_wme(wme).each { y << _1 }
253
170
  if parent
254
- parent.generated_by?(wme, gen) && !hidden_parent_wme_generators.key?(gen)
255
- else
256
- false
171
+ parent.generators(wme).reject { hidden_token?(_1) }.each { y << _1 }
257
172
  end
173
+ end
258
174
  end
259
175
 
260
- private def own_generated_by?(wme, gen)
261
- wme_generators.key?(wme) && wme_generators[wme].include?(gen)
262
- end
263
-
264
- def generators(wme)
265
- own_generators = wme_generators.key?(wme) ? wme_generators[wme] : []
266
- parent_generators =
267
- if parent
268
- parent.generators(wme).reject { |g| hidden_parent_wme_generators.key?(g) }
269
- else
270
- []
176
+ def generated_wmes(token)
177
+ Enumerator.new do |y|
178
+ generator_tracker.for_token(token).each { y << _1 }
179
+ if parent && !hidden_token?(token)
180
+ parent.generated_wmes(token).reject { hidden_wme?(_1) }.each { y << _1 }
271
181
  end
272
- own_generators + parent_generators
182
+ end
273
183
  end
274
184
 
275
185
  private def own_manual?(wme)
@@ -277,7 +187,7 @@ module Wongi::Engine
277
187
  end
278
188
 
279
189
  private def own_generated?(wme)
280
- wme_generators.key?(wme) && wme_generators[wme].any?
190
+ generator_tracker.for_wme(wme).any?
281
191
  end
282
192
 
283
193
  private def find_wme(wme)
@@ -285,7 +195,11 @@ module Wongi::Engine
285
195
  end
286
196
 
287
197
  private def find_own_wme(wme)
288
- wmes.include?(wme) ? wme : nil
198
+ has_own_wme?(wme) ? wme : nil
199
+ end
200
+
201
+ private def has_own_wme?(wme)
202
+ wmes.include?(wme)
289
203
  end
290
204
 
291
205
  private def find_parents_wme(wme)
@@ -302,28 +216,29 @@ module Wongi::Engine
302
216
  end
303
217
  end
304
218
 
305
- private def select_by_template(template)
306
- select_parents_template(template) + select_own_template(template)
219
+ def each_by_template(template)
220
+ Enumerator.new do |y|
221
+ each_own_wme_by_template(template, y)
222
+ each_parent_wme_by_template(template, y)
223
+ end
307
224
  end
308
225
 
309
- private def select_own_template(template)
226
+ private def each_own_wme_by_template(template, y)
310
227
  if template.concrete?
311
228
  wme = find_own_wme(WME.from_concrete_template(template))
312
- wme ? [wme] : []
229
+ y << wme if wme
313
230
  elsif template.root?
314
- wmes
231
+ wmes.each { y << _1 }
315
232
  else
316
233
  indexes.map { |index|
317
234
  index.collections_for_template(template)
318
- }.compact.first
235
+ }.compact.first.each { y << _1 }
319
236
  end
320
237
  end
321
238
 
322
- private def select_parents_template(template)
239
+ private def each_parent_wme_by_template(template, y)
323
240
  if parent
324
- parent.select(template).reject { hidden_wme?(_1) }.to_set
325
- else
326
- Set.new
241
+ parent.each_by_template(template).reject { hidden_wme?(_1) }.each { y << _1 }
327
242
  end
328
243
  end
329
244
 
@@ -332,32 +247,17 @@ module Wongi::Engine
332
247
 
333
248
  # if we previously hid this locally, unhide it
334
249
  hidden_parent_wmes.delete(wme)
335
- if generator
336
- hidden_parent_wme_generators.delete(generator)
337
- else
338
- hidden_parent_wme_manual.delete(wme)
339
- end
340
250
 
341
- if find_own_wme(wme)
342
- if generator
343
- wme_generators[wme] << generator unless own_generated_by?(wme, generator)
344
- else
345
- wme_manual[wme] = true
346
- end
347
- elsif find_parents_wme(wme)
348
- if generator
349
- wme_generators[wme] << generator unless generated_by?(wme, generator)
350
- else
351
- wme_manual[wme] = true unless manual?(wme)
352
- end
353
- else
251
+ unless has_own_wme?(wme)
354
252
  wmes.add(wme)
355
253
  indexes.each { _1.add(wme) }
356
- if generator
357
- wme_generators[wme] << generator
358
- else
359
- wme_manual[wme] = true
360
- end
254
+ end
255
+
256
+ if generator
257
+ generator_tracker.add(wme, generator)
258
+ else
259
+ hidden_parent_wme_manual.delete(wme)
260
+ wme_manual[wme] = true
361
261
  end
362
262
  end
363
263
 
@@ -365,15 +265,9 @@ module Wongi::Engine
365
265
  # p remove_wme: { wme:, generator: !!generator }
366
266
 
367
267
  if find_own_wme(wme)
368
- if generator
369
- if own_generated_by?(wme, generator)
370
- wme_generators[wme].delete(generator)
371
- wme_generators.delete(wme) if wme_generators[wme].empty?
372
- end
373
- elsif own_manual?(wme)
374
- wme_manual.delete(wme)
375
- end
268
+ wme_manual.delete(wme) if generator.nil?
376
269
 
270
+ # no remaining reasons to keep this WME around
377
271
  if !own_generated?(wme) && !own_manual?(wme)
378
272
  wmes.delete(wme)
379
273
  indexes.each { _1.remove(wme) }
@@ -388,23 +282,10 @@ module Wongi::Engine
388
282
 
389
283
  # must be parents' then
390
284
 
391
- if generator
392
- # first, delete local
393
- if own_generated_by?(wme, generator)
394
- wme_generators[wme].delete(generator)
395
- wme_generators.delete(wme) if wme_generators[wme].empty?
396
- end
397
- # if we're still generated, hide parents'
398
- if generated_by?(wme, generator)
399
- hidden_parent_wme_generators[generator] = true
400
- end
401
- else
402
- if own_manual?(wme)
403
- wme_manual.delete(wme)
404
- end
405
- if manual?(wme)
406
- hidden_parent_wme_manual[wme] = true
407
- end
285
+ if generator.nil?
286
+ wme_manual.delete(wme)
287
+ # if still manual, it must be from the parent
288
+ hidden_parent_wme_manual[wme] = true if manual?(wme)
408
289
  end
409
290
 
410
291
  if !manual?(wme) && !generated?(wme)
@@ -416,7 +297,8 @@ module Wongi::Engine
416
297
  # p add_token: {token:}
417
298
  # TODO: is this really likely to happen? we don't normally restore deleted tokens but rather create new ones in the activation
418
299
  if hidden_token?(token)
419
- hidden_parent_tokens.delete(token.object_id)
300
+ puts "odd case"
301
+ unhide_token(token)
420
302
  return
421
303
  end
422
304
 
@@ -425,9 +307,13 @@ module Wongi::Engine
425
307
 
426
308
  def remove_token(token)
427
309
  # p remove_token: {token:}
310
+
311
+ # capture the entire enumerated state
312
+ wmes = generated_wmes(token).to_a
313
+
428
314
  if own_node_tokens(token.node).find { _1.equal?(token) }.nil?
429
315
  if parents_node_tokens(token.node).find { _1.equal?(token) }
430
- hidden_parent_tokens[token.object_id] = true
316
+ hide_token(token)
431
317
 
432
318
  # do not hide JRs from the WME side: it will be done in the alpha deactivation and the JRs have to stay visible until then
433
319
  parent_neg_join_results_for(token: token).each { neg_join_results.hide(_1) }
@@ -437,10 +323,12 @@ module Wongi::Engine
437
323
  hidden_ncc_tokens[token][ncc] = true
438
324
  end
439
325
  end
440
- return
326
+ else
327
+ remove_own_token(token)
441
328
  end
442
329
 
443
- remove_own_token(token)
330
+ wmes.each { retract(_1, generator: token) }
331
+
444
332
  end
445
333
 
446
334
  def remove_own_token(token)
@@ -448,6 +336,7 @@ module Wongi::Engine
448
336
  tokens[token.node.object_id].delete(token)
449
337
  neg_join_results.remove_token(token)
450
338
  opt_join_results.remove_token(token)
339
+ generator_tracker.remove_token(token)
451
340
 
452
341
  # if this is an NCC partner token
453
342
  if (owner = ncc_tokens_owner[token])
@@ -465,9 +354,6 @@ module Wongi::Engine
465
354
  end
466
355
  ncc_tokens.delete(token)
467
356
  hidden_ncc_tokens.delete(token)
468
-
469
- # we know we are the owner, and nobody wants it anymore, so this is the safe place to do it
470
- token.dispose!
471
357
  end
472
358
 
473
359
  def node_tokens(beta)
@@ -482,7 +368,7 @@ module Wongi::Engine
482
368
 
483
369
  private def parents_node_tokens(beta)
484
370
  if parent
485
- parent.node_tokens(beta).reject { hidden_parent_tokens.key?(_1.object_id) }
371
+ parent.node_tokens(beta).reject { hidden_token?(_1) }
486
372
  else
487
373
  []
488
374
  end
@@ -581,7 +467,15 @@ module Wongi::Engine
581
467
  end
582
468
 
583
469
  private def hidden_token?(token)
584
- hidden_parent_tokens.key?(token.object_id)
470
+ hidden_parent_tokens.include?(token.object_id)
471
+ end
472
+
473
+ private def hide_token(token)
474
+ hidden_parent_tokens.add(token.object_id)
475
+ end
476
+
477
+ private def unhide_token(token)
478
+ hidden_parent_tokens.delete(token.object_id)
585
479
  end
586
480
  end
587
481
  end
@@ -2,16 +2,13 @@ require 'set'
2
2
 
3
3
  module Wongi::Engine
4
4
  class Token
5
- attr_reader :wme, :node, :generated_wmes, :parents
5
+ attr_reader :wme, :node, :parents
6
6
 
7
7
  def initialize(node, parents, wme, assignments = {})
8
8
  @node = node
9
9
  @parents = Set.new(Array(parents))
10
10
  @wme = wme
11
11
  @assignments = assignments
12
- @deleted = false
13
- @ncc_results = []
14
- @generated_wmes = []
15
12
  end
16
13
 
17
14
  def ancestors
@@ -30,12 +27,18 @@ module Wongi::Engine
30
27
  @assignments[variable] = value
31
28
  end
32
29
 
30
+ def own_assignments
31
+ @assignments
32
+ end
33
+
33
34
  def assignments
34
- all_assignments
35
+ parents.each_with_object({}) do |parent, acc|
36
+ acc.merge!(parent.assignments)
37
+ end.merge(own_assignments)
35
38
  end
36
39
 
37
40
  def [](var)
38
- a = assignments[var]
41
+ a = assignment(var)
39
42
  a.respond_to?(:call) ? a.call(self) : a
40
43
  end
41
44
 
@@ -43,8 +46,23 @@ module Wongi::Engine
43
46
  vars.map { self[_1] }
44
47
  end
45
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
+
46
60
  def has_var?(x)
47
- 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)
48
66
  end
49
67
 
50
68
  # TODO: ignore assignments?
@@ -52,12 +70,12 @@ module Wongi::Engine
52
70
  instance_of?(other.class) &&
53
71
  parents == other.parents &&
54
72
  wme == other.wme &&
55
- assignments == other.assignments
73
+ own_assignments == other.own_assignments
56
74
  end
57
75
 
58
76
  def to_s
59
77
  str = "TOKEN [ #{object_id} ancestors=#{ancestors.map(&:object_id).map(&:to_s).join('.')} "
60
- 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} " }
61
79
  str << "]"
62
80
  str
63
81
  end
@@ -65,43 +83,5 @@ module Wongi::Engine
65
83
  def inspect
66
84
  to_s
67
85
  end
68
-
69
- # def destroy
70
- # deleted!
71
- # end
72
-
73
- def dispose!
74
- # parent.children.delete(self) if parent
75
- # @parent = nil
76
- @wme = nil
77
- end
78
-
79
- # for neg feedback loop protection
80
- # def generated?(wme)
81
- # return true if generated_wmes.any? { |w| w == wme }
82
- #
83
- # children.any? { |t| t.generated? wme }
84
- # end
85
-
86
- protected
87
-
88
- def all_assignments
89
- parents.each_with_object({}) do |parent, acc|
90
- acc.merge!(parent.assignments)
91
- end.merge(@assignments)
92
- end
93
- end
94
-
95
- class FakeToken < Token
96
- def initialize(token, wme, assignments) # rubocop:disable Lint/MissingSuper
97
- @parent = token
98
- @wme = wme
99
- @assignments = assignments
100
- # @children = []
101
- @neg_join_results = []
102
- @opt_join_results = []
103
- @ncc_results = []
104
- @generated_wmes = []
105
- end
106
86
  end
107
87
  end
@@ -1,5 +1,5 @@
1
1
  module Wongi
2
2
  module Engine
3
- VERSION = "0.4.0-alpha9".freeze
3
+ VERSION = "0.4.0-alpha11".freeze
4
4
  end
5
5
  end
data/lib/wongi-engine.rb CHANGED
@@ -28,6 +28,8 @@ require 'wongi-engine/beta'
28
28
  require 'wongi-engine/dsl'
29
29
  require 'wongi-engine/ruleset'
30
30
  require 'wongi-engine/compiler'
31
+ require 'wongi-engine/join_results'
32
+ require 'wongi-engine/generator_tracker'
31
33
  require 'wongi-engine/overlay'
32
34
  require 'wongi-engine/enumerators'
33
35
  require 'wongi-engine/network'
@@ -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
@@ -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
@@ -136,11 +136,6 @@ describe Wongi::Engine::Overlay do
136
136
 
137
137
  overlay.retract(wme)
138
138
  expect(overlay.find(wme)).to be_nil
139
- expect(child1.find(wme)).to be_nil
140
- expect(child2.find(wme)).to be_nil
141
-
142
- child1.assert(wme)
143
- expect(overlay.find(wme)).to be_nil
144
139
  expect(child1.find(wme)).to eq(wme)
145
140
  expect(child2.find(wme)).to eq(wme)
146
141
  end
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.alpha9
4
+ version: 0.4.0.pre.alpha11
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-03 00:00:00.000000000 Z
11
+ date: 2022-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -139,7 +139,9 @@ files:
139
139
  - lib/wongi-engine/filter/inequality_test.rb
140
140
  - lib/wongi-engine/filter/less_than_or_equal_test.rb
141
141
  - lib/wongi-engine/filter/less_than_test.rb
142
+ - lib/wongi-engine/generator_tracker.rb
142
143
  - lib/wongi-engine/graph.rb
144
+ - lib/wongi-engine/join_results.rb
143
145
  - lib/wongi-engine/network.rb
144
146
  - lib/wongi-engine/network/collectable.rb
145
147
  - lib/wongi-engine/network/debug.rb