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        // 赋值:目标是简单变量 → 对其名字写入;事件节点记 target。
119        // 只递归 RHS(target 的读不算事件——写即事件)。
120        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        // 自增/自减:对目标写入(目标自身不再产生读事件)
135        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        // 声明:写 + 遮蔽(事件节点 = 声明节点自身),全孩子递归
146        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        // catch 绑定:仅遮蔽
158        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}