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::{BoundedValue, KeyedSingletonBound};
15use crate::live_collections::optional::OptionalBound;
16use crate::live_collections::singleton::SingletonBound;
17use crate::live_collections::stream::{Ordering, Retries};
18use crate::location::Location;
19use crate::location::tick::{DeferTick, Tick};
20use crate::nondet::{NonDet, nondet};
21
22pub struct Default<T> {
27 pub(crate) collection: T,
28 pub(crate) nondet: NonDet,
29}
30
31impl<T> Default<T> {
32 pub fn new(collection: T, nondet: NonDet) -> Self {
34 Self { collection, nondet }
35 }
36}
37
38#[doc(hidden)]
40#[deprecated(
41 note = "use `use::batch(...)` for stream-like collections or `use::snapshot(...)` for singleton-like collections instead"
42)]
43pub fn default<T>(t: T, nondet: NonDet) -> Default<T> {
44 Default::new(t, nondet)
45}
46
47pub struct Batch<T, H = ()> {
51 pub(crate) collection: T,
52 pub(crate) nondet: NonDet<H>,
53}
54
55impl<T, H> Batch<T, H> {
56 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
58 Self { collection, nondet }
59 }
60}
61
62pub fn batch<T, H>(t: T, nondet: NonDet<H>) -> Batch<T, H> {
67 Batch::new(t, nondet)
68}
69
70pub struct Snapshot<T, H = ()> {
74 pub(crate) collection: T,
75 pub(crate) nondet: NonDet<H>,
76}
77
78impl<T, H> Snapshot<T, H> {
79 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
81 Self { collection, nondet }
82 }
83}
84
85pub fn snapshot<T, H>(t: T, nondet: NonDet<H>) -> Snapshot<T, H> {
91 Snapshot::new(t, nondet)
92}
93
94pub struct Atomic<T> {
98 pub(crate) collection: T,
99 pub(crate) nondet: NonDet,
100}
101
102impl<T> Atomic<T> {
103 pub fn new(collection: T, nondet: NonDet) -> Self {
105 Self { collection, nondet }
106 }
107}
108
109pub fn atomic<T>(t: T, nondet: NonDet) -> Atomic<T> {
111 Atomic::new(t, nondet)
112}
113
114#[cfg(stageleft_runtime)]
127pub fn state<'t, S, L>(tick: &'t Tick<L>) -> StateBuilder<'t, S, L> {
128 StateBuilder {
129 tick,
130 _phantom: PhantomData,
131 }
132}
133
134#[cfg(stageleft_runtime)]
136pub struct StateBuilder<'t, S, L> {
137 tick: &'t Tick<L>,
138 _phantom: PhantomData<S>,
139}
140
141#[cfg(stageleft_runtime)]
142impl<'t, 'a, S, L: Location<'a>> StateBuilder<'t, S, L> {
143 #[expect(
151 private_bounds,
152 reason = "only Hydro collections can implement CycleCollectionWithInitial"
153 )]
154 pub fn build(self, initial_fn: impl FnOnce(&'t Tick<L>) -> S) -> (TickCycleHandle<'a, S>, S)
155 where
156 S: CycleCollectionWithInitial<'a, TickCycle, Location = Tick<L::DropConsistency>>,
157 {
158 let initial = initial_fn(self.tick);
159 initial.location().clone().cycle_with_initial(initial)
160 }
161}
162
163#[cfg(stageleft_runtime)]
171pub fn state_null<'t, S, L>(tick: &'t Tick<L>) -> StateNullBuilder<'t, S, L> {
172 StateNullBuilder {
173 tick,
174 _phantom: PhantomData,
175 }
176}
177
178#[cfg(stageleft_runtime)]
180pub struct StateNullBuilder<'t, S, L> {
181 tick: &'t Tick<L>,
182 _phantom: PhantomData<S>,
183}
184
185#[cfg(stageleft_runtime)]
186impl<'t, 'a, S, L: Location<'a>> StateNullBuilder<'t, S, L> {
187 #[expect(
189 private_bounds,
190 reason = "only Hydro collections can implement CycleCollection"
191 )]
192 pub fn build(self) -> (TickCycleHandle<'a, S>, S)
193 where
194 S: CycleCollection<'a, TickCycle, Location = Tick<L::DropConsistency>> + DeferTick,
195 {
196 self.tick.cycle::<S, _>()
197 }
198}
199
200impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
208 Slicable<'a, L::DropConsistency> for Default<crate::live_collections::Stream<T, L, B, O, R>>
209{
210 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
211 type Backtrace = crate::compile::ir::backtrace::Backtrace;
212
213 fn get_location(&self) -> L::DropConsistency {
214 self.collection.location().drop_consistency()
215 }
216 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
217 let _ = self.nondet;
218 let out = self.collection.batch(
219 tick,
220 nondet!(),
221 );
222 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
223 out
224 }
225}
226
227impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
228 for Default<crate::live_collections::Singleton<T, L, B>>
229{
230 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
231 type Backtrace = crate::compile::ir::backtrace::Backtrace;
232
233 fn get_location(&self) -> L::DropConsistency {
234 self.collection.location().drop_consistency()
235 }
236 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
237 let _ = self.nondet;
238 let out = self.collection.snapshot(
239 tick,
240 nondet!(),
241 );
242 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
243 out
244 }
245}
246
247impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
248 for Default<crate::live_collections::Optional<T, L, B>>
249{
250 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
251 type Backtrace = crate::compile::ir::backtrace::Backtrace;
252
253 fn get_location(&self) -> L::DropConsistency {
254 self.collection.location().drop_consistency()
255 }
256 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
257 let out = self.collection.snapshot(tick, self.nondet);
258 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
259 out
260 }
261}
262
263impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
264 Slicable<'a, L::DropConsistency>
265 for Default<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
266{
267 type Slice =
268 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
269 type Backtrace = crate::compile::ir::backtrace::Backtrace;
270
271 fn get_location(&self) -> L::DropConsistency {
272 self.collection.location().drop_consistency()
273 }
274 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
275 let out = self.collection.batch(tick, self.nondet);
276 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
277 out
278 }
279}
280
281impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
282 Slicable<'a, L::DropConsistency>
283 for Default<crate::live_collections::KeyedSingleton<K, V, L, B>>
284{
285 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
286 type Backtrace = crate::compile::ir::backtrace::Backtrace;
287
288 fn get_location(&self) -> L::DropConsistency {
289 self.collection.location().drop_consistency()
290 }
291 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
292 let out = self.collection.snapshot(tick, self.nondet);
293 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
294 out
295 }
296}
297
298impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
299 for Default<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
300{
301 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
302 type Backtrace = crate::compile::ir::backtrace::Backtrace;
303
304 fn get_location(&self) -> L::DropConsistency {
305 self.collection.location().drop_consistency()
306 }
307 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
308 let out = self.collection.batch(tick, self.nondet);
309 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
310 out
311 }
312}
313
314impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
322 Slicable<'a, L::DropConsistency>
323 for Batch<
324 crate::live_collections::Stream<T, L, B, O, R>,
325 Option<crate::sim_hooks::BatchHook<T, O, R>>,
326 >
327{
328 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
329 type Backtrace = crate::compile::ir::backtrace::Backtrace;
330
331 fn get_location(&self) -> L::DropConsistency {
332 self.collection.location().drop_consistency()
333 }
334 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
335 let out = self.collection.batch(tick, self.nondet);
336 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
337 out
338 }
339}
340
341impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
342 Slicable<'a, L::DropConsistency>
343 for Batch<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
344{
345 type Slice =
346 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
347 type Backtrace = crate::compile::ir::backtrace::Backtrace;
348
349 fn get_location(&self) -> L::DropConsistency {
350 self.collection.location().drop_consistency()
351 }
352 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
353 let out = self.collection.batch(tick, self.nondet);
354 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
355 out
356 }
357}
358
359impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
360 for Batch<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
361{
362 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
363 type Backtrace = crate::compile::ir::backtrace::Backtrace;
364
365 fn get_location(&self) -> L::DropConsistency {
366 self.collection.location().drop_consistency()
367 }
368 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
369 let out = self.collection.batch(tick, self.nondet);
370 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
371 out
372 }
373}
374
375impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
383 for Snapshot<
384 crate::live_collections::Singleton<T, L, B>,
385 Option<crate::sim_hooks::SnapshotHook<T>>,
386 >
387{
388 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
389 type Backtrace = crate::compile::ir::backtrace::Backtrace;
390
391 fn get_location(&self) -> L::DropConsistency {
392 self.collection.location().drop_consistency()
393 }
394 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
395 let out = self.collection.snapshot(tick, self.nondet);
396 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
397 out
398 }
399}
400
401impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
402 for Snapshot<crate::live_collections::Optional<T, L, B>>
403{
404 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
405 type Backtrace = crate::compile::ir::backtrace::Backtrace;
406
407 fn get_location(&self) -> L::DropConsistency {
408 self.collection.location().drop_consistency()
409 }
410 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
411 let out = self.collection.snapshot(tick, self.nondet);
412 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
413 out
414 }
415}
416
417impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
418 Slicable<'a, L::DropConsistency>
419 for Snapshot<crate::live_collections::KeyedSingleton<K, V, L, B>>
420{
421 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
422 type Backtrace = crate::compile::ir::backtrace::Backtrace;
423
424 fn get_location(&self) -> L::DropConsistency {
425 self.collection.location().drop_consistency()
426 }
427 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
428 let out = self.collection.snapshot(tick, self.nondet);
429 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
430 out
431 }
432}
433
434impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
439 Slicable<'a, L::DropConsistency>
440 for Atomic<crate::live_collections::Stream<T, crate::location::Atomic<L>, B, O, R>>
441{
442 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
443 type Backtrace = crate::compile::ir::backtrace::Backtrace;
444 fn get_location(&self) -> L::DropConsistency {
445 self.collection.location().tick.l.drop_consistency()
446 }
447
448 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
449 let _ = self.nondet;
450 let out = self.collection.batch_atomic(
451 tick,
452 nondet!(),
453 );
454 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
455 out
456 }
457}
458
459impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
460 for Atomic<crate::live_collections::Singleton<T, crate::location::Atomic<L>, B>>
461{
462 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
463 type Backtrace = crate::compile::ir::backtrace::Backtrace;
464 fn get_location(&self) -> L::DropConsistency {
465 self.collection.location().tick.l.drop_consistency()
466 }
467
468 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
469 let _ = self.nondet;
470 let out = self.collection.snapshot_atomic(
471 tick,
472 nondet!(),
473 );
474 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
475 out
476 }
477}
478
479impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
480 for Atomic<crate::live_collections::Optional<T, crate::location::Atomic<L>, B>>
481{
482 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
483 type Backtrace = crate::compile::ir::backtrace::Backtrace;
484 fn get_location(&self) -> L::DropConsistency {
485 self.collection.location().tick.l.drop_consistency()
486 }
487
488 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
489 let out = self.collection.snapshot_atomic(tick, self.nondet);
490 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
491 out
492 }
493}
494
495impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
496 Slicable<'a, L::DropConsistency>
497 for Atomic<crate::live_collections::KeyedStream<K, V, crate::location::Atomic<L>, B, O, R>>
498{
499 type Slice =
500 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
501 type Backtrace = crate::compile::ir::backtrace::Backtrace;
502 fn get_location(&self) -> L::DropConsistency {
503 self.collection.location().tick.l.drop_consistency()
504 }
505
506 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
507 let out = self.collection.batch_atomic(tick, self.nondet);
508 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
509 out
510 }
511}
512
513impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
514 Slicable<'a, L::DropConsistency>
515 for Atomic<crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, B>>
516{
517 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
518 type Backtrace = crate::compile::ir::backtrace::Backtrace;
519 fn get_location(&self) -> L::DropConsistency {
520 self.collection.location().tick.l.drop_consistency()
521 }
522
523 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
524 let out = self.collection.snapshot_atomic(tick, self.nondet);
525 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
526 out
527 }
528}
529
530impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
531 for Atomic<
532 crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, BoundedValue>,
533 >
534{
535 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
536 type Backtrace = crate::compile::ir::backtrace::Backtrace;
537 fn get_location(&self) -> L::DropConsistency {
538 self.collection.location().tick.l.drop_consistency()
539 }
540
541 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
542 let out = self.collection.batch_atomic(tick, self.nondet);
543 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
544 out
545 }
546}