@@ -6,30 +6,83 @@ package Core library "prelude/types/optional";
6
6
7
7
import library "prelude/copy" ;
8
8
import library "prelude/destroy" ;
9
+ import library "prelude/operators/as" ;
9
10
import library "prelude/types/bool" ;
11
+ import library "prelude/types/maybe_unformed" ;
12
+
13
+ // TODO: Decide how to expose this in the public API.
14
+ private interface OptionalStorage {
15
+ let Type:! type ;
16
+ fn None () - > Type;
17
+ fn Some[self: Self]() - > Type;
18
+ fn Has (value: Type) - > bool ;
19
+ fn Get (value: Type) - > Self;
20
+ }
10
21
11
- // For now, an `Optional(T)` is stored as a pair of a `bool` and a `T`, with
12
- // the `T` left uninitialized if the `bool` is `false`. This isn't a viable
13
- // approach in the longer term, but is the best we can do for now.
14
- //
15
- // TODO: Revisit this once we have choice types implemented in the toolchain.
16
- //
17
22
// TODO: We don't have an approved design for an `Optional` type yet, but it's
18
23
// used by the design for `Iterate`. The API here is a placeholder.
19
- class Optional (T:! Copy ) {
24
+ class Optional (T:! OptionalStorage ) {
20
25
fn None () - > Self {
21
- returned var me: Self;
22
- me.has_value = false ;
23
- return var;
26
+ return {.value = T.None ()};
24
27
}
25
-
26
28
fn Some (value: T) - > Self {
27
- return {.has_value = true , .value = value};
29
+ return {.value = value.Some ()};
30
+ }
31
+ fn HasValue[self: Self]() - > bool {
32
+ return T.Has (self.value);
33
+ }
34
+ fn Get[self: Self]() - > T {
35
+ return T.Get (self.value);
28
36
}
29
37
30
- fn HasValue[self: Self]() - > bool { return self.has_value; }
31
- fn Get[self: Self]() - > T { return self.value; }
38
+ private var value: T.Type;
39
+ }
32
40
33
- private var has_value: bool ;
34
- private var value: T;
41
+ // By default, an `Optional(T)` is stored as a pair of a `bool` and a
42
+ // `MaybeUnformed(T)`, with the `MaybeUnformed(T)` left uninitialized if the
43
+ // `bool` is `false`.
44
+ //
45
+ // TODO: Revisit this once we have choice types implemented in the toolchain.
46
+ private class DefaultOptionalStorage (T:! Copy) {
47
+ var value: MaybeUnformed (T);
48
+ var has_value: bool ;
49
+ }
50
+
51
+ impl forall [T:! Copy] T as OptionalStorage
52
+ where .Type = DefaultOptionalStorage (T) {
53
+ fn None () - > DefaultOptionalStorage (T) {
54
+ returned var me: DefaultOptionalStorage (T);
55
+ me.has_value = false ;
56
+ return var;
57
+ }
58
+ fn Some[self: Self]() - > DefaultOptionalStorage (T) {
59
+ returned var me: DefaultOptionalStorage (T);
60
+ // TODO: Should be:
61
+ // me.value = self as MaybeUnformed(T);
62
+ me.value unsafe as T = self;
63
+ me.has_value = true ;
64
+ return var;
65
+ }
66
+ fn Has (value: DefaultOptionalStorage (T)) - > bool {
67
+ return value.has_value;
68
+ }
69
+ fn Get (value: DefaultOptionalStorage (T)) - > T {
70
+ return value.value unsafe as T ;
71
+ }
72
+ }
73
+
74
+ // For pointers, we use a null pointer value as the "None" value. This allows
75
+ // `Optional(T*)` to be ABI-compatible with a C++ nullable pointer.
76
+ final impl forall [T:! type ] T* as OptionalStorage
77
+ where .Type = MaybeUnformed (T* ) {
78
+ fn None () - > MaybeUnformed (T* ) = "pointer.make_null" ;
79
+ fn Some[self: Self]() - > MaybeUnformed (T* ) {
80
+ returned var result: MaybeUnformed (T* );
81
+ result unsafe as T * = self;
82
+ return var;
83
+ }
84
+ fn Has (value: MaybeUnformed (T* )) - > bool = "pointer.is_null" ;
85
+ fn Get (value: MaybeUnformed (T* )) - > T* {
86
+ return value unsafe as T * ;
87
+ }
35
88
}
0 commit comments