cure_engine/kind.rs
1//! 规范节点种类表:引擎共享规则所依赖的最小结构词汇表。
2//!
3//! 语言 crate 把自己的 AST 映射到这些 kind 上。这里**不是** Universal AST:
4//! 它只覆盖主流语句/表达式形态,语言特有节点用 [`NodeKind::Custom`] 逃逸,
5//! 由语言 crate 自己的规则处理,引擎通用规则不会触碰。
6//!
7//! 每种 kind 的 children 布局是共享规则的契约(位置即求值/书写顺序):
8
9use std::fmt;
10
11#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
12pub enum NodeKind {
13 // ---- 语句 ----
14 /// `[stmt…]`
15 Block,
16 /// 空语句 `;`,无 children。
17 Empty,
18 /// `yield expr;`(switch 表达式块内的产出语句)。
19 Yield,
20 /// `[expr]`
21 ExprStmt,
22 /// 局部变量声明,children: `[(init)?]`,名字由 `Lang::var_name` 提供。
23 /// 目标变量必须可写(普通局部变量),声明的类型语义由语言侧保证。
24 VarDecl,
25 /// `[target, value]`;target 必须是 VarRef(复合赋值通过 `Lang::assign_op` 区分)。
26 Assign,
27 /// `[cond, then]` 或 `[cond, then, else]`
28 If,
29 /// `[cond, body]`
30 While,
31 /// `[body, cond]`
32 DoWhile,
33 /// `[(init)?, (cond)?, (step)?, body]`
34 For,
35 /// 增强 for:`[iterable, body]`,变量名/类型为语言侧 attr。
36 ForEach,
37 /// `[(value)?]`
38 Return,
39 /// `[(label)?]`(label 以字符串 attr 提供,不在 children)
40 Break,
41 Continue,
42 /// `[expr]`
43 Throw,
44 /// `[(resource)?, try_block, (catch)?, (finally)?]`;资源是语句节点,catch 子节点。
45 Try,
46 /// `[body]`;参数为语言侧 attr(`var_name` 返回绑定名)。
47 Catch,
48 /// `[lock, block]`
49 Synchronized,
50 /// `[subject, case…]`
51 Switch,
52 /// `[label…, stmts…]`(label 数与是否 default 为语言侧 attr)
53 Case,
54 /// `[stmt]`,标签名为 attr。
55 Label,
56 /// `[(cond, (msg)?)]`
57 Assert,
58
59 // ---- 表达式 ----
60 /// `[lhs, rhs]`,运算符由 `Lang::bin_op` 提供。
61 Binary,
62 /// `[operand]`,运算符由 `Lang::un_op` 提供。
63 Unary,
64 /// `[callee, arg…]`;callee 不能为空。
65 Call,
66 /// 字面量,值由 `Lang::literal` 提供,无 children。
67 Literal,
68 /// 变量读,名字由 `Lang::var_name` 提供。
69 VarRef,
70 /// `[cond, then, else]`
71 Ternary,
72 /// `[expr]`,目标类型为语言侧 attr。
73 Cast,
74 /// `[expr]` 纯括号分组,可被 ParenRemoval 删除。
75 Paren,
76 /// `[object]`,成员名为语言侧 attr(`null` 安全调用等也是语言侧语义)。
77 Member,
78 /// `[array, index]`
79 Index,
80 /// `[arg…]`,构造类型为语言侧 attr。
81 New,
82 /// `[size…, (init)?]`,元素类型与已给尺寸数为语言侧 attr。
83 NewArray,
84 /// `[elem…]`
85 ArrayLit,
86 /// 无 children(或语言侧自定)。
87 This,
88 /// `[expr]`,类型/模式绑定为语言侧 attr。`x instanceof T b`
89 InstanceOf,
90 /// `[body]`(body 为 Block 或表达式),参数原文为语言侧 attr。
91 Lambda,
92 /// `[receiver]`,成员名为语言侧 attr。`recv::name`
93 MethodRef,
94 /// 不可解析的原文区域:语言侧原样保留,通用规则不触碰。
95 Raw,
96 /// 语言特有节点逃逸口;引擎通用规则不匹配。
97 Custom(u16),
98}
99
100impl NodeKind {
101 /// 数组分派用的小整数键:字段变体 Custom 折叠到统一槽位。
102 /// 穷尽 match —— 枚举加变体时编译器强制补分支(不会静默漏桶)。
103 #[inline]
104 pub fn slot(self) -> usize {
105 match self {
106 NodeKind::Block => 0,
107 NodeKind::Empty => 1,
108 NodeKind::Yield => 2,
109 NodeKind::ExprStmt => 2,
110 NodeKind::VarDecl => 3,
111 NodeKind::Assign => 4,
112 NodeKind::If => 5,
113 NodeKind::While => 6,
114 NodeKind::DoWhile => 7,
115 NodeKind::For => 8,
116 NodeKind::ForEach => 9,
117 NodeKind::Return => 10,
118 NodeKind::Break => 11,
119 NodeKind::Continue => 12,
120 NodeKind::Throw => 13,
121 NodeKind::Try => 14,
122 NodeKind::Catch => 15,
123 NodeKind::Synchronized => 16,
124 NodeKind::Switch => 17,
125 NodeKind::Case => 18,
126 NodeKind::Label => 19,
127 NodeKind::Assert => 20,
128 NodeKind::Binary => 21,
129 NodeKind::Unary => 22,
130 NodeKind::Call => 23,
131 NodeKind::Literal => 24,
132 NodeKind::VarRef => 25,
133 NodeKind::Ternary => 26,
134 NodeKind::Cast => 27,
135 NodeKind::Paren => 28,
136 NodeKind::Member => 29,
137 NodeKind::Index => 30,
138 NodeKind::New => 31,
139 NodeKind::NewArray => 32,
140 NodeKind::ArrayLit => 33,
141 NodeKind::This => 34,
142 NodeKind::InstanceOf => 35,
143 NodeKind::Lambda => 36,
144 NodeKind::MethodRef => 37,
145 NodeKind::Raw => 38,
146 NodeKind::Custom(_) => 39,
147 }
148 }
149
150 /// slot 的上界(分派表定容用)。
151 pub const SLOT_COUNT: usize = 42;
152}
153
154impl NodeKind {
155 pub fn is_stmt(self) -> bool {
156 use NodeKind::*;
157 matches!(
158 self,
159 Block | Empty | ExprStmt | VarDecl | Assign | If | While | DoWhile | For | ForEach
160 | Return | Break | Continue | Throw | Switch | Case | Try | Catch
161 | Synchronized | Label | Assert | Raw
162 )
163 }
164}
165
166impl fmt::Display for NodeKind {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "{:?}", self)
169 }
170}
171
172/// 二元运算符(规范词汇表,语言负责映射)。
173#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
174pub enum BinOp {
175 Add,
176 Sub,
177 Mul,
178 Div,
179 Rem,
180 Shl,
181 Shr,
182 UShr,
183 Lt,
184 Le,
185 Gt,
186 Ge,
187 Eq,
188 Ne,
189 BitAnd,
190 BitXor,
191 BitOr,
192 And,
193 Or,
194 // ---- JS 专用(语言映射词汇;Java 不产生)----
195 /// `**`(幂)。右结合且非结合律——重结合类规则须跳过。
196 Pow,
197 /// `===`(严格相等)。与 [`BinOp::Eq`](宽松 `==`)语义不同:
198 /// 折叠规则必须按语言语义分别处理。
199 StrictEq,
200 /// `!==`(严格不等)。
201 StrictNe,
202 /// `??`(空值合并——**非短路布尔**:返回操作数值而非布尔)。
203 Nullish,
204 /// `in`(属性存在性,二元关系)。
205 In,
206 /// `instanceof`(JS 的二元运算形态,RHS 是任意表达式)。
207 Instanceof,
208}
209
210impl BinOp {
211 pub fn is_comparison(self) -> bool {
212 matches!(
213 self,
214 BinOp::Lt
215 | BinOp::Le
216 | BinOp::Gt
217 | BinOp::Ge
218 | BinOp::Eq
219 | BinOp::Ne
220 | BinOp::StrictEq
221 | BinOp::StrictNe
222 | BinOp::In
223 | BinOp::Instanceof
224 )
225 }
226 pub fn is_short_circuit(self) -> bool {
227 matches!(self, BinOp::And | BinOp::Or | BinOp::Nullish)
228 }
229 /// 可能因除零抛异常的运算。
230 pub fn may_div_zero(self) -> bool {
231 matches!(self, BinOp::Div | BinOp::Rem)
232 }
233 /// 整数算术/位运算类(用于精确整数恒等式守卫)。
234 pub fn is_arith(self) -> bool {
235 matches!(
236 self,
237 BinOp::Add
238 | BinOp::Sub
239 | BinOp::Mul
240 | BinOp::Div
241 | BinOp::Rem
242 | BinOp::Shl
243 | BinOp::Shr
244 | BinOp::UShr
245 | BinOp::BitAnd
246 | BinOp::BitXor
247 | BinOp::BitOr
248 )
249 }
250}
251
252/// 一元运算符。
253#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
254pub enum UnOp {
255 Not,
256 Neg,
257 BitNot,
258 // ---- JS 专用(语言映射词汇;Java 不产生)----
259 /// `typeof x`(值恒为字符串;对未声明变量**不抛**——效果 Pure)。
260 TypeOf,
261 /// `void x`(求值操作数、返回 undefined——效果含操作数)。
262 Void,
263 /// `delete x`(可能写:删属性)。
264 Delete,
265 /// `await x`(仅在 async 函数内;暂停语义——效果 Unknown)。
266 Await,
267 /// 一元 `+`(数值提升——char/byte/short 提升 int;装箱类型改变
268 /// `Object o = +c` → Integer 而非 Character)。恒等但**静态类型敏感**,
269 /// 不可丢弃。
270 Plus,
271 /// `++x`(读+写)
272 PreInc,
273 PreDec,
274 /// `x++`(读+写)
275 PostInc,
276 PostDec,
277}
278
279impl UnOp {
280 pub fn is_incdec(self) -> bool {
281 matches!(
282 self,
283 UnOp::PreInc | UnOp::PreDec | UnOp::PostInc | UnOp::PostDec
284 )
285 }
286}
287
288/// 字面量值的借用视图(语言 crate 从自己的负载映射)。
289#[derive(Clone, Copy, PartialEq, Debug)]
290pub enum LitRef<'a> {
291 Bool(bool),
292 Int(i64),
293 Long(i64),
294 Float(f64),
295 Double(f64),
296 Char(char),
297 Str(&'a str),
298 Null,
299}
300
301impl<'a> LitRef<'a> {
302 pub fn is_bool(self) -> bool {
303 matches!(self, LitRef::Bool(_))
304 }
305 /// 整数字面量(Int/Long),返回数值。
306 pub fn as_int(self) -> Option<i64> {
307 match self {
308 LitRef::Int(v) | LitRef::Long(v) => Some(v),
309 _ => None,
310 }
311 }
312}
313
314/// 区域扫描事件(使用索引的原子):语句子树遍历中的一次读/写/遮蔽。
315/// `node` 指向承载名字的节点(Use→VarRef;Write→赋值目标 VarRef 或
316/// 声明节点;Shadow→VarDecl/ForEach/Catch 绑定节点),名字由
317/// `Lang::var_name(node)` 读取——与 scan_region 原递归的判定一致。
318#[derive(Clone, Copy, Debug)]
319pub struct RegionEvent<Id, Key> {
320 pub kind: EventKind,
321 pub node: Id,
322 /// 事件承载者的名字键(语言侧等价类:Java=u32 intern id)——
323 /// 事件构建时预存,查询侧比较为整数等值,免 var_name/memcmp。
324 pub key: Key,
325}
326
327#[derive(Clone, Copy, PartialEq, Eq, Debug)]
328pub enum EventKind {
329 /// 变量读(VarRef)
330 Use,
331 /// 显式局部写(赋值目标 / 自增自减目标 / 声明 / ForEach 绑定)
332 Write,
333 /// 同名遮蔽(VarDecl / ForEach / Catch 声明)
334 Shadow,
335 /// 不透明区域(Raw 不可解析原文):读写集未知——一切"零用途/
336 /// 单用途/无写"的证明失效,规则必须保守拒绝(对抗波 3 抓获:
337 /// 仅被 RAW 引用的变量被误删 + 值被提前传播越过 RAW 赋值)。
338 Opaque,
339}