ruleby 0.8.b1 → 0.8.b2
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.
- data/lib/core/engine.rb +5 -0
- data/lib/core/nodes.rb +44 -17
- data/lib/dsl/ferrari.rb +27 -36
- data/lib/rulebook.rb +1 -1
- metadata +3 -3
data/lib/core/engine.rb
CHANGED
|
@@ -79,6 +79,11 @@ module Ruleby
|
|
|
79
79
|
def ==(a2)
|
|
80
80
|
return a2 != nil && @action == a2.action && @match == a2.match
|
|
81
81
|
end
|
|
82
|
+
|
|
83
|
+
def modify(match)
|
|
84
|
+
@match = match
|
|
85
|
+
# should we update recency, too?
|
|
86
|
+
end
|
|
82
87
|
|
|
83
88
|
def to_s
|
|
84
89
|
return "[#{@action.name}-#{object_id}|#{@counter}|#{@action.priority}|#{@match.recency.join(',')}|#{@match.to_s}] "
|
data/lib/core/nodes.rb
CHANGED
|
@@ -324,6 +324,16 @@ module Ruleby
|
|
|
324
324
|
out_node.assert(assertable)
|
|
325
325
|
end
|
|
326
326
|
end
|
|
327
|
+
|
|
328
|
+
def modify(assertable)
|
|
329
|
+
raise "Modify not supported by default - its only used for :collect. This must be a bug"
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def propagate_modify(assertable,out_nodes=@out_nodes)
|
|
333
|
+
out_nodes.each do |out_node|
|
|
334
|
+
out_node.modify(assertable)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
327
337
|
end
|
|
328
338
|
|
|
329
339
|
# This is a base class for all single input nodes that match facts based on
|
|
@@ -532,16 +542,6 @@ module Ruleby
|
|
|
532
542
|
end
|
|
533
543
|
end
|
|
534
544
|
|
|
535
|
-
def propagate_modify(context, out_nodes=@out_nodes)
|
|
536
|
-
out_nodes.each do |out_node|
|
|
537
|
-
if out_node.is_a?(TerminalNode)
|
|
538
|
-
out_node.modify(context)
|
|
539
|
-
else
|
|
540
|
-
raise "You can't join to :collect patterns yet!"
|
|
541
|
-
end
|
|
542
|
-
end
|
|
543
|
-
end
|
|
544
|
-
|
|
545
545
|
def propagate_assert(fact)
|
|
546
546
|
if block_given?
|
|
547
547
|
yield fact
|
|
@@ -597,6 +597,12 @@ module Ruleby
|
|
|
597
597
|
o.retract_resolve(match)
|
|
598
598
|
end
|
|
599
599
|
end
|
|
600
|
+
|
|
601
|
+
def modify(context)
|
|
602
|
+
@out_nodes.each do |out_node|
|
|
603
|
+
out_node.modify_left(context)
|
|
604
|
+
end
|
|
605
|
+
end
|
|
600
606
|
end
|
|
601
607
|
|
|
602
608
|
# This class is used to plug nodes into the right input of a two-input
|
|
@@ -619,6 +625,12 @@ module Ruleby
|
|
|
619
625
|
o.retract_resolve(match)
|
|
620
626
|
end
|
|
621
627
|
end
|
|
628
|
+
|
|
629
|
+
def modify(context)
|
|
630
|
+
@out_nodes.each do |out_node|
|
|
631
|
+
out_node.modify_right(context)
|
|
632
|
+
end
|
|
633
|
+
end
|
|
622
634
|
end
|
|
623
635
|
|
|
624
636
|
# This class is a two-input node that is used to create a cross-product of the
|
|
@@ -666,7 +678,23 @@ module Ruleby
|
|
|
666
678
|
propagate_assert(new_context)
|
|
667
679
|
end
|
|
668
680
|
end
|
|
669
|
-
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
def modify_left(context)
|
|
684
|
+
@left_memory[context.fact.id] = [context]
|
|
685
|
+
# you can't ref :collect patterns, so there should be anything to do on the right-memory
|
|
686
|
+
#propagate_modify(context)
|
|
687
|
+
|
|
688
|
+
# TODO something needs to happen here - but i'm not sure what!
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def modify_right(context)
|
|
692
|
+
@right_memory[context.fact.id] = context
|
|
693
|
+
# you can't ref :collect patterns, so there should be anything to do on the left-memory
|
|
694
|
+
#propagate_modify(context)
|
|
695
|
+
|
|
696
|
+
# TODO something needs to happen here - but i'm not sure what!
|
|
697
|
+
end
|
|
670
698
|
|
|
671
699
|
def to_s
|
|
672
700
|
return "#{self.class}:#{object_id} | #{@left_memory.values} | #{@right_memory}"
|
|
@@ -723,8 +751,7 @@ module Ruleby
|
|
|
723
751
|
|
|
724
752
|
# This node class is used when a rule is looking for a fact that does not
|
|
725
753
|
# exist. It is a two-input node, and thus has some of the properties of the
|
|
726
|
-
# JoinNode.
|
|
727
|
-
# declared as the first pattern in a rule.
|
|
754
|
+
# JoinNode.
|
|
728
755
|
class NotNode < JoinNode
|
|
729
756
|
def initialize
|
|
730
757
|
super
|
|
@@ -770,7 +797,7 @@ module Ruleby
|
|
|
770
797
|
end
|
|
771
798
|
end
|
|
772
799
|
|
|
773
|
-
def assert_right(context)
|
|
800
|
+
def assert_right(context)
|
|
774
801
|
@right_memory[context.fact.id] = context
|
|
775
802
|
if @ref_nodes.empty?
|
|
776
803
|
@left_memory.values.flatten.each do |left_context|
|
|
@@ -785,7 +812,7 @@ module Ruleby
|
|
|
785
812
|
end
|
|
786
813
|
end
|
|
787
814
|
end
|
|
788
|
-
|
|
815
|
+
|
|
789
816
|
# NOTE this returns a boolean, while the other classes return a MatchResult
|
|
790
817
|
def match_ref_nodes(left_context,right_context)
|
|
791
818
|
@ref_nodes.each do |ref_node|
|
|
@@ -827,11 +854,11 @@ module Ruleby
|
|
|
827
854
|
found = false
|
|
828
855
|
@activations.each do |id, v|
|
|
829
856
|
if context.match.fact_ids.sort == id.sort
|
|
830
|
-
v.
|
|
857
|
+
v.modify(context.match)
|
|
831
858
|
found = true
|
|
832
859
|
end
|
|
833
860
|
end
|
|
834
|
-
if !found
|
|
861
|
+
if !found and context.match.is_match
|
|
835
862
|
assert(context)
|
|
836
863
|
end
|
|
837
864
|
end
|
data/lib/dsl/ferrari.rb
CHANGED
|
@@ -324,31 +324,31 @@ module Ruleby
|
|
|
324
324
|
@tag = tag
|
|
325
325
|
@method = method
|
|
326
326
|
end
|
|
327
|
-
|
|
327
|
+
|
|
328
328
|
def +(arg)
|
|
329
329
|
raise 'Cannot use operators in short-hand mode!'
|
|
330
330
|
end
|
|
331
|
-
|
|
331
|
+
|
|
332
332
|
def -(arg)
|
|
333
333
|
raise 'Cannot use operators in short-hand mode!'
|
|
334
334
|
end
|
|
335
|
-
|
|
335
|
+
|
|
336
336
|
def /(arg)
|
|
337
337
|
raise 'Cannot use operators in short-hand mode!'
|
|
338
338
|
end
|
|
339
|
-
|
|
339
|
+
|
|
340
340
|
def *(arg)
|
|
341
341
|
raise 'Cannot use operators in short-hand mode!'
|
|
342
342
|
end
|
|
343
|
-
|
|
343
|
+
|
|
344
344
|
def to_s
|
|
345
345
|
"BindingBuilder @tag=#{@tag}, @method=#{@method}"
|
|
346
346
|
end
|
|
347
347
|
end
|
|
348
|
-
|
|
348
|
+
|
|
349
349
|
class AtomBuilder
|
|
350
350
|
attr_accessor :tag, :name, :bindings, :deftemplate, :block
|
|
351
|
-
|
|
351
|
+
|
|
352
352
|
def initialize(method_id)
|
|
353
353
|
@name = method_id
|
|
354
354
|
@deftemplate = nil
|
|
@@ -357,48 +357,39 @@ module Ruleby
|
|
|
357
357
|
@block = lambda {|x| true}
|
|
358
358
|
@child_atom_builders = []
|
|
359
359
|
end
|
|
360
|
-
|
|
360
|
+
|
|
361
361
|
def method_missing(method_id, *args, &block)
|
|
362
362
|
if method_id == :not
|
|
363
363
|
return NotOperatorBuilder.new(@name)
|
|
364
364
|
end
|
|
365
365
|
end
|
|
366
|
-
|
|
366
|
+
|
|
367
367
|
def ==(value)
|
|
368
368
|
@atom_type = :equals
|
|
369
369
|
@value = value
|
|
370
|
-
create_block value, lambda {|x,y|
|
|
370
|
+
create_block value, lambda {|x,y| x == y}, lambda {|x| x == value}; self
|
|
371
371
|
end
|
|
372
|
-
|
|
372
|
+
|
|
373
373
|
def >(value)
|
|
374
|
-
create_block value, lambda {|x,y| x
|
|
374
|
+
create_block value, lambda {|x,y| x > y}, lambda {|x| x > value}; self
|
|
375
375
|
end
|
|
376
|
-
|
|
376
|
+
|
|
377
377
|
def <(value)
|
|
378
|
-
create_block value, lambda {|x,y| x
|
|
378
|
+
create_block value, lambda {|x,y| x < y}, lambda {|x| x < value}; self
|
|
379
379
|
end
|
|
380
|
-
|
|
380
|
+
|
|
381
381
|
def =~(value)
|
|
382
|
-
create_block value, lambda {|x,y|
|
|
382
|
+
create_block value, lambda {|x,y| x =~ y}, lambda {|x| x =~ value}; self
|
|
383
383
|
end
|
|
384
|
-
|
|
384
|
+
|
|
385
385
|
def <=(value)
|
|
386
|
-
create_block value, lambda {|x,y| x
|
|
386
|
+
create_block value, lambda {|x,y| x <= y}, lambda {|x| x <= value}; self
|
|
387
387
|
end
|
|
388
|
-
|
|
388
|
+
|
|
389
389
|
def >=(value)
|
|
390
|
-
create_block value, lambda {|x,y| x
|
|
390
|
+
create_block value, lambda {|x,y| x >= y}, lambda {|x| x >= value}; self
|
|
391
391
|
end
|
|
392
|
-
|
|
393
|
-
def convert(x, value)
|
|
394
|
-
if x.nil?
|
|
395
|
-
return x
|
|
396
|
-
end
|
|
397
|
-
return x.to_f if value.kind_of? Float
|
|
398
|
-
return x.to_i if value.kind_of? Numeric
|
|
399
|
-
return x
|
|
400
|
-
end
|
|
401
|
-
|
|
392
|
+
|
|
402
393
|
def build_atoms(tags,methods,when_id)
|
|
403
394
|
atoms = @child_atom_builders.map { |atom_builder|
|
|
404
395
|
tags[atom_builder.tag] = when_id
|
|
@@ -413,7 +404,7 @@ module Ruleby
|
|
|
413
404
|
return atoms << Core::PropertyAtom.new(@tag, @name, @deftemplate, &@block)
|
|
414
405
|
end
|
|
415
406
|
end
|
|
416
|
-
|
|
407
|
+
|
|
417
408
|
if references_self?(tags,when_id)
|
|
418
409
|
bind_methods = @bindings.collect{ |bb| methods[bb.tag] }
|
|
419
410
|
atoms << Core::SelfReferenceAtom.new(@tag,@name,bind_methods,@deftemplate,&@block)
|
|
@@ -422,7 +413,7 @@ module Ruleby
|
|
|
422
413
|
atoms << Core::ReferenceAtom.new(@tag,@name,bind_tags,@deftemplate,&@block)
|
|
423
414
|
end
|
|
424
415
|
end
|
|
425
|
-
|
|
416
|
+
|
|
426
417
|
private
|
|
427
418
|
def references_self?(tags,when_id)
|
|
428
419
|
ref_self = 0
|
|
@@ -431,14 +422,14 @@ module Ruleby
|
|
|
431
422
|
ref_self += 1
|
|
432
423
|
end
|
|
433
424
|
end
|
|
434
|
-
|
|
425
|
+
|
|
435
426
|
if ref_self > 0 and ref_self != @bindings.size
|
|
436
427
|
raise 'Binding to self and another pattern in the same condition is not yet supported.'
|
|
437
428
|
end
|
|
438
|
-
|
|
429
|
+
|
|
439
430
|
return ref_self > 0
|
|
440
431
|
end
|
|
441
|
-
|
|
432
|
+
|
|
442
433
|
def create_block(value, ref_block, basic_block)
|
|
443
434
|
if value && value.kind_of?(BindingBuilder)
|
|
444
435
|
@bindings = [value]
|
|
@@ -452,7 +443,7 @@ module Ruleby
|
|
|
452
443
|
end
|
|
453
444
|
end
|
|
454
445
|
end
|
|
455
|
-
|
|
446
|
+
|
|
456
447
|
class NotOperatorBuilder < AtomBuilder
|
|
457
448
|
def ==(value)
|
|
458
449
|
create_block value, lambda {|x,y| x != y}, lambda {|x| x != value}; self
|
data/lib/rulebook.rb
CHANGED
|
@@ -67,7 +67,7 @@ module Ruleby
|
|
|
67
67
|
# string that is unique for each instance of this class.
|
|
68
68
|
@@tag_counter = 0
|
|
69
69
|
|
|
70
|
-
# every generated tag will be prefixed with this string
|
|
70
|
+
# every generated tag will be prefixed with this string. This isn't full-proof.
|
|
71
71
|
@@unique_seed = 'unique_seed'
|
|
72
72
|
|
|
73
73
|
def initialize()
|
metadata
CHANGED
|
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
7
|
- 8
|
|
8
|
-
-
|
|
9
|
-
version: 0.8.
|
|
8
|
+
- b2
|
|
9
|
+
version: 0.8.b2
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Joe Kutner
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2011-
|
|
18
|
+
date: 2011-04-07 00:00:00 -05:00
|
|
19
19
|
default_executable:
|
|
20
20
|
dependencies: []
|
|
21
21
|
|