Skip to main content

cure_tree/
events.rs

1//! 区域事件索引:存储 + 泛型收集器。
2
3use cure_engine::kind::{EventKind, NodeKind, RegionEvent};
4use cure_engine::Lang;
5
6/// 事件存储(稠密:槽位 = arena 下标)+ B3 惰性重建的清洁标记。
7///
8/// 「空序列 = 未索引」是三重哨兵:未构建、被 `invalidate` 失效、或
9/// 子树含不透明节点(不建索引——键排序分区看不见 Opaque 键,查询侧
10/// 走引擎的 `scan_region` 递归路径,其 Opaque 分支保守拒绝)。
11#[derive(Debug)]
12pub struct EventStore<Id, NameKey> {
13    /// `None` = 未索引(未构建/失效/子树含不透明节点);`Some([])` 是
14    /// **已索引且零事件**——查询侧必须走快路径直接返回,不能回退递归
15    /// (大量 `foo();` 这类无命名事件的语句曾让每次查询重扫整棵子树)。
16    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    /// 槽位扩到 `count`(不缩;新槽为空 = 未索引)。
32    pub fn resize(&mut self, count: usize) {
33        if self.events.len() < count {
34            self.events.resize_with(count, || None);
35        }
36    }
37
38    /// `None` = 未索引(调用方回落引擎递归路径);`Some([])` = 已索引
39    /// 且零事件(调用方直接返回,不再递归)。
40    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    /// 失效一个语句条目(编辑沿祖先链调用):清空该槽 + 整表脏标记
59    /// (B3:下次 prepare 只重建**空**条目——未失效条目的事件是子树
60    /// 局部的,与位置无关)。
61    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
69/// 语句级节点枚举:Block 的直接孩子(引擎规则只对这些调用
70/// `scan_region`)。遍历整树,遇到 Block 就为其每个孩子登记。
71pub 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
87/// 收集 `node` 子树的事件序列,**按键稳定排序**:同键内保持遍历序
88/// (查询侧只消费键内序——Use 的顺序、Write/Shadow 的命中,跨键顺序
89/// 无关),二分定位键区间。
90///
91/// 返回空 Vec = 子树含不透明节点(调用方存空 = 未索引哨兵)。
92/// 事件序与引擎 `scan_region` 原递归**严格一致**(分配器 dispatch 的
93/// 是同一组 Lang 钩子)。
94/// `None` = 子树含不透明节点(不建索引,查询侧回落递归的 Opaque 分支);
95/// `Some(可能为空)` = 索引有效(空=零事件,查询侧应直接返回)。
96pub 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
108/// 返回值:子树是否含不透明节点(读/写集不可证明)。
109fn 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        // 赋值:简单变量目标 → 写;复合赋值还要读目标。
119        // **成员/索引目标**(`a[i] = v`)的基座与键是读——漏掉会让
120        // `i = 0; a[i] = 1; i = 2;` 把前一条 i 存储当死写删除
121        // (jscd 寄存器风格抓获)。
122        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        // 自增/自减:目标既读又写;成员/索引目标递归(基座/键是读)。
145        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        // 声明:写 + 遮蔽(事件节点 = 声明节点自身),全孩子递归
161        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        // catch 绑定:仅遮蔽
173        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}