devela/code/ops/call/semantics.rs
1// devela/src/code/ops/call/semantics.rs
2//
3//! Structural axes for reasoning about invocation semantics and dispatch
4//
5// TOC
6// - struct CallSemantics
7// - enum CallBindTime
8// - enum CallContext
9// - enum CallDispatch
10// - enum CallOpenness
11// - enum CallStorage
12
13use crate::Ordering;
14
15#[doc = crate::_tags!(exec)]
16/// Structural semantics of a call edge.
17#[doc = crate::_doc_meta!{location("core/ops")}]
18///
19/// The axes describe how a call is bound, dispatched, contextualized,
20/// and represented; not merely the callable value itself.
21///
22/// Effective behavior arises at the invocation boundary as the combination of:
23/// - the callable's intrinsic semantics, and
24/// - the dispatcher or container semantics.
25///
26/// Ordered axes form a product partial order (ignoring `CallOpenness`).
27///
28/// ## Invocation Categories
29///
30/// All invocation reduces to one of:
31/// - Direct call
32/// - Branch-based dispatch
33/// - Indirect function pointer call
34/// - Vtable dispatch
35///
36/// Callable representations reduce to:
37/// - Function items
38/// - Enums (closed sets)
39/// - Function pointers
40/// - Trait objects
41/// - Type-erased closures
42#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
43pub struct CallSemantics {
44 /// When callee identity is fixed.
45 pub bind: CallBindTime,
46
47 /// Where the execution environment resides.
48 pub context: CallContext,
49
50 /// Mechanism of control transfer.
51 pub dispatch: CallDispatch,
52
53 /// Whether the behavior set is fixed or extensible.
54 pub open: CallOpenness,
55
56 /// Where the callable representation is stored.
57 pub storage: CallStorage,
58}
59impl PartialOrd for CallSemantics {
60 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
61 use Ordering::{Equal, Greater, Less};
62 let axes = [
63 self.bind.cmp(&other.bind),
64 self.dispatch.cmp(&other.dispatch),
65 self.context.cmp(&other.context),
66 self.storage.cmp(&other.storage),
67 ];
68 let mut less = false;
69 let mut greater = false;
70 for ord in axes {
71 match ord {
72 Less => less = true,
73 Greater => greater = true,
74 Equal => {}
75 }
76 }
77 match (less, greater) {
78 (true, true) => None, // incomparable
79 (true, false) => Some(Less),
80 (false, true) => Some(Greater),
81 (false, false) => Some(Equal),
82 }
83 }
84}
85
86#[doc = crate::_tags!(exec)]
87/// When the callee identity becomes fixed.
88#[doc = crate::_doc_meta!{location("core/ops")}]
89///
90/// Ordered: `Compile < Build < Run`.
91///
92/// Later binding increases runtime dynamism and reduces static visibility.
93#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
94pub enum CallBindTime {
95 /// Callee identity fixed by the compiler.
96 ///
97 /// Boundary: the call graph edge is known statically and may be inlined.
98 ///
99 /// Example: direct function call or monomorphized generic.
100 Compile = 0,
101
102 /// Callee selected by build-time fixed data.
103 ///
104 /// Boundary: selection occurs via branch on a closed set
105 /// (e.g. enum or bytecode), but cannot change without rebuilding.
106 Build = 1,
107
108 /// Callee selected by runtime-provided data.
109 ///
110 /// Boundary: changing runtime data alone can alter the invoked function
111 /// (e.g. function pointers or trait objects).
112 Run = 2,
113}
114
115#[doc = crate::_tags!(exec)]
116/// Where the callable's execution environment resides.
117#[doc = crate::_doc_meta!{location("core/ops")}]
118///
119/// Ordered: `None < Receiver < Captured`.
120///
121/// This axis describes structural coupling, not argument types.
122#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
123pub enum CallContext {
124 /// No distinguished execution environment.
125 ///
126 /// Boundary: all required inputs are ordinary parameters.
127 ///
128 /// Example: `fn add(a: u32, b: u32) -> u32`.
129 None = 0,
130
131 /// Execution environment supplied explicitly by the caller.
132 ///
133 /// Boundary: a persistent state object participates in the invocation
134 /// protocol (e.g. `&mut Vm`, `&World`, or `&self`).
135 Receiver = 1,
136
137 /// Execution environment embedded inside the callable object.
138 ///
139 /// Boundary: the callable owns or encloses state not provided at call site.
140 ///
141 /// Example: `move |x| acc + x`.
142 Captured = 2,
143}
144
145#[doc = crate::_tags!(exec)]
146/// Mechanism by which control transfers to the callee.
147#[doc = crate::_doc_meta!{location("core/ops")}]
148///
149/// Ordered: `Direct < Branch < Indirect < Vtable`.
150///
151/// Later variants introduce more indirection and reduce static visibility.
152#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub enum CallDispatch {
154 /// Statically resolved call.
155 ///
156 /// Boundary: the call site encodes the callee directly.
157 Direct = 0,
158
159 /// Selection among a finite set via conditional branch.
160 ///
161 /// Boundary: dispatch occurs by matching a discriminant.
162 Branch = 1,
163
164 /// Call via function pointer.
165 ///
166 /// Boundary: callee address is loaded from memory at runtime.
167 Indirect = 2,
168
169 /// Dynamic dispatch via trait object.
170 ///
171 /// Boundary: method pointer resolved through a vtable.
172 Vtable = 3,
173}
174
175#[doc = crate::_tags!(exec)]
176/// Whether the behavior set is fixed or extensible.
177#[doc = crate::_doc_meta!{location("core/ops")}]
178///
179/// Not ordered.
180#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
181pub enum CallOpenness {
182 /// Behavior universe fixed at build time.
183 ///
184 /// Boundary: new behaviors require recompilation.
185 Closed = 0,
186
187 /// Behavior universe extensible at runtime.
188 ///
189 /// Boundary: new behaviors may be introduced without rebuilding.
190 Open = 1,
191}
192
193#[doc = crate::_tags!(exec)]
194/// Where the callable representation resides.
195#[doc = crate::_doc_meta!{location("core/ops")}]
196///
197/// Ordered: `Static < Inline < Arena < Heap`.
198///
199/// Later variants increase allocation dynamism and indirection.
200#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
201pub enum CallStorage {
202 /// Representation baked into the binary.
203 ///
204 /// Boundary: no allocation and program-long lifetime.
205 Static = 0,
206
207 /// Stored inline with known size.
208 ///
209 /// Boundary: concrete layout known at compile time.
210 Inline = 1,
211
212 /// Stored in type-erased managed buffer.
213 ///
214 /// Boundary: size erased; lifetime managed externally.
215 Arena = 2,
216
217 /// Stored in heap allocation.
218 ///
219 /// Boundary: allocation-managed memory.
220 Heap = 3,
221}