wongi-engine 0.3.5 → 0.3.7
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +80 -0
- data/.travis.yml +8 -15
- data/Gemfile +4 -0
- data/README.md +3 -3
- data/Rakefile +1 -2
- data/examples/ex01.rb +1 -1
- data/examples/ex02.rb +3 -7
- data/examples/graphviz.rb +1 -1
- data/examples/rdf.rb +1 -1
- data/examples/timeline.rb +6 -6
- data/lib/wongi-engine/alpha_memory.rb +5 -9
- data/lib/wongi-engine/beta/aggregate_node.rb +93 -0
- data/lib/wongi-engine/beta/assignment_node.rb +10 -18
- data/lib/wongi-engine/beta/beta_memory.rb +20 -9
- data/lib/wongi-engine/beta/beta_node.rb +14 -22
- data/lib/wongi-engine/beta/filter_node.rb +12 -15
- data/lib/wongi-engine/beta/join_node.rb +47 -61
- data/lib/wongi-engine/beta/ncc_node.rb +17 -20
- data/lib/wongi-engine/beta/ncc_partner.rb +17 -17
- data/lib/wongi-engine/beta/neg_node.rb +37 -37
- data/lib/wongi-engine/beta/optional_node.rb +53 -60
- data/lib/wongi-engine/beta/or_node.rb +6 -9
- data/lib/wongi-engine/beta/production_node.rb +6 -9
- data/lib/wongi-engine/beta.rb +1 -0
- data/lib/wongi-engine/compiler.rb +38 -22
- data/lib/wongi-engine/core_ext.rb +11 -20
- data/lib/wongi-engine/data_overlay.rb +23 -26
- data/lib/wongi-engine/dsl/action/assign_action.rb +1 -1
- data/lib/wongi-engine/dsl/action/base.rb +1 -4
- data/lib/wongi-engine/dsl/action/error_generator.rb +9 -9
- data/lib/wongi-engine/dsl/action/simple_action.rb +14 -10
- data/lib/wongi-engine/dsl/action/simple_collector.rb +10 -25
- data/lib/wongi-engine/dsl/action/statement_generator.rb +15 -14
- data/lib/wongi-engine/dsl/action/trace_action.rb +9 -9
- data/lib/wongi-engine/dsl/any_rule.rb +16 -20
- data/lib/wongi-engine/dsl/assuming.rb +8 -15
- data/lib/wongi-engine/dsl/builder.rb +13 -12
- data/lib/wongi-engine/dsl/clause/aggregate.rb +21 -0
- data/lib/wongi-engine/dsl/clause/assign.rb +4 -4
- data/lib/wongi-engine/dsl/clause/fact.rb +10 -6
- data/lib/wongi-engine/dsl/clause/gen.rb +3 -5
- data/lib/wongi-engine/dsl/clause/generic.rb +7 -9
- data/lib/wongi-engine/dsl/generated.rb +6 -12
- data/lib/wongi-engine/dsl/ncc_subrule.rb +6 -9
- data/lib/wongi-engine/dsl/query.rb +12 -15
- data/lib/wongi-engine/dsl/rule.rb +45 -50
- data/lib/wongi-engine/dsl.rb +30 -16
- data/lib/wongi-engine/enumerators.rb +2 -1
- data/lib/wongi-engine/error.rb +6 -7
- data/lib/wongi-engine/filter/asserting_test.rb +4 -7
- data/lib/wongi-engine/filter/equality_test.rb +15 -18
- data/lib/wongi-engine/filter/filter_test.rb +3 -6
- data/lib/wongi-engine/filter/greater_than_or_equal_test.rb +5 -2
- data/lib/wongi-engine/filter/greater_than_test.rb +15 -18
- data/lib/wongi-engine/filter/inequality_test.rb +15 -18
- data/lib/wongi-engine/filter/less_than_or_equal_test.rb +5 -2
- data/lib/wongi-engine/filter/less_than_test.rb +15 -18
- data/lib/wongi-engine/filter.rb +1 -1
- data/lib/wongi-engine/graph.rb +13 -20
- data/lib/wongi-engine/network/collectable.rb +10 -14
- data/lib/wongi-engine/network/debug.rb +16 -24
- data/lib/wongi-engine/network.rb +110 -129
- data/lib/wongi-engine/ruleset.rb +18 -20
- data/lib/wongi-engine/template.rb +31 -30
- data/lib/wongi-engine/token.rb +33 -33
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine/wme.rb +17 -23
- data/lib/wongi-engine/wme_match_data.rb +5 -9
- data/lib/wongi-engine.rb +0 -4
- data/spec/action_class_spec.rb +43 -49
- data/spec/beta_node_spec.rb +2 -8
- data/spec/bug_specs/issue_4_spec.rb +12 -20
- data/spec/dataset_spec.rb +3 -6
- data/spec/filter_specs/assert_test_spec.rb +12 -31
- data/spec/filter_specs/greater_than_equality_test_spec.rb +2 -5
- data/spec/filter_specs/less_test_spec.rb +7 -17
- data/spec/filter_specs/less_than_equality_test_spec.rb +3 -6
- data/spec/generation_spec.rb +45 -54
- data/spec/high_level_spec.rb +95 -141
- data/spec/network_spec.rb +77 -68
- data/spec/overlay_spec.rb +4 -5
- data/spec/rule_specs/aggregate_spec.rb +197 -0
- data/spec/rule_specs/any_rule_spec.rb +73 -19
- data/spec/rule_specs/assign_spec.rb +10 -16
- data/spec/rule_specs/assuming_spec.rb +10 -17
- data/spec/rule_specs/maybe_rule_spec.rb +4 -15
- data/spec/rule_specs/ncc_spec.rb +48 -65
- data/spec/rule_specs/negative_rule_spec.rb +13 -27
- data/spec/rule_specs/or_rule_spec.rb +3 -13
- data/spec/ruleset_spec.rb +11 -17
- data/spec/simple_action_spec.rb +4 -14
- data/spec/wme_spec.rb +14 -21
- data/wongi-engine.gemspec +22 -22
- metadata +19 -41
- data/.hgignore +0 -7
- data/spec/dsl_spec.rb +0 -9
@@ -1,29 +1,27 @@
|
|
1
1
|
module Wongi
|
2
2
|
module Engine
|
3
3
|
class OrNode < BetaMemory
|
4
|
+
attr_reader :parents, :rete
|
4
5
|
|
5
|
-
|
6
|
-
attr_reader :rete
|
7
|
-
|
8
|
-
def initialize parents
|
6
|
+
def initialize(parents)
|
9
7
|
super nil
|
10
8
|
@parents = parents
|
11
9
|
parents.each do |parent|
|
12
10
|
parent.children << self
|
13
11
|
end
|
14
|
-
retes = parents.map(
|
12
|
+
retes = parents.map(&:rete).uniq
|
15
13
|
raise "Cannot combine variants from several Retes" if retes.size > 1
|
14
|
+
|
16
15
|
@rete = retes.first
|
17
16
|
end
|
18
17
|
|
19
18
|
def ident
|
20
|
-
ids = parents.map(
|
19
|
+
ids = parents.map(&:id).join ", "
|
21
20
|
"<R> #{self.class} #{id}, parents #{ids}"
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
23
|
def depth
|
26
|
-
parents.map(
|
24
|
+
parents.map(&:depth).max + 1
|
27
25
|
end
|
28
26
|
|
29
27
|
def refresh
|
@@ -31,7 +29,6 @@ module Wongi
|
|
31
29
|
parent.refresh_child self
|
32
30
|
end
|
33
31
|
end
|
34
|
-
|
35
32
|
end
|
36
33
|
end
|
37
34
|
end
|
@@ -1,31 +1,28 @@
|
|
1
1
|
module Wongi
|
2
2
|
module Engine
|
3
|
-
|
4
3
|
class ProductionNode < BetaMemory
|
4
|
+
attr_accessor :tracer, :compilation_context
|
5
5
|
|
6
|
-
|
7
|
-
attr_accessor :compilation_context
|
8
|
-
|
9
|
-
def initialize parent, actions
|
6
|
+
def initialize(parent, actions)
|
10
7
|
super(parent)
|
11
8
|
@actions = actions.each { |action| action.production = self }
|
12
9
|
end
|
13
10
|
|
14
|
-
def beta_activate
|
11
|
+
def beta_activate(token)
|
15
12
|
return unless super
|
13
|
+
|
16
14
|
@actions.each do |action|
|
17
15
|
action.execute token if action.respond_to? :execute
|
18
16
|
end
|
19
17
|
end
|
20
18
|
|
21
|
-
def beta_deactivate
|
19
|
+
def beta_deactivate(token)
|
22
20
|
return unless super
|
21
|
+
|
23
22
|
@actions.each do |action|
|
24
23
|
action.deexecute token if action.respond_to? :deexecute
|
25
24
|
end
|
26
25
|
end
|
27
|
-
|
28
26
|
end
|
29
|
-
|
30
27
|
end
|
31
28
|
end
|
data/lib/wongi-engine/beta.rb
CHANGED
@@ -3,6 +3,7 @@ require 'wongi-engine/beta/beta_memory'
|
|
3
3
|
require 'wongi-engine/beta/filter_node'
|
4
4
|
require 'wongi-engine/beta/assignment_node'
|
5
5
|
require 'wongi-engine/beta/join_node'
|
6
|
+
require 'wongi-engine/beta/aggregate_node'
|
6
7
|
require 'wongi-engine/beta/ncc_partner'
|
7
8
|
require 'wongi-engine/beta/ncc_node'
|
8
9
|
require 'wongi-engine/beta/neg_node'
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
Compiler = Struct.new(:rete, :node, :conditions, :parameters, :alpha_deaf) do
|
3
|
-
|
4
3
|
def compile
|
5
4
|
conditions.inject(self) do |context, condition|
|
6
5
|
condition.compile context
|
@@ -12,9 +11,7 @@ module Wongi::Engine
|
|
12
11
|
end
|
13
12
|
|
14
13
|
def declare(v)
|
15
|
-
unless declared_variables.include?(v)
|
16
|
-
declared_variables << v
|
17
|
-
end
|
14
|
+
declared_variables << v unless declared_variables.include?(v)
|
18
15
|
end
|
19
16
|
|
20
17
|
def declared_variables
|
@@ -31,32 +28,41 @@ module Wongi::Engine
|
|
31
28
|
|
32
29
|
def beta_memory
|
33
30
|
return if node.is_a?(BetaMemory)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
|
32
|
+
self.node = if (existing = node.children.find { |n| n.is_a?(BetaMemory) })
|
33
|
+
existing
|
34
|
+
else
|
35
|
+
BetaMemory.new(node).tap(&:refresh)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def singleton_beta_memory
|
40
|
+
return if node.is_a?(SingletonBetaMemory)
|
41
|
+
|
42
|
+
self.node = if (existing = node.children.find { |n| n.is_a?(SingletonBetaMemory) })
|
43
|
+
existing
|
44
|
+
else
|
45
|
+
SingletonBetaMemory.new(node).tap(&:refresh)
|
46
|
+
end
|
41
47
|
end
|
42
48
|
|
43
49
|
def assignment_node(variable, body)
|
44
50
|
beta_memory
|
45
|
-
self.node = AssignmentNode.new(
|
51
|
+
self.node = AssignmentNode.new(node, variable, body).tap(&:refresh)
|
46
52
|
declare(variable)
|
47
53
|
end
|
48
54
|
|
49
55
|
def join_node(condition, tests, assignment)
|
50
56
|
alpha = rete.compile_alpha(condition)
|
51
57
|
beta_memory
|
52
|
-
self.node = if existing = node.children.find { |n| n.is_a?(JoinNode) && n.equivalent?(alpha, tests, assignment) }
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
self.node = if (existing = node.children.find { |n| n.is_a?(JoinNode) && n.equivalent?(alpha, tests, assignment) && !n.children.map(&:class).include?(Wongi::Engine::OrNode) })
|
59
|
+
existing
|
60
|
+
else
|
61
|
+
JoinNode.new(node, tests, assignment).tap do |join|
|
62
|
+
join.alpha = alpha
|
63
|
+
alpha.betas << join unless alpha_deaf
|
64
|
+
end
|
65
|
+
end
|
60
66
|
end
|
61
67
|
|
62
68
|
def neg_node(condition, tests, unsafe)
|
@@ -75,6 +81,16 @@ module Wongi::Engine
|
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
84
|
+
def aggregate_node(condition, tests, assignment, map, function, assign)
|
85
|
+
declare(assign)
|
86
|
+
alpha = rete.compile_alpha(condition)
|
87
|
+
beta_memory
|
88
|
+
self.node = AggregateNode.new(node, alpha, tests, assignment, map, function, assign).tap do |node|
|
89
|
+
alpha.betas << node unless alpha_deaf
|
90
|
+
end
|
91
|
+
beta_memory
|
92
|
+
end
|
93
|
+
|
78
94
|
def or_node(variants)
|
79
95
|
beta_memory
|
80
96
|
subvariables = []
|
@@ -90,7 +106,7 @@ module Wongi::Engine
|
|
90
106
|
declare(v)
|
91
107
|
end
|
92
108
|
end
|
93
|
-
self.node = OrNode.new(branches).tap
|
109
|
+
self.node = OrNode.new(branches).tap(&:refresh)
|
94
110
|
end
|
95
111
|
|
96
112
|
def ncc_node(subrule, alpha_deaf)
|
@@ -98,7 +114,7 @@ module Wongi::Engine
|
|
98
114
|
subcompiler = Compiler.new(rete, node, subrule.conditions, parameters, alpha_deaf)
|
99
115
|
declared_variables.each { |v| subcompiler.declare(v) }
|
100
116
|
bottom = subcompiler.compile
|
101
|
-
if existing = node.children.find { |n| n.
|
117
|
+
if (existing = node.children.find { |n| n.is_a?(NccNode) && n.partner.parent == bottom })
|
102
118
|
self.node = existing
|
103
119
|
return
|
104
120
|
end
|
@@ -1,13 +1,9 @@
|
|
1
1
|
module Wongi::Engine
|
2
|
-
|
3
2
|
module CoreExt
|
4
|
-
|
5
3
|
module ClassMethods
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
names_hash = names.inject( {} ) do |hash, element|
|
10
|
-
if Hash === element
|
4
|
+
def attr_predicate(*names)
|
5
|
+
names_hash = names.inject({}) do |hash, element|
|
6
|
+
if element.is_a?(Hash)
|
11
7
|
hash.merge element
|
12
8
|
else
|
13
9
|
hash[element] = false
|
@@ -16,7 +12,6 @@ module Wongi::Engine
|
|
16
12
|
end
|
17
13
|
|
18
14
|
names_hash.each do |name, def_value|
|
19
|
-
|
20
15
|
varname = "@#{name}".to_sym
|
21
16
|
predname = "#{name}?".to_sym
|
22
17
|
setname = "#{name}=".to_sym
|
@@ -24,40 +19,36 @@ module Wongi::Engine
|
|
24
19
|
noexclname = "no_#{name}!".to_sym
|
25
20
|
|
26
21
|
define_method predname do
|
27
|
-
if instance_variable_defined?(
|
28
|
-
instance_variable_get(
|
22
|
+
if instance_variable_defined?(varname)
|
23
|
+
instance_variable_get(varname)
|
29
24
|
else
|
30
25
|
def_value
|
31
26
|
end
|
32
27
|
end
|
33
28
|
|
34
29
|
define_method setname do |newvalue|
|
35
|
-
instance_variable_set(
|
30
|
+
instance_variable_set(varname, newvalue == true)
|
36
31
|
end
|
37
32
|
|
38
33
|
define_method exclname do
|
39
|
-
instance_variable_set(
|
34
|
+
instance_variable_set(varname, true)
|
40
35
|
end
|
41
36
|
|
42
37
|
define_method noexclname do
|
43
|
-
instance_variable_set(
|
38
|
+
instance_variable_set(varname, false)
|
44
39
|
end
|
45
|
-
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
49
|
-
def abstract
|
50
|
-
define_method name do |*
|
43
|
+
def abstract(name)
|
44
|
+
define_method name do |*_args|
|
51
45
|
raise NoMethodError.new "#{name} is not implemented for #{self.class.name}", name
|
52
46
|
end
|
53
47
|
end
|
54
|
-
|
55
48
|
end
|
56
49
|
|
57
|
-
def self.included
|
50
|
+
def self.included(mod)
|
58
51
|
mod.extend ClassMethods
|
59
52
|
end
|
60
|
-
|
61
53
|
end
|
62
|
-
|
63
54
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
class DataOverlay
|
3
|
-
|
4
|
-
attr_reader :rete
|
5
|
-
attr_reader :parent
|
3
|
+
attr_reader :rete, :parent
|
6
4
|
|
7
5
|
def initialize(rete, parent = nil)
|
8
6
|
@rete = rete
|
@@ -18,26 +16,26 @@ module Wongi::Engine
|
|
18
16
|
|
19
17
|
def with_child
|
20
18
|
return unless block_given?
|
19
|
+
|
21
20
|
new_child.tap do |overlay|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
overlay.dispose
|
26
|
-
end
|
27
|
-
result
|
21
|
+
yield overlay
|
22
|
+
ensure
|
23
|
+
overlay.dispose
|
28
24
|
end
|
29
25
|
end
|
30
26
|
|
31
27
|
def ancestor?(other)
|
32
28
|
return false if parent.nil?
|
33
29
|
return true if parent == other
|
30
|
+
|
34
31
|
parent.ancestor?(other)
|
35
32
|
end
|
36
33
|
|
37
34
|
def dispose
|
38
35
|
return if self == rete.default_overlay
|
36
|
+
|
39
37
|
rete.remove_overlay(self)
|
40
|
-
@raw_tokens.
|
38
|
+
@raw_tokens.each_value do |tokens|
|
41
39
|
tokens.each(&:dispose!)
|
42
40
|
end
|
43
41
|
@raw_tokens.clear
|
@@ -46,7 +44,7 @@ module Wongi::Engine
|
|
46
44
|
def <<(thing)
|
47
45
|
case thing
|
48
46
|
when Array
|
49
|
-
assert
|
47
|
+
assert(WME.new(*thing).tap { |wme| wme.overlay = self })
|
50
48
|
when WME
|
51
49
|
assert(thing)
|
52
50
|
else
|
@@ -54,27 +52,25 @@ module Wongi::Engine
|
|
54
52
|
end
|
55
53
|
end
|
56
54
|
|
57
|
-
def assert
|
55
|
+
def assert(wme)
|
58
56
|
@next_cascade ||= []
|
59
57
|
@next_cascade << [:assert, wme]
|
60
|
-
if @current_cascade
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
58
|
+
return if @current_cascade
|
59
|
+
|
60
|
+
@current_cascade = @next_cascade
|
61
|
+
@next_cascade = nil
|
62
|
+
process_cascade
|
65
63
|
end
|
66
64
|
|
67
|
-
def retract
|
68
|
-
if wme.is_a? Array
|
69
|
-
wme = WME.new(*wme)
|
70
|
-
end
|
65
|
+
def retract(wme, options = {})
|
66
|
+
wme = WME.new(*wme) if wme.is_a? Array
|
71
67
|
@next_cascade ||= []
|
72
68
|
@next_cascade << [:retract, wme, options]
|
73
|
-
if @current_cascade
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
return if @current_cascade
|
70
|
+
|
71
|
+
@current_cascade = @next_cascade
|
72
|
+
@next_cascade = nil
|
73
|
+
process_cascade
|
78
74
|
end
|
79
75
|
|
80
76
|
def process_cascade
|
@@ -99,6 +95,7 @@ module Wongi::Engine
|
|
99
95
|
return self if other.nil?
|
100
96
|
return self if ancestor?(other)
|
101
97
|
return other if other.ancestor?(self)
|
98
|
+
|
102
99
|
nil # unrelated lineages
|
103
100
|
end
|
104
101
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Action
|
3
3
|
class ErrorGenerator < Base
|
4
|
-
|
5
|
-
|
6
|
-
@message
|
4
|
+
def initialize(message = nil, &messenger)
|
5
|
+
super()
|
6
|
+
@message = message
|
7
|
+
@messenger = messenger
|
7
8
|
end
|
8
9
|
|
9
10
|
def rete=(*)
|
@@ -14,18 +15,17 @@ module Wongi::Engine
|
|
14
15
|
def errors
|
15
16
|
production.tokens.map do |token|
|
16
17
|
message = if @messenger
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
@messenger.call token.assignments
|
19
|
+
else
|
20
|
+
@message
|
21
|
+
end
|
21
22
|
ReteError.new token, message, literate?
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
26
|
def literate?
|
26
|
-
|
27
|
+
!@messenger.nil?
|
27
28
|
end
|
28
|
-
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -1,22 +1,24 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Action
|
3
3
|
class SimpleAction < Base
|
4
|
-
def initialize
|
4
|
+
def initialize(action = nil, *args, &block)
|
5
|
+
super()
|
5
6
|
@args = args
|
6
7
|
case action
|
7
8
|
when Class
|
8
|
-
@action = @deaction = @reaction = action.new
|
9
|
+
@action = @deaction = @reaction = action.new(*args, &block)
|
9
10
|
when Hash
|
10
|
-
@action
|
11
|
+
@action = instance_or_proc action[:activate]
|
11
12
|
@deaction = instance_or_proc action[:deactivate]
|
12
13
|
@reaction = instance_or_proc action[:reactivate]
|
13
14
|
end
|
14
15
|
@action ||= block
|
15
16
|
end
|
16
17
|
|
17
|
-
def execute
|
18
|
+
def execute(token)
|
18
19
|
return unless @action
|
19
|
-
|
20
|
+
|
21
|
+
if @action.is_a?(Proc) || @action.respond_to?(:to_proc)
|
20
22
|
rete.instance_exec token, &@action
|
21
23
|
elsif @action.respond_to? :call
|
22
24
|
@action.call token
|
@@ -25,9 +27,10 @@ module Wongi::Engine
|
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
def deexecute
|
30
|
+
def deexecute(token)
|
29
31
|
return unless @deaction
|
30
|
-
|
32
|
+
|
33
|
+
if @deaction.is_a?(Proc) || @deaction.respond_to?(:to_proc)
|
31
34
|
rete.instance_exec token, &@deaction
|
32
35
|
elsif @deaction.respond_to? :call
|
33
36
|
@deaction.call token
|
@@ -36,9 +39,10 @@ module Wongi::Engine
|
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
39
|
-
def reexecute
|
42
|
+
def reexecute(token, newtoken)
|
40
43
|
return unless @reaction
|
41
|
-
|
44
|
+
|
45
|
+
if @reaction.is_a?(Proc) || @reaction.respond_to?(:to_proc)
|
42
46
|
rete.instance_exec token, newtoken, &@reaction
|
43
47
|
elsif @reaction.respond_to? :call
|
44
48
|
@reaction.call token, newtoken
|
@@ -47,7 +51,7 @@ module Wongi::Engine
|
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
50
|
-
def instance_or_proc
|
54
|
+
def instance_or_proc(thing)
|
51
55
|
case thing
|
52
56
|
when Class
|
53
57
|
thing.new
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Action
|
3
3
|
class SimpleCollector < Base
|
4
|
-
|
5
4
|
def self.collector
|
6
5
|
Class.new self
|
7
6
|
end
|
8
7
|
|
9
|
-
def initialize
|
8
|
+
def initialize(variable, name = nil)
|
9
|
+
super()
|
10
10
|
@variable = variable
|
11
11
|
@name = name if name
|
12
|
-
#(class << self; self; end).instance_eval do
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# (class << self; self; end).instance_eval do
|
13
|
+
# define_method method do
|
14
|
+
# collect variable
|
15
|
+
# end
|
16
16
|
# alias_method method, :default_collect
|
17
17
|
# end
|
18
18
|
end
|
@@ -21,32 +21,17 @@ module Wongi::Engine
|
|
21
21
|
collect @variable
|
22
22
|
end
|
23
23
|
|
24
|
-
def name=
|
25
|
-
@name
|
24
|
+
def name=(n)
|
25
|
+
@name ||= n
|
26
26
|
end
|
27
27
|
|
28
|
-
def rete=
|
28
|
+
def rete=(rete)
|
29
29
|
rete.add_collector self, name
|
30
30
|
end
|
31
31
|
|
32
|
-
def collect
|
32
|
+
def collect(var)
|
33
33
|
production.tokens.map { |token| token[var] }
|
34
34
|
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
class GenericCollectClause
|
39
|
-
|
40
|
-
def initialize name, variable
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
def import_into rete
|
45
|
-
collector = SimpleCollector.new @variable
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
35
|
end
|
50
|
-
|
51
36
|
end
|
52
37
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Action
|
3
3
|
class StatementGenerator < Base
|
4
|
-
|
5
|
-
|
4
|
+
def initialize(template)
|
5
|
+
super()
|
6
6
|
@template = template
|
7
7
|
end
|
8
8
|
|
9
|
-
def execute
|
9
|
+
def execute(token)
|
10
10
|
subject, predicate, object = @template.resolve!(token)
|
11
11
|
|
12
12
|
# link to rete here to ensure proper linking with token
|
@@ -14,10 +14,10 @@ module Wongi::Engine
|
|
14
14
|
wme.manual = false
|
15
15
|
wme.overlay = token.overlay
|
16
16
|
|
17
|
-
production.tracer.trace(
|
18
|
-
if existing = rete.exists?(
|
17
|
+
production.tracer.trace(action: self, wme: wme) if production.tracer
|
18
|
+
if (existing = rete.exists?(wme))
|
19
19
|
generated = existing.generating_tokens.size
|
20
|
-
if generated
|
20
|
+
if generated.positive? && !token.generated_wmes.include?(existing)
|
21
21
|
token.generated_wmes << existing
|
22
22
|
existing.generating_tokens << token
|
23
23
|
end
|
@@ -28,16 +28,17 @@ module Wongi::Engine
|
|
28
28
|
# in order for neg rule invalidation to work
|
29
29
|
wme.overlay.assert wme
|
30
30
|
end
|
31
|
-
|
32
31
|
end
|
33
32
|
|
34
|
-
def deexecute
|
35
|
-
token.generated_wmes.reject(
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
33
|
+
def deexecute(token)
|
34
|
+
generated = token.generated_wmes.reject(&:manual?)
|
35
|
+
|
36
|
+
wmes_for_deletion = generated.each_with_object([]) do |wme, acc|
|
37
|
+
wme.generating_tokens.delete token
|
38
|
+
acc << wme if wme.generating_tokens.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
wmes_for_deletion.each do |wme|
|
41
42
|
wme.overlay.retract wme, automatic: true
|
42
43
|
end
|
43
44
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Action
|
3
3
|
class TraceAction < Base
|
4
|
-
|
5
4
|
class DefaultTracer
|
6
5
|
attr_accessor :action
|
7
|
-
|
6
|
+
|
7
|
+
def trace(args)
|
8
8
|
case args[:action]
|
9
9
|
when TraceAction
|
10
10
|
if args[:token]
|
@@ -19,24 +19,24 @@ module Wongi::Engine
|
|
19
19
|
end
|
20
20
|
|
21
21
|
attr_reader :io
|
22
|
+
|
22
23
|
attr_predicate :generation, :values
|
23
24
|
|
24
|
-
def initialize
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
25
|
+
def initialize(opts = {})
|
26
|
+
super()
|
27
|
+
%i[generation values tracer tracer_class io].each do |option|
|
28
|
+
instance_variable_set "@#{option}", opts[option] if opts.key? option
|
29
29
|
end
|
30
30
|
@io ||= $stdout
|
31
31
|
@tracer ||= (@tracer_class || DefaultTracer).new
|
32
32
|
@tracer.action = self
|
33
33
|
end
|
34
34
|
|
35
|
-
def trace
|
35
|
+
def trace(args)
|
36
36
|
@tracer.trace args
|
37
37
|
end
|
38
38
|
|
39
|
-
def execute
|
39
|
+
def execute(token)
|
40
40
|
production.tracer = self
|
41
41
|
if values?
|
42
42
|
trace action: self, token: token
|