1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
#![feature(fn_traits)] #![feature(unboxed_closures)] #![no_std] extern crate void; #[cfg(test)] #[macro_use] extern crate std; use core::mem; use core::ptr; use void::Void; #[cfg(target_arch = "x86_64")] const n_saved_regs: usize = 8; #[link(name = "jump", kind = "static")] extern "C" { fn mkjump_(ptr: *mut [usize; n_saved_regs]); fn jump_(ptr: *const [usize; n_saved_regs]) -> !; } #[derive(Debug)] pub struct Jump<T>([usize; n_saved_regs], *mut Option<T>); impl<T> Jump<T> { #[inline] pub unsafe fn new() -> (Self, Option<T>) { let mut opt_x = None; let mut jump = Jump(mem::uninitialized(), &mut opt_x); mkjump_(&mut jump.0); (jump, opt_x) } } impl<T> FnOnce<(T,)> for Jump<T> { type Output = Void; #[inline] extern "rust-call" fn call_once(self, a: (T,)) -> Void { self.call(a) } } impl<T> FnMut<(T,)> for Jump<T> { #[inline] extern "rust-call" fn call_mut(&mut self, a: (T,)) -> Void { self.call(a) } } impl<T> Fn<(T,)> for Jump<T> { #[inline] extern "rust-call" fn call(&self, (x,): (T,)) -> Void { unsafe { ptr::write(self.1, Some(x)); jump_(&self.0) } } } #[inline] pub fn call_cc<T, F: FnOnce(&Jump<T>) -> T>(f: F) -> T { match unsafe { Jump::new() } { (jump, None) => f(&jump), (_, Some(x)) => return x, } } #[test] fn test() { let mut opt_y = None; let (jump, opt_x) = unsafe { Jump::new() }; assert_eq!(opt_y, opt_x); if let Some(()) = opt_x { return } else { assert_eq!(None, opt_y) }; opt_y = Some(()); jump(()); }