wongi-engine 0.4.0.pre.alpha11 → 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/beta_node.rb +1 -1
- data/lib/wongi-engine/entity_iterator.rb +60 -0
- data/lib/wongi-engine/network.rb +13 -21
- data/lib/wongi-engine/overlay.rb +35 -27
- data/lib/wongi-engine/template.rb +4 -0
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine.rb +1 -0
- data/spec/entity_iterator_spec.rb +88 -0
- 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
|
@@ -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
@@ -109,6 +109,10 @@ module Wongi::Engine
|
|
109
109
|
overlays.last
|
110
110
|
end
|
111
111
|
|
112
|
+
def entity(subject)
|
113
|
+
current_overlay.entity(subject)
|
114
|
+
end
|
115
|
+
|
112
116
|
def assert(wme)
|
113
117
|
default_overlay.assert(wme)
|
114
118
|
end
|
@@ -130,7 +134,7 @@ module Wongi::Engine
|
|
130
134
|
end
|
131
135
|
|
132
136
|
def wmes
|
133
|
-
|
137
|
+
each.to_a
|
134
138
|
end
|
135
139
|
|
136
140
|
alias statements wmes
|
@@ -168,6 +172,7 @@ module Wongi::Engine
|
|
168
172
|
else
|
169
173
|
raise Error, "I don't know how to accept a #{something.class}"
|
170
174
|
end
|
175
|
+
self
|
171
176
|
end
|
172
177
|
end
|
173
178
|
|
@@ -206,7 +211,7 @@ module Wongi::Engine
|
|
206
211
|
end
|
207
212
|
|
208
213
|
def initial_fill(alpha)
|
209
|
-
default_overlay.
|
214
|
+
default_overlay.each(:_, :_, :_).to_a.each do |wme|
|
210
215
|
alpha.activate wme if wme =~ alpha.template
|
211
216
|
end
|
212
217
|
end
|
@@ -234,32 +239,19 @@ module Wongi::Engine
|
|
234
239
|
end
|
235
240
|
|
236
241
|
def exists?(wme)
|
237
|
-
find(wme.subject, wme.predicate, wme.object)
|
242
|
+
!find(wme.subject, wme.predicate, wme.object).nil?
|
238
243
|
end
|
239
244
|
|
240
245
|
def each(*args, &block)
|
241
|
-
|
242
|
-
when 0
|
243
|
-
Template.new(:_, :_, :_)
|
244
|
-
when 3
|
245
|
-
Template.new(*args)
|
246
|
-
else
|
247
|
-
raise Error, "Network#each expect a template or nothing at all"
|
248
|
-
end
|
249
|
-
matching = current_overlay.select(template)
|
250
|
-
if block_given?
|
251
|
-
matching.each(&block)
|
252
|
-
else
|
253
|
-
matching.each
|
254
|
-
end
|
246
|
+
current_overlay.each(*args, &block)
|
255
247
|
end
|
256
248
|
|
257
|
-
def select(
|
258
|
-
|
249
|
+
def select(*args, &block)
|
250
|
+
each(*args, &block)
|
259
251
|
end
|
260
252
|
|
261
|
-
def find(
|
262
|
-
|
253
|
+
def find(*args)
|
254
|
+
each(*args).first
|
263
255
|
end
|
264
256
|
|
265
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)
|
@@ -230,9 +240,7 @@ module Wongi::Engine
|
|
230
240
|
elsif template.root?
|
231
241
|
wmes.each { y << _1 }
|
232
242
|
else
|
233
|
-
indexes.
|
234
|
-
index.collections_for_template(template)
|
235
|
-
}.compact.first.each { y << _1 }
|
243
|
+
indexes[template.bitmap].collection_for_wme(template).each { y << _1 }
|
236
244
|
end
|
237
245
|
end
|
238
246
|
|
@@ -250,7 +258,7 @@ module Wongi::Engine
|
|
250
258
|
|
251
259
|
unless has_own_wme?(wme)
|
252
260
|
wmes.add(wme)
|
253
|
-
indexes.each { _1.add(wme) }
|
261
|
+
indexes[1..6].each { _1.add(wme) }
|
254
262
|
end
|
255
263
|
|
256
264
|
if generator
|
@@ -270,7 +278,7 @@ module Wongi::Engine
|
|
270
278
|
# no remaining reasons to keep this WME around
|
271
279
|
if !own_generated?(wme) && !own_manual?(wme)
|
272
280
|
wmes.delete(wme)
|
273
|
-
indexes.each { _1.remove(wme) }
|
281
|
+
indexes[1..6].each { _1.remove(wme) }
|
274
282
|
end
|
275
283
|
|
276
284
|
neg_join_results.remove_wme(wme)
|
@@ -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/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'
|
@@ -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/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
|