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

Sign up to get free protection for your applications and to get access to all the features.
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