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 use crate::decode::unwrap_uninhabited;
20 
21 impl Interpreter<'_> {
22     pub fn run(self) -> Done {
23         let mut decoder = Decoder::new();
24         let mut visitor = debug::Debug(self);
25         loop {
26             // Here `decode_one` will call the appropriate `OpVisitor` method on
27             // `self` via the trait implementation in the module above this.
28             // That'll return whether we should keep going or exit the loop,
29             // which is then done here with a conditional `break`.
30             //
31             // This will then continue indefinitely until the bytecode says it's
32             // done. Note that only trusted bytecode is interpreted here.
33             match unwrap_uninhabited(decoder.decode_one(&mut visitor)) {
34                 ControlFlow::Continue(()) => {}
35                 ControlFlow::Break(done) => break done,
36             }
37         }
38     }
39 }
40