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