rune/modules/ops/
generator.rs

1//! Overloadable operators and associated types.
2
3use crate as rune;
4use crate::alloc::fmt::TryWrite;
5use crate::alloc::prelude::*;
6use crate::runtime::generator::Iter;
7use crate::runtime::{EnvProtocolCaller, Formatter, Generator, GeneratorState, Value, VmResult};
8use crate::{ContextError, Module};
9
10/// Types related to generators.
11#[rune::module(::std::ops::generator)]
12pub fn module() -> Result<Module, ContextError> {
13    let mut m = Module::from_meta(self::module_meta)?;
14
15    {
16        m.ty::<Generator>()?;
17        m.function_meta(generator_next__meta)?;
18        m.function_meta(generator_resume__meta)?;
19        m.function_meta(generator_iter__meta)?;
20        m.function_meta(generator_into_iter__meta)?;
21        m.function_meta(generator_debug__meta)?;
22        m.function_meta(generator_clone__meta)?;
23        m.implement_trait::<Generator>(rune::item!(::std::clone::Clone))?;
24
25        m.ty::<Iter>()?.docs(docstring! {
26            /// An iterator over a generator.
27        })?;
28        m.function_meta(Iter::next__meta)?;
29        m.implement_trait::<Iter>(rune::item!(::std::iter::Iterator))?;
30    }
31
32    {
33        m.ty::<GeneratorState>()?.docs(docstring! {
34            /// Enum indicating the state of a generator.
35        })?;
36
37        m.function_meta(generator_state_partial_eq__meta)?;
38        m.implement_trait::<GeneratorState>(rune::item!(::std::cmp::PartialEq))?;
39        m.function_meta(generator_state_eq__meta)?;
40        m.implement_trait::<GeneratorState>(rune::item!(::std::cmp::Eq))?;
41        m.function_meta(generator_state_debug__meta)?;
42        m.function_meta(generator_state_clone__meta)?;
43        m.implement_trait::<GeneratorState>(rune::item!(::std::clone::Clone))?;
44    }
45
46    Ok(m)
47}
48
49/// Advance a generator producing the next value yielded.
50///
51/// Unlike [`Generator::resume`], this can only consume the yielded values.
52///
53/// # Examples
54///
55/// ```rune
56/// use std::ops::{Generator, GeneratorState};
57///
58/// fn generate() {
59///     yield 1;
60///     yield 2;
61/// }
62///
63/// let g = generate();
64///
65/// assert_eq!(g.next(), Some(1));
66/// assert_eq!(g.next(), Some(2));
67/// assert_eq!(g.next(), None);
68/// ``
69#[rune::function(keep, instance, path = next)]
70fn generator_next(this: &mut Generator) -> VmResult<Option<Value>> {
71    this.next()
72}
73
74/// Resumes the execution of this generator.
75///
76/// This function will resume execution of the generator or start execution if
77/// it hasn't already. This call will return back into the generator's last
78/// suspension point, resuming execution from the latest `yield`. The generator
79/// will continue executing until it either yields or returns, at which point
80/// this function will return.
81///
82/// # Return value
83///
84/// The `GeneratorState` enum returned from this function indicates what state
85/// the generator is in upon returning. If the `Yielded` variant is returned
86/// then the generator has reached a suspension point and a value has been
87/// yielded out. Generators in this state are available for resumption at a
88/// later point.
89///
90/// If `Complete` is returned then the generator has completely finished with
91/// the value provided. It is invalid for the generator to be resumed again.
92///
93/// # Panics
94///
95/// This function may panic if it is called after the `Complete` variant has
96/// been returned previously. While generator literals in the language are
97/// guaranteed to panic on resuming after `Complete`, this is not guaranteed for
98/// all implementations of the `Generator`.
99///
100/// # Examples
101///
102/// ```rune
103/// use std::ops::{Generator, GeneratorState};
104///
105/// fn generate() {
106///     let n = yield 1;
107///     yield 2 + n;
108/// }
109///
110/// let g = generate();
111///
112/// assert_eq!(g.resume(()), GeneratorState::Yielded(1));
113/// assert_eq!(g.resume(1), GeneratorState::Yielded(3));
114/// assert_eq!(g.resume(()), GeneratorState::Complete(()));
115/// ``
116#[rune::function(keep, instance, path = resume)]
117fn generator_resume(this: &mut Generator, value: Value) -> VmResult<GeneratorState> {
118    this.resume(value)
119}
120
121/// Convert a generator into an iterator.
122///
123/// # Examples
124///
125/// ```rune
126/// fn count_numbers(limit) {
127///     for n in 0..limit.unwrap_or(10) {
128///         yield n;
129///     }
130/// }
131///
132/// assert_eq!(count_numbers(None).iter().collect::<Vec>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
133/// assert_eq!(count_numbers(Some(2)).iter().collect::<Vec>(), [0, 1]);
134/// ```
135#[rune::function(keep, instance, path = iter)]
136#[inline]
137fn generator_iter(this: Generator) -> Iter {
138    this.rune_iter()
139}
140
141/// Construct an iterator over a generator.
142///
143/// # Examples
144///
145/// ```rune
146/// fn count_numbers(limit) {
147///     for n in 0..limit {
148///         yield n;
149///     }
150/// }
151///
152/// let result = 0;
153///
154/// for n in count_numbers(3) {
155///     result += n;
156/// }
157///
158/// assert_eq!(result, 3);
159/// ```
160#[rune::function(keep, instance, protocol = INTO_ITER)]
161#[inline]
162fn generator_into_iter(this: Generator) -> Iter {
163    this.rune_iter()
164}
165
166/// Debug print this generator.
167///
168/// # Examples
169///
170/// ```rune
171/// use std::ops::GeneratorState;
172///
173/// fn generate() {
174///     let n = yield 1;
175///     yield 2 + n;
176/// }
177///
178/// let a = generate();
179///
180/// println!("{a:?}");
181/// ``
182#[rune::function(keep, instance, protocol = DEBUG_FMT)]
183fn generator_debug(this: &Generator, f: &mut Formatter) -> VmResult<()> {
184    vm_write!(f, "{this:?}")
185}
186
187/// Clone a generator.
188///
189/// This clones the state of the generator too, allowing it to be resumed
190/// independently.
191///
192/// # Examples
193///
194/// ```rune
195/// use std::ops::GeneratorState;
196///
197/// fn generate() {
198///     let n = yield 1;
199///     yield 2 + n;
200/// }
201///
202/// let a = generate();
203///
204/// assert_eq!(a.resume(()), GeneratorState::Yielded(1));
205/// let b = a.clone();
206/// assert_eq!(a.resume(2), GeneratorState::Yielded(4));
207/// assert_eq!(b.resume(3), GeneratorState::Yielded(5));
208///
209/// assert_eq!(a.resume(()), GeneratorState::Complete(()));
210/// assert_eq!(b.resume(()), GeneratorState::Complete(()));
211/// ``
212#[rune::function(keep, instance, protocol = CLONE)]
213fn generator_clone(this: &Generator) -> VmResult<Generator> {
214    VmResult::Ok(vm_try!(this.try_clone()))
215}
216
217/// Test for partial equality over a generator state.
218///
219/// # Examples
220///
221/// ```rune
222/// use std::ops::{Generator, GeneratorState};
223///
224/// fn generate() {
225///     let n = yield 1;
226///     yield 2 + n;
227/// }
228///
229/// let g = generate();
230///
231/// assert_eq!(g.resume(()), GeneratorState::Yielded(1));
232/// assert_eq!(g.resume(1), GeneratorState::Yielded(3));
233/// assert_eq!(g.resume(()), GeneratorState::Complete(()));
234/// ``
235#[rune::function(keep, instance, protocol = PARTIAL_EQ)]
236fn generator_state_partial_eq(this: &GeneratorState, other: &GeneratorState) -> VmResult<bool> {
237    this.partial_eq_with(other, &mut EnvProtocolCaller)
238}
239
240/// Test for total equality over a generator state.
241///
242/// # Examples
243///
244/// ```rune
245/// use std::ops::{Generator, GeneratorState};
246/// use std::ops::eq;
247///
248/// fn generate() {
249///     let n = yield 1;
250///     yield 2 + n;
251/// }
252///
253/// let g = generate();
254///
255/// assert!(eq(g.resume(()), GeneratorState::Yielded(1)));
256/// assert!(eq(g.resume(1), GeneratorState::Yielded(3)));
257/// assert!(eq(g.resume(()), GeneratorState::Complete(())));
258/// ``
259#[rune::function(keep, instance, protocol = EQ)]
260fn generator_state_eq(this: &GeneratorState, other: &GeneratorState) -> VmResult<bool> {
261    this.eq_with(other, &mut EnvProtocolCaller)
262}
263
264/// Debug print this generator state.
265///
266/// # Examples
267///
268/// ```rune
269/// use std::ops::GeneratorState;
270///
271/// let a = GeneratorState::Yielded(1);
272/// let b = GeneratorState::Complete(());
273///
274/// println!("{a:?}");
275/// println!("{b:?}");
276/// ``
277#[rune::function(keep, instance, protocol = DEBUG_FMT)]
278fn generator_state_debug(this: &GeneratorState, f: &mut Formatter) -> VmResult<()> {
279    match this {
280        GeneratorState::Yielded(value) => {
281            vm_try!(vm_write!(f, "Yielded("));
282            vm_try!(value.debug_fmt_with(f, &mut EnvProtocolCaller));
283            vm_try!(vm_write!(f, ")"));
284        }
285        GeneratorState::Complete(value) => {
286            vm_try!(vm_write!(f, "Complete("));
287            vm_try!(value.debug_fmt_with(f, &mut EnvProtocolCaller));
288            vm_try!(vm_write!(f, ")"));
289        }
290    }
291
292    VmResult::Ok(())
293}
294
295/// Clone a generator state.
296///
297/// # Examples
298///
299/// ```rune
300/// use std::ops::GeneratorState;
301///
302/// let a = GeneratorState::Yielded(1);
303/// let b = a.clone();
304///
305/// assert_eq!(a, b);
306/// ``
307#[rune::function(keep, instance, protocol = CLONE)]
308fn generator_state_clone(this: &GeneratorState) -> VmResult<GeneratorState> {
309    VmResult::Ok(vm_try!(this.try_clone()))
310}