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 +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
|