1use cure_engine::kind::{EventKind, NodeKind, RegionEvent};
4use cure_engine::Lang;
5
6#[derive(Debug)]
12pub struct EventStore<Id, NameKey> {
13 events: Vec<Option<Vec<RegionEvent<Id, NameKey>>>>,
17 clean: bool,
18}
19
20impl<Id, NameKey> Default for EventStore<Id, NameKey> {
21 fn default() -> Self {
22 Self { events: Vec::new(), clean: false }
23 }
24}
25
26impl<Id: Clone, NameKey: Clone> EventStore<Id, NameKey> {
27 pub fn new() -> Self {
28 Self::default()
29 }
30
31 pub fn resize(&mut self, count: usize) {
33 if self.events.len() < count {
34 self.events.resize_with(count, || None);
35 }
36 }
37
38 pub fn slot(&self, idx: usize) -> Option<&[RegionEvent<Id, NameKey>]> {
41 self.events.get(idx).and_then(|v| v.as_deref())
42 }
43
44 pub fn put(&mut self, idx: usize, events: Vec<RegionEvent<Id, NameKey>>) {
45 if self.events.len() <= idx {
46 self.events.resize_with(idx + 1, || None);
47 }
48 self.events[idx] = Some(events);
49 }
50
51 pub fn is_clean(&self) -> bool {
52 self.clean
53 }
54 pub fn mark_clean(&mut self) {
55 self.clean = true;
56 }
57
58 pub fn invalidate(&mut self, idx: usize) {
62 self.clean = false;
63 if let Some(slot) = self.events.get_mut(idx) {
64 *slot = None;
65 }
66 }
67}
68
69pub fn stmt_roots<L: Lang>(lang: &L, root: L::Id) -> Vec<L::Id> {
72 let mut stack = vec![root];
73 let mut stmt_roots: Vec<L::Id> = Vec::new();
74 while let Some(n) = stack.pop() {
75 if lang.kind(n) == NodeKind::Block {
76 for &c in lang.children(n) {
77 stmt_roots.push(c);
78 }
79 }
80 for &c in lang.children(n) {
81 stack.push(c);
82 }
83 }
84 stmt_roots
85}
86
87pub fn collect_region_events<L: Lang>(
97 lang: &L,
98 node: L::Id,
99) -> Option<Vec<RegionEvent<L::Id, L::NameKey>>> {
100 let mut out = Vec::new();
101 if collect_events_into(lang, node, &mut out) {
102 return None;
103 }
104 out.sort_by_key(|e| e.key);
105 Some(out)
106}
107
108fn collect_events_into<L: Lang>(
110 lang: &L,
111 node: L::Id,
112 out: &mut Vec<RegionEvent<L::Id, L::NameKey>>,
113) -> bool {
114 if lang.is_opaque(node) {
115 return true;
116 }
117 match lang.kind(node) {
118 NodeKind::Assign => {
123 let ch = lang.children(node);
124 let mut opaque = false;
125 if let Some(&t) = ch.first() {
126 if lang.kind(t) == NodeKind::VarRef {
127 if lang.assign_op(node).is_some() {
128 if let Some(k) = lang.var_key(t) {
129 out.push(RegionEvent { kind: EventKind::Use, node: t, key: k });
130 }
131 }
132 if let Some(k) = lang.var_key(t) {
133 out.push(RegionEvent { kind: EventKind::Write, node: t, key: k });
134 }
135 } else {
136 opaque |= collect_events_into(lang, t, out);
137 }
138 }
139 if let Some(&v) = ch.get(1) {
140 opaque |= collect_events_into(lang, v, out);
141 }
142 opaque
143 }
144 NodeKind::Unary if lang.un_op(node).is_some_and(|o| o.is_incdec()) => {
146 if let Some(&t) = lang.children(node).first() {
147 if lang.kind(t) == NodeKind::VarRef {
148 if let Some(k) = lang.var_key(t) {
149 out.push(RegionEvent { kind: EventKind::Use, node: t, key: k });
150 out.push(RegionEvent { kind: EventKind::Write, node: t, key: k });
151 }
152 false
153 } else {
154 collect_events_into(lang, t, out)
155 }
156 } else {
157 false
158 }
159 }
160 NodeKind::VarDecl | NodeKind::ForEach => {
162 if let Some(k) = lang.var_key(node) {
163 out.push(RegionEvent { kind: EventKind::Write, node, key: k });
164 out.push(RegionEvent { kind: EventKind::Shadow, node, key: k });
165 }
166 let mut opaque = false;
167 for &c in lang.children(node) {
168 opaque |= collect_events_into(lang, c, out);
169 }
170 opaque
171 }
172 NodeKind::Catch => {
174 if let Some(k) = lang.var_key(node) {
175 out.push(RegionEvent { kind: EventKind::Shadow, node, key: k });
176 }
177 let mut opaque = false;
178 for &c in lang.children(node) {
179 opaque |= collect_events_into(lang, c, out);
180 }
181 opaque
182 }
183 NodeKind::VarRef => {
184 if let Some(k) = lang.var_key(node) {
185 out.push(RegionEvent { kind: EventKind::Use, node, key: k });
186 }
187 false
188 }
189 _ => {
190 let mut opaque = false;
191 for &c in lang.children(node) {
192 opaque |= collect_events_into(lang, c, out);
193 }
194 opaque
195 }
196 }
197}