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