wongi-engine 0.0.2 → 0.0.3
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/.gitignore +2 -0
- data/README.md +17 -5
- data/lib/wongi-engine/alpha_memory.rb +1 -1
- data/lib/wongi-engine/beta/assignment_node.rb +39 -0
- data/lib/wongi-engine/beta/beta_memory.rb +22 -8
- data/lib/wongi-engine/beta/beta_node.rb +23 -52
- data/lib/wongi-engine/beta/filter_node.rb +12 -86
- data/lib/wongi-engine/beta/join_node.rb +12 -3
- data/lib/wongi-engine/beta/ncc_node.rb +22 -3
- data/lib/wongi-engine/beta/ncc_partner.rb +13 -14
- data/lib/wongi-engine/beta/neg_node.rb +22 -3
- data/lib/wongi-engine/beta/optional_node.rb +19 -2
- data/lib/wongi-engine/beta/or_node.rb +3 -3
- data/lib/wongi-engine/beta/production_node.rb +2 -6
- data/lib/wongi-engine/beta.rb +1 -0
- data/lib/wongi-engine/dsl.rb +7 -1
- data/lib/wongi-engine/filter/asserting_test.rb +20 -0
- data/lib/wongi-engine/filter/equality_test.rb +36 -0
- data/lib/wongi-engine/filter/filter_test.rb +21 -0
- data/lib/wongi-engine/filter/inequality_test.rb +36 -0
- data/lib/wongi-engine/filter.rb +4 -0
- data/lib/wongi-engine/network/debug.rb +60 -0
- data/lib/wongi-engine/network.rb +5 -1
- data/lib/wongi-engine/token.rb +5 -41
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine/wme.rb +4 -4
- data/lib/wongi-engine.rb +1 -0
- data/spec/filter_specs/assert_test_spec.rb +85 -0
- data/spec/high_level_spec.rb +5 -61
- data/spec/rule_specs/any_rule_spec.rb +75 -0
- data/spec/rule_specs/assign_spec.rb +52 -0
- data/spec/rule_specs/maybe_rule_spec.rb +54 -0
- data/spec/rule_specs/ncc_spec.rb +64 -0
- metadata +18 -2
data/lib/wongi-engine/beta.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'wongi-engine/beta/beta_node'
|
2
2
|
require 'wongi-engine/beta/beta_memory'
|
3
3
|
require 'wongi-engine/beta/filter_node'
|
4
|
+
require 'wongi-engine/beta/assignment_node'
|
4
5
|
require 'wongi-engine/beta/join_node'
|
5
6
|
require 'wongi-engine/beta/ncc_partner'
|
6
7
|
require 'wongi-engine/beta/ncc_node'
|
data/lib/wongi-engine/dsl.rb
CHANGED
@@ -55,7 +55,7 @@ dsl {
|
|
55
55
|
accept Wongi::Engine::NccProductionRule
|
56
56
|
|
57
57
|
clause :any
|
58
|
-
|
58
|
+
accept Wongi::Engine::AnyRule
|
59
59
|
|
60
60
|
clause :maybe, :optional
|
61
61
|
accept Wongi::Engine::OptionalTemplate
|
@@ -66,6 +66,12 @@ dsl {
|
|
66
66
|
clause :diff, :ne
|
67
67
|
accept Wongi::Engine::InequalityTest
|
68
68
|
|
69
|
+
clause :assert, :dynamic
|
70
|
+
accept Wongi::Engine::AssertingTest
|
71
|
+
|
72
|
+
clause :assign, :introduce
|
73
|
+
accept Wongi::Engine::Assignment
|
74
|
+
|
69
75
|
clause :asserted, :added
|
70
76
|
body { |s, p, o|
|
71
77
|
missing s, p, o, -1
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class AssertingTest < FilterTest
|
4
|
+
|
5
|
+
def initialize *vars, &body
|
6
|
+
@vars = vars
|
7
|
+
@body = body
|
8
|
+
end
|
9
|
+
|
10
|
+
def passes? token
|
11
|
+
if @vars.empty?
|
12
|
+
@body.call token
|
13
|
+
else
|
14
|
+
@body.call *( @vars.map { |var| token[var] } )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class EqualityTest < FilterTest
|
4
|
+
|
5
|
+
attr_reader :x, :y
|
6
|
+
|
7
|
+
def initialize x, y
|
8
|
+
@x, @y = x, y
|
9
|
+
end
|
10
|
+
|
11
|
+
def passes? token
|
12
|
+
|
13
|
+
x = if Template.variable? @x
|
14
|
+
token[@x]
|
15
|
+
else
|
16
|
+
@x
|
17
|
+
end
|
18
|
+
|
19
|
+
y = if Template.variable? @y
|
20
|
+
token[@y]
|
21
|
+
else
|
22
|
+
@y
|
23
|
+
end
|
24
|
+
|
25
|
+
return false if x == :_ || y == :_
|
26
|
+
return x == y
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def == other
|
31
|
+
super && x == other.x && y == other.y
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class FilterTest
|
4
|
+
|
5
|
+
def passes? token
|
6
|
+
raise "#{self.class} must implement #passes?"
|
7
|
+
end
|
8
|
+
|
9
|
+
def compile context
|
10
|
+
context.node = context.node.beta_memory.filter_node( self )
|
11
|
+
context.earlier << self
|
12
|
+
context
|
13
|
+
end
|
14
|
+
|
15
|
+
def == other
|
16
|
+
self.class == other.class
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
|
3
|
+
class InequalityTest < FilterTest
|
4
|
+
|
5
|
+
attr_reader :x, :y
|
6
|
+
|
7
|
+
def initialize x, y
|
8
|
+
@x, @y = x, y
|
9
|
+
end
|
10
|
+
|
11
|
+
def passes? token
|
12
|
+
|
13
|
+
x = if Template.variable? @x
|
14
|
+
token[@x]
|
15
|
+
else
|
16
|
+
@x
|
17
|
+
end
|
18
|
+
|
19
|
+
y = if Template.variable? @y
|
20
|
+
token[@y]
|
21
|
+
else
|
22
|
+
@y
|
23
|
+
end
|
24
|
+
|
25
|
+
return false if x == :_ || y == :_
|
26
|
+
return x != y
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def == other
|
31
|
+
super && x == other.x && y == other.y
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -18,6 +18,66 @@ module Wongi::Engine
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
def full_dump io = $stdout
|
22
|
+
|
23
|
+
alpha_hash.each_value do |alpha|
|
24
|
+
io.puts "ALPHA #{alpha.template}"
|
25
|
+
alpha.wmes.each do |wme|
|
26
|
+
dump_wme wme, io
|
27
|
+
end
|
28
|
+
end
|
29
|
+
dump_beta beta_top, io
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def token_lineage token
|
36
|
+
result = []
|
37
|
+
while token.parent
|
38
|
+
result << token.parent
|
39
|
+
token = token.parent
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def dump_wme wme, io
|
45
|
+
io.puts "\tWME: #{wme.object_id} #{wme}"
|
46
|
+
wme.tokens.each { |token| io.puts "\t\tTOKEN #{token.object_id}" }
|
47
|
+
io.puts "\tGENERATING:" unless wme.generating_tokens.empty?
|
48
|
+
wme.generating_tokens.each { |token| io.puts "\t\tTOKEN #{token.object_id}" }
|
49
|
+
end
|
50
|
+
|
51
|
+
def dump_beta beta, io
|
52
|
+
case beta
|
53
|
+
when BetaMemory
|
54
|
+
dump_beta_memory beta, io
|
55
|
+
when NccNode
|
56
|
+
dump_ncc beta, io
|
57
|
+
else
|
58
|
+
io.puts "BETA #{beta.object_id} #{beta.class} : TODO"
|
59
|
+
|
60
|
+
end
|
61
|
+
io.puts "\tCHILDREN: #{beta.children.map(&:object_id).join ", "}"
|
62
|
+
beta.children.each { |child| dump_beta child, io } unless beta.children.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def dump_beta_memory beta, io
|
66
|
+
io.puts "BETA MEMORY #{beta.object_id}"
|
67
|
+
beta.tokens.each { |token|
|
68
|
+
io.puts "\tTOKEN #{token.object_id} [#{token_lineage(token).map(&:object_id).map(&:to_s).join(" - ")}]"
|
69
|
+
token.wmes.each { |wme| io.puts "\t\tWME " + wme.object_id.to_s }
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def dump_ncc beta, io
|
74
|
+
io.puts "NCC #{beta.object_id}"
|
75
|
+
beta.tokens.each { |token|
|
76
|
+
io.puts "\tTOKEN #{token.object_id} [#{token_lineage(token).map(&:object_id).map(&:to_s).join(" - ")}]"
|
77
|
+
token.wmes.each { |wme| io.puts "\t\tWME " + wme.object_id.to_s }
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
21
81
|
end
|
22
82
|
|
23
83
|
end
|
data/lib/wongi-engine/network.rb
CHANGED
@@ -169,6 +169,10 @@ module Wongi::Engine
|
|
169
169
|
|
170
170
|
def retract wme, is_real = false
|
171
171
|
|
172
|
+
if wme.is_a? Array
|
173
|
+
return retract( WME.new(*wme), is_real )
|
174
|
+
end
|
175
|
+
|
172
176
|
if ! is_real
|
173
177
|
if @current_context
|
174
178
|
@current_context.retracted_wmes << wme
|
@@ -386,7 +390,7 @@ module Wongi::Engine
|
|
386
390
|
beta = root.network conditions, [], parameters, alpha_deaf
|
387
391
|
|
388
392
|
production = ProductionNode.new( beta, actions )
|
389
|
-
production.
|
393
|
+
production.refresh
|
390
394
|
production
|
391
395
|
end
|
392
396
|
|
data/lib/wongi-engine/token.rb
CHANGED
@@ -19,7 +19,6 @@ module Wongi::Engine
|
|
19
19
|
@opt_join_results = []
|
20
20
|
@ncc_results = []
|
21
21
|
@generated_wmes = []
|
22
|
-
@deexecutors = []
|
23
22
|
token.children << self if token
|
24
23
|
wme.tokens << self if wme
|
25
24
|
end
|
@@ -48,51 +47,21 @@ module Wongi::Engine
|
|
48
47
|
|
49
48
|
def wmes
|
50
49
|
if parent
|
51
|
-
parent.wmes + [wme]
|
50
|
+
parent.wmes + (wme ? [wme] : [])
|
52
51
|
else
|
53
|
-
[wme]
|
52
|
+
wme ? [wme] : []
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
def delete
|
56
|
+
def delete
|
58
57
|
delete_children
|
59
|
-
|
60
|
-
@node.tokens.delete self unless preserve_self# or @node.kind_of?( NccPartner )
|
58
|
+
@node.tokens.delete self unless @node.kind_of?( NccPartner )
|
61
59
|
@wme.tokens.delete self if @wme
|
62
60
|
@parent.children.delete self if @parent
|
63
61
|
|
64
62
|
retract_generated
|
65
|
-
deexecute
|
66
|
-
|
67
|
-
case @node
|
68
|
-
when NegNode
|
69
|
-
@neg_join_results.each do |njr|
|
70
|
-
njr.wme.neg_join_results.delete njr if njr.wme
|
71
|
-
end
|
72
|
-
@neg_join_results = []
|
73
|
-
|
74
|
-
when OptionalNode
|
75
|
-
@opt_join_results.each do |ojr|
|
76
|
-
ojr.wme.opt_join_results.delete ojr
|
77
|
-
end
|
78
|
-
@opt_join_results = []
|
79
|
-
|
80
|
-
when NccNode
|
81
|
-
@ncc_results.each do |nccr|
|
82
|
-
nccr.wme.tokens.delete nccr
|
83
|
-
nccr.parent.children.delete nccr
|
84
|
-
end
|
85
|
-
@ncc_results = []
|
86
|
-
|
87
|
-
when NccPartner
|
88
|
-
@owner.ncc_results.delete self
|
89
|
-
if @owner.ncc_results.empty?
|
90
|
-
@node.ncc.children.each do |node|
|
91
|
-
node.left_activate @owner, nil, {}
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
63
|
|
64
|
+
@node.delete_token self
|
96
65
|
end
|
97
66
|
|
98
67
|
def delete_children
|
@@ -118,11 +87,6 @@ module Wongi::Engine
|
|
118
87
|
|
119
88
|
end
|
120
89
|
|
121
|
-
def deexecute
|
122
|
-
@deexecutors.each { |deexec| deexec.deexecute self }
|
123
|
-
@deexecutors = []
|
124
|
-
end
|
125
|
-
|
126
90
|
def all_assignments
|
127
91
|
raise "Assignments is not a hash" unless @assignments.kind_of?( Hash )
|
128
92
|
if @parent
|
data/lib/wongi-engine/version.rb
CHANGED
data/lib/wongi-engine/wme.rb
CHANGED
@@ -57,7 +57,7 @@ module Wongi::Engine
|
|
57
57
|
|
58
58
|
alphas.each { |alpha| alpha.remove self }.clear
|
59
59
|
while tokens.first
|
60
|
-
tokens.first.delete
|
60
|
+
tokens.first.delete # => will remove itself from the array
|
61
61
|
end
|
62
62
|
|
63
63
|
destroy_neg_join_results
|
@@ -90,9 +90,9 @@ module Wongi::Engine
|
|
90
90
|
results = token.neg_join_results
|
91
91
|
results.delete njr
|
92
92
|
|
93
|
-
if results.empty?
|
93
|
+
if results.empty? #&& !rete.in_snapshot?
|
94
94
|
token.node.children.each { |beta|
|
95
|
-
beta.
|
95
|
+
beta.beta_activate token, nil, { }
|
96
96
|
}
|
97
97
|
end
|
98
98
|
|
@@ -109,7 +109,7 @@ module Wongi::Engine
|
|
109
109
|
if results.empty?
|
110
110
|
token.delete_children
|
111
111
|
token.node.children.each { |beta|
|
112
|
-
beta.
|
112
|
+
beta.beta_activate token
|
113
113
|
}
|
114
114
|
end
|
115
115
|
|
data/lib/wongi-engine.rb
CHANGED
@@ -14,6 +14,7 @@ require 'wongi-engine/template'
|
|
14
14
|
require 'wongi-engine/wme'
|
15
15
|
require 'wongi-engine/wme_match_data'
|
16
16
|
require 'wongi-engine/token'
|
17
|
+
require 'wongi-engine/filter'
|
17
18
|
require 'wongi-engine/alpha_memory'
|
18
19
|
require 'wongi-engine/beta'
|
19
20
|
require 'wongi-engine/dsl'
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "ASSERT test" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@engine = Wongi::Engine.create
|
7
|
+
end
|
8
|
+
|
9
|
+
def engine
|
10
|
+
@engine
|
11
|
+
end
|
12
|
+
|
13
|
+
def production
|
14
|
+
@production
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_rule &block
|
18
|
+
@production = ( engine << rule( 'test-rule', &block ) )
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should pass with a constant 'true'" do
|
22
|
+
|
23
|
+
test_rule {
|
24
|
+
forall {
|
25
|
+
assert { |token|
|
26
|
+
true
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
production.should have(1).tokens
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should fail with a constant 'false'" do
|
36
|
+
|
37
|
+
test_rule {
|
38
|
+
forall {
|
39
|
+
assert { |token|
|
40
|
+
false
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
production.should have(0).tokens
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should use the token with no arguments" do
|
50
|
+
|
51
|
+
test_rule {
|
52
|
+
forall {
|
53
|
+
has :X, "is", :Y
|
54
|
+
assert { |token|
|
55
|
+
token[:X] == "resistance"
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
engine << ["resistance", "is", "futile"]
|
61
|
+
|
62
|
+
production.should have(1).tokens
|
63
|
+
production.tokens.first[:X].should == "resistance"
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should use individual variables with arguments" do
|
68
|
+
|
69
|
+
test_rule {
|
70
|
+
forall {
|
71
|
+
has :X, "is", :Y
|
72
|
+
assert :X, :Y do |x, y|
|
73
|
+
y == "futile"
|
74
|
+
end
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
engine << ["resistance", "is", "futile"]
|
79
|
+
|
80
|
+
production.should have(1).tokens
|
81
|
+
production.tokens.first[:X].should == "resistance"
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/spec/high_level_spec.rb
CHANGED
@@ -178,63 +178,7 @@ describe 'the engine' do
|
|
178
178
|
rete.results["test-query"].tokens.first[:Y].should == 42
|
179
179
|
|
180
180
|
end
|
181
|
-
|
182
|
-
it 'should support negative subnets' do
|
183
|
-
|
184
|
-
production = (rete << rule('ncc') {
|
185
|
-
forall {
|
186
|
-
has "base", "is", :Base
|
187
|
-
none {
|
188
|
-
has :Base, 2, :X
|
189
|
-
has :X, 4, 5
|
190
|
-
}
|
191
|
-
}
|
192
|
-
})
|
193
|
-
|
194
|
-
rete << ["base", "is", 1]
|
195
|
-
|
196
|
-
production.should have(1).tokens
|
197
|
-
|
198
|
-
rete << [1, 2, 3]
|
199
|
-
|
200
|
-
production.should have(1).tokens
|
201
|
-
|
202
|
-
rete << [3, 4, 5]
|
203
|
-
|
204
|
-
production.should have(0).tokens
|
205
|
-
|
206
|
-
rete << ["base", "is", 2]
|
207
|
-
|
208
|
-
production.should have(1).tokens
|
209
|
-
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'should support optional matches' do
|
213
|
-
|
214
|
-
production = (rete << rule('optional') {
|
215
|
-
forall {
|
216
|
-
has "answer", "is", :Answer
|
217
|
-
maybe :Answer, "is", :Kind
|
218
|
-
}
|
219
|
-
})
|
220
|
-
|
221
|
-
rete << ["answer", "is", 42]
|
222
|
-
rete << ["answer", "is", 43]
|
223
|
-
rete << [42, "is", "canonical"]
|
224
|
-
|
225
|
-
production.should have(2).tokens
|
226
|
-
|
227
|
-
canon = production.tokens.select { |token| not token[:Kind].nil? }
|
228
|
-
canon.should have(1).items
|
229
|
-
canon.first[:Answer].should == 42
|
230
|
-
canon.first[:Kind].should == "canonical"
|
231
|
-
|
232
|
-
non_canon = production.tokens.select { |token| token[:Kind].nil? }
|
233
|
-
non_canon.should have(1).items
|
234
|
-
non_canon.first[:Answer].should == 43
|
235
|
-
|
236
|
-
end
|
237
|
-
|
181
|
+
|
238
182
|
context 'with timelines' do
|
239
183
|
|
240
184
|
it 'should not match with no past point' do
|
@@ -282,7 +226,7 @@ describe 'the engine' do
|
|
282
226
|
rete.snapshot!
|
283
227
|
rete << [1, 2, 3]
|
284
228
|
production.should have(1).tokens
|
285
|
-
puts count
|
229
|
+
#puts count
|
286
230
|
end
|
287
231
|
|
288
232
|
it 'should not match kept items' do
|
@@ -297,7 +241,7 @@ describe 'the engine' do
|
|
297
241
|
production.should have(1).tokens
|
298
242
|
rete.snapshot!
|
299
243
|
production.should have(0).tokens
|
300
|
-
puts count
|
244
|
+
#puts count
|
301
245
|
end
|
302
246
|
|
303
247
|
end
|
@@ -316,7 +260,7 @@ describe 'the engine' do
|
|
316
260
|
production.should have(0).tokens
|
317
261
|
rete.snapshot!
|
318
262
|
production.should have(1).tokens
|
319
|
-
puts count
|
263
|
+
#puts count
|
320
264
|
end
|
321
265
|
|
322
266
|
it 'should not match asserted wmes' do
|
@@ -331,7 +275,7 @@ describe 'the engine' do
|
|
331
275
|
rete.snapshot!
|
332
276
|
rete << [1, 2, 3]
|
333
277
|
production.should have(0).tokens
|
334
|
-
puts count
|
278
|
+
#puts count
|
335
279
|
end
|
336
280
|
|
337
281
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "ANY rule" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@engine = Wongi::Engine.create
|
7
|
+
end
|
8
|
+
|
9
|
+
def engine
|
10
|
+
@engine
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with just one option" do
|
14
|
+
|
15
|
+
it "should act like a positive matcher" do
|
16
|
+
|
17
|
+
engine << rule('one-option') {
|
18
|
+
forall {
|
19
|
+
any {
|
20
|
+
option {
|
21
|
+
has 1, 2, :X
|
22
|
+
has :X, 4, 5
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
production = engine.productions['one-option']
|
29
|
+
|
30
|
+
engine << [1, 2, 3]
|
31
|
+
engine << [3, 4, 5]
|
32
|
+
|
33
|
+
production.should have(1).tokens
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with several options" do
|
40
|
+
|
41
|
+
specify "all matching branches must pass" do
|
42
|
+
|
43
|
+
engine << rule('two-options') {
|
44
|
+
forall {
|
45
|
+
has 1, 2, :X
|
46
|
+
any {
|
47
|
+
option {
|
48
|
+
has :X, 4, 5
|
49
|
+
}
|
50
|
+
option {
|
51
|
+
has :X, "four", "five"
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
make {
|
56
|
+
collect :X, :threes
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
production = engine.productions['two-options']
|
61
|
+
|
62
|
+
engine << [1, 2, 3]
|
63
|
+
engine << [3, 4, 5]
|
64
|
+
engine << [1, 2, "three"]
|
65
|
+
engine << ["three", "four", "five"]
|
66
|
+
|
67
|
+
production.should have(2).tokens
|
68
|
+
engine.collection(:threes).should include(3)
|
69
|
+
engine.collection(:threes).should include("three")
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "ASSIGN rule" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@engine = Wongi::Engine.create
|
7
|
+
end
|
8
|
+
|
9
|
+
def engine
|
10
|
+
@engine
|
11
|
+
end
|
12
|
+
|
13
|
+
def production
|
14
|
+
@production
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_rule &block
|
18
|
+
@production = ( engine << rule( 'test-rule', &block ) )
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should assign simple expressions" do
|
22
|
+
|
23
|
+
test_rule {
|
24
|
+
forall {
|
25
|
+
assign :X do
|
26
|
+
42
|
27
|
+
end
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
production.should have(1).tokens
|
32
|
+
production.tokens.first[:X].should == 42
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to access previous assignments" do
|
37
|
+
|
38
|
+
test_rule {
|
39
|
+
forall {
|
40
|
+
has 1, 2, :X
|
41
|
+
assign :Y do |token|
|
42
|
+
token[:X] * 2
|
43
|
+
end
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
engine << [1, 2, 5]
|
48
|
+
production.tokens.first[:Y].should == 10
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|