aver/types/effect_event.rs
1//! EffectEvent — opaque builtin representing one recorded effect emission.
2//!
3//! In Oracle v1's trace API, each call to `trace.event(k)` returns an
4//! `Option<EffectEvent>`. The event carries enough data to answer:
5//!
6//! - "What effect method was emitted?" → `event.is(Console.print)`
7//! - "What value was passed?" → `match event ... Some(Console.print(msg))`
8//! - "Is it equal to this literal?" → `trace.contains(Console.print("hi"))`
9//!
10//! User code never constructs `EffectEvent` directly. Three elaboration
11//! paths in verify-trace context produce event values:
12//!
13//! - Expression position: `Console.print("x")` → event literal.
14//! - Pattern position: `Console.print(msg)` in a `match` arm → destructuring.
15//! - Bare reference: `Console.print` → effect-type predicate (used with
16//! `event.is(...)` and overloaded `trace.contains(...)`).
17//!
18//! Internal representation: `{ method: String, args: List<Value> }` where
19//! `args` carries the runtime values emitted, typed per the effect
20//! method's signature (polymorphic `T` for `Console.print`, concrete types
21//! for classified generative effects).
22
23use crate::nan_value::Arena;
24
25pub const TYPE_NAME: &str = "EffectEvent";
26pub const FIELD_METHOD: &str = "method";
27pub const FIELD_ARGS: &str = "args";
28/// Dewey-decimal path string identifying the structural position
29/// where the event was emitted. Empty for sequential-level events
30/// (outside any `!`/`?!` group) — matches the `BranchPath.root`
31/// convention. `BranchPath.parse(event.path)` round-trips the value
32/// back to an opaque `BranchPath`.
33pub const FIELD_PATH: &str = "path";
34
35/// Construct the arena type registration. Called alongside other builtin
36/// record types from `vm::register_service_types`.
37pub fn register(arena: &mut Arena) {
38 arena.register_record_type(
39 TYPE_NAME,
40 vec![FIELD_METHOD.into(), FIELD_ARGS.into(), FIELD_PATH.into()],
41 );
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::nan_value::Arena;
48
49 #[test]
50 fn registers_type_with_expected_fields() {
51 let mut arena = Arena::new();
52 register(&mut arena);
53 let type_id = arena
54 .find_type_id(TYPE_NAME)
55 .expect("EffectEvent must register");
56 // Round-trip a record with the expected field arity to confirm the
57 // registration actually wired through. Fields come back in the order
58 // they were registered.
59 let method = crate::nan_value::NanValue::new_string_value("Console.print", &mut arena);
60 let args = crate::nan_value::NanValue::new_string_value("[]", &mut arena);
61 let idx = arena.push_record(type_id, vec![method, args]);
62 let nv = crate::nan_value::NanValue::new_record(idx);
63 let (tid, fields) = arena.get_record(nv.arena_index());
64 assert_eq!(tid, type_id);
65 assert_eq!(fields.len(), 2);
66 }
67}