1use cure_engine::kind::{EventKind, NodeKind, RegionEvent};
4use cure_engine::Lang;
5
6#[derive(Debug)]
12pub struct EventStore<Id, NameKey> {
13 events: Vec<Vec<RegionEvent<Id, NameKey>>>,
14 clean: bool,
15}
16
17impl<Id, NameKey> Default for EventStore<Id, NameKey> {
18 fn default() -> Self {
19 Self { events: Vec::new(), clean: false }
20 }
21}
22
23impl<Id: Clone, NameKey: Clone> EventStore<Id, NameKey> {
24 pub fn new() -> Self {
25 Self::default()
26 }
27
28 pub fn resize(&mut self, count: usize) {
30 if self.events.len() < count {
31 self.events.resize(count, Vec::new());
32 }
33 }
34
35 pub fn slot(&self, idx: usize) -> &[RegionEvent<Id, NameKey>] {
37 self.events.get(idx).map(|v| v.as_slice()).unwrap_or(&[])
38 }
39
40 pub fn put(&mut self, idx: usize, events: Vec<RegionEvent<Id, NameKey>>) {
41 if self.events.len() <= idx {
42 self.events.resize(idx + 1, Vec::new());
43 }
44 self.events[idx] = events;
45 }
46
47 pub fn is_clean(&self) -> bool {
48 self.clean
49 }
50 pub fn mark_clean(&mut self) {
51 self.clean = true;
52 }
53
54 pub fn invalidate(&mut self, idx: usize) {
58 self.clean = false;
59 if let Some(slot) = self.events.get_mut(idx) {
60 slot.clear();
61 }
62 }
63}
64
65pub fn stmt_roots<L: Lang>(lang: &L, root: L::Id) -> Vec<L::Id> {
68 let mut stack = vec![root];
69 let mut stmt_roots: Vec<L::Id> = Vec::new();
70 while let Some(n) = stack.pop() {
71 if lang.kind(n) == NodeKind::Block {
72 for &c in lang.children(n) {
73 stmt_roots.push(c);
74 }
75 }
76 for &c in lang.children(n) {
77 stack.push(c);
78 }
79 }
80 stmt_roots
81}
82
83pub fn collect_region_events<L: Lang>(
91 lang: &L,
92 node: L::Id,
93) -> Vec<RegionEvent<L::Id, L::NameKey>> {
94 let mut out = Vec::new();
95 let opaque = collect_events_into(lang, node, &mut out);
96 if opaque {
97 return Vec::new();
98 }
99 out.sort_by_key(|e| e.key);
100 out
101}
102
103fn collect_events_into<L: Lang>(
105 lang: &L,
106 node: L::Id,
107 out: &mut Vec<RegionEvent<L::Id, L::NameKey>>,
108) -> bool {
109 if lang.is_opaque(node) {
110 return true;
111 }
112 match lang.kind(node) {
113 NodeKind::Assign => {
116 let ch = lang.children(node);
117 if let Some(&t) = ch.first() {
118 if lang.kind(t) == NodeKind::VarRef {
119 if let Some(k) = lang.var_key(t) {
120 out.push(RegionEvent { kind: EventKind::Write, node: t, key: k });
121 }
122 }
123 }
124 match ch.get(1) {
125 Some(&v) => collect_events_into(lang, v, out),
126 None => false,
127 }
128 }
129 NodeKind::Unary if lang.un_op(node).is_some_and(|o| o.is_incdec()) => {
131 if let Some(&t) = lang.children(node).first() {
132 if lang.kind(t) == NodeKind::VarRef {
133 if let Some(k) = lang.var_key(t) {
134 out.push(RegionEvent { kind: EventKind::Write, node: t, key: k });
135 }
136 }
137 }
138 false
139 }
140 NodeKind::VarDecl | NodeKind::ForEach => {
142 if let Some(k) = lang.var_key(node) {
143 out.push(RegionEvent { kind: EventKind::Write, node, key: k });
144 out.push(RegionEvent { kind: EventKind::Shadow, node, key: k });
145 }
146 let mut opaque = false;
147 for &c in lang.children(node) {
148 opaque |= collect_events_into(lang, c, out);
149 }
150 opaque
151 }
152 NodeKind::Catch => {
154 if let Some(k) = lang.var_key(node) {
155 out.push(RegionEvent { kind: EventKind::Shadow, node, key: k });
156 }
157 let mut opaque = false;
158 for &c in lang.children(node) {
159 opaque |= collect_events_into(lang, c, out);
160 }
161 opaque
162 }
163 NodeKind::VarRef => {
164 if let Some(k) = lang.var_key(node) {
165 out.push(RegionEvent { kind: EventKind::Use, node, key: k });
166 }
167 false
168 }
169 _ => {
170 let mut opaque = false;
171 for &c in lang.children(node) {
172 opaque |= collect_events_into(lang, c, out);
173 }
174 opaque
175 }
176 }
177}