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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6618cdaae22d90fec75bb11bbfeb27477d9aca0661d0de91ab04ce3b434ce6e
4
- data.tar.gz: c9973d3a202faa0882653e99a3db546af9b02f6d1e09af075e4749681903743b
3
+ metadata.gz: 18bc1bfbc38b0ae08b505d3209fb6f0776c9abfa532d8c90b4ef8c6d26461c44
4
+ data.tar.gz: b10cc7b4fae950742ae4471d7385d745f23bb875d6436a80139c355e35c9370f
5
5
  SHA512:
6
- metadata.gz: 2ec734eba8278f9ed3b8571b67a5e7449c4d172143673953d568bc4299383dc60579c295457010a3e9160de5698ecd529713dad80940751fce6c8b599d05dc91
7
- data.tar.gz: ead1a3405786c7be13882c24ce8457ff31efa003bd9a84722073ff543ddff028b201c5d769756a2fadadfa84bbf0d5289db810f4e06d574c6b5960cb3a55302e
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
@@ -59,7 +59,7 @@ module Wongi::Engine
59
59
 
60
60
  private def select_wmes(template)
61
61
  # capture the enumerator
62
- rete.current_overlay.select(template).to_a
62
+ rete.current_overlay.each(template).to_a
63
63
  end
64
64
 
65
65
  private def specialize(template, tests, token)
@@ -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
@@ -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
- current_overlay.select(:_, :_, :_)
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.select(:_, :_, :_).to_a.each do |wme|
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
- template = case args.length
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(s, p, o, &block)
258
- current_overlay.select(s, p, o, &block)
249
+ def select(*args, &block)
250
+ each(*args, &block)
259
251
  end
260
252
 
261
- def find(s, p, o)
262
- select(s, p, o).first
253
+ def find(*args)
254
+ each(*args).first
263
255
  end
264
256
 
265
257
  protected
@@ -22,12 +22,14 @@ module Wongi::Engine
22
22
 
23
23
  @wmes = Set.new
24
24
  @indexes = [
25
- AlphaIndex.new(%i[subject]),
26
- AlphaIndex.new(%i[predicate]),
25
+ nil,
27
26
  AlphaIndex.new(%i[object]),
28
- AlphaIndex.new(%i[subject predicate]),
29
- AlphaIndex.new(%i[subject object]),
27
+ AlphaIndex.new(%i[predicate]),
30
28
  AlphaIndex.new(%i[predicate object]),
29
+ AlphaIndex.new(%i[subject]),
30
+ AlphaIndex.new(%i[subject object]),
31
+ AlphaIndex.new(%i[subject predicate]),
32
+ nil,
31
33
  ]
32
34
  @hidden_parent_wmes = {}
33
35
 
@@ -69,6 +71,8 @@ module Wongi::Engine
69
71
  else
70
72
  raise Error, "overlays can only accept data"
71
73
  end
74
+
75
+ self
72
76
  end
73
77
 
74
78
  def assert(wme, generator: nil)
@@ -76,6 +80,8 @@ module Wongi::Engine
76
80
  queue.push(operation)
77
81
 
78
82
  run_queue if queue.length == 1
83
+
84
+ self
79
85
  end
80
86
 
81
87
  def retract(wme, options = {})
@@ -87,9 +93,11 @@ module Wongi::Engine
87
93
  queue.push(operation)
88
94
 
89
95
  run_queue if queue.length == 1
96
+
97
+ self
90
98
  end
91
99
 
92
- def run_queue
100
+ private def run_queue
93
101
  until queue.empty?
94
102
  operation, wme, options = queue.shift
95
103
 
@@ -117,19 +125,6 @@ module Wongi::Engine
117
125
  self == rete.default_overlay
118
126
  end
119
127
 
120
- # TODO: this is inconsistent.
121
- # A WME retracted in-flight will be visible in active enumerators
122
- # but a token will not.
123
- # But this is how it works.
124
-
125
- # def wmes(template)
126
- # DuplicatingEnumerator.new(index(template))
127
- # end
128
-
129
- # def tokens(beta)
130
- # DeleteSafeEnumerator.new(raw_tokens(beta))
131
- # end
132
-
133
128
  def find(wme)
134
129
  if wme.is_a?(Array)
135
130
  wme = WME.new(*wme)
@@ -137,20 +132,35 @@ module Wongi::Engine
137
132
  find_wme(wme)
138
133
  end
139
134
 
140
- def select(*args)
135
+ def each(*args, &block)
136
+ template = nil
141
137
  case args.length
138
+ when 0
139
+ template = Template.new(:_, :_, :_)
142
140
  when 1
143
- case args.first
141
+ arg = args.first
142
+ case arg
143
+ when Array
144
+ template = Template.new(*arg)
144
145
  when Template
145
- each_by_template(args.first)
146
+ template = arg
147
+ when WME
148
+ template = Template.new(arg.subject, arg.predicate, arg.object)
146
149
  else
147
150
  raise ArgumentError
148
151
  end
149
152
  when 3
150
- each_by_template(Template.new(*args))
153
+ template = Template.new(*args)
151
154
  else
152
155
  raise ArgumentError
153
156
  end
157
+
158
+ each_by_template(template, &block)
159
+ end
160
+
161
+ def entity(subject)
162
+ # 4 is the bitmap for <s _ _>
163
+ EntityIterator.new(subject, indexes[4].collection_for_wme(Template.new(subject, :_, :_)))
154
164
  end
155
165
 
156
166
  def manual?(wme)
@@ -230,9 +240,7 @@ module Wongi::Engine
230
240
  elsif template.root?
231
241
  wmes.each { y << _1 }
232
242
  else
233
- indexes.map { |index|
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)
@@ -1,5 +1,5 @@
1
1
  module Wongi
2
2
  module Engine
3
- VERSION = "0.4.0-alpha11".freeze
3
+ VERSION = "0.4.0-alpha12".freeze
4
4
  end
5
5
  end
data/lib/wongi-engine.rb CHANGED
@@ -31,6 +31,7 @@ require 'wongi-engine/compiler'
31
31
  require 'wongi-engine/join_results'
32
32
  require 'wongi-engine/generator_tracker'
33
33
  require 'wongi-engine/overlay'
34
+ require 'wongi-engine/entity_iterator'
34
35
  require 'wongi-engine/enumerators'
35
36
  require 'wongi-engine/network'
36
37
  require 'wongi-engine/graph'
@@ -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.select(1, :_, :_)).to have(5).items
56
- expect(overlay.select(2, :_, :_)).to have(4).items
57
- expect(overlay.select(3, :_, :_)).to have(3).items
58
- expect(overlay.select(1, 11, :_)).to have(3).items
59
- expect(overlay.select(:_, 11, :_)).to have(5).items
60
- expect(overlay.select(:_, :_, 113)).to have(2).items
61
- expect(overlay.select(:_, 22, :_)).to have(2).items
62
- expect(overlay.select(:_, 22, 222)).to have(1).items
63
- expect(overlay.select(:_, :_, 222)).to have(2).items
64
- expect(overlay.select(:_, :_, 223)).to have(1).items
65
-
66
- expect(overlay.select(:_, :_, :_)).to have(wmes.length).items
67
-
68
- expect(overlay.select(1, 11, 111)).to have(1).items
69
- expect(overlay.select(1, 11, 111).first).to eq(wmes.first)
55
+ expect(overlay.each(1, :_, :_)).to have(5).items
56
+ expect(overlay.each(2, :_, :_)).to have(4).items
57
+ expect(overlay.each(3, :_, :_)).to have(3).items
58
+ expect(overlay.each(1, 11, :_)).to have(3).items
59
+ expect(overlay.each(:_, 11, :_)).to have(5).items
60
+ expect(overlay.each(:_, :_, 113)).to have(2).items
61
+ expect(overlay.each(:_, 22, :_)).to have(2).items
62
+ expect(overlay.each(:_, 22, 222)).to have(1).items
63
+ expect(overlay.each(:_, :_, 222)).to have(2).items
64
+ expect(overlay.each(:_, :_, 223)).to have(1).items
65
+
66
+ expect(overlay.each(:_, :_, :_)).to have(wmes.length).items
67
+
68
+ expect(overlay.each(1, 11, 111)).to have(1).items
69
+ expect(overlay.each(1, 11, 111).first).to eq(wmes.first)
70
70
  end
71
71
  end
72
72
 
@@ -85,10 +85,10 @@ describe Wongi::Engine::Overlay do
85
85
  wme = Wongi::Engine::WME.new(1, 11, 111)
86
86
 
87
87
  overlay.assert(wme)
88
- expect(overlay.select(:_, :_, :_)).to have(1).items
88
+ expect(overlay.each(:_, :_, :_)).to have(1).items
89
89
 
90
90
  overlay.retract(wme)
91
- expect(overlay.select(:_, :_, :_)).to have(0).items
91
+ expect(overlay.each(:_, :_, :_)).to have(0).items
92
92
  end
93
93
  end
94
94
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wongi-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre.alpha11
4
+ version: 0.4.0.pre.alpha12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valeri Sokolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-05 00:00:00.000000000 Z
11
+ date: 2022-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -128,6 +128,7 @@ files:
128
128
  - lib/wongi-engine/dsl/ncc_subrule.rb
129
129
  - lib/wongi-engine/dsl/query.rb
130
130
  - lib/wongi-engine/dsl/rule.rb
131
+ - lib/wongi-engine/entity_iterator.rb
131
132
  - lib/wongi-engine/enumerators.rb
132
133
  - lib/wongi-engine/error.rb
133
134
  - lib/wongi-engine/filter.rb
@@ -163,6 +164,7 @@ files:
163
164
  - spec/beta_node_spec.rb
164
165
  - spec/bug_specs/issue_4_spec.rb
165
166
  - spec/dataset_spec.rb
167
+ - spec/entity_iterator_spec.rb
166
168
  - spec/generation_spec.rb
167
169
  - spec/greater_than_equality_test_spec.rb
168
170
  - spec/high_level_spec.rb