ruleby 0.3 → 0.4
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/atoms.rb +76 -27
- data/lib/core/engine.rb +11 -5
- data/lib/core/nodes.rb +175 -71
- data/lib/core/patterns.rb +21 -18
- data/lib/dsl/ferrari.rb +50 -33
- data/lib/dsl/letigre.rb +43 -17
- data/lib/dsl/steel.rb +1 -0
- data/lib/dsl/yaml_dsl.rb +23 -0
- data/lib/rulebook.rb +18 -3
- data/lib/ruleby.rb +37 -0
- data/tests/test.rb +15 -0
- metadata +53 -57
- data/benchmarks/basic_rules.rb +0 -66
- data/benchmarks/joined_rules.rb +0 -73
- data/benchmarks/miss_manners/data.rb +0 -146
- data/benchmarks/miss_manners/miss_manners.rb +0 -33
- data/benchmarks/miss_manners/model.rb +0 -193
- data/benchmarks/miss_manners/rules.rb +0 -104
- data/benchmarks/model.rb +0 -36
- data/examples/example_diagnosis.rb +0 -117
- data/examples/example_hello.rb +0 -46
- data/examples/example_politician.rb +0 -97
- data/examples/example_ticket.rb +0 -113
- data/examples/fibonacci_example1.rb +0 -44
- data/examples/fibonacci_example2.rb +0 -40
- data/examples/fibonacci_rulebook.rb +0 -84
- data/examples/test_self_reference.rb +0 -77
data/examples/example_hello.rb
DELETED
@@ -1,46 +0,0 @@
|
|
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
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
-
require 'ruleby'
|
14
|
-
|
15
|
-
include Ruleby
|
16
|
-
|
17
|
-
class Message
|
18
|
-
def initialize(status,message)
|
19
|
-
@status = status
|
20
|
-
@message = message
|
21
|
-
end
|
22
|
-
attr :status, true
|
23
|
-
attr :message, true
|
24
|
-
end
|
25
|
-
|
26
|
-
class HelloWorldRulebook < Rulebook
|
27
|
-
def rules
|
28
|
-
rule [Message, :m, m.status == :HELLO] do |e,v|
|
29
|
-
puts v[:m].message
|
30
|
-
v[:m].message = "Goodbye world"
|
31
|
-
v[:m].status = :GOODBYE
|
32
|
-
e.modify v[:m]
|
33
|
-
end
|
34
|
-
|
35
|
-
rule [Message, :m, m.status == :GOODBYE] do |e,v|
|
36
|
-
puts v[:m].message
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
engine :engine do |e|
|
43
|
-
HelloWorldRulebook.new(e).rules
|
44
|
-
e.assert Message.new(:HELLO, 'Hello World')
|
45
|
-
e.match
|
46
|
-
end
|
@@ -1,97 +0,0 @@
|
|
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
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
-
require 'ruleby'
|
14
|
-
|
15
|
-
include Ruleby
|
16
|
-
|
17
|
-
class Politician
|
18
|
-
def initialize(name,honest)
|
19
|
-
@name = name
|
20
|
-
@honest = honest
|
21
|
-
end
|
22
|
-
attr_accessor :name, :honest
|
23
|
-
def to_s
|
24
|
-
return "[#{@name.to_s},#{@honest.to_s}]"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Hope
|
29
|
-
end
|
30
|
-
|
31
|
-
# NOTE this example demonstrates the BlueSteel (block based) DSL syntax
|
32
|
-
class PoliticianRulebook < Rulebook
|
33
|
-
def rules
|
34
|
-
rule :We_have_an_honest_Politician do |r|
|
35
|
-
r.when do |has|
|
36
|
-
has.p Politician
|
37
|
-
has.p.honest = true
|
38
|
-
end
|
39
|
-
r.then do |e,vars|
|
40
|
-
e.assert Hope.new
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
rule :Hope_Lives do |r|
|
45
|
-
r.when do |has|
|
46
|
-
has.h Hope
|
47
|
-
end
|
48
|
-
r.then do |e,vars|
|
49
|
-
puts 'Hurrah!!! Democracy Lives'
|
50
|
-
end
|
51
|
-
r.priority = 10
|
52
|
-
end
|
53
|
-
|
54
|
-
# This example was taken from the JBoss-Rules project. That example
|
55
|
-
# demonstrates a feature that Ruleby does not support: logical assertions.
|
56
|
-
# The JBoss-Rules example, the following rule is fired as the last
|
57
|
-
# activation (because Hope is retracted during fact maintenence).
|
58
|
-
# rule do |r|
|
59
|
-
# r.when = pattern do |p|
|
60
|
-
# p.not :h, Hope
|
61
|
-
# end
|
62
|
-
# r.then 'Hope is Dead' do |r,vars|
|
63
|
-
# puts 'We are all Doomed!!! Democracy is Dead'
|
64
|
-
# end
|
65
|
-
# r.priority = -1
|
66
|
-
# end
|
67
|
-
|
68
|
-
rule :Corrupt_the_Honest do |r|
|
69
|
-
r.when do |has|
|
70
|
-
has.p Politician
|
71
|
-
has.p.honest = true
|
72
|
-
|
73
|
-
has.h Hope
|
74
|
-
end
|
75
|
-
r.then do |e,vars|
|
76
|
-
puts 'I am an evil corporation and I have corrupted ' + vars[:p].name
|
77
|
-
vars[:p].honest = false
|
78
|
-
e.modify vars[:p]
|
79
|
-
end
|
80
|
-
r.priority = 5
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
p1 = Politician.new('blair', true)
|
86
|
-
p2 = Politician.new('bush', true)
|
87
|
-
p3 = Politician.new('chirac', true)
|
88
|
-
p4 = Politician.new('schroder', true)
|
89
|
-
|
90
|
-
engine :engine do |e|
|
91
|
-
PoliticianRulebook.new(e).rules
|
92
|
-
e.assert p1
|
93
|
-
e.assert p2
|
94
|
-
e.assert p3
|
95
|
-
e.assert p4
|
96
|
-
e.match
|
97
|
-
end
|
data/examples/example_ticket.rb
DELETED
@@ -1,113 +0,0 @@
|
|
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
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
-
require 'ruleby'
|
14
|
-
|
15
|
-
include Ruleby
|
16
|
-
|
17
|
-
class Customer
|
18
|
-
def initialize(name,subscription)
|
19
|
-
@name = name
|
20
|
-
@subscription = subscription
|
21
|
-
end
|
22
|
-
attr_reader :name,:subscription
|
23
|
-
def to_s
|
24
|
-
return '[Customer ' + @name.to_s + ' : ' + @subscription.to_s + ']';
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class Ticket
|
29
|
-
def initialize(customer)
|
30
|
-
@customer = customer
|
31
|
-
@status = :New
|
32
|
-
end
|
33
|
-
attr :status, true
|
34
|
-
attr_reader :customer
|
35
|
-
def to_s
|
36
|
-
return '[Ticket ' + @customer.to_s + ' : ' + @status.to_s + ']';
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# This example is used in JBoss-Rules to demonstrate durations and the use of
|
41
|
-
# custom DSL. We are simply using it here to demonstrate another example.
|
42
|
-
class TroubleTicketRulebook < Rulebook
|
43
|
-
def rules
|
44
|
-
|
45
|
-
# This is uses the letigre syntax... but we can mix and match syntaxes in
|
46
|
-
# the same rule set.
|
47
|
-
rule :New_Ticket, {:priority => 10}, # :duration => 10},
|
48
|
-
'Customer as :c',
|
49
|
-
'Ticket as :ticket where #customer == #:c #&& #status == :New' do |e,vars|
|
50
|
-
puts 'New : ' + vars[:ticket].to_s
|
51
|
-
end
|
52
|
-
|
53
|
-
# Now we are using the ferrari syntax. The rule method can detect which
|
54
|
-
# syntax we are using, and compile accordingly.
|
55
|
-
rule :Silver_Priority, #{:duration => 3000},
|
56
|
-
[Customer, :customer, m.subscription == 'Silver'],
|
57
|
-
[Ticket,:ticket, m.customer == b(:customer), m.status == :New] do |e,vars|
|
58
|
-
vars[:ticket].status = :Escalate
|
59
|
-
e.modify vars[:ticket]
|
60
|
-
end
|
61
|
-
|
62
|
-
rule :Gold_Priority, #{:duration => 1000},
|
63
|
-
[Customer, :customer, m.subscription == 'Gold'],
|
64
|
-
[Ticket,:ticket, m.customer == b(:customer), m.status == :New] do |e,vars|
|
65
|
-
vars[:ticket].status = :Escalate
|
66
|
-
e.modify vars[:ticket]
|
67
|
-
end
|
68
|
-
|
69
|
-
rule :Platinum_Priority,
|
70
|
-
[Customer, :customer, m.subscription == 'Platinum'],
|
71
|
-
[Ticket,:ticket, m.customer == b(:customer), m.status == :New] do |e,vars|
|
72
|
-
vars[:ticket].status = :Escalate
|
73
|
-
e.modify vars[:ticket]
|
74
|
-
end
|
75
|
-
|
76
|
-
rule :Escalate,
|
77
|
-
'Customer as :c',
|
78
|
-
'Ticket as :ticket where #customer == #:c #&& #status == :Escalate' do |e,vars|
|
79
|
-
puts 'Email : ' + vars[:ticket].to_s
|
80
|
-
end
|
81
|
-
|
82
|
-
rule :Done,
|
83
|
-
'Customer as :c',
|
84
|
-
'Ticket as :ticket where #customer == #:c #&& #status == :Done' do |e,vars|
|
85
|
-
puts 'Done : ' + vars[:ticket].to_s
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# FACTS
|
91
|
-
|
92
|
-
a = Customer.new('A', 'Gold')
|
93
|
-
b = Customer.new('B', 'Platinum')
|
94
|
-
c = Customer.new('C', 'Silver')
|
95
|
-
d = Customer.new('D', 'Silver')
|
96
|
-
|
97
|
-
t1 = Ticket.new(a)
|
98
|
-
t2 = Ticket.new(b)
|
99
|
-
t3 = Ticket.new(c)
|
100
|
-
t4 = Ticket.new(d)
|
101
|
-
|
102
|
-
engine :engine do |e|
|
103
|
-
TroubleTicketRulebook.new(e).rules
|
104
|
-
e.assert a
|
105
|
-
e.assert b
|
106
|
-
e.assert c
|
107
|
-
e.assert d
|
108
|
-
e.assert t1
|
109
|
-
e.assert t2
|
110
|
-
e.assert t3
|
111
|
-
e.assert t4
|
112
|
-
e.match
|
113
|
-
end
|
@@ -1,44 +0,0 @@
|
|
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
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
-
require 'ruleby'
|
14
|
-
require 'fibonacci_rulebook'
|
15
|
-
class Fibonacci
|
16
|
-
def initialize(sequence,value=-1)
|
17
|
-
@sequence = sequence
|
18
|
-
@value = value
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_reader :sequence
|
22
|
-
attr :value, true
|
23
|
-
|
24
|
-
def to_s
|
25
|
-
return '['+super + " sequence=" + @sequence.to_s + ",value=" + @value.to_s + ']'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
include Ruleby
|
30
|
-
|
31
|
-
# This example is borrowed from the JBoss-Rule project.
|
32
|
-
|
33
|
-
# FACTS
|
34
|
-
fib1 = Fibonacci.new(150)
|
35
|
-
|
36
|
-
t1 = Time.new
|
37
|
-
engine :engine do |e|
|
38
|
-
FibonacciRulebookFerrari.new(e).rules
|
39
|
-
e.assert fib1
|
40
|
-
e.match
|
41
|
-
end
|
42
|
-
t2 = Time.new
|
43
|
-
diff = t2.to_f - t1.to_f
|
44
|
-
puts diff.to_s
|
@@ -1,40 +0,0 @@
|
|
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
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
-
require 'ruleby'
|
14
|
-
require 'fibonacci_rulebook'
|
15
|
-
class Fibonacci
|
16
|
-
def initialize(sequence,value=-1)
|
17
|
-
@sequence = sequence
|
18
|
-
@value = value
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_reader :sequence
|
22
|
-
attr :value, true
|
23
|
-
|
24
|
-
def to_s
|
25
|
-
return super + "::sequence=" + @sequence.to_s + ",value=" + @value.to_s
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
include Ruleby
|
30
|
-
|
31
|
-
# FACTS
|
32
|
-
fib1 = Fibonacci.new(1,1)
|
33
|
-
fib2 = Fibonacci.new(2,1)
|
34
|
-
|
35
|
-
engine :engine do |e|
|
36
|
-
FibonacciRulebook2.new(e).rules
|
37
|
-
e.assert fib1
|
38
|
-
e.assert fib2
|
39
|
-
e.match
|
40
|
-
end
|
@@ -1,84 +0,0 @@
|
|
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 'ruleby'
|
13
|
-
|
14
|
-
include Ruleby
|
15
|
-
|
16
|
-
# NOTE this example uses the LeTigre DSL syntax. In addition, its semantics are
|
17
|
-
# different from the other classes.
|
18
|
-
class FibonacciRulebook2 < Rulebook
|
19
|
-
MAX_SEQUENCE = 100
|
20
|
-
def rules
|
21
|
-
rule :Calculate, {:priority => 2 },
|
22
|
-
'Fibonacci as :f1 where #value != -1 #&& #sequence as :s1',
|
23
|
-
'Fibonacci as :f2 where #value != -1 #&& #sequence == #:s1 + 1 as :s2',
|
24
|
-
'Fibonacci as :f3 where #value == -1 #&& #sequence == #:s2 + 1' do |e, vars|
|
25
|
-
e.retract vars[:f1]
|
26
|
-
e.retract vars[:f3]
|
27
|
-
if(vars[:f2].sequence == MAX_SEQUENCE)
|
28
|
-
e.retract vars[:f2]
|
29
|
-
else
|
30
|
-
f3 = Fibonacci.new(vars[:f2].sequence + 1, vars[:f1].value + vars[:f2].value)
|
31
|
-
e.assert f3
|
32
|
-
puts "#{f3.sequence} == #{f3.value}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
rule :Build, {:priority => 1},
|
37
|
-
'Fibonacci as :f1 where #value != -1 #&& #sequence as :s1',
|
38
|
-
'Fibonacci as :f2 where #value != -1 #&& #sequence == #:s1 + 1' do |e, vars|
|
39
|
-
f3 = Fibonacci.new(vars[:f2].sequence + 1, -1)
|
40
|
-
e.assert f3
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# NOTE
|
46
|
-
# In this class we demonstrate the Ferrari DSL syntax.
|
47
|
-
class FibonacciRulebookFerrari < Rulebook
|
48
|
-
def rules
|
49
|
-
# Bootstrap1
|
50
|
-
rule :Bootstrap1, {:priority => 4},
|
51
|
-
[Fibonacci, :f, m.value == -1, m.sequence == 1 ] do |e,vars|
|
52
|
-
vars[:f].value = 1
|
53
|
-
e.modify vars[:f]
|
54
|
-
puts vars[:f].sequence.to_s + ' == ' + vars[:f].value.to_s
|
55
|
-
end
|
56
|
-
|
57
|
-
# Recurse
|
58
|
-
rule :Recurse, {:priority => 3},
|
59
|
-
[Fibonacci, :f, m.value == -1] do |e,vars|
|
60
|
-
f2 = Fibonacci.new(vars[:f].sequence - 1)
|
61
|
-
e.assert f2
|
62
|
-
puts 'recurse for ' + f2.sequence.to_s
|
63
|
-
end
|
64
|
-
|
65
|
-
# Bootstrap2
|
66
|
-
rule :Bootstrap2,
|
67
|
-
[Fibonacci, :f, m.value == -1 , m.sequence == 2] do |e,vars|
|
68
|
-
vars[:f].value = 1
|
69
|
-
e.modify vars[:f]
|
70
|
-
puts vars[:f].sequence.to_s + ' == ' + vars[:f].value.to_s
|
71
|
-
end
|
72
|
-
|
73
|
-
# Calculate
|
74
|
-
rule :Calculate,
|
75
|
-
[Fibonacci,:f1, m.value.not== -1, {m.sequence => :s1}],
|
76
|
-
[Fibonacci,:f2, m.value.not== -1, {m.sequence( :s1, &c{ |s2,s1| s2 == s1 + 1 } ) => :s2}],
|
77
|
-
[Fibonacci,:f3, m.value == -1, m.sequence(:s2, &c{ |s3,s2| s3 == s2 + 1 }) ] do |e,vars|
|
78
|
-
vars[:f3].value = vars[:f1].value + vars[:f2].value
|
79
|
-
e.modify vars[:f3]
|
80
|
-
e.retract vars[:f1]
|
81
|
-
puts vars[:f3].sequence.to_s + ' == ' + vars[:f3].value.to_s
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,77 +0,0 @@
|
|
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
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
13
|
-
require 'ruleby'
|
14
|
-
|
15
|
-
include Ruleby
|
16
|
-
|
17
|
-
class Message
|
18
|
-
def initialize(status,message)
|
19
|
-
@status = status
|
20
|
-
@message = message
|
21
|
-
end
|
22
|
-
attr :status, true
|
23
|
-
attr :message, true
|
24
|
-
end
|
25
|
-
|
26
|
-
class SelfRefRulebook < Rulebook
|
27
|
-
def rules
|
28
|
-
rule :LeTigreTest,
|
29
|
-
'For each Message as :m where #message as :x #&& #status == #:x' do |r,v|
|
30
|
-
puts 'Success'
|
31
|
-
end
|
32
|
-
|
33
|
-
rule :LeTigreTest,
|
34
|
-
[Message, :m, {m.message => :x}, m.status == b(:x)] do |r,v|
|
35
|
-
puts 'Success'
|
36
|
-
end
|
37
|
-
|
38
|
-
rule :BlueSteelTest do |r|
|
39
|
-
r.when do |has|
|
40
|
-
has.m Message
|
41
|
-
has.m.message :x
|
42
|
-
has.m.status = :x, :%
|
43
|
-
end
|
44
|
-
r.then do |e,vars|
|
45
|
-
puts 'Success'
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# NOTE references the self class binding is not allowed yet
|
50
|
-
|
51
|
-
# rule 'LeTigreTest',
|
52
|
-
# 'exists? Message as :m where #status == #:m.message' do |r,v|
|
53
|
-
# puts 'Success'
|
54
|
-
# end
|
55
|
-
|
56
|
-
# rule 'LeTigreTest',
|
57
|
-
# [Message, :m, m.status(:m, &c{|s,m| s == m.message})] do |r,v|
|
58
|
-
# puts 'Success'
|
59
|
-
# end
|
60
|
-
|
61
|
-
# rule :BlueSteelTest do |r|
|
62
|
-
# r.when do |has|
|
63
|
-
# has.m Message
|
64
|
-
# has.m.status :m do |s,m| s == m.message end
|
65
|
-
# end
|
66
|
-
# r.then do |e,vars|
|
67
|
-
# puts 'Success'
|
68
|
-
# end
|
69
|
-
# end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
engine :engine do |e|
|
74
|
-
SelfRefRulebook.new(e).rules
|
75
|
-
e.assert Message.new(:HELLO, :HELLO)
|
76
|
-
e.match
|
77
|
-
end
|