1 //! Implementation of the interpreter loop for Pulley with a simple `match`
2 //! statement.
3 //!
4 //! This module is notably in contrast to the `tail_loop.rs` which implements
5 //! the interpreter loop with tail calls. It's predicted that tail calls are a
6 //! more performant solution but that's also not available on stable Rust today,
7 //! so this module instead compiles on stable Rust.
8 //!
9 //! This interpreter loop is a simple `loop` with a "moral `match`" despite not
10 //! actually having one here. The `Decoder` API is used to dispatch to the
11 //! `OpVisitor` trait implementation on `Interpreter<'_>`. The literal `match`
12 //! is embedded within the `Decoder::decode_one` function.
13 //!
14 //! Note that as of the time of this writing there hasn't been much performance
15 //! analysis of this loop just yet. It's probably too simple to compile well and
16 //! will probably need tweaks to make it more performant.
17 
18 use super::*;
19 
20 impl Interpreter<'_> {
run(self) -> Done21     pub fn run(self) -> Done {
22         let mut decoder = Decoder::new();
23         let mut visitor = debug::Debug(self);
24         loop {
25             // Here `decode_one` will call the appropriate `OpVisitor` method on
26             // `self` via the trait implementation in the module above this.
27             // That'll return whether we should keep going or exit the loop,
28             // which is then done here with a conditional `break`.
29             //
30             // This will then continue indefinitely until the bytecode says it's
31             // done. Note that only trusted bytecode is interpreted here.
32             match decoder.decode_one(&mut visitor) {
33                 Ok(ControlFlow::Continue(())) => {}
34                 Ok(ControlFlow::Break(done)) => break done,
35             }
36         }
37     }
38 }
39