1#[cfg(stageleft_runtime)]
7use std::marker::PhantomData;
8
9use super::Slicable;
10#[cfg(stageleft_runtime)]
11use crate::forward_handle::{CycleCollection, CycleCollectionWithInitial};
12use crate::forward_handle::{TickCycle, TickCycleHandle};
13use crate::live_collections::boundedness::{Bounded, Boundedness, Unbounded};
14use crate::live_collections::keyed_singleton::{
15 BoundedValue, KeyedSingletonBound, KeyedSingletonSnapshotBound,
16};
17use crate::live_collections::optional::OptionalBound;
18use crate::live_collections::singleton::SingletonBound;
19use crate::live_collections::stream::{ExactlyOnce, Ordering, Retries, TotalOrder};
20use crate::location::Location;
21use crate::location::tick::{DeferTick, Tick};
22use crate::nondet::{NonDet, nondet};
23
24pub struct Default<T> {
29 pub(crate) collection: T,
30 pub(crate) nondet: NonDet,
31}
32
33impl<T> Default<T> {
34 pub fn new(collection: T, nondet: NonDet) -> Self {
36 Self { collection, nondet }
37 }
38}
39
40#[doc(hidden)]
42#[deprecated(
43 note = "use `use::batch(...)` for stream-like collections or `use::snapshot(...)` for singleton-like collections instead"
44)]
45pub fn default<T>(t: T, nondet: NonDet) -> Default<T> {
46 Default::new(t, nondet)
47}
48
49pub struct Batch<T, H = ()> {
53 pub(crate) collection: T,
54 pub(crate) nondet: NonDet<H>,
55}
56
57impl<T, H> Batch<T, H> {
58 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
60 Self { collection, nondet }
61 }
62}
63
64pub fn batch<T, H>(t: T, nondet: NonDet<H>) -> Batch<T, H> {
69 Batch::new(t, nondet)
70}
71
72pub struct Snapshot<T, H = ()> {
76 pub(crate) collection: T,
77 pub(crate) nondet: NonDet<H>,
78}
79
80impl<T, H> Snapshot<T, H> {
81 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
83 Self { collection, nondet }
84 }
85}
86
87pub fn snapshot<T, H>(t: T, nondet: NonDet<H>) -> Snapshot<T, H> {
93 Snapshot::new(t, nondet)
94}
95
96pub struct Atomic<T> {
100 pub(crate) collection: T,
101 pub(crate) nondet: NonDet,
102}
103
104impl<T> Atomic<T> {
105 pub fn new(collection: T, nondet: NonDet) -> Self {
107 Self { collection, nondet }
108 }
109}
110
111pub fn atomic<T>(t: T, nondet: NonDet) -> Atomic<T> {
113 Atomic::new(t, nondet)
114}
115
116#[cfg(stageleft_runtime)]
129pub fn state<'t, S, L>(tick: &'t Tick<L>) -> StateBuilder<'t, S, L> {
130 StateBuilder {
131 tick,
132 _phantom: PhantomData,
133 }
134}
135
136#[cfg(stageleft_runtime)]
138pub struct StateBuilder<'t, S, L> {
139 tick: &'t Tick<L>,
140 _phantom: PhantomData<S>,
141}
142
143#[cfg(stageleft_runtime)]
144impl<'t, 'a, S, L: Location<'a>> StateBuilder<'t, S, L> {
145 #[expect(
153 private_bounds,
154 reason = "only Hydro collections can implement CycleCollectionWithInitial"
155 )]
156 pub fn build(self, initial_fn: impl FnOnce(&'t Tick<L>) -> S) -> (TickCycleHandle<'a, S>, S)
157 where
158 S: CycleCollectionWithInitial<'a, TickCycle, Location = Tick<L::DropConsistency>>,
159 {
160 let initial = initial_fn(self.tick);
161 initial.location().clone().cycle_with_initial(initial)
162 }
163}
164
165#[cfg(stageleft_runtime)]
173pub fn state_null<'t, S, L>(tick: &'t Tick<L>) -> StateNullBuilder<'t, S, L> {
174 StateNullBuilder {
175 tick,
176 _phantom: PhantomData,
177 }
178}
179
180#[cfg(stageleft_runtime)]
182pub struct StateNullBuilder<'t, S, L> {
183 tick: &'t Tick<L>,
184 _phantom: PhantomData<S>,
185}
186
187#[cfg(stageleft_runtime)]
188impl<'t, 'a, S, L: Location<'a>> StateNullBuilder<'t, S, L> {
189 #[expect(
191 private_bounds,
192 reason = "only Hydro collections can implement CycleCollection"
193 )]
194 pub fn build(self) -> (TickCycleHandle<'a, S>, S)
195 where
196 S: CycleCollection<'a, TickCycle, Location = Tick<L::DropConsistency>> + DeferTick,
197 {
198 self.tick.cycle::<S, _>()
199 }
200}
201
202impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
210 Slicable<'a, L::DropConsistency> for Default<crate::live_collections::Stream<T, L, B, O, R>>
211{
212 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
213 type Backtrace = crate::compile::ir::backtrace::Backtrace;
214
215 fn get_location(&self) -> L::DropConsistency {
216 self.collection.location().drop_consistency()
217 }
218 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
219 let _ = self.nondet;
220 let out = self.collection.batch(
221 tick,
222 nondet!(),
223 );
224 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
225 out
226 }
227}
228
229impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
230 for Default<crate::live_collections::Singleton<T, L, B>>
231{
232 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
233 type Backtrace = crate::compile::ir::backtrace::Backtrace;
234
235 fn get_location(&self) -> L::DropConsistency {
236 self.collection.location().drop_consistency()
237 }
238 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
239 let _ = self.nondet;
240 let out = self.collection.snapshot(
241 tick,
242 nondet!(),
243 );
244 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
245 out
246 }
247}
248
249impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
250 for Default<crate::live_collections::Optional<T, L, B>>
251{
252 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
253 type Backtrace = crate::compile::ir::backtrace::Backtrace;
254
255 fn get_location(&self) -> L::DropConsistency {
256 self.collection.location().drop_consistency()
257 }
258 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
259 let out = self.collection.snapshot(tick, self.nondet);
260 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
261 out
262 }
263}
264
265impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
266 Slicable<'a, L::DropConsistency>
267 for Default<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
268{
269 type Slice =
270 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
271 type Backtrace = crate::compile::ir::backtrace::Backtrace;
272
273 fn get_location(&self) -> L::DropConsistency {
274 self.collection.location().drop_consistency()
275 }
276 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
277 let _ = self.nondet;
278 let out = self.collection.batch(
279 tick,
280 nondet!(),
281 );
282 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
283 out
284 }
285}
286
287impl<'a, K, V, L: Location<'a>, B: KeyedSingletonSnapshotBound<ValueBound = Unbounded>>
288 Slicable<'a, L::DropConsistency>
289 for Default<crate::live_collections::KeyedSingleton<K, V, L, B>>
290{
291 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
292 type Backtrace = crate::compile::ir::backtrace::Backtrace;
293
294 fn get_location(&self) -> L::DropConsistency {
295 self.collection.location().drop_consistency()
296 }
297 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
298 let _ = self.nondet;
299 let out = self.collection.snapshot(
300 tick,
301 nondet!(),
302 );
303 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
304 out
305 }
306}
307
308impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
309 for Default<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
310{
311 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
312 type Backtrace = crate::compile::ir::backtrace::Backtrace;
313
314 fn get_location(&self) -> L::DropConsistency {
315 self.collection.location().drop_consistency()
316 }
317 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
318 let _ = self.nondet;
319 let out = self.collection.batch(
320 tick,
321 nondet!(),
322 );
323 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
324 out
325 }
326}
327
328impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
336 Slicable<'a, L::DropConsistency>
337 for Batch<
338 crate::live_collections::Stream<T, L, B, O, R>,
339 Option<crate::sim_hooks::BatchHook<T, O, R, L::SimHookScope>>,
340 >
341{
342 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
343 type Backtrace = crate::compile::ir::backtrace::Backtrace;
344
345 fn get_location(&self) -> L::DropConsistency {
346 self.collection.location().drop_consistency()
347 }
348 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
349 let out = self.collection.batch(tick, self.nondet);
350 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
351 out
352 }
353}
354
355impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
356 Slicable<'a, L::DropConsistency>
357 for Batch<
358 crate::live_collections::KeyedStream<K, V, L, B, O, R>,
359 Option<crate::sim_hooks::KeyedBatchHook<K, V, O, R, L::SimHookScope>>,
360 >
361{
362 type Slice =
363 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
364 type Backtrace = crate::compile::ir::backtrace::Backtrace;
365
366 fn get_location(&self) -> L::DropConsistency {
367 self.collection.location().drop_consistency()
368 }
369 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
370 let out = self.collection.batch(tick, self.nondet);
371 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
372 out
373 }
374}
375
376impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Bounded>>
377 Slicable<'a, L::DropConsistency>
378 for Batch<
379 crate::live_collections::KeyedSingleton<K, V, L, B>,
380 Option<crate::sim_hooks::KeyedBatchHook<K, V, TotalOrder, ExactlyOnce, L::SimHookScope>>,
381 >
382{
383 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
384 type Backtrace = crate::compile::ir::backtrace::Backtrace;
385
386 fn get_location(&self) -> L::DropConsistency {
387 self.collection.location().drop_consistency()
388 }
389 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
390 let out = self.collection.batch(tick, self.nondet);
391 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
392 out
393 }
394}
395
396impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
404 for Snapshot<
405 crate::live_collections::Singleton<T, L, B>,
406 Option<crate::sim_hooks::SnapshotHook<T, L::SimHookScope>>,
407 >
408{
409 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
410 type Backtrace = crate::compile::ir::backtrace::Backtrace;
411
412 fn get_location(&self) -> L::DropConsistency {
413 self.collection.location().drop_consistency()
414 }
415 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
416 let out = self.collection.snapshot(tick, self.nondet);
417 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
418 out
419 }
420}
421
422impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
423 for Snapshot<crate::live_collections::Optional<T, L, B>>
424{
425 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
426 type Backtrace = crate::compile::ir::backtrace::Backtrace;
427
428 fn get_location(&self) -> L::DropConsistency {
429 self.collection.location().drop_consistency()
430 }
431 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
432 let out = self.collection.snapshot(tick, self.nondet);
433 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
434 out
435 }
436}
437
438impl<'a, K, V, L: Location<'a>, B: KeyedSingletonSnapshotBound> Slicable<'a, L::DropConsistency>
439 for Snapshot<
440 crate::live_collections::KeyedSingleton<K, V, L, B>,
441 Option<crate::sim_hooks::KeyedSnapshotHook<K, V, L::SimHookScope>>,
442 >
443{
444 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
445 type Backtrace = crate::compile::ir::backtrace::Backtrace;
446
447 fn get_location(&self) -> L::DropConsistency {
448 self.collection.location().drop_consistency()
449 }
450 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
451 let out = self.collection.snapshot(tick, self.nondet);
452 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
453 out
454 }
455}
456
457impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
462 Slicable<'a, L::DropConsistency>
463 for Atomic<crate::live_collections::Stream<T, crate::location::Atomic<L>, B, O, R>>
464{
465 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
466 type Backtrace = crate::compile::ir::backtrace::Backtrace;
467 fn get_location(&self) -> L::DropConsistency {
468 self.collection.location().tick.l.drop_consistency()
469 }
470
471 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
472 let _ = self.nondet;
473 let out = self.collection.batch_atomic(
474 tick,
475 nondet!(),
476 );
477 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
478 out
479 }
480}
481
482impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
483 for Atomic<crate::live_collections::Singleton<T, crate::location::Atomic<L>, B>>
484{
485 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
486 type Backtrace = crate::compile::ir::backtrace::Backtrace;
487 fn get_location(&self) -> L::DropConsistency {
488 self.collection.location().tick.l.drop_consistency()
489 }
490
491 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
492 let _ = self.nondet;
493 let out = self.collection.snapshot_atomic(
494 tick,
495 nondet!(),
496 );
497 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
498 out
499 }
500}
501
502impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
503 for Atomic<crate::live_collections::Optional<T, crate::location::Atomic<L>, B>>
504{
505 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
506 type Backtrace = crate::compile::ir::backtrace::Backtrace;
507 fn get_location(&self) -> L::DropConsistency {
508 self.collection.location().tick.l.drop_consistency()
509 }
510
511 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
512 let out = self.collection.snapshot_atomic(tick, self.nondet);
513 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
514 out
515 }
516}
517
518impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
519 Slicable<'a, L::DropConsistency>
520 for Atomic<crate::live_collections::KeyedStream<K, V, crate::location::Atomic<L>, B, O, R>>
521{
522 type Slice =
523 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
524 type Backtrace = crate::compile::ir::backtrace::Backtrace;
525 fn get_location(&self) -> L::DropConsistency {
526 self.collection.location().tick.l.drop_consistency()
527 }
528
529 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
530 let out = self.collection.batch_atomic(tick, self.nondet);
531 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
532 out
533 }
534}
535
536impl<'a, K, V, L: Location<'a>, B: KeyedSingletonSnapshotBound<ValueBound = Unbounded>>
537 Slicable<'a, L::DropConsistency>
538 for Atomic<crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, B>>
539{
540 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
541 type Backtrace = crate::compile::ir::backtrace::Backtrace;
542 fn get_location(&self) -> L::DropConsistency {
543 self.collection.location().tick.l.drop_consistency()
544 }
545
546 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
547 let out = self.collection.snapshot_atomic(tick, self.nondet);
548 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
549 out
550 }
551}
552
553impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
554 for Atomic<
555 crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, BoundedValue>,
556 >
557{
558 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
559 type Backtrace = crate::compile::ir::backtrace::Backtrace;
560 fn get_location(&self) -> L::DropConsistency {
561 self.collection.location().tick.l.drop_consistency()
562 }
563
564 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
565 let out = self.collection.batch_atomic(tick, self.nondet);
566 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
567 out
568 }
569}