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 +4 -4
- data/lib/wongi-engine/alpha_index.rb +0 -21
- data/lib/wongi-engine/beta/aggregate_node.rb +6 -5
- data/lib/wongi-engine/beta/beta_node.rb +2 -1
- data/lib/wongi-engine/dsl/action/statement_generator.rb +10 -2
- data/lib/wongi-engine/entity_iterator.rb +60 -0
- data/lib/wongi-engine/network.rb +16 -27
- data/lib/wongi-engine/overlay.rb +58 -50
- data/lib/wongi-engine/template.rb +4 -0
- data/lib/wongi-engine/token.rb +26 -13
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine.rb +1 -0
- data/spec/bug_specs/issue_4_spec.rb +12 -12
- data/spec/entity_iterator_spec.rb +88 -0
- data/spec/high_level_spec.rb +2 -2
- data/spec/overlay_spec.rb +17 -17
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18bc1bfbc38b0ae08b505d3209fb6f0776c9abfa532d8c90b4ef8c6d26461c44
|
4
|
+
data.tar.gz: b10cc7b4fae950742ae4471d7385d745f23bb875d6436a80139c355e35c9370f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
@@ -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
|
-
|
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
|
-
|
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
|
data/lib/wongi-engine/network.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
-
|
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(
|
256
|
-
|
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(
|
265
|
-
|
253
|
+
def find(*args)
|
254
|
+
each(*args).first
|
266
255
|
end
|
267
256
|
|
268
257
|
protected
|
data/lib/wongi-engine/overlay.rb
CHANGED
@@ -22,12 +22,14 @@ module Wongi::Engine
|
|
22
22
|
|
23
23
|
@wmes = Set.new
|
24
24
|
@indexes = [
|
25
|
-
|
26
|
-
AlphaIndex.new(%i[predicate]),
|
25
|
+
nil,
|
27
26
|
AlphaIndex.new(%i[object]),
|
28
|
-
AlphaIndex.new(%i[
|
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
|
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
|
-
|
141
|
+
arg = args.first
|
142
|
+
case arg
|
143
|
+
when Array
|
144
|
+
template = Template.new(*arg)
|
144
145
|
when Template
|
145
|
-
|
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
|
-
|
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
|
-
|
169
|
-
|
178
|
+
Enumerator.new do |y|
|
179
|
+
generator_tracker.for_wme(wme).each { y << _1 }
|
170
180
|
if parent
|
171
|
-
parent.generators(wme).reject {
|
172
|
-
else
|
173
|
-
Set.new
|
181
|
+
parent.generators(wme).reject { hidden_token?(_1) }.each { y << _1 }
|
174
182
|
end
|
175
|
-
|
183
|
+
end
|
176
184
|
end
|
177
185
|
|
178
186
|
def generated_wmes(token)
|
179
|
-
|
180
|
-
|
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) }.
|
183
|
-
else
|
184
|
-
Set.new
|
190
|
+
parent.generated_wmes(token).reject { hidden_wme?(_1) }.each { y << _1 }
|
185
191
|
end
|
186
|
-
|
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)
|
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
|
-
|
222
|
-
|
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
|
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
|
-
|
239
|
+
y << wme if wme
|
229
240
|
elsif template.root?
|
230
|
-
wmes
|
241
|
+
wmes.each { y << _1 }
|
231
242
|
else
|
232
|
-
indexes.
|
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
|
247
|
+
private def each_parent_wme_by_template(template, y)
|
239
248
|
if parent
|
240
|
-
parent.
|
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
|
-
|
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)
|
data/lib/wongi-engine/token.rb
CHANGED
@@ -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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/wongi-engine/version.rb
CHANGED
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 "
|
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.
|
26
|
-
expect(evens.
|
25
|
+
expect(numbers.count).to eq(0)
|
26
|
+
expect(evens.count).to eq(10)
|
27
27
|
end
|
28
28
|
|
29
|
-
it "
|
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.
|
51
|
-
expect(evens.
|
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.
|
84
|
-
expect(evens.
|
85
|
-
expect(odds.
|
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.
|
130
|
-
expect(evens.
|
131
|
-
expect(odds.
|
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
|
data/spec/high_level_spec.rb
CHANGED
@@ -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.
|
118
|
+
expect(items.count).to eq(1)
|
119
119
|
|
120
120
|
items = engine.select "Bob", :older, "Alice"
|
121
|
-
expect(items.
|
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.
|
56
|
-
expect(overlay.
|
57
|
-
expect(overlay.
|
58
|
-
expect(overlay.
|
59
|
-
expect(overlay.
|
60
|
-
expect(overlay.
|
61
|
-
expect(overlay.
|
62
|
-
expect(overlay.
|
63
|
-
expect(overlay.
|
64
|
-
expect(overlay.
|
65
|
-
|
66
|
-
expect(overlay.
|
67
|
-
|
68
|
-
expect(overlay.
|
69
|
-
expect(overlay.
|
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.
|
88
|
+
expect(overlay.each(:_, :_, :_)).to have(1).items
|
89
89
|
|
90
90
|
overlay.retract(wme)
|
91
|
-
expect(overlay.
|
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.
|
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-
|
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
|