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 => {
121 let ch = lang.children(node);
122 if let Some(&t) = ch.first() {
123 if lang.kind(t) == NodeKind::VarRef {
124 if let Some(k) = lang.var_key(t) {
125 out.push(RegionEvent { kind: EventKind::Write, node: t, key: k });
126 }
127 }
128 }
129 match ch.get(1) {
130 Some(&v) => collect_events_into(lang, v, out),
131 None => false,
132 }
133 }
134 NodeKind::Unary if lang.un_op(node).is_some_and(|o| o.is_incdec()) => {
136 if let Some(&t) = lang.children(node).first() {
137 if lang.kind(t) == NodeKind::VarRef {
138 if let Some(k) = lang.var_key(t) {
139 out.push(RegionEvent { kind: EventKind::Write, node: t, key: k });
140 }
141 }
142 }
143 false
144 }
145 NodeKind::VarDecl | NodeKind::ForEach => {
147 if let Some(k) = lang.var_key(node) {
148 out.push(RegionEvent { kind: EventKind::Write, node, key: k });
149 out.push(RegionEvent { kind: EventKind::Shadow, node, key: k });
150 }
151 let mut opaque = false;
152 for &c in lang.children(node) {
153 opaque |= collect_events_into(lang, c, out);
154 }
155 opaque
156 }
157 NodeKind::Catch => {
159 if let Some(k) = lang.var_key(node) {
160 out.push(RegionEvent { kind: EventKind::Shadow, node, key: k });
161 }
162 let mut opaque = false;
163 for &c in lang.children(node) {
164 opaque |= collect_events_into(lang, c, out);
165 }
166 opaque
167 }
168 NodeKind::VarRef => {
169 if let Some(k) = lang.var_key(node) {
170 out.push(RegionEvent { kind: EventKind::Use, node, key: k });
171 }
172 false
173 }
174 _ => {
175 let mut opaque = false;
176 for &c in lang.children(node) {
177 opaque |= collect_events_into(lang, c, out);
178 }
179 opaque
180 }
181 }
182}