From f01c278a26e0f248d188c10bdb852b0859b98b3b Mon Sep 17 00:00:00 2001 From: Till Höppner Date: Tue, 23 Feb 2016 17:00:53 +0100 Subject: Test CI --- src/lazy.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/lazy.rs (limited to 'src/lazy.rs') diff --git a/src/lazy.rs b/src/lazy.rs new file mode 100644 index 0000000..b4f801b --- /dev/null +++ b/src/lazy.rs @@ -0,0 +1,74 @@ +#![macro_escape] + +use std::ptr; +use std::cell::UnsafeCell; +use std::ops::Deref; +use std::boxed::FnBox; + +pub enum State { + Evaluated(V), + Evaluating, + Unevaluated(Box V>) +} + +pub struct Lazy { + state: UnsafeCell>, +} + +impl Lazy { + pub fn new(f: Box V>) -> Lazy { + Lazy { state: UnsafeCell::new(State::Unevaluated(f)) } + } + + pub fn ready(v: V) -> Lazy { + Lazy { state: UnsafeCell::new(State::Evaluated(v)) } + } + + pub fn force(&mut self) { + self.value(); + } + + pub fn unwrap(self) -> V { + unsafe { + match self.state.into_inner() { + State::Unevaluated(f) => f(), + State::Evaluating => panic!("Illegal state, can't call unwrap during evaluation"), + State::Evaluated(v) => v + } + } + } + + pub fn value(&self) -> &V { + unsafe { + let state = self.state.get(); + match *state { + State::Evaluated(ref v) => v, + State::Evaluating => panic!("Illegal state, can't call value during evaluation"), + State::Unevaluated(_) => { + if let State::Unevaluated(f) = ptr::replace(state, State::Evaluating) { + ptr::replace(state, State::Evaluated(f())); + } + if let State::Evaluated(ref v) = *state { return v } + unreachable!() + } + } + } + } +} + +impl Deref for Lazy { + type Target = V; + fn deref(&self) -> &V { self.value() } +} + +#[macro_export] +macro_rules! lazy { + (@as_expr $val: expr) => { $val }; + ($($val: tt)*) => { Lazy::new(Box::new(move || lazy![@as_expr { $($val)* }])) }; +} + +#[macro_export] +macro_rules! eager { + (@as_expr $val: expr) => { $val }; + ($($val: tt)*) => { Lazy::<_>::ready(eager![@as_expr { $($val)* }]) }; +} -- cgit v1.2.3