1use ruda_kernel_macros::derive_expand;
2
3use crate::dsl::prelude::*;
4
5#[derive_expand(RudaType, RudaTypeMut, IntoRuntime)]
6#[ruda(runtime_variants, no_constructors)]
7pub enum Option<T: RudaType> {
8 None,
10 Some(T),
12}
13
14fn discriminant(variant_name: &'static str) -> i32 {
15 OptionExpand::<u32>::discriminant_of(variant_name)
16}
17
18pub enum OptionArgs<T: LaunchArg, R: Runtime> {
19 Some(<T as LaunchArg>::RuntimeArg<R>),
20 None,
21}
22
23impl<T: LaunchArg, R: Runtime> From<Option<<T as LaunchArg>::RuntimeArg<R>>> for OptionArgs<T, R> {
24 fn from(value: Option<<T as LaunchArg>::RuntimeArg<R>>) -> Self {
25 match value {
26 Some(arg) => Self::Some(arg),
27 None => Self::None,
28 }
29 }
30}
31
32impl<T: LaunchArg + Default + IntoRuntime> LaunchArg for Option<T> {
33 type RuntimeArg<R: Runtime> = OptionArgs<T, R>;
34 type CompilationArg = OptionCompilationArg<T>;
35
36 fn register<R: Runtime>(
37 arg: Self::RuntimeArg<R>,
38 launcher: &mut KernelLauncher<R>,
39 ) -> Self::CompilationArg {
40 match arg {
41 OptionArgs::Some(arg) => OptionCompilationArg::Some(T::register(arg, launcher)),
42 OptionArgs::None => OptionCompilationArg::None,
43 }
44 }
45
46 fn expand(
47 arg: &Self::CompilationArg,
48 builder: &mut KernelBuilder,
49 ) -> <Self as RudaType>::ExpandType {
50 match arg {
51 OptionCompilationArg::Some(value) => {
52 let value = T::expand(value, builder);
53 OptionExpand {
54 discriminant: discriminant("Some").into(),
55 value,
56 }
57 }
58 OptionCompilationArg::None => OptionExpand {
59 discriminant: discriminant("None").into(),
60 value: T::default().__expand_runtime_method(&mut builder.scope),
61 },
62 }
63 }
64
65 fn expand_output(
66 arg: &Self::CompilationArg,
67 builder: &mut KernelBuilder,
68 ) -> <Self as RudaType>::ExpandType {
69 match arg {
70 OptionCompilationArg::Some(value) => {
71 let value = T::expand_output(value, builder);
72 OptionExpand {
73 discriminant: discriminant("Some").into(),
74 value,
75 }
76 }
77 OptionCompilationArg::None => OptionExpand {
78 discriminant: discriminant("None").into(),
79 value: T::default().__expand_runtime_method(&mut builder.scope),
80 },
81 }
82 }
83}
84
85pub enum OptionCompilationArg<T: LaunchArg> {
86 Some(T::CompilationArg),
87 None,
88}
89
90impl<T: LaunchArg> Clone for OptionCompilationArg<T> {
91 fn clone(&self) -> Self {
92 match self {
93 OptionCompilationArg::Some(value) => OptionCompilationArg::Some(value.clone()),
94 OptionCompilationArg::None => OptionCompilationArg::None,
95 }
96 }
97}
98
99impl<T: LaunchArg> PartialEq for OptionCompilationArg<T> {
100 fn eq(&self, other: &Self) -> bool {
101 match (self, other) {
102 (Self::Some(l0), Self::Some(r0)) => l0 == r0,
103 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
104 }
105 }
106}
107
108impl<T: LaunchArg> Eq for OptionCompilationArg<T> {}
109
110impl<T: LaunchArg> core::hash::Hash for OptionCompilationArg<T> {
111 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
112 core::mem::discriminant(self).hash(state);
113 match self {
114 OptionCompilationArg::Some(value) => value.hash(state),
115 OptionCompilationArg::None => {}
116 }
117 }
118}
119
120impl<T: LaunchArg> core::fmt::Debug for OptionCompilationArg<T> {
121 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
122 match self {
123 Self::Some(arg0) => f.debug_tuple("Some").field(arg0).finish(),
124 Self::None => write!(f, "None"),
125 }
126 }
127}
128
129#[allow(non_snake_case)]
131pub trait RudaOption<T: RudaType> {
132 fn new_Some(_0: T) -> Option<T> {
134 Option::Some(_0)
135 }
136 fn none_with_default(_0: T) -> Option<T> {
137 Option::None
138 }
139
140 #[doc(hidden)]
141 fn __expand_Some(scope: &mut Scope, value: T::ExpandType) -> OptionExpand<T> {
142 Self::__expand_new_Some(scope, value)
143 }
144 #[doc(hidden)]
145 fn __expand_new_Some(_scope: &mut Scope, value: T::ExpandType) -> OptionExpand<T> {
146 OptionExpand::<T> {
147 discriminant: discriminant("Some").into(),
148 value,
149 }
150 }
151 fn __expand_none_with_default(_scope: &mut Scope, value: T::ExpandType) -> OptionExpand<T> {
152 OptionExpand {
153 discriminant: discriminant("None").into(),
154 value,
155 }
156 }
157}
158
159#[allow(non_snake_case)]
161pub trait RudaOptionDefault<T: RudaType + Default + IntoRuntime>: RudaOption<T> {
162 fn new_None() -> Option<T> {
164 Option::None
165 }
166
167 #[doc(hidden)]
168 fn __expand_new_None(scope: &mut Scope) -> OptionExpand<T> {
169 let value = T::default().__expand_runtime_method(scope);
170 Self::__expand_none_with_default(scope, value)
171 }
172}
173
174impl<T: RudaType> RudaOption<T> for Option<T> {}
175impl<T: RudaType + Default + IntoRuntime> RudaOptionDefault<T> for Option<T> {}
176
177mod impls {
178 use core::ops::{Deref, DerefMut};
179
180 use super::*;
181
182 #[doc(hidden)]
187 impl<T: RudaType> OptionExpand<T> {
188 pub fn __expand_is_some_and_method(
189 self,
190 scope: &mut Scope,
191 f: impl FnOnce(&mut Scope, T::ExpandType) -> NativeExpand<bool>,
192 ) -> NativeExpand<bool> {
193 match_expand_expr(scope, self, discriminant("None"), |_, _| false.into())
194 .case(scope, discriminant("Some"), |scope, value| f(scope, value))
195 .finish(scope)
196 }
197
198 pub fn __expand_is_none_or_method(
199 self,
200 scope: &mut Scope,
201 f: impl FnOnce(&mut Scope, T::ExpandType) -> NativeExpand<bool>,
202 ) -> NativeExpand<bool> {
203 match_expand_expr(scope, self, discriminant("None"), |_, _| true.into())
204 .case(scope, discriminant("Some"), |scope, value| f(scope, value))
205 .finish(scope)
206 }
207
208 pub fn __expand_as_ref_method(&self, _scope: &mut Scope) -> OptionExpand<T> {
209 self.clone()
210 }
211
212 pub fn __expand_as_mut_method(&mut self, _scope: &mut Scope) -> OptionExpand<T> {
213 self.clone()
214 }
215
216 pub fn __expand_expect_method(self, scope: &mut Scope, msg: &str) -> T::ExpandType
217 where
218 T::ExpandType: Assign,
219 {
220 match_expand_expr(scope, self, discriminant("Some"), |_, value| value)
222 .case(scope, discriminant("None"), |scope, value| {
223 printf_expand(scope, msg, alloc::vec![]);
224 terminate!();
225 value
226 })
227 .finish(scope)
228 }
229
230 pub fn __expand_unwrap_or_else_method<F>(self, scope: &mut Scope, f: F) -> T::ExpandType
231 where
232 F: FnOnce(&mut Scope) -> T::ExpandType,
233 T::ExpandType: Assign,
234 {
235 match_expand_expr(scope, self, discriminant("Some"), |_, value| value)
236 .case(scope, discriminant("None"), |scope, _| f(scope))
237 .finish(scope)
238 }
239
240 pub fn __expand_map_method<U, F>(self, scope: &mut Scope, f: F) -> OptionExpand<U>
241 where
242 F: FnOnce(&mut Scope, T::ExpandType) -> U::ExpandType,
243 U: RudaType + IntoRuntime + Default,
244 OptionExpand<U>: Assign,
245 {
246 match_expand_expr(scope, self, discriminant("Some"), |scope, value| {
247 let value = f(scope, value);
248 Option::__expand_new_Some(scope, value)
249 })
250 .case(scope, discriminant("None"), |scope, _| {
251 Option::__expand_new_None(scope)
252 })
253 .finish(scope)
254 }
255
256 pub fn __expand_inspect_method<F>(self, scope: &mut Scope, f: F) -> Self
257 where
258 F: FnOnce(&mut Scope, &T::ExpandType),
259 {
260 match_expand(scope, self.clone(), discriminant("Some"), |scope, value| {
261 f(scope, &value)
262 })
263 .case(scope, discriminant("None"), |_, _| {})
264 .finish(scope);
265 self
266 }
267
268 pub fn __expand_map_or_method<U, F>(
269 self,
270 scope: &mut Scope,
271 default: U::ExpandType,
272 f: F,
273 ) -> U::ExpandType
274 where
275 F: FnOnce(&mut Scope, T::ExpandType) -> U::ExpandType,
276 U: RudaType + Default + IntoRuntime,
277 U::ExpandType: Assign,
278 {
279 match_expand_expr(scope, self, discriminant("Some"), f)
280 .case(scope, discriminant("None"), |_, _| default)
281 .finish(scope)
282 }
283
284 pub fn __expand_map_or_else_method<U, D, F>(
285 self,
286 scope: &mut Scope,
287 default: D,
288 f: F,
289 ) -> U::ExpandType
290 where
291 D: FnOnce(&mut Scope) -> U::ExpandType,
292 F: FnOnce(&mut Scope, T::ExpandType) -> U::ExpandType,
293 U: RudaType + Default + IntoRuntime,
294 U::ExpandType: Assign,
295 {
296 match_expand_expr(scope, self, discriminant("Some"), f)
297 .case(scope, discriminant("None"), |scope, _| default(scope))
298 .finish(scope)
299 }
300
301 pub fn __expand_map_or_default_method<U, F>(self, scope: &mut Scope, f: F) -> U::ExpandType
302 where
303 U: RudaType + IntoRuntime + Default,
304 F: FnOnce(&mut Scope, T::ExpandType) -> U::ExpandType,
305 U::ExpandType: Assign,
306 {
307 match_expand_expr(scope, self, discriminant("Some"), f)
308 .case(scope, discriminant("None"), |scope, _| {
309 U::default().__expand_runtime_method(scope)
310 })
311 .finish(scope)
312 }
313
314 pub fn __expand_as_deref_method(self, scope: &mut Scope) -> OptionExpand<T::Target>
315 where
316 T: Deref<Target: RudaType + Default + IntoRuntime>,
317 T::ExpandType: Deref<Target = <T::Target as RudaType>::ExpandType>,
318 <T::Target as RudaType>::ExpandType: Assign,
319 {
320 self.__expand_map_method(scope, |_, value| (*value).clone())
321 }
322
323 pub fn __expand_as_deref_mut_method(self, scope: &mut Scope) -> OptionExpand<T::Target>
324 where
325 T: DerefMut<Target: RudaType + Default + IntoRuntime>,
326 T::ExpandType: Deref<Target = <T::Target as RudaType>::ExpandType>,
327 <T::Target as RudaType>::ExpandType: Assign,
328 {
329 self.__expand_map_method(scope, |_, value| (*value).clone())
330 }
331
332 pub fn __expand_and_then_method<U, F>(self, scope: &mut Scope, f: F) -> OptionExpand<U>
333 where
334 F: FnOnce(&mut Scope, T::ExpandType) -> OptionExpand<U>,
335 U: RudaType + IntoRuntime + Default,
336 U::ExpandType: Assign,
337 {
338 match_expand_expr(scope, self, discriminant("Some"), f)
339 .case(scope, discriminant("None"), |scope, _| {
340 Option::__expand_new_None(scope)
341 })
342 .finish(scope)
343 }
344
345 pub fn __expand_filter_method<P>(self, scope: &mut Scope, predicate: P) -> Self
346 where
347 P: FnOnce(&mut Scope, T::ExpandType) -> NativeExpand<bool>,
348 T: Default + IntoRuntime,
349 Self: Assign,
350 {
351 match_expand_expr(scope, self, discriminant("Some"), |scope, value| {
352 let cond = predicate(scope, value.clone());
353 if_else_expr_expand(scope, cond, |scope| Option::__expand_new_Some(scope, value))
354 .or_else(scope, |scope| Option::__expand_new_None(scope))
355 })
356 .case(scope, discriminant("None"), |scope, _| {
357 Option::__expand_new_None(scope)
358 })
359 .finish(scope)
360 }
361
362 pub fn __expand_or_else_method<F>(self, scope: &mut Scope, f: F) -> OptionExpand<T>
363 where
364 F: FnOnce(&mut Scope) -> OptionExpand<T>,
365 OptionExpand<T>: Assign,
366 {
367 let is_some = self.clone().__expand_is_some_method(scope);
368 if_else_expr_expand(scope, is_some, |_| self).or_else(scope, |scope| f(scope))
369 }
370
371 pub fn __expand_zip_with_method<U, F, R>(
372 self,
373 scope: &mut Scope,
374 other: OptionExpand<U>,
375 f: F,
376 ) -> OptionExpand<R>
377 where
378 F: FnOnce(&mut Scope, T::ExpandType, U::ExpandType) -> R::ExpandType,
379 U: RudaType,
380 R: RudaType + IntoRuntime + Default,
381 OptionExpand<R>: Assign,
382 {
383 match_expand_expr(scope, self, discriminant("Some"), |scope, value| {
384 match_expand_expr(scope, other, discriminant("Some"), |scope, other| {
385 let value = f(scope, value, other);
386 Option::__expand_new_Some(scope, value)
387 })
388 .case(scope, discriminant("None"), |scope, _| {
389 Option::__expand_new_None(scope)
390 })
391 .finish(scope)
392 })
393 .case(scope, discriminant("None"), |scope, _| {
394 Option::__expand_new_None(scope)
395 })
396 .finish(scope)
397 }
398
399 pub fn __expand_reduce_method<U, R, F>(
400 self,
401 scope: &mut Scope,
402 other: OptionExpand<U>,
403 f: F,
404 ) -> OptionExpand<R>
405 where
406 T::ExpandType: Into<R::ExpandType>,
407 U::ExpandType: Into<R::ExpandType>,
408 F: FnOnce(&mut Scope, T::ExpandType, U::ExpandType) -> R::ExpandType,
409 U: RudaType + IntoRuntime + Default,
410 R: RudaType + IntoRuntime + Default,
411 OptionExpand<R>: Assign,
412 {
413 match_expand_expr(scope, self, discriminant("Some"), {
414 let other = other.clone();
415 |scope, value| {
416 match_expand_expr(scope, other, discriminant("Some"), {
417 let value = value.clone();
418 |scope, other| {
419 let value = f(scope, value, other);
420 Option::__expand_new_Some(scope, value)
421 }
422 })
423 .case(scope, discriminant("None"), |scope, _| {
424 Option::__expand_new_Some(scope, value.into())
425 })
426 .finish(scope)
427 }
428 })
429 .case(scope, discriminant("None"), |scope, _| {
430 match_expand_expr(scope, other, discriminant("Some"), |scope, other| {
431 Option::__expand_new_Some(scope, other.into())
432 })
433 .case(scope, discriminant("None"), |scope, _| {
434 Option::__expand_new_None(scope)
435 })
436 .finish(scope)
437 })
438 .finish(scope)
439 }
440
441 #[allow(clippy::missing_safety_doc)]
442 pub unsafe fn __expand_unwrap_unchecked_method(self, scope: &mut Scope) -> T::ExpandType
443 where
444 T::ExpandType: Assign,
445 {
446 match_expand_expr(scope, self, discriminant("Some"), |_, value| value).finish(scope)
447 }
448 }
449
450 #[ruda(expand_only)]
451 impl<T: RudaType> Option<T> {
452 pub fn is_some(&self) -> bool {
468 match self {
469 Option::Some(_) => true.runtime(),
470 Option::None => false.runtime(),
471 }
472 }
473
474 #[must_use = "if you intended to assert that this doesn't have a value, consider \
486 wrapping this in an `assert!()` instead"]
487 pub fn is_none(&self) -> bool {
488 !self.is_some()
489 }
490
491 pub fn unwrap(self) -> T
528 where
529 T::ExpandType: Assign,
530 {
531 self.expect("called `Option::unwrap()` on a `None` value")
532 }
533
534 pub fn unwrap_or(self, default: T) -> T
549 where
550 T::ExpandType: Assign,
551 {
552 match self {
553 Some(x) => x,
554 None => default,
555 }
556 }
557
558 pub fn unwrap_or_default(self) -> T
578 where
579 T: Default + IntoRuntime,
580 T::ExpandType: Assign,
581 {
582 match self {
583 Some(x) => x,
584 None => comptime![T::default()].runtime(),
585 }
586 }
587
588 pub fn and<U>(self, optb: Option<U>) -> Option<U>
624 where
625 U: RudaType + IntoRuntime + Default,
626 U::ExpandType: Assign,
627 {
628 match self {
629 Option::Some(_) => optb,
630 Option::None => Option::new_None(),
631 }
632 }
633
634 pub fn or(self, optb: Option<T>) -> Option<T>
662 where
663 T::ExpandType: Assign,
664 {
665 if self.is_some() { self } else { optb }
666 }
667
668 pub fn xor(self, optb: Option<T>) -> Option<T>
690 where
691 T: Default + IntoRuntime,
692 T::ExpandType: Assign,
693 {
694 if self.is_some() && optb.is_none() {
695 self
696 } else if self.is_none() && optb.is_some() {
697 optb
698 } else {
699 Option::new_None()
700 }
701 }
702
703 pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)>
725 where
726 U: RudaType,
727 (T, U): Default + IntoRuntime,
728 (T::ExpandType, U::ExpandType): Into<<(T, U) as RudaType>::ExpandType>,
729 OptionExpand<(T, U)>: Assign,
730 {
731 match self {
732 Some(a) => match other {
733 Some(b) => Option::Some((a, b)),
734 None => Option::new_None(),
735 },
736 None => Option::new_None(),
737 }
738 }
739 }
740
741 #[ruda(expand_only)]
742 impl<
743 T: RudaType<ExpandType: Assign> + IntoRuntime + Default,
744 U: RudaType<ExpandType: Assign> + IntoRuntime + Default,
745 > Option<(T, U)>
746 {
747 #[inline]
762 pub fn unzip(self) -> (Option<T>, Option<U>) {
763 match self {
764 Option::Some(value) => (Option::Some(value.0), Option::Some(value.1)),
765 Option::None => (Option::new_None(), Option::new_None()),
766 }
767 }
768 }
769}