wongi-engine 0.3.8 → 0.4.0.pre.alpha1
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/.github/workflows/test.yml +2 -2
- data/.gitignore +2 -0
- data/README.md +13 -13
- data/lib/wongi-engine/alpha_index.rb +58 -0
- data/lib/wongi-engine/alpha_memory.rb +2 -24
- data/lib/wongi-engine/beta/aggregate_node.rb +16 -15
- data/lib/wongi-engine/beta/assignment_node.rb +7 -2
- data/lib/wongi-engine/beta/beta_node.rb +27 -23
- data/lib/wongi-engine/beta/filter_node.rb +8 -13
- data/lib/wongi-engine/beta/join_node.rb +15 -28
- data/lib/wongi-engine/beta/ncc_node.rb +14 -26
- data/lib/wongi-engine/beta/ncc_partner.rb +18 -18
- data/lib/wongi-engine/beta/neg_node.rb +23 -55
- data/lib/wongi-engine/beta/optional_node.rb +24 -48
- data/lib/wongi-engine/beta/or_node.rb +24 -1
- data/lib/wongi-engine/beta/production_node.rb +9 -3
- data/lib/wongi-engine/beta/root_node.rb +47 -0
- data/lib/wongi-engine/beta.rb +1 -1
- data/lib/wongi-engine/compiler.rb +6 -34
- data/lib/wongi-engine/dsl/action/{base.rb → base_action.rb} +5 -1
- data/lib/wongi-engine/dsl/action/error_generator.rb +1 -1
- data/lib/wongi-engine/dsl/action/simple_action.rb +1 -1
- data/lib/wongi-engine/dsl/action/simple_collector.rb +1 -1
- data/lib/wongi-engine/dsl/action/statement_generator.rb +21 -22
- data/lib/wongi-engine/dsl/action/trace_action.rb +1 -1
- data/lib/wongi-engine/dsl/clause/fact.rb +2 -6
- data/lib/wongi-engine/dsl.rb +1 -25
- data/lib/wongi-engine/graph.rb +1 -1
- data/lib/wongi-engine/network/debug.rb +2 -10
- data/lib/wongi-engine/network.rb +44 -105
- data/lib/wongi-engine/overlay.rb +589 -0
- data/lib/wongi-engine/template.rb +22 -2
- data/lib/wongi-engine/token.rb +10 -26
- data/lib/wongi-engine/token_assignment.rb +15 -0
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine/wme.rb +10 -39
- data/lib/wongi-engine.rb +3 -1
- data/spec/alpha_index_spec.rb +78 -0
- data/spec/bug_specs/issue_4_spec.rb +11 -11
- data/spec/high_level_spec.rb +8 -101
- data/spec/network_spec.rb +8 -6
- data/spec/overlay_spec.rb +177 -1
- data/spec/rule_specs/any_rule_spec.rb +39 -0
- data/spec/rule_specs/assign_spec.rb +1 -1
- data/spec/rule_specs/maybe_rule_spec.rb +58 -1
- data/spec/rule_specs/ncc_spec.rb +78 -19
- data/spec/rule_specs/negative_rule_spec.rb +27 -13
- data/spec/spec_helper.rb +4 -0
- data/spec/wme_spec.rb +0 -32
- metadata +11 -9
- data/lib/wongi-engine/beta/beta_memory.rb +0 -60
- data/lib/wongi-engine/data_overlay.rb +0 -141
- data/spec/rule_specs/or_rule_spec.rb +0 -40
@@ -1,15 +1,8 @@
|
|
1
1
|
module Wongi
|
2
2
|
module Engine
|
3
|
-
NegJoinResult = Struct.new :token, :wme
|
4
|
-
def unlink
|
5
|
-
wme.neg_join_results.delete self
|
6
|
-
token.neg_join_results.delete self
|
7
|
-
end
|
8
|
-
end
|
3
|
+
NegJoinResult = Struct.new :token, :wme
|
9
4
|
|
10
5
|
class NegNode < BetaNode
|
11
|
-
include TokenContainer
|
12
|
-
|
13
6
|
attr_reader :alpha, :tests
|
14
7
|
|
15
8
|
def initialize(parent, tests, alpha, unsafe)
|
@@ -19,79 +12,60 @@ module Wongi
|
|
19
12
|
@unsafe = unsafe
|
20
13
|
end
|
21
14
|
|
22
|
-
def alpha_activate(wme)
|
15
|
+
def alpha_activate(wme, children: self.children)
|
16
|
+
# p alpha_activate: {class: self.class, object_id:, wme:}
|
23
17
|
tokens.each do |token|
|
24
18
|
next unless matches?(token, wme) && (@unsafe || !token.generated?(wme)) # feedback loop protection
|
25
19
|
|
26
20
|
# order matters for proper invalidation
|
27
|
-
|
28
|
-
|
29
|
-
children.each do |child|
|
30
|
-
child.tokens.each do |t|
|
31
|
-
if t.parent == token
|
32
|
-
child.beta_deactivate t
|
33
|
-
# token.destroy
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
21
|
+
overlay.add_neg_join_result(NegJoinResult.new(token, wme))
|
22
|
+
beta_deactivate_children(token: token, children: children)
|
37
23
|
end
|
38
24
|
end
|
39
25
|
|
40
26
|
def alpha_deactivate(wme)
|
41
|
-
|
27
|
+
# p alpha_deactivate: {class: self.class, object_id:, wme:}
|
28
|
+
overlay.neg_join_results_for(wme: wme).each do |njr|
|
42
29
|
tokens.each do |token|
|
43
30
|
next unless token == njr.token
|
44
31
|
|
45
|
-
njr
|
46
|
-
next unless token.
|
32
|
+
overlay.remove_neg_join_result(njr)
|
33
|
+
next unless overlay.neg_join_results_for(token: token).empty?
|
47
34
|
|
48
35
|
children.each do |child|
|
49
|
-
child.beta_activate
|
36
|
+
child.beta_activate(Token.new(child, token, nil))
|
50
37
|
end
|
51
38
|
end
|
52
39
|
end
|
53
40
|
end
|
54
41
|
|
55
42
|
def beta_activate(token)
|
56
|
-
|
43
|
+
# p beta_activate: {class: self.class, object_id:, token:}
|
44
|
+
return if tokens.find { |t| t.duplicate? token }
|
57
45
|
|
58
|
-
|
59
|
-
alpha.
|
60
|
-
|
46
|
+
overlay.add_token(token)
|
47
|
+
select_wmes(alpha.template).each do |wme|
|
48
|
+
overlay.add_neg_join_result(NegJoinResult.new(token, wme)) if matches?(token, wme)
|
61
49
|
end
|
62
|
-
return
|
50
|
+
return if overlay.neg_join_results_for(token: token).any?
|
63
51
|
|
64
52
|
children.each do |child|
|
65
|
-
child.beta_activate
|
53
|
+
child.beta_activate(Token.new(child, token, nil, {}))
|
66
54
|
end
|
67
55
|
end
|
68
56
|
|
69
57
|
def beta_deactivate(token)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
token.deleted!
|
74
|
-
if token.parent
|
75
|
-
token.parent.children.delete token # should this go into Token#destroy?
|
76
|
-
end
|
77
|
-
token.neg_join_results.each(&:unlink)
|
78
|
-
children.each do |child|
|
79
|
-
child.tokens.each do |t|
|
80
|
-
if t.parent == token
|
81
|
-
child.beta_deactivate t
|
82
|
-
# token.destroy
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
token
|
58
|
+
# p beta_deactivate: {class: self.class, object_id:, token:}
|
59
|
+
overlay.remove_token(token)
|
60
|
+
beta_deactivate_children(token: token)
|
87
61
|
end
|
88
62
|
|
89
63
|
def refresh_child(child)
|
90
64
|
tokens.each do |token|
|
91
|
-
child.beta_activate
|
65
|
+
child.beta_activate(Token.new(child, token, nil, {})) if overlay.neg_join_results_for(token: token).empty?
|
92
66
|
end
|
93
|
-
alpha.
|
94
|
-
alpha_activate wme
|
67
|
+
select_wmes(alpha.template).each do |wme|
|
68
|
+
alpha_activate wme, children: [child]
|
95
69
|
end
|
96
70
|
end
|
97
71
|
|
@@ -104,12 +78,6 @@ module Wongi
|
|
104
78
|
end
|
105
79
|
true
|
106
80
|
end
|
107
|
-
|
108
|
-
def make_join_result(token, wme)
|
109
|
-
njr = NegJoinResult.new token, wme
|
110
|
-
token.neg_join_results << njr
|
111
|
-
wme.neg_join_results << njr
|
112
|
-
end
|
113
81
|
end
|
114
82
|
end
|
115
83
|
end
|
@@ -1,15 +1,8 @@
|
|
1
1
|
module Wongi
|
2
2
|
module Engine
|
3
|
-
OptionalJoinResult = Struct.new :token, :wme
|
4
|
-
def unlink
|
5
|
-
wme.opt_join_results.delete self
|
6
|
-
token.opt_join_results.delete self
|
7
|
-
end
|
8
|
-
end
|
3
|
+
OptionalJoinResult = Struct.new :token, :wme
|
9
4
|
|
10
5
|
class OptionalNode < BetaNode
|
11
|
-
include TokenContainer
|
12
|
-
|
13
6
|
attr_reader :alpha, :tests, :assignment_pattern
|
14
7
|
|
15
8
|
def initialize(parent, alpha, tests, assignments)
|
@@ -19,56 +12,51 @@ module Wongi
|
|
19
12
|
@assignment_pattern = assignments
|
20
13
|
end
|
21
14
|
|
22
|
-
def
|
23
|
-
jr = OptionalJoinResult.new token, wme
|
24
|
-
token.opt_join_results << jr
|
25
|
-
wme.opt_join_results << jr
|
26
|
-
end
|
27
|
-
|
28
|
-
def alpha_activate(wme)
|
15
|
+
def alpha_activate(wme, children: self.children)
|
29
16
|
assignments = collect_assignments(wme)
|
30
17
|
tokens.each do |token|
|
31
18
|
next unless matches? token, wme
|
32
19
|
|
20
|
+
optional = overlay.opt_join_results_for(token: token).empty?
|
21
|
+
|
33
22
|
children.each do |child|
|
34
|
-
if
|
35
|
-
|
23
|
+
if optional
|
24
|
+
# we're going to change the optional state so the old ones need to be removed
|
36
25
|
child.tokens.each do |ct|
|
37
26
|
child.beta_deactivate(ct) if ct.parent == token
|
38
27
|
end
|
39
28
|
end
|
40
29
|
child.beta_activate Token.new(child, token, wme, assignments)
|
41
30
|
end
|
42
|
-
|
31
|
+
overlay.add_opt_join_result(OptionalJoinResult.new(token, wme))
|
43
32
|
end
|
44
33
|
end
|
45
34
|
|
46
35
|
def alpha_deactivate(wme)
|
47
|
-
|
36
|
+
# p alpha_deactivate: {wme:}
|
37
|
+
overlay.opt_join_results_for(wme: wme).each do |ojr|
|
48
38
|
tokens.each do |token|
|
49
39
|
next unless token == ojr.token
|
50
40
|
|
51
|
-
ojr
|
52
|
-
next unless token.
|
41
|
+
overlay.remove_opt_join_result(ojr)
|
42
|
+
next unless overlay.opt_join_results_for(token: token).empty?
|
53
43
|
|
54
44
|
children.each do |child|
|
55
45
|
child.tokens.each do |ct|
|
56
46
|
child.beta_deactivate(ct) if ct.parent == token
|
57
47
|
end
|
58
|
-
token.optional!
|
59
48
|
child.beta_activate Token.new(child, token, nil, {})
|
60
49
|
end
|
61
50
|
end
|
62
51
|
end
|
63
52
|
end
|
64
53
|
|
65
|
-
def beta_activate(
|
66
|
-
return if tokens.find { |
|
54
|
+
def beta_activate(token)
|
55
|
+
return if tokens.find { |t| t.duplicate? token }
|
67
56
|
|
68
|
-
|
69
|
-
token.overlay.add_token(token, self)
|
57
|
+
overlay.add_token(token)
|
70
58
|
match = false
|
71
|
-
alpha.
|
59
|
+
select_wmes(alpha.template).each do |wme|
|
72
60
|
assignments = collect_assignments(wme)
|
73
61
|
next unless matches? token, wme
|
74
62
|
|
@@ -80,36 +68,24 @@ module Wongi
|
|
80
68
|
end
|
81
69
|
return if match
|
82
70
|
|
83
|
-
token.optional!
|
84
71
|
children.each do |child|
|
85
72
|
child.beta_activate Token.new(child, token, nil, {})
|
86
73
|
end
|
87
74
|
end
|
88
75
|
|
89
|
-
def beta_deactivate(
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
token.overlay.remove_token(token, self)
|
94
|
-
token.deleted!
|
95
|
-
token.parent.children.delete token if token.parent
|
96
|
-
token.opt_join_results.each(&:unlink)
|
97
|
-
children.each do |child|
|
98
|
-
child.tokens.each do |child_token|
|
99
|
-
child.beta_deactivate(child_token) if child_token.parent == token
|
100
|
-
end
|
101
|
-
end
|
102
|
-
token
|
76
|
+
def beta_deactivate(token)
|
77
|
+
# p beta_deactivate: {class: self.class, object_id:, token:}
|
78
|
+
overlay.remove_token(token)
|
79
|
+
beta_deactivate_children(token: token)
|
103
80
|
end
|
104
81
|
|
105
82
|
def refresh_child(child)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
alpha.
|
110
|
-
alpha_activate wme
|
83
|
+
tokens.each do |token|
|
84
|
+
child.beta_activate(Token.new(child, token, nil, {}))
|
85
|
+
end
|
86
|
+
select_wmes(alpha.template).each do |wme|
|
87
|
+
alpha_activate wme, children: [child]
|
111
88
|
end
|
112
|
-
self.children = tmp
|
113
89
|
end
|
114
90
|
|
115
91
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Wongi
|
2
2
|
module Engine
|
3
|
-
class OrNode <
|
3
|
+
class OrNode < BetaNode
|
4
4
|
attr_reader :parents, :rete
|
5
5
|
|
6
6
|
def initialize(parents)
|
@@ -24,11 +24,34 @@ module Wongi
|
|
24
24
|
parents.map(&:depth).max + 1
|
25
25
|
end
|
26
26
|
|
27
|
+
def beta_activate(token)
|
28
|
+
# p beta_activate: {class: self.class, object_id:, token:}
|
29
|
+
return if tokens.find { token.duplicate?(_1) }
|
30
|
+
|
31
|
+
overlay.add_token(token)
|
32
|
+
|
33
|
+
children.each do |child|
|
34
|
+
child.beta_activate(Token.new(child, token, nil))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def beta_deactivate(token)
|
39
|
+
# p beta_deactivate: {class: self.class, object_id:, token:}
|
40
|
+
overlay.remove_token(token)
|
41
|
+
beta_deactivate_children(token: token)
|
42
|
+
end
|
43
|
+
|
27
44
|
def refresh
|
28
45
|
parents.each do |parent|
|
29
46
|
parent.refresh_child self
|
30
47
|
end
|
31
48
|
end
|
49
|
+
|
50
|
+
def refresh_child(child)
|
51
|
+
tokens.each do |token|
|
52
|
+
child.beta_activate(Token.new(child, token, nil))
|
53
|
+
end
|
54
|
+
end
|
32
55
|
end
|
33
56
|
end
|
34
57
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Wongi
|
2
2
|
module Engine
|
3
|
-
class ProductionNode <
|
3
|
+
class ProductionNode < BetaNode
|
4
4
|
attr_accessor :tracer, :compilation_context
|
5
5
|
|
6
6
|
def initialize(parent, actions)
|
@@ -9,7 +9,10 @@ module Wongi
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def beta_activate(token)
|
12
|
-
|
12
|
+
# p beta_activate: {class: self.class, object_id:, token:}
|
13
|
+
return if tokens.find { |t| t.duplicate? token }
|
14
|
+
|
15
|
+
overlay.add_token(token)
|
13
16
|
|
14
17
|
@actions.each do |action|
|
15
18
|
action.execute token if action.respond_to? :execute
|
@@ -17,7 +20,10 @@ module Wongi
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def beta_deactivate(token)
|
20
|
-
|
23
|
+
# p beta_deactivate: {class: self.class, object_id:, token:}
|
24
|
+
|
25
|
+
# we should remove before the actions because otherwise the longer rule chains (like the infinite neg-gen cycle) don't work as expected
|
26
|
+
overlay.remove_token(token)
|
21
27
|
|
22
28
|
@actions.each do |action|
|
23
29
|
action.deexecute token if action.respond_to? :deexecute
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Wongi::Engine
|
2
|
+
class RootNode < BetaNode
|
3
|
+
def seed(assignments = {})
|
4
|
+
@seed = assignments
|
5
|
+
t = Token.new(self, nil, nil, assignments)
|
6
|
+
rete.default_overlay.add_token(t)
|
7
|
+
end
|
8
|
+
|
9
|
+
def subst(valuations)
|
10
|
+
beta_deactivate(tokens.first)
|
11
|
+
token = Token.new(self, nil, nil, @seed)
|
12
|
+
valuations.each { |variable, value| token.subst variable, value }
|
13
|
+
beta_activate(token)
|
14
|
+
end
|
15
|
+
|
16
|
+
def beta_activate(token)
|
17
|
+
# existing = tokens.find { |et| et.duplicate? token }
|
18
|
+
# return if existing # TODO: really?
|
19
|
+
|
20
|
+
overlay.add_token(token)
|
21
|
+
|
22
|
+
children.each do |child|
|
23
|
+
child.beta_activate(Token.new(child, token, nil))
|
24
|
+
end
|
25
|
+
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def beta_deactivate(token)
|
30
|
+
return nil unless tokens.find token
|
31
|
+
|
32
|
+
overlay.remove_token(token)
|
33
|
+
|
34
|
+
children.each do |child|
|
35
|
+
child.tokens.select { _1.parent == token }.each { child.beta_deactivate(_1) }
|
36
|
+
end
|
37
|
+
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def refresh_child(child)
|
42
|
+
tokens.each do |token|
|
43
|
+
child.beta_activate(Token.new(child, token, nil))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/wongi-engine/beta.rb
CHANGED
@@ -24,37 +24,13 @@ module Wongi::Engine
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
# TODO: should the following be the responsibility of Compiler or of each individual DSL clause?
|
28
|
-
|
29
|
-
def beta_memory
|
30
|
-
return if node.is_a?(BetaMemory)
|
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
|
47
|
-
end
|
48
|
-
|
49
27
|
def assignment_node(variable, body)
|
50
|
-
beta_memory
|
51
28
|
self.node = AssignmentNode.new(node, variable, body).tap(&:refresh)
|
52
29
|
declare(variable)
|
53
30
|
end
|
54
31
|
|
55
32
|
def join_node(condition, tests, assignment)
|
56
33
|
alpha = rete.compile_alpha(condition)
|
57
|
-
beta_memory
|
58
34
|
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
35
|
existing
|
60
36
|
else
|
@@ -63,6 +39,7 @@ module Wongi::Engine
|
|
63
39
|
alpha.betas << join unless alpha_deaf
|
64
40
|
end
|
65
41
|
end
|
42
|
+
node.tap(&:refresh)
|
66
43
|
end
|
67
44
|
|
68
45
|
def neg_node(condition, tests, unsafe)
|
@@ -75,24 +52,21 @@ module Wongi::Engine
|
|
75
52
|
|
76
53
|
def opt_node(condition, tests, assignment)
|
77
54
|
alpha = rete.compile_alpha(condition)
|
78
|
-
beta_memory
|
79
55
|
self.node = OptionalNode.new(node, alpha, tests, assignment).tap do |node|
|
80
56
|
alpha.betas << node unless alpha_deaf
|
57
|
+
node.refresh
|
81
58
|
end
|
82
59
|
end
|
83
60
|
|
84
61
|
def aggregate_node(condition, tests, assignment, map, function, assign)
|
85
62
|
declare(assign)
|
86
63
|
alpha = rete.compile_alpha(condition)
|
87
|
-
beta_memory
|
88
64
|
self.node = AggregateNode.new(node, alpha, tests, assignment, map, function, assign).tap do |node|
|
89
65
|
alpha.betas << node unless alpha_deaf
|
90
|
-
end
|
91
|
-
beta_memory
|
66
|
+
end.tap(&:refresh)
|
92
67
|
end
|
93
68
|
|
94
69
|
def or_node(variants)
|
95
|
-
beta_memory
|
96
70
|
subvariables = []
|
97
71
|
branches = variants.map do |variant|
|
98
72
|
subcompiler = Compiler.new(rete, node, variant.conditions, parameters, false)
|
@@ -110,7 +84,6 @@ module Wongi::Engine
|
|
110
84
|
end
|
111
85
|
|
112
86
|
def ncc_node(subrule, alpha_deaf)
|
113
|
-
beta_memory
|
114
87
|
subcompiler = Compiler.new(rete, node, subrule.conditions, parameters, alpha_deaf)
|
115
88
|
declared_variables.each { |v| subcompiler.declare(v) }
|
116
89
|
bottom = subcompiler.compile
|
@@ -118,8 +91,8 @@ module Wongi::Engine
|
|
118
91
|
self.node = existing
|
119
92
|
return
|
120
93
|
end
|
121
|
-
ncc = NccNode.new
|
122
|
-
partner = NccPartner.new
|
94
|
+
ncc = NccNode.new(node)
|
95
|
+
partner = NccPartner.new(subcompiler.node)
|
123
96
|
ncc.partner = partner
|
124
97
|
partner.ncc = ncc
|
125
98
|
partner.divergent = node
|
@@ -130,8 +103,7 @@ module Wongi::Engine
|
|
130
103
|
end
|
131
104
|
|
132
105
|
def filter_node(filter)
|
133
|
-
|
134
|
-
self.node = FilterNode.new(node, filter)
|
106
|
+
self.node = FilterNode.new(node, filter).tap(&:refresh)
|
135
107
|
end
|
136
108
|
end
|
137
109
|
end
|
@@ -1,45 +1,44 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Action
|
3
|
-
class StatementGenerator <
|
3
|
+
class StatementGenerator < BaseAction
|
4
|
+
GeneratorOrigin = Struct.new(:token, :action)
|
5
|
+
|
6
|
+
attr_reader :template
|
7
|
+
private :template
|
8
|
+
|
4
9
|
def initialize(template)
|
5
10
|
super()
|
6
11
|
@template = template
|
7
12
|
end
|
8
13
|
|
9
14
|
def execute(token)
|
10
|
-
|
15
|
+
# p execute: {token:}
|
16
|
+
subject, predicate, object = template.resolve!(token)
|
17
|
+
|
18
|
+
wme = WME.new(subject, predicate, object)
|
11
19
|
|
12
|
-
|
13
|
-
wme = WME.new subject, predicate, object, rete
|
14
|
-
wme.manual = false
|
15
|
-
wme.overlay = token.overlay
|
20
|
+
origin = GeneratorOrigin.new(token, self)
|
16
21
|
|
17
22
|
production.tracer.trace(action: self, wme: wme) if production.tracer
|
18
|
-
if (existing =
|
19
|
-
generated
|
20
|
-
|
23
|
+
if (existing = overlay.find(wme))
|
24
|
+
# do not mark purely manual tokens as generated, because a circular rule such as the symmetric friend generator this would cause both sides to become self-sustaining
|
25
|
+
# TODO: but this may have to be smarter, because there may be more indirect ways of creating such a situation
|
26
|
+
if overlay.generated?(wme)
|
21
27
|
token.generated_wmes << existing
|
22
|
-
existing
|
28
|
+
overlay.assert(existing, generator: origin)
|
23
29
|
end
|
24
30
|
else
|
25
31
|
token.generated_wmes << wme
|
26
|
-
wme
|
27
|
-
# this MUST be done after we link the wme and the token
|
28
|
-
# in order for neg rule invalidation to work
|
29
|
-
wme.overlay.assert wme
|
32
|
+
overlay.assert(wme, generator: origin)
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
36
|
def deexecute(token)
|
34
|
-
|
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
|
37
|
+
origin = GeneratorOrigin.new(token, self)
|
40
38
|
|
41
|
-
|
42
|
-
|
39
|
+
generated = token.generated_wmes.select { overlay.generators(_1).include?(origin) }
|
40
|
+
generated.each do |wme|
|
41
|
+
overlay.retract wme, generator: origin
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
@@ -1,17 +1,13 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL::Clause
|
3
|
-
Has = Struct.new(:subject, :predicate, :object
|
3
|
+
Has = Struct.new(:subject, :predicate, :object) do
|
4
4
|
include CoreExt
|
5
5
|
attr_predicate :debug
|
6
6
|
|
7
7
|
def initialize(s, p, o, options = {})
|
8
|
-
time = options[:time] || 0
|
9
8
|
@unsafe = options[:unsafe] || false
|
10
9
|
debug! if options[:debug]
|
11
|
-
|
12
|
-
raise "Cannot look into the future" if time.positive?
|
13
|
-
|
14
|
-
super(s, p, o, time)
|
10
|
+
super(s, p, o)
|
15
11
|
end
|
16
12
|
|
17
13
|
def compile(context)
|
data/lib/wongi-engine/dsl.rb
CHANGED
@@ -36,7 +36,7 @@ require 'wongi-engine/dsl/clause/fact'
|
|
36
36
|
require 'wongi-engine/dsl/clause/aggregate'
|
37
37
|
require 'wongi-engine/dsl/clause/assign'
|
38
38
|
require 'wongi-engine/dsl/clause/gen'
|
39
|
-
require 'wongi-engine/dsl/action/
|
39
|
+
require 'wongi-engine/dsl/action/base_action'
|
40
40
|
require 'wongi-engine/dsl/rule'
|
41
41
|
require 'wongi-engine/dsl/ncc_subrule'
|
42
42
|
require 'wongi-engine/dsl/any_rule'
|
@@ -110,30 +110,6 @@ module Wongi::Engine::DSL
|
|
110
110
|
clause :assign, :introduce, :let
|
111
111
|
accept Clause::Assign
|
112
112
|
|
113
|
-
clause :asserted, :added
|
114
|
-
body { |s, p, o|
|
115
|
-
has s, p, o, time: 0
|
116
|
-
missing s, p, o, time: -1
|
117
|
-
}
|
118
|
-
|
119
|
-
clause :retracted, :removed
|
120
|
-
body { |s, p, o|
|
121
|
-
has s, p, o, time: -1
|
122
|
-
missing s, p, o, time: 0
|
123
|
-
}
|
124
|
-
|
125
|
-
clause :kept, :still_has
|
126
|
-
body { |s, p, o|
|
127
|
-
has s, p, o, time: -1
|
128
|
-
has s, p, o, time: 0
|
129
|
-
}
|
130
|
-
|
131
|
-
clause :kept_missing, :still_missing
|
132
|
-
body { |s, p, o|
|
133
|
-
missing s, p, o, time: -1
|
134
|
-
missing s, p, o, time: 0
|
135
|
-
}
|
136
|
-
|
137
113
|
clause :assuming
|
138
114
|
accept Wongi::Engine::AssumingClause
|
139
115
|
|