1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
//! Effect Row Types - Type-Level Effect Sets
//!
//! Effect rows represent sets of effects at the type level. This module provides
//! the foundation for zero-cost effects by enabling compile-time effect tracking
//! without runtime overhead.
//!
//! # Design
//!
//! Effect rows use const-generic bitmasks for O(1) effect membership checking:
//!
//! ```text
//! Row Representation (u128 bitmask):
//! ┌─────────────────────────────────────────────────────────────┐
//! │ Bit 0: IO │ Bit 1: State │ Bit 2: Error │ ... │
//! │ Bit 3: Reader │ Bit 4: Writer │ Bit 5: Async │ ... │
//! │ Bit 6: Choice │ Bit 7: Nondet │ Bit 8-127: User │ │
//! └─────────────────────────────────────────────────────────────┘
//! ```
//!
//! This allows effect operations (union, intersection, membership) to compile
//! to single CPU instructions.
//!
//! # Relation to `effects::row_v2`
//!
//! This module and `effects::row_v2` are two deliberate, coexisting
//! type-level effect-set encodings: this `Row<const MASK: u128>` serves the
//! `nexus`-gated effect system; `row_v2`'s `EffectSet<const MASK: u128>`
//! serves the `async`-gated `effects` system (inline-const verified). No
//! bridge exists, deliberately — no consumer composes both in one signature.
//! Revisit unification only if such a consumer appears; this module is then
//! the donor encoding and `EffectSet` the target.
// =============================================================================
// Effect Row Trait
// =============================================================================
/// A type-level effect row representing a set of effects.
///
/// This trait is implemented for effect row types and provides const-generic
/// operations for zero-cost effect tracking.
///
/// # Const Parameters
///
/// The row is represented as a u128 bitmask where each bit represents the
/// presence of a specific effect. This allows all row operations to be
/// computed at compile time.
// =============================================================================
// Effect Bit Constants
// =============================================================================
/// Bit position for the IO effect.
pub const IO_BIT: u128 = 1 << 0;
/// Bit position for the State effect.
pub const STATE_BIT: u128 = 1 << 1;
/// Bit position for the Error effect.
pub const ERROR_BIT: u128 = 1 << 2;
/// Bit position for the Reader effect.
pub const READER_BIT: u128 = 1 << 3;
/// Bit position for the Writer effect.
pub const WRITER_BIT: u128 = 1 << 4;
/// Bit position for the Async effect.
pub const ASYNC_BIT: u128 = 1 << 5;
/// Bit position for the Choice effect.
pub const CHOICE_BIT: u128 = 1 << 6;
/// Bit position for the Nondet effect.
pub const NONDET_BIT: u128 = 1 << 7;
/// Start of user-defined effect bits.
pub const USER_EFFECT_START: u128 = 1 << 8;
// =============================================================================
// Pure Effect Row
// =============================================================================
/// The empty effect row representing pure computation.
///
/// `Pure` is the identity for effect row union and indicates that a computation
/// has no side effects. Computations with `Pure` effect row can be:
/// - Freely reordered
/// - Automatically parallelized
/// - Memoized without concern
///
/// # Example
///
/// ```rust
/// use ordofp_core::nexus::{pure, Eff, Pure};
///
/// // A pure computation can be run directly
/// let result: Eff<Pure, i32> = pure(42);
/// assert_eq!(result.run_pure(), 42);
/// ```
;
// =============================================================================
// Concrete Row Types
// =============================================================================
/// A concrete effect row with a specific bitmask.
///
/// This type represents effect rows at runtime, though most operations
/// are performed at compile time through const generics.
;
// =============================================================================
// Row Operations
// =============================================================================
// Note: Type aliases with const-generic expressions and where clauses
// require the lazy_type_alias feature. For now, we use functions instead.
/// Compute the union of two effect row bitmasks.
///
/// Returns the set of effects present in **either** `R1` or `R2` (or both).
/// An effect bit is set in the result whenever it is set in at least one of
/// the two input rows.
///
/// The result is evaluated at **compile time** when both `R1::BITS` and
/// `R2::BITS` are `const`.
///
/// # Use cases
///
/// - Combining the effects of two computations that will be sequenced
/// together (e.g. via `.and_then`).
/// - Building composite effect rows from individual effect markers.
///
/// # Examples
///
/// ```rust
/// use ordofp_core::nexus::prelude::{IoRow, StateRow};
/// use ordofp_core::nexus::{row_union_bits, EffectRow, Pure};
///
/// // IO ∪ State contains both effect bits.
/// let combined = row_union_bits::<IoRow, StateRow>();
/// assert!(combined & IoRow::BITS != 0);
/// assert!(combined & StateRow::BITS != 0);
///
/// // Any row unioned with Pure equals itself (Pure has no effect bits).
/// assert_eq!(row_union_bits::<IoRow, Pure>(), IoRow::BITS);
///
/// // Idempotent: a row unioned with itself is itself.
/// assert_eq!(row_union_bits::<StateRow, StateRow>(), StateRow::BITS);
/// ```
pub const
/// Compute the intersection of two effect row bitmasks.
///
/// Returns the set of effects that are present in **both** `R1` and `R2`.
/// An effect bit is set in the result only when it is set in both input rows.
///
/// The check is evaluated at **compile time** when both `R1::BITS` and
/// `R2::BITS` are `const`.
///
/// # Use cases
///
/// - Verifying that two computations share a common set of effects before
/// combining them.
/// - Effect analysis passes that need to identify overlapping requirements.
///
/// # Examples
///
/// ```rust
/// use ordofp_core::nexus::prelude::{IoRow, IoStateRow, StateRow};
/// use ordofp_core::nexus::{row_intersect_bits, Pure};
///
/// // IO ∩ State = ∅ (no bits in common)
/// assert_eq!(row_intersect_bits::<IoRow, StateRow>(), 0);
///
/// // (IO + State) ∩ IO = IO
/// assert_eq!(row_intersect_bits::<IoStateRow, IoRow>(), row_intersect_bits::<IoRow, IoRow>());
///
/// // Any row intersected with Pure gives the empty row.
/// assert_eq!(row_intersect_bits::<IoRow, Pure>(), 0);
/// ```
pub const
/// Compute the difference of two effect row bitmasks.
pub const
/// Returns `true` if every effect in `R1` is also present in `R2`.
///
/// A computation typed as `Eff<R1, A>` can be safely widened to `Eff<R2, A>`
/// whenever `row_subset::<R1, R2>()` holds — the handler for `R2` knows how
/// to discharge all of `R1`'s effects because `R2` is a superset of them.
///
/// The check is a single bitmask test and is evaluated at **compile time**
/// when both `R1::BITS` and `R2::BITS` are `const`.
///
/// # Examples
///
/// ```rust
/// use ordofp_core::nexus::prelude::{row_subset, IoRow, IoStateRow, Pure, StateRow};
///
/// // A pure row is a subset of every row (no effects to satisfy).
/// assert!(row_subset::<Pure, IoRow>());
///
/// // IO ⊆ IO + State, but IO + State ⊄ IO.
/// assert!( row_subset::<IoRow, IoStateRow>());
/// assert!(!row_subset::<IoStateRow, IoRow>());
///
/// // Any row is a subset of itself.
/// assert!(row_subset::<StateRow, StateRow>());
/// ```
pub const
/// Check if two rows are equal.
pub const
// =============================================================================
// Effect Row Macros
// =============================================================================
/// Macro for creating effect row types.
///
/// # Example
///
/// ```rust
/// use ordofp_core::effect_row;
/// use ordofp_core::nexus::{EffectRow, Error, State, IO};
///
/// struct Config;
/// struct AppError;
///
/// type MyEffects = effect_row![IO, State<Config>, Error<AppError>];
///
/// assert!(MyEffects::HAS_IO);
/// assert!(MyEffects::HAS_STATE);
/// assert!(MyEffects::HAS_ERROR);
/// ```
;
=> >
};
}
// =============================================================================
// Row Type Aliases for Common Patterns
// =============================================================================
/// IO-only effect row.
pub type IoRow = ;
/// State-only effect row.
pub type StateRow = ;
/// Error-only effect row.
pub type ErrorRow = ;
/// Reader-only effect row.
pub type ReaderRow = ;
/// Writer-only effect row.
pub type WriterRow = ;
/// Async-only effect row.
pub type AsyncRow = ;
/// IO + Error effects (common pattern).
pub type IoErrorRow = IO_BIT | ERROR_BIT }>;
/// IO + State effects.
pub type IoStateRow = IO_BIT | STATE_BIT }>;
/// Full synchronous effects (IO + State + Error + Reader + Writer).
pub type FullSyncRow = IO_BIT | STATE_BIT | ERROR_BIT | READER_BIT | WRITER_BIT }>;
// =============================================================================
// Tests
// =============================================================================