cure-engine 0.3.0

Language-agnostic semantic code simplification engine (patterns, rewrites, passes, fixed point, cost model)
Documentation
//! 规范节点种类表:引擎共享规则所依赖的最小结构词汇表。
//!
//! 语言 crate 把自己的 AST 映射到这些 kind 上。这里**不是** Universal AST:
//! 它只覆盖主流语句/表达式形态,语言特有节点用 [`NodeKind::Custom`] 逃逸,
//! 由语言 crate 自己的规则处理,引擎通用规则不会触碰。
//!
//! 每种 kind 的 children 布局是共享规则的契约(位置即求值/书写顺序):

use std::fmt;

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub enum NodeKind {
    // ---- 语句 ----
    /// `[stmt…]`
    Block,
    /// 空语句 `;`,无 children。
    Empty,
    /// `yield expr;`(switch 表达式块内的产出语句)。
    Yield,
    /// `[expr]`
    ExprStmt,
    /// 局部变量声明,children: `[(init)?]`,名字由 `Lang::var_name` 提供。
    /// 目标变量必须可写(普通局部变量),声明的类型语义由语言侧保证。
    VarDecl,
    /// `[target, value]`;target 必须是 VarRef(复合赋值通过 `Lang::assign_op` 区分)。
    Assign,
    /// `[cond, then]` 或 `[cond, then, else]`
    If,
    /// `[cond, body]`
    While,
    /// `[body, cond]`
    DoWhile,
    /// `[(init)?, (cond)?, (step)?, body]`
    For,
    /// 增强 for:`[iterable, body]`,变量名/类型为语言侧 attr。
    ForEach,
    /// `[(value)?]`
    Return,
    /// `[(label)?]`(label 以字符串 attr 提供,不在 children)
    Break,
    Continue,
    /// `[expr]`
    Throw,
    /// `[(resource)?, try_block, (catch)?, (finally)?]`;资源是语句节点,catch 子节点。
    Try,
    /// `[body]`;参数为语言侧 attr(`var_name` 返回绑定名)。
    Catch,
    /// `[lock, block]`
    Synchronized,
    /// `[subject, case…]`
    Switch,
    /// `[label…, stmts…]`(label 数与是否 default 为语言侧 attr)
    Case,
    /// `[stmt]`,标签名为 attr。
    Label,
    /// `[(cond, (msg)?)]`
    Assert,

    // ---- 表达式 ----
    /// `[lhs, rhs]`,运算符由 `Lang::bin_op` 提供。
    Binary,
    /// `[operand]`,运算符由 `Lang::un_op` 提供。
    Unary,
    /// `[callee, arg…]`;callee 不能为空。
    Call,
    /// 字面量,值由 `Lang::literal` 提供,无 children。
    Literal,
    /// 变量读,名字由 `Lang::var_name` 提供。
    VarRef,
    /// `[cond, then, else]`
    Ternary,
    /// `[expr]`,目标类型为语言侧 attr。
    Cast,
    /// `[expr]` 纯括号分组,可被 ParenRemoval 删除。
    Paren,
    /// `[object]`,成员名为语言侧 attr(`null` 安全调用等也是语言侧语义)。
    Member,
    /// `[array, index]`
    Index,
    /// `[arg…]`,构造类型为语言侧 attr。
    New,
    /// `[size…, (init)?]`,元素类型与已给尺寸数为语言侧 attr。
    NewArray,
    /// `[elem…]`
    ArrayLit,
    /// 无 children(或语言侧自定)。
    This,
    /// `[expr]`,类型/模式绑定为语言侧 attr。`x instanceof T b`
    InstanceOf,
    /// `[body]`(body 为 Block 或表达式),参数原文为语言侧 attr。
    Lambda,
    /// `[receiver]`,成员名为语言侧 attr。`recv::name`
    MethodRef,
    /// 不可解析的原文区域:语言侧原样保留,通用规则不触碰。
    Raw,
    /// 语言特有节点逃逸口;引擎通用规则不匹配。
    Custom(u16),
}

impl NodeKind {
    /// 数组分派用的小整数键:字段变体 Custom 折叠到统一槽位。
    /// 穷尽 match —— 枚举加变体时编译器强制补分支(不会静默漏桶)。
    #[inline]
    pub fn slot(self) -> usize {
        match self {
            NodeKind::Block => 0,
            NodeKind::Empty => 1,
            NodeKind::Yield => 2,
            NodeKind::ExprStmt => 2,
            NodeKind::VarDecl => 3,
            NodeKind::Assign => 4,
            NodeKind::If => 5,
            NodeKind::While => 6,
            NodeKind::DoWhile => 7,
            NodeKind::For => 8,
            NodeKind::ForEach => 9,
            NodeKind::Return => 10,
            NodeKind::Break => 11,
            NodeKind::Continue => 12,
            NodeKind::Throw => 13,
            NodeKind::Try => 14,
            NodeKind::Catch => 15,
            NodeKind::Synchronized => 16,
            NodeKind::Switch => 17,
            NodeKind::Case => 18,
            NodeKind::Label => 19,
            NodeKind::Assert => 20,
            NodeKind::Binary => 21,
            NodeKind::Unary => 22,
            NodeKind::Call => 23,
            NodeKind::Literal => 24,
            NodeKind::VarRef => 25,
            NodeKind::Ternary => 26,
            NodeKind::Cast => 27,
            NodeKind::Paren => 28,
            NodeKind::Member => 29,
            NodeKind::Index => 30,
            NodeKind::New => 31,
            NodeKind::NewArray => 32,
            NodeKind::ArrayLit => 33,
            NodeKind::This => 34,
            NodeKind::InstanceOf => 35,
            NodeKind::Lambda => 36,
            NodeKind::MethodRef => 37,
            NodeKind::Raw => 38,
            NodeKind::Custom(_) => 39,
        }
    }

    /// slot 的上界(分派表定容用)。
    pub const SLOT_COUNT: usize = 42;
}

impl NodeKind {
    pub fn is_stmt(self) -> bool {
        use NodeKind::*;
        matches!(
            self,
            Block | Empty | ExprStmt | VarDecl | Assign | If | While | DoWhile | For | ForEach
                | Return | Break | Continue | Throw | Switch | Case | Try | Catch
                | Synchronized | Label | Assert | Raw
        )
    }
}

impl fmt::Display for NodeKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

/// 二元运算符(规范词汇表,语言负责映射)。
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum BinOp {
    Add,
    Sub,
    Mul,
    Div,
    Rem,
    Shl,
    Shr,
    UShr,
    Lt,
    Le,
    Gt,
    Ge,
    Eq,
    Ne,
    BitAnd,
    BitXor,
    BitOr,
    And,
    Or,
    // ---- JS 专用(语言映射词汇;Java 不产生)----
    /// `**`(幂)。右结合且非结合律——重结合类规则须跳过。
    Pow,
    /// `===`(严格相等)。与 [`BinOp::Eq`](宽松 `==`)语义不同:
    /// 折叠规则必须按语言语义分别处理。
    StrictEq,
    /// `!==`(严格不等)。
    StrictNe,
    /// `??`(空值合并——**非短路布尔**:返回操作数值而非布尔)。
    Nullish,
    /// `in`(属性存在性,二元关系)。
    In,
    /// `instanceof`(JS 的二元运算形态,RHS 是任意表达式)。
    Instanceof,
}

impl BinOp {
    pub fn is_comparison(self) -> bool {
        matches!(
            self,
            BinOp::Lt
                | BinOp::Le
                | BinOp::Gt
                | BinOp::Ge
                | BinOp::Eq
                | BinOp::Ne
                | BinOp::StrictEq
                | BinOp::StrictNe
                | BinOp::In
                | BinOp::Instanceof
        )
    }
    pub fn is_short_circuit(self) -> bool {
        matches!(self, BinOp::And | BinOp::Or | BinOp::Nullish)
    }
    /// 可能因除零抛异常的运算。
    pub fn may_div_zero(self) -> bool {
        matches!(self, BinOp::Div | BinOp::Rem)
    }
    /// 整数算术/位运算类(用于精确整数恒等式守卫)。
    pub fn is_arith(self) -> bool {
        matches!(
            self,
            BinOp::Add
                | BinOp::Sub
                | BinOp::Mul
                | BinOp::Div
                | BinOp::Rem
                | BinOp::Shl
                | BinOp::Shr
                | BinOp::UShr
                | BinOp::BitAnd
                | BinOp::BitXor
                | BinOp::BitOr
        )
    }
}

/// 一元运算符。
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum UnOp {
    Not,
    Neg,
    BitNot,
    // ---- JS 专用(语言映射词汇;Java 不产生)----
    /// `typeof x`(值恒为字符串;对未声明变量**不抛**——效果 Pure)。
    TypeOf,
    /// `void x`(求值操作数、返回 undefined——效果含操作数)。
    Void,
    /// `delete x`(可能写:删属性)。
    Delete,
    /// `await x`(仅在 async 函数内;暂停语义——效果 Unknown)。
    Await,
    /// 一元 `+`(数值提升——char/byte/short 提升 int;装箱类型改变
    /// `Object o = +c` → Integer 而非 Character)。恒等但**静态类型敏感**,
    /// 不可丢弃。
    Plus,
    /// `++x`(读+写)
    PreInc,
    PreDec,
    /// `x++`(读+写)
    PostInc,
    PostDec,
}

impl UnOp {
    pub fn is_incdec(self) -> bool {
        matches!(
            self,
            UnOp::PreInc | UnOp::PreDec | UnOp::PostInc | UnOp::PostDec
        )
    }
}

/// 字面量值的借用视图(语言 crate 从自己的负载映射)。
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum LitRef<'a> {
    Bool(bool),
    Int(i64),
    Long(i64),
    Float(f64),
    Double(f64),
    Char(char),
    Str(&'a str),
    Null,
}

impl<'a> LitRef<'a> {
    pub fn is_bool(self) -> bool {
        matches!(self, LitRef::Bool(_))
    }
    /// 整数字面量(Int/Long),返回数值。
    pub fn as_int(self) -> Option<i64> {
        match self {
            LitRef::Int(v) | LitRef::Long(v) => Some(v),
            _ => None,
        }
    }
}

/// 区域扫描事件(使用索引的原子):语句子树遍历中的一次读/写/遮蔽。
/// `node` 指向承载名字的节点(Use→VarRef;Write→赋值目标 VarRef 或
/// 声明节点;Shadow→VarDecl/ForEach/Catch 绑定节点),名字由
/// `Lang::var_name(node)` 读取——与 scan_region 原递归的判定一致。
#[derive(Clone, Copy, Debug)]
pub struct RegionEvent<Id, Key> {
    pub kind: EventKind,
    pub node: Id,
    /// 事件承载者的名字键(语言侧等价类:Java=u32 intern id)——
    /// 事件构建时预存,查询侧比较为整数等值,免 var_name/memcmp。
    pub key: Key,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum EventKind {
    /// 变量读(VarRef)
    Use,
    /// 显式局部写(赋值目标 / 自增自减目标 / 声明 / ForEach 绑定)
    Write,
    /// 同名遮蔽(VarDecl / ForEach / Catch 声明)
    Shadow,
    /// 不透明区域(Raw 不可解析原文):读写集未知——一切"零用途/
    /// 单用途/无写"的证明失效,规则必须保守拒绝(对抗波 3 抓获:
    /// 仅被 RAW 引用的变量被误删 + 值被提前传播越过 RAW 赋值)。
    Opaque,
}