wongi-engine 0.3.9 → 0.4.0.pre.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -2
- data/.gitignore +2 -0
- data/README.md +12 -12
- 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 +161 -3
- 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 +12 -14
- 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 -149
- 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, self
|
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
|
|