@@ -42,6 +42,7 @@ struct TraverseState {
42
42
43
43
enum ActionType {
44
44
TRAVERSE,
45
+ SOURCE_SET,
45
46
INSERT_GOALS_TO_REMOVE,
46
47
ERASE_GOALS_TO_REMOVE,
47
48
ERASE_SEEN_GOALS,
@@ -57,20 +58,36 @@ enum ActionType {
57
58
// through "actions".
58
59
struct Action {
59
60
ActionType action_type;
60
- // Goal either to delete are added to the corresponding set.
61
- const Binding* goal;
62
- // The iterator is for std::set and this is stable upon deletion and insertion
63
- // if it's not directly the element being deleted or inserted. We will only
64
- // try to erase the element on the exact node traversal, so we can safely
65
- // reuse the iterator that was returned from the insertion.
66
- // Not using this for action ERASE_GOALS_TO_REMOVE, as we are requesting
67
- // for removal before the insertion has happened.
68
- GoalSet::iterator erase_it;
61
+ union {
62
+ // Goal either to delete are added to the corresponding set.
63
+ const Binding* goal;
64
+ // Source set to handle by a SOURCE_SET action. This is never the same as
65
+ // source_sets_end for actions on the actions stack.
66
+ std::set<SourceSet>::const_iterator source_sets_it;
67
+ };
68
+ union {
69
+ // The iterator is for std::set and this is stable upon deletion and
70
+ // insertion if it's not directly the element being deleted or inserted.
71
+ // We will only try to erase the element on the exact node traversal, so
72
+ // we can safely reuse the iterator that was returned from the insertion.
73
+ // Not using this for action ERASE_GOALS_TO_REMOVE, as we are requesting
74
+ // for removal before the insertion has happened.
75
+ GoalSet::iterator erase_it;
76
+ // End of the source sets in a SOURCE_SET action.
77
+ std::set<SourceSet>::const_iterator source_sets_end;
78
+ };
79
+
69
80
Action (ActionType action_type, const Binding* goal)
70
81
: action_type(action_type), goal(goal) {}
71
82
Action (ActionType action_type, const Binding* goal,
72
83
GoalSet::iterator erase_it)
73
84
: action_type(action_type), goal(goal), erase_it(erase_it) {}
85
+ Action (ActionType action_type,
86
+ std::set<SourceSet>::const_iterator source_sets_it,
87
+ std::set<SourceSet>::const_iterator source_sets_end)
88
+ : action_type(action_type),
89
+ source_sets_it (source_sets_it),
90
+ source_sets_end(source_sets_end) {}
74
91
};
75
92
76
93
static void traverse (const CFGNode* position,
@@ -104,19 +121,10 @@ static void traverse(const CFGNode* position,
104
121
}
105
122
106
123
state.removed_goals .push_back (goal);
107
- actions.emplace (ERASE_REMOVED_GOALS, nullptr );
108
- for (const auto & source_set : origin->source_sets ) {
109
- for (const Binding* next_goal : source_set) {
110
- if (!state.goals_to_remove .count (next_goal)) {
111
- actions.emplace (ERASE_GOALS_TO_REMOVE, next_goal);
112
- }
113
- }
114
- actions.emplace (TRAVERSE, nullptr );
115
- for (const Binding* next_goal : source_set) {
116
- if (!state.goals_to_remove .count (next_goal)) {
117
- actions.emplace (INSERT_GOALS_TO_REMOVE, next_goal);
118
- }
119
- }
124
+ actions.emplace (ERASE_REMOVED_GOALS, nullptr , it);
125
+ if (!origin->source_sets .empty ()) {
126
+ actions.emplace (SOURCE_SET, origin->source_sets .cbegin (),
127
+ origin->source_sets .cend ());
120
128
}
121
129
}
122
130
@@ -149,6 +157,21 @@ static std::vector<RemoveResult> remove_finished_goals(const CFGNode* pos,
149
157
case TRAVERSE:
150
158
traverse (pos, results, actions, state);
151
159
break ;
160
+ case SOURCE_SET: {
161
+ const auto & source_set = *action.source_sets_it ;
162
+ action.source_sets_it ++;
163
+ if (action.source_sets_it != action.source_sets_end ) {
164
+ actions.push (action);
165
+ }
166
+ for (const Binding* next_goal : source_set) {
167
+ auto [it, added] = state.goals_to_remove .insert (next_goal);
168
+ if (added) {
169
+ actions.emplace (ERASE_GOALS_TO_REMOVE, next_goal);
170
+ }
171
+ }
172
+ actions.emplace (TRAVERSE, nullptr );
173
+ break ;
174
+ }
152
175
case INSERT_GOALS_TO_REMOVE:
153
176
state.goals_to_remove .insert (action.goal );
154
177
break ;
0 commit comments