wongi-engine 0.3.5 → 0.3.7

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +80 -0
  4. data/.travis.yml +8 -15
  5. data/Gemfile +4 -0
  6. data/README.md +3 -3
  7. data/Rakefile +1 -2
  8. data/examples/ex01.rb +1 -1
  9. data/examples/ex02.rb +3 -7
  10. data/examples/graphviz.rb +1 -1
  11. data/examples/rdf.rb +1 -1
  12. data/examples/timeline.rb +6 -6
  13. data/lib/wongi-engine/alpha_memory.rb +5 -9
  14. data/lib/wongi-engine/beta/aggregate_node.rb +93 -0
  15. data/lib/wongi-engine/beta/assignment_node.rb +10 -18
  16. data/lib/wongi-engine/beta/beta_memory.rb +20 -9
  17. data/lib/wongi-engine/beta/beta_node.rb +14 -22
  18. data/lib/wongi-engine/beta/filter_node.rb +12 -15
  19. data/lib/wongi-engine/beta/join_node.rb +47 -61
  20. data/lib/wongi-engine/beta/ncc_node.rb +17 -20
  21. data/lib/wongi-engine/beta/ncc_partner.rb +17 -17
  22. data/lib/wongi-engine/beta/neg_node.rb +37 -37
  23. data/lib/wongi-engine/beta/optional_node.rb +53 -60
  24. data/lib/wongi-engine/beta/or_node.rb +6 -9
  25. data/lib/wongi-engine/beta/production_node.rb +6 -9
  26. data/lib/wongi-engine/beta.rb +1 -0
  27. data/lib/wongi-engine/compiler.rb +38 -22
  28. data/lib/wongi-engine/core_ext.rb +11 -20
  29. data/lib/wongi-engine/data_overlay.rb +23 -26
  30. data/lib/wongi-engine/dsl/action/assign_action.rb +1 -1
  31. data/lib/wongi-engine/dsl/action/base.rb +1 -4
  32. data/lib/wongi-engine/dsl/action/error_generator.rb +9 -9
  33. data/lib/wongi-engine/dsl/action/simple_action.rb +14 -10
  34. data/lib/wongi-engine/dsl/action/simple_collector.rb +10 -25
  35. data/lib/wongi-engine/dsl/action/statement_generator.rb +15 -14
  36. data/lib/wongi-engine/dsl/action/trace_action.rb +9 -9
  37. data/lib/wongi-engine/dsl/any_rule.rb +16 -20
  38. data/lib/wongi-engine/dsl/assuming.rb +8 -15
  39. data/lib/wongi-engine/dsl/builder.rb +13 -12
  40. data/lib/wongi-engine/dsl/clause/aggregate.rb +21 -0
  41. data/lib/wongi-engine/dsl/clause/assign.rb +4 -4
  42. data/lib/wongi-engine/dsl/clause/fact.rb +10 -6
  43. data/lib/wongi-engine/dsl/clause/gen.rb +3 -5
  44. data/lib/wongi-engine/dsl/clause/generic.rb +7 -9
  45. data/lib/wongi-engine/dsl/generated.rb +6 -12
  46. data/lib/wongi-engine/dsl/ncc_subrule.rb +6 -9
  47. data/lib/wongi-engine/dsl/query.rb +12 -15
  48. data/lib/wongi-engine/dsl/rule.rb +45 -50
  49. data/lib/wongi-engine/dsl.rb +30 -16
  50. data/lib/wongi-engine/enumerators.rb +2 -1
  51. data/lib/wongi-engine/error.rb +6 -7
  52. data/lib/wongi-engine/filter/asserting_test.rb +4 -7
  53. data/lib/wongi-engine/filter/equality_test.rb +15 -18
  54. data/lib/wongi-engine/filter/filter_test.rb +3 -6
  55. data/lib/wongi-engine/filter/greater_than_or_equal_test.rb +5 -2
  56. data/lib/wongi-engine/filter/greater_than_test.rb +15 -18
  57. data/lib/wongi-engine/filter/inequality_test.rb +15 -18
  58. data/lib/wongi-engine/filter/less_than_or_equal_test.rb +5 -2
  59. data/lib/wongi-engine/filter/less_than_test.rb +15 -18
  60. data/lib/wongi-engine/filter.rb +1 -1
  61. data/lib/wongi-engine/graph.rb +13 -20
  62. data/lib/wongi-engine/network/collectable.rb +10 -14
  63. data/lib/wongi-engine/network/debug.rb +16 -24
  64. data/lib/wongi-engine/network.rb +110 -129
  65. data/lib/wongi-engine/ruleset.rb +18 -20
  66. data/lib/wongi-engine/template.rb +31 -30
  67. data/lib/wongi-engine/token.rb +33 -33
  68. data/lib/wongi-engine/version.rb +1 -1
  69. data/lib/wongi-engine/wme.rb +17 -23
  70. data/lib/wongi-engine/wme_match_data.rb +5 -9
  71. data/lib/wongi-engine.rb +0 -4
  72. data/spec/action_class_spec.rb +43 -49
  73. data/spec/beta_node_spec.rb +2 -8
  74. data/spec/bug_specs/issue_4_spec.rb +12 -20
  75. data/spec/dataset_spec.rb +3 -6
  76. data/spec/filter_specs/assert_test_spec.rb +12 -31
  77. data/spec/filter_specs/greater_than_equality_test_spec.rb +2 -5
  78. data/spec/filter_specs/less_test_spec.rb +7 -17
  79. data/spec/filter_specs/less_than_equality_test_spec.rb +3 -6
  80. data/spec/generation_spec.rb +45 -54
  81. data/spec/high_level_spec.rb +95 -141
  82. data/spec/network_spec.rb +77 -68
  83. data/spec/overlay_spec.rb +4 -5
  84. data/spec/rule_specs/aggregate_spec.rb +197 -0
  85. data/spec/rule_specs/any_rule_spec.rb +73 -19
  86. data/spec/rule_specs/assign_spec.rb +10 -16
  87. data/spec/rule_specs/assuming_spec.rb +10 -17
  88. data/spec/rule_specs/maybe_rule_spec.rb +4 -15
  89. data/spec/rule_specs/ncc_spec.rb +48 -65
  90. data/spec/rule_specs/negative_rule_spec.rb +13 -27
  91. data/spec/rule_specs/or_rule_spec.rb +3 -13
  92. data/spec/ruleset_spec.rb +11 -17
  93. data/spec/simple_action_spec.rb +4 -14
  94. data/spec/wme_spec.rb +14 -21
  95. data/wongi-engine.gemspec +22 -22
  96. metadata +19 -41
  97. data/.hgignore +0 -7
  98. data/spec/dsl_spec.rb +0 -9
@@ -3,18 +3,14 @@ require 'wongi-engine/network/debug'
3
3
 
4
4
  module Wongi::Engine
5
5
  class Network
6
-
7
- attr_reader :alpha_top, :beta_top
8
- attr_reader :queries, :results
9
- attr_reader :productions
10
- attr_reader :overlays
6
+ attr_reader :alpha_top, :beta_top, :queries, :results, :productions
11
7
 
12
8
  include NetworkParts::Collectable
13
9
 
14
10
  protected
11
+
15
12
  attr_accessor :alpha_hash
16
- attr_writer :alpha_top, :beta_top
17
- attr_writer :queries, :results
13
+ attr_writer :alpha_top, :beta_top, :queries, :results
18
14
 
19
15
  public
20
16
 
@@ -23,43 +19,43 @@ module Wongi::Engine
23
19
  end
24
20
 
25
21
  def rdf!
26
- if ! defined? Wongi::RDF::DocumentSupport
22
+ unless defined? Wongi::RDF::DocumentSupport
27
23
  begin
28
24
  require 'wongi-rdf'
29
- rescue LoadError => e
25
+ rescue LoadError
30
26
  raise "'wongi-rdf' is required for RDF support"
31
27
  end
32
28
  end
33
29
 
34
30
  extend Wongi::RDF::DocumentSupport
31
+
35
32
  class << self
36
33
  def statements
37
34
  alpha_top.wmes
38
35
  end
39
36
  end
40
37
 
41
- @namespaces = { }
38
+ @namespaces = {}
42
39
  @blank_counter = 1
43
40
  @ns_counter = 0
44
- @used_blanks = { }
41
+ @used_blanks = {}
45
42
  end
46
43
 
47
44
  def initialize
48
45
  @timeline = []
49
- self.alpha_top = AlphaMemory.new( Template.new( :_, :_, :_ ), self )
46
+ self.alpha_top = AlphaMemory.new(Template.new(:_, :_, :_), self)
50
47
  self.alpha_hash = { alpha_top.template.hash => alpha_top }
51
48
  self.beta_top = BetaMemory.new(nil)
52
- self.beta_top.rete = self
53
- self.beta_top.seed
49
+ beta_top.rete = self
50
+ beta_top.seed
54
51
  self.queries = {}
55
52
  self.results = {}
56
53
  @revns = {}
57
54
 
58
- @productions = { }
55
+ @productions = {}
59
56
 
60
57
  @collectors = {}
61
58
  @collectors[:error] = []
62
-
63
59
  end
64
60
 
65
61
  def dump
@@ -118,46 +114,42 @@ module Wongi::Engine
118
114
  end
119
115
 
120
116
  # @private
121
- def real_assert( wme )
122
- unless wme.rete == self
123
- wme = wme.import_into self
124
- end
117
+ def real_assert(wme)
118
+ wme = wme.import_into self unless wme.rete == self
125
119
 
126
- source = best_alpha(wme)
127
- if existing = find(wme.subject, wme.predicate, wme.object)
120
+ # source = best_alpha(wme)
121
+ if (existing = find(wme.subject, wme.predicate, wme.object))
128
122
  existing.manual! if wme.manual?
129
123
  return
130
124
  end
131
125
 
132
- alphas_for( wme ).each { |a| a.activate wme }
126
+ alphas_for(wme).each { |a| a.activate wme }
133
127
 
134
128
  wme
135
129
  end
136
130
 
137
131
  # @private
138
- def real_retract wme, options
132
+ def real_retract(wme, options)
139
133
  real = find(wme.subject, wme.predicate, wme.object)
140
134
  return if real.nil?
135
+
141
136
  if real.generated? # still some generator tokens left
142
- if real.manual?
143
- real.manual = false
144
- else
145
- raise Error, "cannot retract automatic facts"
146
- end
147
- else
148
- if options[:automatic] && real.manual? # auto-retracting a fact that has been added manually
149
- return
150
- end
137
+ raise Error, "cannot retract automatic facts" unless real.manual?
138
+
139
+ real.manual = false
140
+ elsif options[:automatic] && real.manual?
141
+ return
151
142
  end
152
143
 
153
- alphas_for( real ).each { |a| a.deactivate real }
144
+ alphas_for(real).each { |a| a.deactivate real }
154
145
  end
155
146
 
156
147
  def wmes
157
148
  alpha_top.wmes
158
149
  end
159
- alias_method :statements, :wmes
160
- alias_method :facts, :wmes
150
+
151
+ alias statements wmes
152
+ alias facts wmes
161
153
 
162
154
  def in_snapshot?
163
155
  @in_snapshot
@@ -166,128 +158,127 @@ module Wongi::Engine
166
158
  def snapshot!
167
159
  @timeline.each_with_index do |slice, index|
168
160
  source = if index == @timeline.size - 1
169
- alpha_hash
170
- else
171
- @timeline[index+1]
172
- end
161
+ alpha_hash
162
+ else
163
+ @timeline[index + 1]
164
+ end
173
165
  # puts "source = #{source}"
174
166
  wmes = {}
175
- slice.each { |key, alpha| wmes[key] = alpha.wmes }
176
167
  slice.each do |key, alpha|
168
+ wmes[key] = alpha.wmes
177
169
  in_snapshot {
178
- wmes[key].dup.each { |wme| wme.destroy }
170
+ wmes[key].dup.each(&:destroy)
179
171
  }
180
172
  alpha.snapshot! source[key]
181
173
  end
182
174
  end
183
175
  end
184
176
 
185
- def rule name = nil, &block
186
- r = DSL::Rule.new( name || generate_rule_name )
187
- r.instance_eval &block
177
+ def rule(name = nil, &block)
178
+ r = DSL::Rule.new(name || generate_rule_name)
179
+ r.instance_eval(&block)
188
180
  self << r
189
181
  end
190
182
 
191
- def query name, &block
183
+ def query(name, &block)
192
184
  q = DSL::Query.new name
193
- q.instance_eval &block
185
+ q.instance_eval(&block)
194
186
  self << q
195
187
  end
196
188
 
197
- def << something
198
- if something.respond_to?( :install )
199
- something.install( self )
189
+ def <<(something)
190
+ if something.respond_to?(:install)
191
+ something.install(self)
200
192
  else
201
193
  case something
202
194
  when Array
203
- assert WME.new( *something ).tap { |wme| wme.overlay = default_overlay }
195
+ assert(WME.new(*something).tap { |wme| wme.overlay = default_overlay })
204
196
  when WME
205
197
  assert something
206
- # when Wongi::RDF::Statement
207
- # assert WME.new( something.subject, something.predicate, something.object, self )
208
- #when Wongi::RDF::Document
198
+ # when Wongi::RDF::Statement
199
+ # assert WME.new( something.subject, something.predicate, something.object, self )
200
+ # when Wongi::RDF::Document
209
201
  # something.statements.each do |st|
210
202
  # assert WME.new( st.subject, st.predicate, st.object, self )
211
203
  # end
212
204
  when Network
213
- something.wmes.each { |wme| assert( wme ) }
205
+ something.wmes.each { |wme| assert(wme) }
214
206
  else
215
207
  raise Error, "I don't know how to accept a #{something.class}"
216
208
  end
217
209
  end
218
210
  end
219
211
 
220
- def install_rule( rule )
212
+ def install_rule(rule)
221
213
  derived = rule.import_into self
222
214
  production = build_production beta_top, derived.conditions, [], derived.actions, false
223
- if rule.name
224
- productions[ rule.name ] = production
225
- end
215
+ productions[rule.name] = production if rule.name
226
216
  production
227
217
  end
228
218
 
229
- def install_query( query )
219
+ def install_query(query)
230
220
  derived = query.import_into self
231
221
  prepare_query derived.name, derived.conditions, derived.parameters, derived.actions
232
222
  end
233
223
 
234
- def compile_alpha condition
224
+ def compile_alpha(condition)
235
225
  template = Template.new :_, :_, :_
236
226
  time = condition.time
237
227
 
238
- template.subject = condition.subject unless Template.variable?( condition.subject )
239
- template.predicate = condition.predicate unless Template.variable?( condition.predicate )
240
- template.object = condition.object unless Template.variable?( condition.object )
228
+ template.subject = condition.subject unless Template.variable?(condition.subject)
229
+ template.predicate = condition.predicate unless Template.variable?(condition.predicate)
230
+ template.object = condition.object unless Template.variable?(condition.object)
241
231
 
242
232
  hash = template.hash
243
233
  # puts "COMPILED CONDITION #{condition} WITH KEY #{key}"
244
- if time == 0
245
- return self.alpha_hash[ hash ] if self.alpha_hash.has_key?( hash )
246
- else
247
- return @timeline[time+1][ hash ] if @timeline[time+1] && @timeline[time+1].has_key?( hash )
234
+ if time.zero?
235
+ return alpha_hash[hash] if alpha_hash.key?(hash)
236
+ elsif @timeline[time + 1] && @timeline[time + 1].key?(hash)
237
+ return @timeline[time + 1][hash]
248
238
  end
249
239
 
250
- alpha = AlphaMemory.new( template, self )
240
+ alpha = AlphaMemory.new(template, self)
251
241
 
252
- if time == 0
253
- self.alpha_hash[ hash ] = alpha
242
+ if time.zero?
243
+ alpha_hash[hash] = alpha
254
244
  initial_fill alpha
255
245
  else
256
- if @timeline[time+1].nil?
246
+ if @timeline[time + 1].nil?
257
247
  # => ensure lineage from 0 to time
258
248
  compile_alpha condition.class.new(condition.subject, condition.predicate, condition.object, time: time + 1)
259
- @timeline.unshift Hash.new
249
+ @timeline.unshift({})
260
250
  end
261
- @timeline[time+1][ hash ] = alpha
251
+ @timeline[time + 1][hash] = alpha
262
252
  end
263
253
  alpha
264
254
  end
265
255
 
266
- def cache s, p, o
256
+ def cache(s, p, o)
267
257
  compile_alpha Template.new(s, p, o)
268
258
  end
269
259
 
270
260
  # TODO: pick an alpha with fewer candidates to go through
271
- def initial_fill alpha
261
+ def initial_fill(alpha)
272
262
  alpha_top.wmes.each do |wme|
273
263
  alpha.activate wme if wme =~ alpha.template
274
264
  end
275
265
  end
276
266
 
277
- def remove_production pnode
267
+ def remove_production(pnode)
278
268
  delete_node_with_ancestors pnode
279
269
  end
280
270
 
281
- def prepare_query name, conditions, parameters, actions = []
282
- query = self.queries[ name ] = BetaMemory.new( nil )
271
+ def prepare_query(name, conditions, parameters, actions = [])
272
+ query = queries[name] = BetaMemory.new(nil)
283
273
  query.rete = self
284
- query.seed(Hash[parameters.map{ |param| [param, nil]}])
285
- self.results[ name ] = build_production query, conditions, parameters, actions, true
274
+ query.seed(parameters.to_h { |param| [param, nil] })
275
+ results[name] = build_production query, conditions, parameters, actions, true
286
276
  end
287
277
 
288
- def execute name, valuations
289
- beta = self.queries[name]
278
+ def execute(name, valuations)
279
+ beta = queries[name]
290
280
  raise Error, "Undefined query #{name}; known queries are #{queries.keys}" unless beta
281
+
291
282
  beta.subst valuations
292
283
  end
293
284
 
@@ -295,19 +286,19 @@ module Wongi::Engine
295
286
  "<Rete>"
296
287
  end
297
288
 
298
- def exists? wme
289
+ def exists?(wme)
299
290
  find(wme.subject, wme.predicate, wme.object)
300
291
  end
301
292
 
302
- def each *args, &block
293
+ def each(*args, &block)
303
294
  template = case args.length
304
- when 0
305
- Template.new(:_, :_, :_)
306
- when 3
307
- Template.new(*args)
308
- else
309
- raise Error, "Network#each expect a template or nothing at all"
310
- end
295
+ when 0
296
+ Template.new(:_, :_, :_)
297
+ when 3
298
+ Template.new(*args)
299
+ else
300
+ raise Error, "Network#each expect a template or nothing at all"
301
+ end
311
302
  source = best_alpha(template)
312
303
  matching = current_overlay.wmes(source).select { |wme| wme =~ template }
313
304
  if block_given?
@@ -317,17 +308,15 @@ module Wongi::Engine
317
308
  end
318
309
  end
319
310
 
320
- def select s, p, o
311
+ def select(s, p, o)
321
312
  template = Template.new(s, p, o)
322
313
  source = best_alpha(template)
323
314
  matching = current_overlay.wmes(source).select { |wme| wme =~ template }
324
- if block_given?
325
- matching.each { |st| yield st.subject, st.predicate, st.object }
326
- end
315
+ matching.each { |st| yield st.subject, st.predicate, st.object } if block_given?
327
316
  matching
328
317
  end
329
318
 
330
- def find s, p, o
319
+ def find(s, p, o)
331
320
  template = Template.new(s, p, o)
332
321
  source = best_alpha(template)
333
322
  # puts "looking for #{template} among #{source.wmes.size} triples of #{source.template}"
@@ -336,7 +325,6 @@ module Wongi::Engine
336
325
 
337
326
  protected
338
327
 
339
-
340
328
  def in_snapshot
341
329
  @in_snapshot = true
342
330
  yield
@@ -348,31 +336,33 @@ module Wongi::Engine
348
336
  "rule_#{productions.length}"
349
337
  end
350
338
 
351
- def alphas_for wme
352
- s, p, o = wme.subject, wme.predicate, wme.object
339
+ def alphas_for(wme)
340
+ s = wme.subject
341
+ p = wme.predicate
342
+ o = wme.object
353
343
  [
354
- lookup( s, p, o),
355
- lookup( s, p, :_),
356
- lookup( s, :_, o),
357
- lookup(:_, p, o),
358
- lookup( s, :_, :_),
359
- lookup(:_, p, :_),
360
- lookup(:_, :_, o),
344
+ lookup(s, p, o),
345
+ lookup(s, p, :_),
346
+ lookup(s, :_, o),
347
+ lookup(:_, p, o),
348
+ lookup(s, :_, :_),
349
+ lookup(:_, p, :_),
350
+ lookup(:_, :_, o),
361
351
  lookup(:_, :_, :_),
362
352
  ].compact!.tap(&:uniq!)
363
353
  end
364
354
 
365
- def lookup s, p, o
355
+ def lookup(s, p, o)
366
356
  key = Template.hash_for(s, p, o)
367
357
  # puts "Lookup for #{key}"
368
- self.alpha_hash[ key ]
358
+ alpha_hash[key]
369
359
  end
370
360
 
371
- def alpha_activate alpha, wme
361
+ def alpha_activate(alpha, wme)
372
362
  alpha.activate(wme)
373
363
  end
374
364
 
375
- def best_alpha template
365
+ def best_alpha(template)
376
366
  alpha_hash.inject(nil) do |best, (_, alpha)|
377
367
  if template =~ alpha.template && (best.nil? || alpha.size < best.size)
378
368
  alpha
@@ -382,7 +372,7 @@ module Wongi::Engine
382
372
  end
383
373
  end
384
374
 
385
- def build_production root, conditions, parameters, actions, alpha_deaf
375
+ def build_production(root, conditions, parameters, actions, alpha_deaf)
386
376
  compiler = Compiler.new(self, root, conditions, parameters, alpha_deaf)
387
377
  ProductionNode.new(compiler.compile, actions).tap do |production|
388
378
  production.compilation_context = compiler
@@ -390,27 +380,18 @@ module Wongi::Engine
390
380
  end
391
381
  end
392
382
 
393
- def delete_node_with_ancestors node
383
+ def delete_node_with_ancestors(node)
384
+ delete_node_with_ancestors node.partner if node.is_a?(NccNode)
394
385
 
395
- if node.kind_of?( NccNode )
396
- delete_node_with_ancestors node.partner
397
- end
386
+ # the root node should not be deleted
387
+ return unless node.parent
398
388
 
399
- if [BetaMemory, NegNode, NccNode, NccPartner].any? { | klass| node.kind_of? klass }
400
- while node.tokens.first
401
- node.tokens.first.delete
402
- end
403
- end
404
-
405
- if node.parent
406
- node.parent.children.delete node
407
- if node.parent.children.empty?
408
- delete_node_with_ancestors(node.parent)
409
- end
389
+ if [BetaMemory, NegNode, NccNode, NccPartner].any? { |klass| node.is_a? klass }
390
+ node.tokens.first.destroy while node.tokens.first
410
391
  end
411
392
 
393
+ node.parent.children.delete node
394
+ delete_node_with_ancestors(node.parent) if node.parent.children.empty?
412
395
  end
413
-
414
396
  end
415
-
416
397
  end
@@ -1,17 +1,17 @@
1
1
  module Wongi
2
2
  module Engine
3
3
  class Ruleset
4
-
5
4
  class << self
5
+ def [](name)
6
+ raise Error, "undefined ruleset #{name}" unless rulesets.key?(name)
6
7
 
7
- def [] name
8
- raise Error, "undefined ruleset #{name}" unless rulesets.has_key?( name )
9
- rulesets[ name ]
8
+ rulesets[name]
10
9
  end
11
10
 
12
- def register name, ruleset
13
- raise Error, "ruleset #{name} already exists" if rulesets.has_key?( name )
14
- rulesets[ name ] = ruleset
11
+ def register(name, ruleset)
12
+ raise Error, "ruleset #{name} already exists" if rulesets.key?(name)
13
+
14
+ rulesets[name] = ruleset
15
15
  end
16
16
 
17
17
  def rulesets
@@ -19,31 +19,30 @@ module Wongi
19
19
  end
20
20
 
21
21
  def reset
22
- @rulesets = { }
22
+ @rulesets = {}
23
23
  end
24
-
25
24
  end
26
25
 
27
- def initialize name = nil
26
+ def initialize(name = nil)
28
27
  @rules = []
29
- self.name( name ) if name
28
+ self.name(name) if name
30
29
  end
31
30
 
32
31
  def inspect
33
32
  "<Ruleset #{name}>"
34
33
  end
35
34
 
36
- def install rete
35
+ def install(rete)
37
36
  # puts "Installing ruleset #{name}"
38
37
  @rules.each { |rule| rete << rule }
39
38
  rescue StandardError => e
40
- e1 = Error.new "error installing ruleset '#{name||'<unnamed>'}': #{e}"
39
+ e1 = Error.new "error installing ruleset '#{name || '<unnamed>'}': #{e}"
41
40
  e1.set_backtrace e.backtrace
42
41
  raise e1
43
42
  end
44
43
 
45
- def name name = nil
46
- if name && ! @name
44
+ def name(name = nil)
45
+ if name && !@name
47
46
  self.class.register name, self
48
47
  @name = name
49
48
  end
@@ -55,20 +54,19 @@ module Wongi
55
54
  # @uri
56
55
  # end
57
56
 
58
- def rule name, &definition
57
+ def rule(name, &definition)
59
58
  r = DSL::Rule.new name
60
- r.instance_eval &definition
59
+ r.instance_eval(&definition)
61
60
  @rules << r
62
61
  r
63
62
  end
64
63
 
65
- def query name, &definition
64
+ def query(name, &definition)
66
65
  r = DSL::Query.new name
67
- r.instance_eval &definition
66
+ r.instance_eval(&definition)
68
67
  @rules << r
69
68
  r
70
69
  end
71
-
72
70
  end
73
71
  end
74
72
  end
@@ -1,9 +1,8 @@
1
1
  module Wongi::Engine
2
-
3
- Template = Struct.new( :subject, :predicate, :object ) do
4
-
5
- def self.variable? thing
2
+ Template = Struct.new(:subject, :predicate, :object) do
3
+ def self.variable?(thing)
6
4
  return false unless thing.is_a?(Symbol)
5
+
7
6
  thing[0] >= 'A' && thing[0] <= 'Z'
8
7
  end
9
8
 
@@ -15,9 +14,9 @@ module Wongi::Engine
15
14
 
16
15
  def variables
17
16
  [].tap do |a|
18
- a << subject if Template.variable?( subject )
19
- a << predicate if Template.variable?( predicate )
20
- a << object if Template.variable?( object )
17
+ a << subject if Template.variable?(subject)
18
+ a << predicate if Template.variable?(predicate)
19
+ a << object if Template.variable?(object)
21
20
  end
22
21
  end
23
22
 
@@ -25,20 +24,20 @@ module Wongi::Engine
25
24
  @hash ||= [subject.hash, predicate.hash, object.hash].hash
26
25
  end
27
26
 
28
- def self.hash_for *args
29
- args.map( &:hash ).hash
27
+ def self.hash_for(*args)
28
+ args.map(&:hash).hash
30
29
  end
31
30
 
32
- def == other
31
+ def ==(other)
33
32
  other.is_a?(Template) && subject == other.subject && predicate == other.predicate && object == other.object
34
33
  end
35
34
 
36
- def =~ template
35
+ def =~(template)
37
36
  case template
38
37
  when Template
39
- ( template.subject == :_ || template.subject == subject ) &&
40
- ( template.predicate == :_ || template.predicate == predicate ) &&
41
- ( template.object == :_ || template.object == object )
38
+ (template.subject == :_ || template.subject == subject) &&
39
+ (template.predicate == :_ || template.predicate == predicate) &&
40
+ (template.object == :_ || template.object == object)
42
41
  else
43
42
  raise Error, "templates can only match other templates"
44
43
  end
@@ -54,25 +53,27 @@ module Wongi::Engine
54
53
 
55
54
  def resolve!(token)
56
55
  s = if Template.variable?(subject)
57
- raise DefinitionError, "unbound variable #{subject} in token #{token}" unless token.has_var?(subject)
58
- token[subject]
59
- else
60
- subject
61
- end
56
+ raise DefinitionError, "unbound variable #{subject} in token #{token}" unless token.has_var?(subject)
57
+
58
+ token[subject]
59
+ else
60
+ subject
61
+ end
62
62
  p = if Template.variable?(predicate)
63
- raise DefinitionError, "unbound variable #{predicate} in token #{token}" unless token.has_var?(predicate)
64
- token[predicate]
65
- else
66
- predicate
67
- end
63
+ raise DefinitionError, "unbound variable #{predicate} in token #{token}" unless token.has_var?(predicate)
64
+
65
+ token[predicate]
66
+ else
67
+ predicate
68
+ end
68
69
  o = if Template.variable?(object)
69
- raise DefinitionError, "unbound variable #{object} in token #{token}" unless token.has_var?(object)
70
- token[object]
71
- else
72
- object
73
- end
70
+ raise DefinitionError, "unbound variable #{object} in token #{token}" unless token.has_var?(object)
71
+
72
+ token[object]
73
+ else
74
+ object
75
+ end
74
76
  [s, p, o]
75
77
  end
76
-
77
78
  end
78
79
  end