ruleby 0.1

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.
@@ -0,0 +1,205 @@
1
+ require 'ruleby'
2
+
3
+ class Rulebook
4
+ include Ruleby
5
+ def initialize(rete)
6
+ @rete = rete
7
+ end
8
+
9
+ attr_reader :rete
10
+
11
+ def rule(name, &block)
12
+ r = Core::Rule.new name
13
+ yield r if block_given?
14
+ @rete.assert_rule r
15
+ r
16
+ end
17
+
18
+ def action(&block)
19
+ return Core::Action.new(&block)
20
+ end
21
+
22
+ def pattern(&block)
23
+ pb = PatternBuilder.new
24
+ yield pb
25
+ return pb.condition
26
+ end
27
+ end
28
+
29
+
30
+ class PatternInternal
31
+ def initialize(tag, type)
32
+ @tag = tag
33
+ @type = type
34
+ @atoms = []
35
+ end
36
+
37
+ def atom(tag, name, references, &block)
38
+ if references
39
+ references = [references] unless references.kind_of?(Array)
40
+ return Core::ReferenceAtom.new(tag, name, references, &block)
41
+ else
42
+ return Core::PropertyAtom.new(tag, name, &block)
43
+ end
44
+ end
45
+ def method_missing(method_id, *args, &block)
46
+ if block_given?
47
+ with(method_id.to_s, *args, &block)
48
+ else
49
+ with(method_id.to_s, *args)
50
+ end
51
+ end
52
+ def with(property, options={}, &block)
53
+ tag = options[:name]
54
+ tag = GeneratedTag.new if tag == options.default
55
+ if block_given?
56
+ @atoms.push atom(tag, property, options[:references], &block)
57
+ else
58
+ # QUESTION do we really want to do this? What if someone does:
59
+ # :equals => -1
60
+ # How do we handle a case where it is not a ReferenceAtom? should we
61
+ # have a :equals_ref key too?
62
+ # if options[:equals] != options.default
63
+ # @atoms.push(atom(tag, property, [options[:equals]]) do |p,a| p==a end)
64
+ # elsif options[:not_equals] != options.default
65
+ # @atoms.push(atom(tag, property, [options[:not_equals]]) do |p,a| p!=a end)
66
+ # else
67
+ @atoms.push(atom(tag, property, nil) do |p| true end)
68
+ # end
69
+ end
70
+ end
71
+
72
+ def pattern
73
+ @atoms = Array.new(1){@atoms} unless @atoms.kind_of?(Array)
74
+ return Core::ObjectPattern.new(@tag, @type, @atoms)
75
+ end
76
+
77
+ def not
78
+ @atoms = Array.new(1){@atoms} unless @atoms.kind_of?(Array)
79
+ return Core::NotPattern.new(@tag, @type, @atoms)
80
+ end
81
+ end
82
+ class PatternInternal
83
+ public_instance_methods.each do |m|
84
+ a = [:not, :pattern, :with, :method_missing, :atom, :new, :public_instance_methods, :__send__, :__id__]
85
+ undef_method m.to_sym unless a.include? m.to_sym
86
+ end
87
+ end
88
+
89
+ class PatternBuilder < Rulebook
90
+
91
+ attr_reader :condition
92
+
93
+ def initialize()
94
+ @condition = nil
95
+ end
96
+
97
+ def has(type, tag=GeneratedTag.new, &block)
98
+ pi = pattern_internal(tag, type)
99
+ yield pi if block_given?
100
+ op = pi.pattern
101
+ if(@condition)
102
+ pat = [@condition, op]
103
+ @condition = and_pattern(pat)
104
+ else
105
+ @condition = op
106
+ end
107
+ @condition
108
+ end
109
+ def and(operands)
110
+ if @condition
111
+ p = [@condition] + operands
112
+ @condition = and_pattern(p)
113
+ else
114
+ @condition = and_pattern(operands)
115
+ end
116
+ @condition
117
+ end
118
+
119
+ def or(operands)
120
+ if(@condition)
121
+ p = [@condition] + operands
122
+ @condition = or_pattern(p)
123
+ else
124
+ @condition = or_pattern(operands)
125
+ end
126
+ @condition
127
+ end
128
+
129
+ def not(type, tag=GeneratedTag.new, &block)
130
+ pi = pattern_internal(tag, type)
131
+ yield pi if block_given?
132
+ n = pi.not
133
+ if(@condition)
134
+ p = [@condition, n]
135
+ @condition = and_pattern(p)
136
+ else
137
+ @condition = n
138
+ end
139
+ end
140
+
141
+ private
142
+ def pattern_internal(tag, type)
143
+ return PatternInternal.new(tag, type)
144
+ end
145
+
146
+ def or_pattern(operands)
147
+ # TODO raise exception if referenceAtoms from the right do not
148
+ # have the values they referenece in the left
149
+ # TODO raise exception if there are repeated tags?
150
+ left = nil
151
+ operands.each do |operand|
152
+ if left.nil?
153
+ left = operand
154
+ else
155
+ right = operand
156
+ left = Core::OrPattern.new(left, right)
157
+ end
158
+ end
159
+ left
160
+ end
161
+
162
+ def and_pattern(operands)
163
+ # TODO raise exception if referenceAtoms from the right do not
164
+ # have the values they referenece in the left
165
+ # TODO raise exception if there are repeated tags?
166
+ left = nil
167
+ operands.each do |operand|
168
+ if left.nil?
169
+ left = operand
170
+ else
171
+ right = operand
172
+ left = Core::AndPattern.new(left, right)
173
+ end
174
+ end
175
+ left
176
+ end
177
+ end
178
+
179
+ class GeneratedTag
180
+
181
+ # this counter is incremented for each UniqueTag created, and is
182
+ # appended to the end of the unique_seed in order to create a
183
+ # string that is unique for each instance of this class.
184
+ @@tag_counter = 0
185
+
186
+ # every generated tag will be prefixed with this string
187
+ @@unique_seed = 'unique_seed'
188
+
189
+ def initialize()
190
+ @@tag_counter += 1
191
+ @tag = @@unique_seed + @@tag_counter.to_s
192
+ end
193
+
194
+ attr_reader:tag_counter
195
+ attr_reader:unique_seed
196
+ attr_reader:tag
197
+
198
+ def ==(ut)
199
+ return ut && ut.kind_of?(GeneratedTag) && @tag == ut.tag
200
+ end
201
+
202
+ def to_s
203
+ return @tag.to_s
204
+ end
205
+ end
@@ -0,0 +1,29 @@
1
+ require 'core/engine'
2
+ module Ruleby
3
+ #helper classes for using ruleby go here
4
+ def engine(name, &block)
5
+ e = Core::Engine.new
6
+ yield e if block_given?
7
+ return e
8
+ end
9
+ def assert(rete,object,&block)
10
+ fact(rete,object,:plus,&block)
11
+ end
12
+
13
+ def retract(rete,object,&block)
14
+ fact(rete,object,:minus,&block)
15
+ end
16
+
17
+ def modify(rete,object,&block)
18
+ retract(rete,object,&block)
19
+ assert(rete,object,&block)
20
+ end
21
+
22
+ private
23
+ def fact(rete, object, sign=:plus, &block)
24
+ f = Core::Fact.new object, sign
25
+ yield f if block_given?
26
+ rete.assert_fact f
27
+ f
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: ruleby
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2007-04-29 00:00:00 -05:00
8
+ summary: the Rule Engine for Ruby
9
+ require_paths:
10
+ - lib
11
+ email: matt@ruleby.org
12
+ homepage: http://www.ruleby.org
13
+ rubyforge_project:
14
+ description: ruleby is the Rule Engine for Ruby
15
+ autorequire: ruleby
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.4
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - Joe Kutner, Matt Smith
30
+ files:
31
+ - lib/rulebook.rb
32
+ - lib/ruleby.rb
33
+ - lib/core/atoms.rb
34
+ - lib/core/engine.rb
35
+ - lib/core/nodes.rb
36
+ - lib/core/patterns.rb
37
+ - lib/core/utils.rb
38
+ test_files: []
39
+
40
+ rdoc_options: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ requirements: []
49
+
50
+ dependencies: []
51
+