Skip to main content

cure_engine/
effect.rs

1//! 副作用格(effect lattice)。
2//!
3//! `Lang::effect(id)` 返回**整棵子树**的聚合效果(最坏情况),
4//! 节点自身贡献由 `Lang::own_effect` 给出,引擎按 `worst(own, children)` 聚合。
5//!
6//! 排序约定(全序简化):`Pure < MayRead < MayThrow < MayWrite < Unknown`。
7//! `Pure` 蕴含**无任何可观察效果且结果确定**(同输入同值,可安全重求值/移动)。
8//! `MayRead` 表示只读局部变量等确定值;局部变量读与调用之间没有未知写,
9//! 因为调用无法修改语言层的局部变量。
10
11use std::cmp::Ordering;
12
13#[derive(Clone, Copy, PartialEq, Eq, Debug)]
14pub enum Effect {
15    /// 无可观察效果、结果确定。可自由移动/重求值。
16    Pure,
17    /// 只读(局部变量等)。与纯读之间可重排;被写依赖阻断。
18    MayRead,
19    /// 可能抛异常 / 读堆内存(字段、数组)等。
20    MayThrow,
21    /// 可能写内存。
22    MayWrite,
23    /// 完全未知(未知调用等)。一律视为不可简化。
24    Unknown,
25}
26
27impl Effect {
28    pub fn is_pure(self) -> bool {
29        self == Effect::Pure
30    }
31
32    pub fn worst(self, other: Effect) -> Effect {
33        if self.rank() >= other.rank() {
34            self
35        } else {
36            other
37        }
38    }
39
40    fn rank(self) -> u8 {
41        match self {
42            Effect::Pure => 0,
43            Effect::MayRead => 1,
44            Effect::MayThrow => 2,
45            Effect::MayWrite => 3,
46            Effect::Unknown => 4,
47        }
48    }
49}
50
51impl PartialOrd for Effect {
52    fn partial_cmp(&self, other: &Effect) -> Option<Ordering> {
53        Some(self.cmp(other))
54    }
55}
56
57impl Ord for Effect {
58    fn cmp(&self, other: &Effect) -> Ordering {
59        self.rank().cmp(&other.rank())
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn ordering() {
69        assert!(Effect::Pure < Effect::MayRead);
70        assert!(Effect::MayRead < Effect::MayThrow);
71        assert!(Effect::MayThrow < Effect::MayWrite);
72        assert!(Effect::MayWrite < Effect::Unknown);
73        assert_eq!(Effect::Pure.worst(Effect::MayThrow), Effect::MayThrow);
74    }
75}