ruleby 0.9.b4 → 0.9.b7

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 (48) hide show
  1. data/.gitignore +5 -0
  2. data/GPL.txt +341 -0
  3. data/LICENSE.txt +52 -0
  4. data/README.markdown +22 -0
  5. data/benchmarks/basic_rules.rb +61 -0
  6. data/benchmarks/joined_rules.rb +66 -0
  7. data/benchmarks/miss_manners/data.rb +146 -0
  8. data/benchmarks/miss_manners/miss_manners.rb +33 -0
  9. data/benchmarks/miss_manners/model.rb +193 -0
  10. data/benchmarks/miss_manners/rules.rb +105 -0
  11. data/benchmarks/model.rb +36 -0
  12. data/examples/diagnosis.rb +129 -0
  13. data/examples/fibonacci_example1.rb +44 -0
  14. data/examples/fibonacci_example2.rb +40 -0
  15. data/examples/fibonacci_example3.rb +78 -0
  16. data/examples/fibonacci_rulebook.rb +84 -0
  17. data/examples/hello.rb +45 -0
  18. data/examples/ticket.rb +113 -0
  19. data/examples/wordgame.rb +107 -0
  20. data/lib/core/engine.rb +26 -24
  21. data/lib/core/nodes.rb +77 -35
  22. data/lib/ruleby.rb +0 -37
  23. data/ruleby.gemspec +17 -0
  24. data/spec/and_or_spec.rb +252 -0
  25. data/spec/coercion_spec.rb +5 -0
  26. data/spec/collect_spec.rb +1021 -0
  27. data/spec/errors_spec.rb +148 -0
  28. data/spec/ferrari_spec.rb +39 -0
  29. data/spec/function_spec.rb +199 -0
  30. data/spec/hello_spec.rb +34 -0
  31. data/spec/node_sharing_spec.rb +53 -0
  32. data/spec/property_spec.rb +69 -0
  33. data/spec/spec.opts +4 -0
  34. data/spec/spec_helper.rb +9 -0
  35. data/tasks/documentation.rake +32 -0
  36. data/tasks/rspec.rake +21 -0
  37. data/tasks/test.rake +9 -0
  38. data/tests/assert_facts.rb +130 -0
  39. data/tests/common.rb +29 -0
  40. data/tests/duck_type.rb +79 -0
  41. data/tests/gets.rb +48 -0
  42. data/tests/join_nodes.rb +63 -0
  43. data/tests/nil.rb +72 -0
  44. data/tests/not_patterns.rb +91 -0
  45. data/tests/or_patterns.rb +154 -0
  46. data/tests/regex.rb +47 -0
  47. data/tests/self_reference.rb +54 -0
  48. metadata +81 -49
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ class PropFact
4
+ attr :value, true
5
+ def initialize(v=nil); @value = v; end
6
+ end
7
+
8
+ class PropCtx
9
+
10
+ end
11
+
12
+
13
+ include Ruleby
14
+
15
+ class PropRulebook < Rulebook
16
+ def gt_rules
17
+ rule [PropFact, :p, m.value > 0] do
18
+ assert Success.new
19
+ end
20
+ end
21
+
22
+ def lte_rules
23
+ rule [PropFact, :p, m.value > 42], [PropCtx, :pc] do
24
+ # do nothing, just being here helps reproduce a bug
25
+ end
26
+ rule [PropFact, :p, m.value <= 42], [PropCtx, :pc] do
27
+ assert Success.new
28
+ end
29
+ end
30
+ end
31
+
32
+ describe Ruleby::Core::Engine do
33
+ describe "property gt_rules" do
34
+ subject do
35
+ engine :engine do |e|
36
+ PropRulebook.new(e).gt_rules
37
+ end
38
+ end
39
+
40
+ before do
41
+ subject.assert PropFact.new(1)
42
+ subject.match
43
+ end
44
+
45
+ it "should have matched" do
46
+ subject.errors.should == []
47
+ subject.retrieve(Success).size.should == 1
48
+ end
49
+ end
50
+ describe "property lte_rules" do
51
+ subject do
52
+ engine :engine do |e|
53
+ PropRulebook.new(e).lte_rules
54
+ end
55
+ end
56
+
57
+ before do
58
+ subject.assert PropCtx.new
59
+ subject.assert PropFact.new(42)
60
+ subject.assert PropFact.new(41)
61
+ subject.match
62
+ end
63
+
64
+ it "should have matched" do
65
+ subject.errors.should == []
66
+ subject.retrieve(Success).size.should == 2
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --loadby random
3
+ --format profile
4
+ --backtrace
@@ -0,0 +1,9 @@
1
+ require 'ruleby'
2
+ #require 'rspec'
3
+
4
+ class Success
5
+ attr :status, true
6
+ def initialize(status=nil)
7
+ @status = status
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ # DOCUMENTATION
3
+
4
+ #ALLISON=`allison --path`
5
+ #ALLISON="/Library/Ruby/Gems/1.8/gems/allison-2.0.3/lib/allison.rb"
6
+
7
+ Rake::RDocTask.new do |rd|
8
+
9
+ #rd.main = "README.txt"
10
+ #rd.rdoc_dir = "html/rufus-verbs"
11
+
12
+ rd.rdoc_files.include(
13
+ "LICENSE.txt",
14
+ "lib/**/*.rb")
15
+
16
+ rd.title = "ruleby rdoc"
17
+
18
+ rd.options << '-N' # line numbers
19
+ rd.options << '-S' # inline source
20
+
21
+ #rd.template = ALLISON if File.exist?(ALLISON)
22
+ end
23
+
24
+
25
+ #
26
+ # WEBSITE
27
+
28
+ #task :upload_website => [ :clean, :rdoc ] do
29
+ # account = "whoever@rubyforge.org"
30
+ # webdir = "/var/www/gforge-projects/ruleby"
31
+ # sh "rsync -azv -e ssh html/source #{account}:#{webdir}/"
32
+ #end
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
@@ -0,0 +1,9 @@
1
+
2
+ #
3
+ # TESTING
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << "tests"
7
+ t.test_files = FileList['tests/test.rb']
8
+ t.verbose = true
9
+ end
@@ -0,0 +1,130 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2008 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner
10
+ #
11
+
12
+ require 'test/unit'
13
+
14
+ require 'ruleby'
15
+
16
+ include Ruleby
17
+
18
+ module AssertFacts
19
+
20
+ class Fibonacci
21
+ def initialize(sequence,value=-1)
22
+ @sequence = sequence
23
+ @value = value
24
+ end
25
+
26
+ attr_reader :sequence
27
+ attr :value, true
28
+
29
+ def to_s
30
+ return super + "::sequence=" + @sequence.to_s + ",value=" + @value.to_s
31
+ end
32
+ end
33
+
34
+ class SimpleRulebook < Rulebook
35
+ def rules
36
+ rule [Message, :m, {m.message => :x}, m.status == b(:x)],
37
+ [Context, :c] do |v|
38
+ v[:c].inc :rule1
39
+ end
40
+ end
41
+ end
42
+
43
+ class FibonacciRulebook < Rulebook
44
+ def rules
45
+ # Bootstrap1
46
+ rule :Bootstrap1, {:priority => 4},
47
+ [Fibonacci, :f, m.value == -1, m.sequence == 1 ] do |vars|
48
+ vars[:f].value = 1
49
+ modify vars[:f]
50
+ end
51
+
52
+ # Recurse
53
+ rule :Recurse, {:priority => 3},
54
+ [Fibonacci, :f, m.value == -1] do |vars|
55
+ f2 = Fibonacci.new(vars[:f].sequence - 1)
56
+ assert f2
57
+ end
58
+
59
+ # Bootstrap2
60
+ rule :Bootstrap2,
61
+ [Fibonacci, :f, m.value == -1 , m.sequence == 2] do |vars|
62
+ vars[:f].value = 1
63
+ modify vars[:f]
64
+ end
65
+
66
+ # Calculate
67
+ rule :Calculate,
68
+ [Context, :c],
69
+ [Fibonacci,:f1, m.value.not== -1, {m.sequence => :s1}],
70
+ [Fibonacci,:f2, m.value.not== -1, {m.sequence( :s1, &c{ |s2,s1| s2 == s1 + 1 } ) => :s2}],
71
+ [Fibonacci,:f3, m.value == -1, m.sequence(:s2, &c{ |s3,s2| s3 == s2 + 1 }) ] do |vars|
72
+ vars[:f3].value = vars[:f1].value + vars[:f2].value
73
+ modify vars[:f3]
74
+ retract vars[:f1]
75
+ vars[:c].set vars[:f3].sequence, vars[:f3].value
76
+ end
77
+ end
78
+ end
79
+
80
+ class Test < Test::Unit::TestCase
81
+
82
+ def test_0
83
+ engine :engine do |e|
84
+ ctx = Context.new
85
+ e.assert ctx
86
+ e.assert Message.new(:HELLO, :HELLO)
87
+ SimpleRulebook.new(e).rules
88
+ e.assert Message.new(:HELLO, :GOODBYE)
89
+ e.match
90
+ assert_equal 1, ctx.get(:rule1)
91
+ end
92
+ end
93
+
94
+ def test_1
95
+ engine :engine do |e|
96
+ ctx = Context.new
97
+ e.assert ctx
98
+ e.assert Message.new(:HELLO, :HELLO)
99
+ e.assert Message.new(:HELLO, :GOODBYE)
100
+ SimpleRulebook.new(e).rules
101
+ e.match
102
+ assert_equal 1, ctx.get(:rule1)
103
+ end
104
+ end
105
+
106
+ def test_2
107
+ fib1 = Fibonacci.new(150)
108
+ engine :engine do |e|
109
+ FibonacciRulebook.new(e).rules
110
+ ctx = Context.new
111
+ e.assert ctx
112
+ e.assert fib1
113
+ e.match
114
+ assert_equal 9969216677189303386214405760200, ctx.get(150)
115
+ end
116
+ end
117
+
118
+ def test_3
119
+ fib1 = Fibonacci.new(150)
120
+ engine :engine do |e|
121
+ ctx = Context.new
122
+ e.assert ctx
123
+ e.assert fib1
124
+ FibonacciRulebook.new(e).rules
125
+ e.match
126
+ assert_equal 9969216677189303386214405760200, ctx.get(150)
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,29 @@
1
+
2
+ class Context
3
+
4
+ def initialize
5
+ @counts = {}
6
+ @counts.default = 0
7
+ end
8
+
9
+ def inc(key)
10
+ @counts[key] += 1
11
+ end
12
+
13
+ def set(key,value)
14
+ @counts[key] = value
15
+ end
16
+
17
+ def get(key)
18
+ @counts[key]
19
+ end
20
+ end
21
+
22
+ class Message
23
+ def initialize(status,message)
24
+ @status = status
25
+ @message = message
26
+ end
27
+ attr :status, true
28
+ attr :message, true
29
+ end
@@ -0,0 +1,79 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2008 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith, John Mettraux
10
+ #
11
+ require 'test/unit'
12
+ require 'ruleby'
13
+
14
+ include Ruleby
15
+
16
+ module Duck
17
+ class Foobar
18
+ end
19
+
20
+ class Email < Message
21
+ end
22
+
23
+ class Loan
24
+ def initialize(name,age)
25
+ @name = name
26
+ @age = age
27
+ @status = :HELLO
28
+ end
29
+ attr :name, true
30
+ attr :age, true
31
+ attr :status, true
32
+ end
33
+
34
+
35
+ class DuckRulebook < Rulebook
36
+
37
+ def rules
38
+
39
+ rule [m.status == :HELLO], [Context, :c] do |v|
40
+ v[:c].inc :rule1
41
+ end
42
+
43
+ rule [:is_a?, Message, m.status == :HELLO], [Context, :c] do |v|
44
+ v[:c].inc :rule2
45
+ end
46
+
47
+ rule [Message, m.status == :HELLO], [Context, :c] do |v|
48
+ v[:c].inc :rule3
49
+ end
50
+ end
51
+ end
52
+
53
+ class DuckTypeTest < Test::Unit::TestCase
54
+
55
+ def test_0
56
+
57
+ engine :engine do |e|
58
+ DuckRulebook.new(e).rules
59
+ ctx = Context.new
60
+ a = Loan.new('A','B')
61
+ b = Message.new(:HELLO, 'test')
62
+ c = Email.new(:HELLO, 'test')
63
+ d = Message.new(:FOOBAR, 'foobar')
64
+ f = Foobar.new
65
+
66
+ e.assert ctx
67
+ e.assert a; e.match; e.retract a
68
+ e.assert b; e.match; e.retract b
69
+ e.assert c; e.match; e.retract c
70
+ e.assert d; e.match; e.retract d
71
+ e.assert f; e.match; e.retract f
72
+
73
+ assert_equal 3, ctx.get(:rule1)
74
+ assert_equal 2, ctx.get(:rule2)
75
+ assert_equal 1, ctx.get(:rule3)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,48 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2007 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner, Matt Smith
10
+ #
11
+
12
+ require 'test/unit'
13
+ require 'ruleby'
14
+
15
+ include Ruleby
16
+
17
+ TEST_STR = String.new("it worked")
18
+
19
+ module Get
20
+
21
+ class GetRulebook < Rulebook
22
+ def rules
23
+
24
+ rule [Message, :m, m.status == :HELLO] do |v|
25
+ @engine.assert TEST_STR
26
+ end
27
+
28
+ end
29
+ end
30
+
31
+ class Test < Test::Unit::TestCase
32
+
33
+ def test_0
34
+
35
+ engine :engine do |e|
36
+ GetRulebook.new(e).rules
37
+ e.assert Message.new(:HELLO, 'test')
38
+ e.match
39
+
40
+ strs = e.retrieve(String)
41
+
42
+ assert_equal 1, strs.size
43
+
44
+ assert_equal TEST_STR, strs[0]
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,63 @@
1
+ # This file is part of the Ruleby project (http://ruleby.org)
2
+ #
3
+ # This application is free software; you can redistribute it and/or
4
+ # modify it under the terms of the Ruby license defined in the
5
+ # LICENSE.txt file.
6
+ #
7
+ # Copyright (c) 2009 Joe Kutner and Matt Smith. All rights reserved.
8
+ #
9
+ # * Authors: Joe Kutner
10
+ #
11
+
12
+ require 'test/unit'
13
+
14
+ require 'ruleby'
15
+
16
+ include Ruleby
17
+
18
+ module JoinNodes
19
+
20
+ class A
21
+
22
+ end
23
+
24
+ class B
25
+
26
+ end
27
+
28
+ class JoinNodesRulebook < Rulebook
29
+ def rules
30
+ rule [A], [B], [Context, :c] do |v|
31
+ v[:c].inc :rule1
32
+ end
33
+ end
34
+ end
35
+
36
+ class Test < Test::Unit::TestCase
37
+ def test_0
38
+ engine :engine do |e|
39
+ JoinNodesRulebook.new(e).rules
40
+ ctx = Context.new
41
+ a = A.new
42
+ b = B.new
43
+ e.assert ctx
44
+ e.assert a
45
+ e.assert b
46
+ e.match
47
+ assert_equal 1, ctx.get(:rule1)
48
+ e.retract a
49
+ e.match
50
+ assert_equal 1, ctx.get(:rule1)
51
+ e.assert B.new
52
+ e.match
53
+ assert_equal 1, ctx.get(:rule1)
54
+ e.assert A.new
55
+ e.match
56
+ assert_equal 3, ctx.get(:rule1)
57
+ e.retract b
58
+ e.match
59
+ assert_equal 4, ctx.get(:rule1)
60
+ end
61
+ end
62
+ end
63
+ end