Skip to main content

aleph_syntax_tree/
effects.rs

1use serde::{Deserialize, Serialize};
2use std::collections::BTreeSet;
3
4/// What a function is declared to be able to do. Attached to a subtree via
5/// `AlephTree::WithEffects`. A function whose effect row is `[Pure]` cannot
6/// call one whose row includes `Io`, `Net`, `Mut`, or `Act` — that check is
7/// the type/effect checker's job, not this crate's; this crate only defines
8/// the vocabulary.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
10pub enum Effect {
11    /// No observable side effect.
12    Pure,
13    /// Reads or writes outside the program (files, stdout, environment).
14    Io,
15    /// Network access.
16    Net,
17    /// Mutates shared/external state in place.
18    Mut,
19    /// Invokes the cognitive runtime (`Intend`/`Suggest`/`Act`/`Remember`/`Perceive`).
20    Act,
21}
22
23/// A function's declared effect row. `BTreeSet`, not `Vec`: duplicates are
24/// meaningless here, and — unlike `HashSet` — iteration order is fixed, so
25/// two structurally-identical effect rows always serialize to identical
26/// bytes (required for deterministic content hashing elsewhere in this crate).
27pub type EffectSet = BTreeSet<Effect>;
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32
33    #[test]
34    fn serializes_and_round_trips_through_json() {
35        let effects: EffectSet = EffectSet::from([Effect::Io, Effect::Act]);
36        let json = serde_json::to_string(&effects).unwrap();
37        let back: EffectSet = serde_json::from_str(&json).unwrap();
38        assert_eq!(effects, back);
39    }
40
41    #[test]
42    fn json_wire_format_is_locked() {
43        // Guards against an accidental #[serde(rename_all = ...)] or
44        // re-tagging change silently breaking non-Rust consumers.
45        assert_eq!(serde_json::to_string(&Effect::Io).unwrap(), "\"Io\"");
46        assert_eq!(serde_json::to_string(&Effect::Act).unwrap(), "\"Act\"");
47    }
48
49    #[test]
50    fn duplicates_collapse_and_serialization_order_is_stable() {
51        let a: EffectSet = EffectSet::from([Effect::Act, Effect::Io, Effect::Io]);
52        let b: EffectSet = EffectSet::from([Effect::Io, Effect::Act]);
53        assert_eq!(a, b);
54        assert_eq!(serde_json::to_string(&a).unwrap(), serde_json::to_string(&b).unwrap());
55    }
56}