<commit_before>// vim: tw=80

/// Common methods of the Common struct
// Ideally methods like with and withf that are identical for all
// Expectation types would be defined here, too.  But that's not possible for
// methods that need any of the variable-length argument fields due to this Rust
// bug:
// https://github.com/rust-lang/rust/issues/35853
#[macro_export]
#[doc(hidden)]
macro_rules! common_methods {
    () => {
        fn in_sequence(&mut self, seq: &mut $crate::Sequence)
            -> &mut Self
        {
            assert!(self.times.is_exact(),
                "Only Expectations with an exact call count have sequences");
            self.seq_handle = Some(seq.next());
            self
        }

        fn is_done(&self) -> bool {
            self.times.is_done()
        }

        /// Forbid this expectation from ever being called
        fn never(&mut self) {
            self.times.never();
        }

        fn satisfy_sequence(&self) {
            if let Some(handle) = &self.seq_handle {
                handle.satisfy()
            }
        }

        /// Require this expectation to be called exactly `n` times.
        fn times(&mut self, n: usize) {
            self.times.n(n);
        }

        /// Allow this expectation to be called any number of times
        fn times_any(&mut self) {
            self.times.any();
        }

        /// Allow this expectation to be called any number of times within a
        /// given range
        fn times_range(&mut self, range: ::std::ops::Range<usize>) {
            self.times.range(range);
        }

        fn verify_sequence(&self) {
            if let Some(handle) = &self.seq_handle {
                handle.verify()
            }
        }
    }
}

/// Common methods of the Expectation, RefExpectation, and RefMutExpectation
/// structs
// Rust bug 35853 applies here, too.
#[macro_export]
#[doc(hidden)]
macro_rules! expectation_methods {
    () => {
        /// Add this expectation to a [`Sequence`](struct.Sequence.html).
        pub fn in_sequence(&mut self, seq: &mut $crate::Sequence) -> &mut Self {
            self.common.in_sequence(seq);
            self
        }

        pub fn is_done(&self) -> bool {
            self.common.is_done()
        }

        /// Forbid this expectation from ever being called
        pub fn never(&mut self) -> &mut Self {
            self.common.never();
            self
        }

        /// Expect this expectation to be called exactly once.  Shortcut for
        /// [`times(1)`](#method.times).
        pub fn once(&mut self) -> &mut Self {
            self.times(1)
        }

        /// Require this expectation to be called exactly `n` times.
        pub fn times(&mut self, n: usize) -> &mut Self {
            self.common.times(n);
            self
        }

        /// Allow this expectation to be called any number of times
        ///
        /// This behavior is the default, but the method is provided in case the
        /// default behavior changes.
        pub fn times_any(&mut self) -> &mut Self {
            self.common.times_any();
            self
        }

        /// Allow this expectation to be called any number of times within a
        /// given range
        pub fn times_range(&mut self, range: ::std::ops::Range<usize>)
            -> &mut Self
        {
            self.common.times_range(range);
            self
        }
    }
}

/// Generate Expectation and Expectations types with specific signatures
///
/// # Arguments
///
/// * `expectation`:    Name of the generated Expectation type
/// * `module`:         Name of the private module to create
/// * `o`:              Output type.  Must be static
/// * `methty`:         Comma-delimited sequence of arguments types for the
///                     method being mocked.
/// * `matchcall`:      Comma-delimited sequence of expressions that produce
///                     values of type `matchty` from values of type `methty`.
/// * `args`:           comma-delimited sequence of argument names for each
///                     argument.  Ideally this wouldn't need to be specified,
///                     but it is due to Rust's macro hygiene rules.
/// * `predargs`:       Comma-delimited sequence of identifiers of the same
///                     length as `args`, but distinct.
/// * `matchty`:        comma-delimited sequence of types for each match
///                     argument.  Must all be `'static`.
///
/// # Examples
///
/// ```
/// // Mock a method like foo(&self, x: u32, y: &i16) -> u32
/// expectation!{(u32, &i16), u32, i, [&i.0, i.1], [i0, i1], [u32, i16]}
#[macro_export]
macro_rules! expectation {(
        $expectation:ident,
        $module:ident,
        $o:ty,
        [ $( $methty:ty ),* ],
        [ $( $matchcall:expr ),* ],
        [ $( $args:ident ),* ],
        [ $( $predargs:ident ),* ],
        [ $( $matchty:ty ),* ]) =>
    {
        mod $module {
        use ::predicates_tree::CaseTreeExt;
        use ::std::ops::DerefMut;
        use super::*;

        enum Rfunc {
            Default,
            // Indicates that a `return_once` expectation has already returned
            Expired,
            Mut(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
            // Should be Box<dyn FnOnce> once that feature is stabilized
            // https://github.com/rust-lang/rust/issues/28796
            Once(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
        }

        impl  Rfunc {
            fn call_mut(&mut self, $( $args: $methty, )* ) -> $o {
                match self {
                    Rfunc::Default => {
                        unimplemented!()
                        //Self::return_default()
                    },
                    Rfunc::Expired => {
                        panic!("Called a method twice that was expected only once")
                    },
                    Rfunc::Mut(f) => {
                        f( $( $args, )* )
                    },
                    Rfunc::Once(_) => {
                        let fo = ::std::mem::replace(self, Rfunc::Expired);
                        if let Rfunc::Once(mut f) = fo {
                            f( $( $args, )* )
                        } else {
                            unreachable!()
                        }
                    },
                }
            }
        }

        impl std::default::Default for Rfunc {
            fn default() -> Self {
                Rfunc::Default
            }
        }

        enum Matcher {
            Func(Box<Fn($( &$matchty, )* ) -> bool>),
            Pred( $( Box<$crate::Predicate<$matchty>>, )* )
        }

        impl Matcher {
            fn eval(&self, $( $args: &$matchty, )*) -> bool {
                match self {
                    Matcher::Func(f) => f($( $args, )*),
                    Matcher::Pred($( $predargs, )*) =>
                        [$( $predargs.eval($args), )*]
                        .into_iter()
                        .all(|x| *x),
                }
            }

            fn verify(&self, $( $args: &$matchty, )* ) {
                match self {
                    Matcher::Func(f) => assert!(f($( $args, )*),
                        "Expectation didn't match arguments"),
                    Matcher::Pred($( $predargs, )*) => {
                        $(if let Some(c) = $predargs.find_case(false, $args) {
                            panic!("Expectation didn't match arguments:\n{}",
                                   c.tree());
                        })*
                    }
                }
            }
        }

        impl Default for Matcher {
            #[allow(unused_variables)]
            fn default() -> Self {
                Matcher::Func(Box::new(|$( $args, )*| true))
            }
        }

        /// Holds the stuff that is independent of the output type
        #[derive(Default)]
        struct Common {
            matcher: ::std::sync::Mutex<Matcher>,
            seq_handle: Option<$crate::SeqHandle>,
            times: $crate::Times
        }

        impl Common {
            fn call(&self, $( $args: &$matchty, )* ) {
                self.matcher.lock().unwrap().verify($( $args, )*);
                self.times.call();
                self.verify_sequence();
                if self.times.is_satisfied() {
                    self.satisfy_sequence()
                }
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            fn with<$( $predargs: $crate::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*)
            {
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Pred($( Box::new($args), )*);
                ::std::mem::replace(guard.deref_mut(), m);
            }

            fn withf<F>(&mut self, f: F)
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Func(Box::new(f));
                ::std::mem::replace(guard.deref_mut(), m);
            }

            $crate::common_methods!{}
        }

        #[derive(Default)]
        pub struct Expectation {
            common: Common,
            rfunc: ::std::sync::Mutex<Rfunc>,
        }

        impl Expectation {
            pub fn call(&self, $( $args: $methty, )* ) -> $o {
                self.common.call($( $matchcall, )*);
                self.rfunc.lock().unwrap().call_mut($( $args, )*)
            }

            /// Supply an `FnOnce` closure that will provide the return value
            /// for this Expectation.  This is useful for return types that
            /// aren't `Clone`.  It will be an error to call this Expectation
            /// multiple times.
            pub fn return_once<F>(&mut self, f: F) -> &mut Self
                where F: FnOnce($( $methty, )*) -> $o + Send + 'static
            {
                let mut fopt = Some(f);
                let fmut = move |$( $args: $methty, )*| {
                    if let Some(f) = fopt.take() {
                        f($( $args, )*)
                    } else {
                        panic!("Called a method twice that was expected only once")
                    }
                };
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(),
                                        Rfunc::Once(Box::new(fmut)));
                }
                self
            }

            /// Single-threaded version of [`return_once`](#method.return_once).
            /// This is useful for return types that are neither `Send` nor
            /// `Clone`.
            ///
            /// It is a runtime error to call the mock method from a different
            /// thread than the one that originally called this method.  It is
            /// also a runtime error to call the method more than once.
            pub fn return_once_st<F>(&mut self, f: F) -> &mut Self
                where F: FnOnce($( $methty, )*) -> $o + 'static
            {
                let mut fragile = Some(::fragile::Fragile::new(f));
                let fmut = Box::new(move |$( $args: $methty, )*| {
                    match fragile.take() {
                        Some(frag) => (frag.into_inner())($( $args, )*),
                        None => panic!(
                            "Called a method twice that was expected only once")
                    }
                });
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(), Rfunc::Once(fmut));
                }
                self
            }

            pub fn returning<F>(&mut self, f: F) -> &mut Self
                where F: FnMut($( $methty, )*) -> $o + Send + 'static
            {
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(), Rfunc::Mut(Box::new(f)));
                }
                self
            }

            /// Single-threaded version of [`returning`](#method.returning).
            /// Can be used when the argument or return type isn't `Send`.
            ///
            /// It is a runtime error to call the mock method from a different
            /// thread than the one that originally called this method.
            pub fn returning_st<F>(&mut self, f: F) -> &mut Self
                where F: FnMut($( $methty, )*) -> $o + 'static
            {
                let mut fragile = ::fragile::Fragile::new(f);
                let fmut = move |$( $args: $methty, )*| {
                    (fragile.get_mut())($( $args, )*)
                };
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(),
                                        Rfunc::Mut(Box::new(fmut)));
                }
                self
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            pub fn with<$( $predargs: $crate::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*) -> &mut Self
            {
                self.common.with($( $args, )*);
                self
            }

            pub fn withf<F>(&mut self, f: F) -> &mut Self
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                self.common.withf(f);
                self
            }

            $crate::expectation_methods!{}
        }

        }
        use $module::Expectation as $expectation;
    }
}
<commit_msg>Add ref_expectation!, equivalent to the old RefExpectation<commit_after>// vim: tw=80

/// Common methods of the Common struct
// Ideally methods like with and withf that are identical for all
// Expectation types would be defined here, too.  But that's not possible for
// methods that need any of the variable-length argument fields due to this Rust
// bug:
// https://github.com/rust-lang/rust/issues/35853
#[macro_export]
#[doc(hidden)]
macro_rules! common_methods {
    () => {
        fn in_sequence(&mut self, seq: &mut $crate::Sequence)
            -> &mut Self
        {
            assert!(self.times.is_exact(),
                "Only Expectations with an exact call count have sequences");
            self.seq_handle = Some(seq.next());
            self
        }

        fn is_done(&self) -> bool {
            self.times.is_done()
        }

        /// Forbid this expectation from ever being called
        fn never(&mut self) {
            self.times.never();
        }

        fn satisfy_sequence(&self) {
            if let Some(handle) = &self.seq_handle {
                handle.satisfy()
            }
        }

        /// Require this expectation to be called exactly `n` times.
        fn times(&mut self, n: usize) {
            self.times.n(n);
        }

        /// Allow this expectation to be called any number of times
        fn times_any(&mut self) {
            self.times.any();
        }

        /// Allow this expectation to be called any number of times within a
        /// given range
        fn times_range(&mut self, range: ::std::ops::Range<usize>) {
            self.times.range(range);
        }

        fn verify_sequence(&self) {
            if let Some(handle) = &self.seq_handle {
                handle.verify()
            }
        }
    }
}

/// Common methods of the Expectation, RefExpectation, and RefMutExpectation
/// structs
// Rust bug 35853 applies here, too.
#[macro_export]
#[doc(hidden)]
macro_rules! expectation_methods {
    () => {
        /// Add this expectation to a [`Sequence`](struct.Sequence.html).
        pub fn in_sequence(&mut self, seq: &mut $crate::Sequence) -> &mut Self {
            self.common.in_sequence(seq);
            self
        }

        pub fn is_done(&self) -> bool {
            self.common.is_done()
        }

        /// Forbid this expectation from ever being called
        pub fn never(&mut self) -> &mut Self {
            self.common.never();
            self
        }

        /// Expect this expectation to be called exactly once.  Shortcut for
        /// [`times(1)`](#method.times).
        pub fn once(&mut self) -> &mut Self {
            self.times(1)
        }

        /// Require this expectation to be called exactly `n` times.
        pub fn times(&mut self, n: usize) -> &mut Self {
            self.common.times(n);
            self
        }

        /// Allow this expectation to be called any number of times
        ///
        /// This behavior is the default, but the method is provided in case the
        /// default behavior changes.
        pub fn times_any(&mut self) -> &mut Self {
            self.common.times_any();
            self
        }

        /// Allow this expectation to be called any number of times within a
        /// given range
        pub fn times_range(&mut self, range: ::std::ops::Range<usize>)
            -> &mut Self
        {
            self.common.times_range(range);
            self
        }
    }
}

/// Generate Expectation and Expectations types with specific signatures, for
/// `'static` return types.
///
/// # Arguments
///
/// * `expectation`:    Name of the generated Expectation type
/// * `module`:         Name of the private module to create
/// * `o`:              Output type.  Must be static
/// * `methty`:         Comma-delimited sequence of arguments types for the
///                     method being mocked.
/// * `matchcall`:      Comma-delimited sequence of expressions that produce
///                     values of type `matchty` from values of type `methty`.
/// * `args`:           comma-delimited sequence of argument names for each
///                     argument.  Ideally this wouldn't need to be specified,
///                     but it is due to Rust's macro hygiene rules.
/// * `predargs`:       Comma-delimited sequence of identifiers of the same
///                     length as `args`, but distinct.
/// * `matchty`:        comma-delimited sequence of types for each match
///                     argument.  Must all be `'static`.
///
/// # Examples
///
/// ```
/// // Mock a method like foo(&self, x: u32, y: &i16) -> u32
/// expectation!{
///     FooExpectation, __foo__priv, u32, (u32, &i16),
///     [&i.0, i.1], [i0, i1], [p0, p1], [u32, i16]
/// }
#[macro_export]
macro_rules! expectation {(
        $expectation:ident,
        $module:ident,
        $o:ty,
        [ $( $methty:ty ),* ],
        [ $( $matchcall:expr ),* ],
        [ $( $args:ident ),* ],
        [ $( $predargs:ident ),* ],
        [ $( $matchty:ty ),* ]) =>
    {
        mod $module {
        use ::predicates_tree::CaseTreeExt;
        use ::std::ops::DerefMut;
        use super::*;

        enum Rfunc {
            Default,
            // Indicates that a `return_once` expectation has already returned
            Expired,
            Mut(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
            // Should be Box<dyn FnOnce> once that feature is stabilized
            // https://github.com/rust-lang/rust/issues/28796
            Once(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
        }

        impl  Rfunc {
            fn call_mut(&mut self, $( $args: $methty, )* ) -> $o {
                match self {
                    Rfunc::Default => {
                        unimplemented!()
                        //Self::return_default()
                    },
                    Rfunc::Expired => {
                        panic!("Called a method twice that was expected only once")
                    },
                    Rfunc::Mut(f) => {
                        f( $( $args, )* )
                    },
                    Rfunc::Once(_) => {
                        let fo = ::std::mem::replace(self, Rfunc::Expired);
                        if let Rfunc::Once(mut f) = fo {
                            f( $( $args, )* )
                        } else {
                            unreachable!()
                        }
                    },
                }
            }
        }

        impl std::default::Default for Rfunc {
            fn default() -> Self {
                Rfunc::Default
            }
        }

        enum Matcher {
            Func(Box<Fn($( &$matchty, )* ) -> bool>),
            Pred( $( Box<$crate::Predicate<$matchty>>, )* )
        }

        impl Matcher {
            fn eval(&self, $( $args: &$matchty, )*) -> bool {
                match self {
                    Matcher::Func(f) => f($( $args, )*),
                    Matcher::Pred($( $predargs, )*) =>
                        [$( $predargs.eval($args), )*]
                        .into_iter()
                        .all(|x| *x),
                }
            }

            fn verify(&self, $( $args: &$matchty, )* ) {
                match self {
                    Matcher::Func(f) => assert!(f($( $args, )*),
                        "Expectation didn't match arguments"),
                    Matcher::Pred($( $predargs, )*) => {
                        $(if let Some(c) = $predargs.find_case(false, $args) {
                            panic!("Expectation didn't match arguments:\n{}",
                                   c.tree());
                        })*
                    }
                }
            }
        }

        impl Default for Matcher {
            #[allow(unused_variables)]
            fn default() -> Self {
                Matcher::Func(Box::new(|$( $args, )*| true))
            }
        }

        /// Holds the stuff that is independent of the output type
        #[derive(Default)]
        struct Common {
            matcher: ::std::sync::Mutex<Matcher>,
            seq_handle: Option<$crate::SeqHandle>,
            times: $crate::Times
        }

        impl Common {
            fn call(&self, $( $args: &$matchty, )* ) {
                self.matcher.lock().unwrap().verify($( $args, )*);
                self.times.call();
                self.verify_sequence();
                if self.times.is_satisfied() {
                    self.satisfy_sequence()
                }
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            fn with<$( $predargs: $crate::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*)
            {
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Pred($( Box::new($args), )*);
                ::std::mem::replace(guard.deref_mut(), m);
            }

            fn withf<F>(&mut self, f: F)
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Func(Box::new(f));
                ::std::mem::replace(guard.deref_mut(), m);
            }

            $crate::common_methods!{}
        }

        #[derive(Default)]
        pub struct Expectation {
            common: Common,
            rfunc: ::std::sync::Mutex<Rfunc>,
        }

        impl Expectation {
            pub fn call(&self, $( $args: $methty, )* ) -> $o {
                self.common.call($( $matchcall, )*);
                self.rfunc.lock().unwrap().call_mut($( $args, )*)
            }

            /// Supply an `FnOnce` closure that will provide the return value
            /// for this Expectation.  This is useful for return types that
            /// aren't `Clone`.  It will be an error to call this Expectation
            /// multiple times.
            pub fn return_once<F>(&mut self, f: F) -> &mut Self
                where F: FnOnce($( $methty, )*) -> $o + Send + 'static
            {
                let mut fopt = Some(f);
                let fmut = move |$( $args: $methty, )*| {
                    if let Some(f) = fopt.take() {
                        f($( $args, )*)
                    } else {
                        panic!("Called a method twice that was expected only once")
                    }
                };
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(),
                                        Rfunc::Once(Box::new(fmut)));
                }
                self
            }

            /// Single-threaded version of [`return_once`](#method.return_once).
            /// This is useful for return types that are neither `Send` nor
            /// `Clone`.
            ///
            /// It is a runtime error to call the mock method from a different
            /// thread than the one that originally called this method.  It is
            /// also a runtime error to call the method more than once.
            pub fn return_once_st<F>(&mut self, f: F) -> &mut Self
                where F: FnOnce($( $methty, )*) -> $o + 'static
            {
                let mut fragile = Some(::fragile::Fragile::new(f));
                let fmut = Box::new(move |$( $args: $methty, )*| {
                    match fragile.take() {
                        Some(frag) => (frag.into_inner())($( $args, )*),
                        None => panic!(
                            "Called a method twice that was expected only once")
                    }
                });
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(), Rfunc::Once(fmut));
                }
                self
            }

            pub fn returning<F>(&mut self, f: F) -> &mut Self
                where F: FnMut($( $methty, )*) -> $o + Send + 'static
            {
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(), Rfunc::Mut(Box::new(f)));
                }
                self
            }

            /// Single-threaded version of [`returning`](#method.returning).
            /// Can be used when the argument or return type isn't `Send`.
            ///
            /// It is a runtime error to call the mock method from a different
            /// thread than the one that originally called this method.
            pub fn returning_st<F>(&mut self, f: F) -> &mut Self
                where F: FnMut($( $methty, )*) -> $o + 'static
            {
                let mut fragile = ::fragile::Fragile::new(f);
                let fmut = move |$( $args: $methty, )*| {
                    (fragile.get_mut())($( $args, )*)
                };
                {
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(),
                                        Rfunc::Mut(Box::new(fmut)));
                }
                self
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            pub fn with<$( $predargs: $crate::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*) -> &mut Self
            {
                self.common.with($( $args, )*);
                self
            }

            pub fn withf<F>(&mut self, f: F) -> &mut Self
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                self.common.withf(f);
                self
            }

            $crate::expectation_methods!{}
        }

        }
        use $module::Expectation as $expectation;
    }
}

/// Generate Expectation and Expectations types with specific signatures, for
/// methods that return references.
///
/// # Arguments
///
/// * `expectation`:    Name of the generated Expectation type
/// * `module`:         Name of the private module to create
/// * `o`:              Owned version of the output type.  Must be a `'static`.
///                     The real output type will be a reference to this one.
/// * `methty`:         Comma-delimited sequence of arguments types for the
///                     method being mocked.
/// * `matchcall`:      Comma-delimited sequence of expressions that produce
///                     values of type `matchty` from values of type `methty`.
/// * `args`:           comma-delimited sequence of argument names for each
///                     argument.  Ideally this wouldn't need to be specified,
///                     but it is due to Rust's macro hygiene rules.
/// * `predargs`:       Comma-delimited sequence of identifiers of the same
///                     length as `args`, but distinct.
/// * `matchty`:        comma-delimited sequence of types for each match
///                     argument.  Must all be `'static`.
///
/// # Examples
///
/// ```
/// // Mock a method like foo(&self, x: u32, y: &i16) -> &u32
/// ref_expectation!{
///     FooExpectation, __foo__priv, u32, (u32, &i16),
///     [&i.0, i.1], [i0, i1], [p0, p1], [u32, i16]
/// }
#[macro_export]
macro_rules! ref_expectation {(
        $expectation:ident,
        $module:ident,
        $o:ty,
        [ $( $methty:ty ),* ],
        [ $( $matchcall:expr ),* ],
        [ $( $args:ident ),* ],
        [ $( $predargs:ident ),* ],
        [ $( $matchty:ty ),* ]) =>
    {
        mod $module {
        use ::predicates_tree::CaseTreeExt;
        use ::std::ops::DerefMut;
        use super::*;

        enum Matcher {
            Func(Box<Fn($( &$matchty, )* ) -> bool>),
            Pred( $( Box<$crate::Predicate<$matchty>>, )* )
        }

        impl Matcher {
            fn eval(&self, $( $args: &$matchty, )*) -> bool {
                match self {
                    Matcher::Func(f) => f($( $args, )*),
                    Matcher::Pred($( $predargs, )*) =>
                        [$( $predargs.eval($args), )*]
                        .into_iter()
                        .all(|x| *x),
                }
            }

            fn verify(&self, $( $args: &$matchty, )* ) {
                match self {
                    Matcher::Func(f) => assert!(f($( $args, )*),
                        "Expectation didn't match arguments"),
                    Matcher::Pred($( $predargs, )*) => {
                        $(if let Some(c) = $predargs.find_case(false, $args) {
                            panic!("Expectation didn't match arguments:\n{}",
                                   c.tree());
                        })*
                    }
                }
            }
        }

        impl Default for Matcher {
            #[allow(unused_variables)]
            fn default() -> Self {
                Matcher::Func(Box::new(|$( $args, )*| true))
            }
        }

        /// Holds the stuff that is independent of the output type
        #[derive(Default)]
        struct Common {
            matcher: ::std::sync::Mutex<Matcher>,
            seq_handle: Option<$crate::SeqHandle>,
            times: $crate::Times
        }

        impl Common {
            fn call(&self, $( $args: &$matchty, )* ) {
                self.matcher.lock().unwrap().verify($( $args, )*);
                self.times.call();
                self.verify_sequence();
                if self.times.is_satisfied() {
                    self.satisfy_sequence()
                }
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            fn with<$( $predargs: $crate::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*)
            {
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Pred($( Box::new($args), )*);
                ::std::mem::replace(guard.deref_mut(), m);
            }

            fn withf<F>(&mut self, f: F)
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Func(Box::new(f));
                ::std::mem::replace(guard.deref_mut(), m);
            }

            $crate::common_methods!{}
        }

        #[derive(Default)]
        pub struct Expectation {
            common: Common,
            result: Option<$o>,
        }

        impl Expectation {
            pub fn call(&self, $( $args: $methty, )* ) -> &$o {
                self.common.call($( $matchcall, )*);
                &self.result.as_ref()
                    .expect("Must set return value with return_const")
            }

            pub fn new() -> Self {
                Self::default()
            }

            /// Return a reference to a constant value from the `Expectation`
            pub fn return_const(&mut self, o: $o) -> &mut Self {
                self.result = Some(o);
                self
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            pub fn with<$( $predargs: $crate::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*) -> &mut Self
            {
                self.common.with($( $args, )*);
                self
            }

            pub fn withf<F>(&mut self, f: F) -> &mut Self
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                self.common.withf(f);
                self
            }

            $crate::expectation_methods!{}
        }

        }
        use $module::Expectation as $expectation;
    }
}
<|endoftext|>


<commit_before>/*!

Generates an iterator type `__Matcher` that looks roughly like

```ignore
mod __intern_token {
    extern crate regex as __regex;

    pub struct __Matcher<'input> {
        text: &'input str,
        consumed: usize,
        regex_set: __regex::RegexSet,
        regex_vec: Vec<__regex::Regex>,
    }

    impl __Matcher<'input> {
        fn __tokenize(&self, text: &str) -> Option<(usize, usize)> { ... }
    }

    impl<'input> Iterator for __Matcher<'input> {
        type Item = Result<(usize, (usize, &'input str), usize), ParseError>;
        //                  ~~~~~   ~~~~~  ~~~~~~~~~~~   ~~~~~
        //                  start   token  token         end
        //                          index  text
    }
}
```

 */

use intern;
use lexer::re;
use grammar::parse_tree::InternToken;
use grammar::repr::{Grammar, TerminalLiteral};
use rust::RustWrite;
use std::io::{self, Write};

pub fn compile<W: Write>(
    grammar: &Grammar,
    intern_token: &InternToken,
    out: &mut RustWrite<W>)
    -> io::Result<()>
{
    let prefix = &grammar.prefix;

    rust!(out, "mod {}intern_token {{", prefix);
    try!(out.write_standard_uses(prefix));
    rust!(out, "extern crate regex as {}regex;", prefix);
    rust!(out, "pub struct {}Matcher<'input> {{", prefix);
    rust!(out, "text: &'input str,"); // remaining input
    rust!(out, "consumed: usize,"); // number of chars consumed thus far
    rust!(out, "regex_set: {}regex::RegexSet,", prefix);
    rust!(out, "regex_vec: Vec<{}regex::Regex>,", prefix);
    rust!(out, "}}");
    rust!(out, "");
    rust!(out, "impl<'input> {}Matcher<'input> {{", prefix);
    rust!(out, "pub fn new(s: &'input str) -> {}Matcher<'input> {{", prefix);

    // create a vector of rust string literals with the text of each
    // regular expression
    let regex_strings: Vec<String> = intern::read(|interner| {
        intern_token.literals
                    .iter()
                    .map(|&literal| match literal {
                        TerminalLiteral::Quoted(s) => re::parse_literal(interner.data(s)),
                        TerminalLiteral::Regex(s) => re::parse_regex(interner.data(s)).unwrap(),
                    })
                    .map(|regex| {
                        // make sure all regex are anchored at the beginning of the input
                        format!("^{}", regex)
                    })
                    .map(|regex_str| {
                        // create a rust string with text of the regex; the Debug impl
                        // will add quotes and escape
                        format!("{:?}", regex_str)
                    })
                    .collect()
    });

    rust!(out, "let {}regex_set = {}regex::RegexSet::new(&[", prefix, prefix);
    for literal in &regex_strings {
        rust!(out, "{},", literal);
    }
    rust!(out, "]).unwrap();");

    rust!(out, "let {}regex_vec = vec![", prefix);
    for literal in &regex_strings {
        rust!(out, "{}regex::Regex::new({}).unwrap(),", prefix, literal);
    }
    rust!(out, "];");

    rust!(out, "{}Matcher {{", prefix);
    rust!(out, "text: s,");
    rust!(out, "consumed: 0,");
    rust!(out, "regex_set: {}regex_set,", prefix);
    rust!(out, "regex_vec: {}regex_vec,", prefix);
    rust!(out, "}}"); // struct literal
    rust!(out, "}}"); // fn new()
    rust!(out, "}}"); // impl Matcher<'input>
    rust!(out, "");
    rust!(out, "impl<'input> Iterator for {}Matcher<'input> {{", prefix);
    rust!(out, "type Item = Result<(usize, (usize, &'input str), usize), \
                {}lalrpop_util::ParseError<usize,(usize, &'input str),{}>>;",
          prefix, grammar.types.error_type());
    rust!(out, "");
    rust!(out, "fn next(&mut self) -> Option<Self::Item> {{");

    // start by trimming whitespace from left
    rust!(out, "let {}text = self.text.trim_left();", prefix);
    rust!(out, "let {}whitespace = self.text.len() - {}text.len();", prefix, prefix);
    rust!(out, "let {}start_offset = self.consumed + {}whitespace;", prefix, prefix);

    // if nothing left, return None
    rust!(out, "if {}text.is_empty() {{", prefix);
    rust!(out, "self.text = {}text;", prefix);
    rust!(out, "self.consumed = {}start_offset;", prefix);
    rust!(out, "None");
    rust!(out, "}} else {{");

    // otherwise, use regex-set to find list of matching tokens
    rust!(out, "let {}matches = self.regex_set.matches({}text);", prefix, prefix);

    // if nothing matched, return an error
    rust!(out, "if !{}matches.matched_any() {{", prefix);
    rust!(out, "Some(Err({}lalrpop_util::ParseError::InvalidToken {{", prefix);
    rust!(out, "location: {}start_offset,", prefix);
    rust!(out, "}}))");
    rust!(out, "}} else {{");

    // otherwise, have to find longest, highest-priority match. We have the literals
    // sorted in order of increasing precedence, so we'll iterate over them one by one,
    // checking if each one matches, and remembering the longest one.
    rust!(out, "let mut {}longest_match = 0;", prefix); // length of longest match
    rust!(out, "let mut {}index = 0;", prefix); // index of longest match
    rust!(out, "for {}i in 0 .. {} {{", prefix, intern_token.literals.len());
    rust!(out, "if {}matches.matched({}i) {{", prefix, prefix);

    // re-run the regex to find out how long this particular match
    // was, then compare that against the longest-match so far. Note
    // that the order of the tuple is carefully constructed to ensure
    // that (a) we get the longest-match but (b) if two matches are
    // equal, we get the largest index. This is because the indices
    // are sorted in order of increasing priority, and because we know
    // that indices of equal priority cannot both match (because of
    // the DFA check).
    rust!(out, "let {}match = self.regex_vec[{}i].find({}text).unwrap();", prefix, prefix, prefix);
    rust!(out, "let {}len = {}match.end();", prefix, prefix);
    rust!(out, "if {}len >= {}longest_match {{", prefix, prefix);
    rust!(out, "{}longest_match = {}len;", prefix, prefix);
    rust!(out, "{}index = {}i;", prefix, prefix);
    rust!(out, "}}"); // if is longest match
    rust!(out, "}}"); // if matches.matched(i)
    rust!(out, "}}"); // for loop

    // transform the result into the expected return value
    rust!(out, "let {}result = &{}text[..{}longest_match];", prefix, prefix, prefix);
    rust!(out, "let {}remaining = &{}text[{}longest_match..];", prefix, prefix, prefix);
    rust!(out, "let {}end_offset = {}start_offset + {}longest_match;", prefix, prefix, prefix);
    rust!(out, "self.text = {}remaining;", prefix);
    rust!(out, "self.consumed = {}end_offset;", prefix);
    rust!(out, "Some(Ok(({}start_offset, ({}index, {}result), {}end_offset)))",
          prefix, prefix, prefix, prefix);

    rust!(out, "}}"); // else
    rust!(out, "}}"); // else
    rust!(out, "}}"); // fn
    rust!(out, "}}"); // impl
    rust!(out, "}}"); // mod
    Ok(())
}

<commit_msg>store the string list into a local, so we can coerce it<commit_after>/*!

Generates an iterator type `__Matcher` that looks roughly like

```ignore
mod __intern_token {
    extern crate regex as __regex;

    pub struct __Matcher<'input> {
        text: &'input str,
        consumed: usize,
        regex_set: __regex::RegexSet,
        regex_vec: Vec<__regex::Regex>,
    }

    impl __Matcher<'input> {
        fn __tokenize(&self, text: &str) -> Option<(usize, usize)> { ... }
    }

    impl<'input> Iterator for __Matcher<'input> {
        type Item = Result<(usize, (usize, &'input str), usize), ParseError>;
        //                  ~~~~~   ~~~~~  ~~~~~~~~~~~   ~~~~~
        //                  start   token  token         end
        //                          index  text
    }
}
```

 */

use intern;
use lexer::re;
use grammar::parse_tree::InternToken;
use grammar::repr::{Grammar, TerminalLiteral};
use rust::RustWrite;
use std::io::{self, Write};

pub fn compile<W: Write>(
    grammar: &Grammar,
    intern_token: &InternToken,
    out: &mut RustWrite<W>)
    -> io::Result<()>
{
    let prefix = &grammar.prefix;

    rust!(out, "mod {}intern_token {{", prefix);
    try!(out.write_standard_uses(prefix));
    rust!(out, "extern crate regex as {}regex;", prefix);
    rust!(out, "pub struct {}Matcher<'input> {{", prefix);
    rust!(out, "text: &'input str,"); // remaining input
    rust!(out, "consumed: usize,"); // number of chars consumed thus far
    rust!(out, "regex_set: {}regex::RegexSet,", prefix);
    rust!(out, "regex_vec: Vec<{}regex::Regex>,", prefix);
    rust!(out, "}}");
    rust!(out, "");
    rust!(out, "impl<'input> {}Matcher<'input> {{", prefix);
    rust!(out, "pub fn new(s: &'input str) -> {}Matcher<'input> {{", prefix);

    // create a vector of rust string literals with the text of each
    // regular expression
    let regex_strings: Vec<String> = intern::read(|interner| {
        intern_token.literals
                    .iter()
                    .map(|&literal| match literal {
                        TerminalLiteral::Quoted(s) => re::parse_literal(interner.data(s)),
                        TerminalLiteral::Regex(s) => re::parse_regex(interner.data(s)).unwrap(),
                    })
                    .map(|regex| {
                        // make sure all regex are anchored at the beginning of the input
                        format!("^{}", regex)
                    })
                    .map(|regex_str| {
                        // create a rust string with text of the regex; the Debug impl
                        // will add quotes and escape
                        format!("{:?}", regex_str)
                    })
                    .collect()
    });

    rust!(out, "let {}strs: &[&str] = &[", prefix);
    for literal in &regex_strings {
        rust!(out, "{},", literal);
    }
    rust!(out, "];");
    rust!(out, "let {}regex_set = {}regex::RegexSet::new({}strs).unwrap();",
          prefix, prefix, prefix);

    rust!(out, "let {}regex_vec = vec![", prefix);
    for literal in &regex_strings {
        rust!(out, "{}regex::Regex::new({}).unwrap(),", prefix, literal);
    }
    rust!(out, "];");

    rust!(out, "{}Matcher {{", prefix);
    rust!(out, "text: s,");
    rust!(out, "consumed: 0,");
    rust!(out, "regex_set: {}regex_set,", prefix);
    rust!(out, "regex_vec: {}regex_vec,", prefix);
    rust!(out, "}}"); // struct literal
    rust!(out, "}}"); // fn new()
    rust!(out, "}}"); // impl Matcher<'input>
    rust!(out, "");
    rust!(out, "impl<'input> Iterator for {}Matcher<'input> {{", prefix);
    rust!(out, "type Item = Result<(usize, (usize, &'input str), usize), \
                {}lalrpop_util::ParseError<usize,(usize, &'input str),{}>>;",
          prefix, grammar.types.error_type());
    rust!(out, "");
    rust!(out, "fn next(&mut self) -> Option<Self::Item> {{");

    // start by trimming whitespace from left
    rust!(out, "let {}text = self.text.trim_left();", prefix);
    rust!(out, "let {}whitespace = self.text.len() - {}text.len();", prefix, prefix);
    rust!(out, "let {}start_offset = self.consumed + {}whitespace;", prefix, prefix);

    // if nothing left, return None
    rust!(out, "if {}text.is_empty() {{", prefix);
    rust!(out, "self.text = {}text;", prefix);
    rust!(out, "self.consumed = {}start_offset;", prefix);
    rust!(out, "None");
    rust!(out, "}} else {{");

    // otherwise, use regex-set to find list of matching tokens
    rust!(out, "let {}matches = self.regex_set.matches({}text);", prefix, prefix);

    // if nothing matched, return an error
    rust!(out, "if !{}matches.matched_any() {{", prefix);
    rust!(out, "Some(Err({}lalrpop_util::ParseError::InvalidToken {{", prefix);
    rust!(out, "location: {}start_offset,", prefix);
    rust!(out, "}}))");
    rust!(out, "}} else {{");

    // otherwise, have to find longest, highest-priority match. We have the literals
    // sorted in order of increasing precedence, so we'll iterate over them one by one,
    // checking if each one matches, and remembering the longest one.
    rust!(out, "let mut {}longest_match = 0;", prefix); // length of longest match
    rust!(out, "let mut {}index = 0;", prefix); // index of longest match
    rust!(out, "for {}i in 0 .. {} {{", prefix, intern_token.literals.len());
    rust!(out, "if {}matches.matched({}i) {{", prefix, prefix);

    // re-run the regex to find out how long this particular match
    // was, then compare that against the longest-match so far. Note
    // that the order of the tuple is carefully constructed to ensure
    // that (a) we get the longest-match but (b) if two matches are
    // equal, we get the largest index. This is because the indices
    // are sorted in order of increasing priority, and because we know
    // that indices of equal priority cannot both match (because of
    // the DFA check).
    rust!(out, "let {}match = self.regex_vec[{}i].find({}text).unwrap();", prefix, prefix, prefix);
    rust!(out, "let {}len = {}match.end();", prefix, prefix);
    rust!(out, "if {}len >= {}longest_match {{", prefix, prefix);
    rust!(out, "{}longest_match = {}len;", prefix, prefix);
    rust!(out, "{}index = {}i;", prefix, prefix);
    rust!(out, "}}"); // if is longest match
    rust!(out, "}}"); // if matches.matched(i)
    rust!(out, "}}"); // for loop

    // transform the result into the expected return value
    rust!(out, "let {}result = &{}text[..{}longest_match];", prefix, prefix, prefix);
    rust!(out, "let {}remaining = &{}text[{}longest_match..];", prefix, prefix, prefix);
    rust!(out, "let {}end_offset = {}start_offset + {}longest_match;", prefix, prefix, prefix);
    rust!(out, "self.text = {}remaining;", prefix);
    rust!(out, "self.consumed = {}end_offset;", prefix);
    rust!(out, "Some(Ok(({}start_offset, ({}index, {}result), {}end_offset)))",
          prefix, prefix, prefix, prefix);

    rust!(out, "}}"); // else
    rust!(out, "}}"); // else
    rust!(out, "}}"); // fn
    rust!(out, "}}"); // impl
    rust!(out, "}}"); // mod
    Ok(())
}

<|endoftext|>


<commit_before>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
#[derive(PartialEq)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
#[derive(PartialEq)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, detector: &Detector) {
        self.spin = match detector {
            &Detector::D12 => SpinUp,
            &Detector::D3 => match random::<f32>() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
            &Detector::D9 => match random::<f32>() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
        };
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let detector1 = Detector::D12; //Particle::get_detector_direction();
        let detector2 = Particle::get_detector_direction();

        self.measure (&detector1);

        if detector1 == detector2 { // 1/3
            friend.spin = match self.spin {
                SpinUp => SpinDown,
                SpinDown => SpinUp,
                _ => unreachable!()
            };
        } else { // 2/3
            friend.measure(&detector2);
        }

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {
        let rnd = random::<f32>();

        let detector = match rnd {
            0.0  ... 0.33 => Detector::D12,
            0.33 ... 0.66 => Detector::D3,
            0.66 ... 1.00 => Detector::D9,
            _ => unreachable!()
        };

        return detector;
    }

    pub fn hidden_information (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

// hidden_information should give +55.6% difference, spooky would give 50%
fn main () {

    let mut trials: f64 = 1000000f64;
    let mut num_different: f64 = 0f64;

    let particles = Particle::new_pair();
    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        lhs.spooky(&mut rhs);

        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for spooky {}%", 100f64 * (num_different) / trials as f64);
    println!("      Should be about 1/2 or 50%");

    num_different = 0f64;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        if random::<f32>() < 0.50 {
            lhs.hidden_information(&mut rhs, OddBall);
        } else {
            lhs.hidden_information(&mut rhs, Trivial);
        }

        //println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);
        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for hidden info {}%", 100f64 * (num_different) / trials as f64);
    println!("  Should be greater than 5/9th or {}%", 100.0 * 5.0/9.0);

}
<commit_msg>fix round off error<commit_after>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
#[derive(PartialEq)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
#[derive(PartialEq)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, detector: &Detector) {
        self.spin = match detector {
            &Detector::D12 => SpinUp,
            &Detector::D3 => match random::<f32>() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
            &Detector::D9 => match random::<f32>() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
        };
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let detector1 = Detector::D12; //Particle::get_detector_direction();
        let detector2 = Particle::get_detector_direction();

        self.measure (&detector1);

        if detector1 == detector2 { // 1/3
            friend.spin = match self.spin {
                SpinUp => SpinDown,
                SpinDown => SpinUp,
                _ => unreachable!()
            };
        } else { // 2/3
            friend.measure(&detector2);
        }

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {
        let rnd = random::<f32>();

        let detector = match rnd {
            0.0       ... 0.3333333 => Detector::D12,
            0.3333333 ... 0.6666666 => Detector::D3,
            0.6666666 ... 1.00 => Detector::D9,
            _ => unreachable!()
        };

        return detector;
    }

    pub fn hidden_information (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

// hidden_information should give +55.6% difference, spooky would give 50%
fn main () {

    let mut trials: f64 = 1000000f64;
    let mut num_different: f64 = 0f64;

    let particles = Particle::new_pair();
    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        lhs.spooky(&mut rhs);

        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for spooky {}%", 100f64 * (num_different) / trials as f64);
    println!("      Should be about 1/2 or 50%");

    num_different = 0f64;

    for _ in range(0, trials as usize) {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        if random::<f32>() < 0.50 {
            lhs.hidden_information(&mut rhs, OddBall);
        } else {
            lhs.hidden_information(&mut rhs, Trivial);
        }

        //println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);
        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for hidden info {}%", 100f64 * (num_different) / trials as f64);
    println!("  Should be greater than 5/9th or {}%", 100.0 * 5.0/9.0);

}
<|endoftext|>


<commit_before>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f\n", time as float));
        io::println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f : %d cells -> %s.\n",time as float, crowd.size() as int, self.fname));
        let outfile=self.new_filename();
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%u\n", cell.id));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<commit_msg>Affichage correct du fichier de sortie<commit_after>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f\n", time as float));
        io::println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        let outfile=self.new_filename();
        io::println(fmt!("%f : %d cells -> %s.\n",time as float, crowd.size() as int, outfile));
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%u\n", cell.id));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<|endoftext|>


<commit_before>use rust2html::htmlwriter::HtmlWriter;
use std::str;
use std::io::{File, UserDir};
use std::io::fs::{mkdir_recursive,copy,walk_dir};
use rust2html::RF_Options;
use collections::hashmap::HashMap;
use collections::hashmap::HashSet;
use rust2html;
use std::cmp;

// create index page. Show subdirectories and files matching extentions.
// each subdirectory links to the subdir.html
// each listed file links to its 'file.html'.

pub fn write_index_html(source_dir: &Path,extentions:&[~str], options:&RF_Options) {

	//println!("output dir={}",options.output_dir.as_str().unwrap_or(""));
	println!("Generating index page:-");

	// the index page shows: all source in root dir,
	// all dirs containing source,
	// direct link to any 'mod.rs' or 'lib.rs'

	// hmm, why dont we just make a treeview, ffs.
	let mut source_dirs= HashSet::<(Path,~str)>::new();
	let mut source_files=HashSet::<(Path,~str)>::new();
	match walk_dir(source_dir) {
		Ok(mut dirs)=> {
//			write_index_html_sub(source_dir, dirs, extentions);
//			println!("dir contents {:?} {:?}", source_dir, dirs);
			for path in dirs {
				match path.as_str() {
					Some( ref s)=> {
						let ext=path.extension_str().unwrap_or(&"");;
						let filename=path.filename_str().unwrap_or(&"");
						let dirname=path.dirname_str().unwrap_or(&"");
						if (ext=="rs" ||
							ext=="cpp"||
							ext=="c"||
							ext=="h") {
							source_dirs.insert((path.clone(), dirname.to_owned()));
							source_files.insert((path.clone(), filename.to_owned()));
						}
					}
					None=>{},
				}
			}
		},
		_=>{}
	};

	let mut doc=HtmlWriter::new();
	let index_path = options.output_dir.join(Path::new("index.html"));
	rust2html::write_head(&mut doc, &index_path, options);

	doc.begin_tag_check("body");
	doc.begin_tag("div");
	doc.begin_tag_check("maintext");

	doc.writeln("Index of " + source_dir.as_str().unwrap_or(""));
	doc.writeln(rust2html::get_git_branch_info());
	doc.writeln("");

	// write as grid, todo abstract it ffs.
	// TODO we're writing HTML, ffs, its got tables and all sorts..
	// TODO: Grid Layout - seperate path/filename to make squarer items.

	let mut max_line_len:uint=0;
	for &(ref sp,ref sf) in source_files.iter() {
		max_line_len =cmp::max(max_line_len, sf.len())
	}
	let desired_width=100;
	let num_cols = desired_width / max_line_len;

	for &(ref sp,ref sf) in source_files.iter() {
		doc.begin_tag_link( sp.as_str().unwrap_or("") + ".html");
		doc.writeln(*sf);
		doc.end_tag();
	}

    doc.end_tag();
    doc.end_tag();
    doc.end_tag();

	rust2html::file_write_bytes_as(&index_path, doc.as_bytes());
}

/*
pub fn write_index_html_sub(source_dir:&Path, contents:[&Path]{
	doc = htmlwrite::HtmlWriter::new();
	::rust2html::write_head(doc, source_dir+"/index.html");

}*/
<commit_msg>columns in index page<commit_after>use rust2html::htmlwriter::HtmlWriter;
use std::str;
use std::io::{File, UserDir};
use std::io::fs::{mkdir_recursive,copy,walk_dir};
use rust2html::RF_Options;
use collections::hashmap::HashMap;
use collections::hashmap::HashSet;
use rust2html;
use std::cmp;

// create index page. Show subdirectories and files matching extentions.
// each subdirectory links to the subdir.html
// each listed file links to its 'file.html'.

pub fn write_index_html(source_dir: &Path,extentions:&[~str], options:&RF_Options) {

	//println!("output dir={}",options.output_dir.as_str().unwrap_or(""));
	println!("Generating index page:-");

	// the index page shows: all source in root dir,
	// all dirs containing source,
	// direct link to any 'mod.rs' or 'lib.rs'

	// hmm, why dont we just make a treeview, ffs.
	let mut source_dirs= HashSet::<(Path,~str)>::new();
	let mut source_files=HashSet::<(Path,~str)>::new();
	match walk_dir(source_dir) {
		Ok(mut dirs)=> {
//			write_index_html_sub(source_dir, dirs, extentions);
//			println!("dir contents {:?} {:?}", source_dir, dirs);
			for path in dirs {
				match path.as_str() {
					Some( ref s)=> {
						let ext=path.extension_str().unwrap_or(&"");;
						let filename=path.filename_str().unwrap_or(&"");
						let dirname=path.dirname_str().unwrap_or(&"");
						if (ext=="rs") {
							source_dirs.insert((path.clone(), dirname.to_owned()));
							source_files.insert((path.clone(), filename.to_owned()));
						}
					}
					None=>{},
				}
			}
		},
		_=>{}
	};

	let mut doc=HtmlWriter::new();
	let index_path = options.output_dir.join(Path::new("index.html"));
	rust2html::write_head(&mut doc, &index_path, options);

	doc.begin_tag_check("body");
	doc.begin_tag("div");
	doc.begin_tag_check("maintext");

	doc.writeln("Index of " + source_dir.as_str().unwrap_or(""));
	doc.writeln(rust2html::get_git_branch_info());
	doc.writeln("");

	// write as grid, todo abstract it ffs.
	// TODO we're writing HTML, ffs, its got tables and all sorts..
	// TODO: Grid Layout - seperate path/filename to make squarer items.

	let mut max_line_len:uint=0;
	for &(ref sp,ref sf) in source_files.iter() {
		max_line_len =cmp::max(max_line_len, sf.len())
	}
	let desired_width=100;
	let num_cols = desired_width / max_line_len;

	let mut column=0;
	for &(ref sp,ref sf) in source_files.iter() {
		doc.begin_tag_link( sp.as_str().unwrap_or("") + ".html");
		let sp_str=sp.as_str().unwrap_or("");
		doc.write(sp_str);
		doc.end_tag();
		let mut i=sp_str.len();
		while i<max_line_len { doc.write(" "); i+=1;}
		column+=1;
		if column>=num_cols {
			doc.write_tag("br");
			column=0;
		}
	}

    doc.end_tag();
    doc.end_tag();
    doc.end_tag();

	rust2html::file_write_bytes_as(&index_path, doc.as_bytes());
}

/*
pub fn write_index_html_sub(source_dir:&Path, contents:[&Path]{
	doc = htmlwrite::HtmlWriter::new();
	::rust2html::write_head(doc, source_dir+"/index.html");

}*/
<|endoftext|>


<commit_before>use std::str::Chars;

struct Lexer<'a> {
    source: Chars<'a>,
    c: Option<char>,
}

#[derive(Debug, PartialEq)]
enum TokenType {
    Num,
    Add,
    Eof,
}

#[derive(Debug, PartialEq)]
struct Token(TokenType, String);

impl<'a> Lexer<'a> {

    fn new(source: &'a String) -> Lexer<'a> {
        let mut source = source.chars();
        let c = None;
        let mut lexer = Lexer {
            source,
            c,
        };
        lexer.consume();
        lexer
    }

    fn consume(&mut self) {
        self.c = self.source.next();
    }

    fn next(&mut self) -> Token {
        while let Some(c) = self.c {
            match c {
                ' ' => {
                    self.consume();
                },
                '0'..='9' => {
                    let mut s = String::new();
                    s.push(c);
                    self.consume();
                    while let Some(c) = self.c {
                        match c {
                            '0'..='9' => {
                                s.push(c);
                                self.consume();
                            },
                            _ => {
                                break;
                            },
                        }
                    }
                    return Token(TokenType::Num, s)
                },
                '+' => {
                    self.consume();
                    return Token(TokenType::Add, String::from("+"))
                },
                _ => {
                    panic!("Illegal character: {}", c);
                }
            }
        }
        Token(TokenType::Eof, String::new())
    }
}

#[derive(Debug, PartialEq)]
enum Node {
    Num(i32),
    Add(Box<Node>, Box<Node>),
}

struct Parser<'a> {
    lexer: Lexer<'a>,
    token: Token,
}

impl<'a> Parser<'a> {

    fn new(source: &'a String) -> Parser<'a> {
        let mut lexer = Lexer::new(source);
        let token = lexer.next();
        Parser {
            lexer,
            token,
        }
    }

    fn consume(&mut self) {
        self.token = self.lexer.next();
    }

    fn expect(&mut self, tokenType: TokenType) {
        if self.token.0 != tokenType {
            panic!("Unexpected token: expected = {:?}, actual = {:?}", tokenType, self.token);
        }
    }

    fn parse(&mut self) -> Node {
        let node = self.parse_add();
        self.expect(TokenType::Eof);
        node
    }

    fn parse_add(&mut self) -> Node {
        let mut node = self.parse_num();
        while self.token.0 == TokenType::Add {
            self.consume();
            let right = self.parse_num();
            node = Node::Add(Box::new(node), Box::new(right))
        }
        node
    }

    fn parse_num(&mut self) -> Node {
        self.expect(TokenType::Num);
        let node = Node::Num(self.token.1.parse().unwrap());
        self.consume();
        node
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn next_eof() {
        let source = String::new();
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Eof, String::new()), token);
    }

    #[test]
    fn next_num_0() {
        let source = String::from("0");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("0")), token);
    }

    #[test]
    fn next_num_12() {
        let source = String::from("12");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("12")), token);
    }

    #[test]
    fn next_num_345() {
        let source = String::from("345");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("345")), token);
    }

    #[test]
    fn next_num_6789() {
        let source = String::from("6789");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("6789")), token);
    }

    #[test]
    fn next_add() {
        let source = String::from("+");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Add, String::from("+")), token);
    }

    #[test]
    #[should_panic]
    fn next_illegal_char() {
        let source = String::from("abc");
        let mut sut = Lexer::new(&source);
        sut.next();
    }

    #[test]
    fn next_combination() {
        let source = String::from("1234 + 567890");
        let mut sut = Lexer::new(&source);
        assert_eq!(Token(TokenType::Num, String::from("1234")), sut.next());
        assert_eq!(Token(TokenType::Add, String::from("+")), sut.next());
        assert_eq!(Token(TokenType::Num, String::from("567890")), sut.next());
        assert_eq!(Token(TokenType::Eof, String::from("")), sut.next());
    }

    #[test]
    fn parse_num() {
        let source = String::from("12345");
        let mut sut = Parser::new(&source);
        assert_eq!(Node::Num(12345), sut.parse());
    }

    #[test]
    fn parse_num_add_num() {
        let source = String::from("678 + 90");
        let mut sut = Parser::new(&source);
        assert_eq!(Node::Add(Box::new(Node::Num(678)), Box::new(Node::Num(90))), sut.parse());
    }

    #[test]
    fn parse_num_add_num_repeat() {
        let source = String::from("1 + 23 + 456 + 7890");
        let mut sut = Parser::new(&source);
        let a = Box::new(Node::Num(1));
        let b = Box::new(Node::Num(23));
        let c = Box::new(Node::Num(456));
        let d = Box::new(Node::Num(7890));
        let e = Box::new(Node::Add(a, b));
        let f = Box::new(Node::Add(e, c));
        let g = Node::Add(f, d);
        assert_eq!(g, sut.parse());
    }
}

<commit_msg>ASTの評価<commit_after>use std::str::Chars;

struct Lexer<'a> {
    source: Chars<'a>,
    c: Option<char>,
}

#[derive(Debug, PartialEq)]
enum TokenType {
    Num,
    Add,
    Eof,
}

#[derive(Debug, PartialEq)]
struct Token(TokenType, String);

impl<'a> Lexer<'a> {

    fn new(source: &'a String) -> Lexer<'a> {
        let mut source = source.chars();
        let c = None;
        let mut lexer = Lexer {
            source,
            c,
        };
        lexer.consume();
        lexer
    }

    fn consume(&mut self) {
        self.c = self.source.next();
    }

    fn next(&mut self) -> Token {
        while let Some(c) = self.c {
            match c {
                ' ' => {
                    self.consume();
                },
                '0'..='9' => {
                    let mut s = String::new();
                    s.push(c);
                    self.consume();
                    while let Some(c) = self.c {
                        match c {
                            '0'..='9' => {
                                s.push(c);
                                self.consume();
                            },
                            _ => {
                                break;
                            },
                        }
                    }
                    return Token(TokenType::Num, s)
                },
                '+' => {
                    self.consume();
                    return Token(TokenType::Add, String::from("+"))
                },
                _ => {
                    panic!("Illegal character: {}", c);
                }
            }
        }
        Token(TokenType::Eof, String::new())
    }
}

#[derive(Debug, PartialEq)]
enum Node {
    Num(i32),
    Add(Box<Node>, Box<Node>),
}

struct Parser<'a> {
    lexer: Lexer<'a>,
    token: Token,
}

impl<'a> Parser<'a> {

    fn new(source: &'a String) -> Parser<'a> {
        let mut lexer = Lexer::new(source);
        let token = lexer.next();
        Parser {
            lexer,
            token,
        }
    }

    fn consume(&mut self) {
        self.token = self.lexer.next();
    }

    fn expect(&mut self, tokenType: TokenType) {
        if self.token.0 != tokenType {
            panic!("Unexpected token: expected = {:?}, actual = {:?}", tokenType, self.token);
        }
    }

    fn parse(&mut self) -> Node {
        let node = self.parse_add();
        self.expect(TokenType::Eof);
        node
    }

    fn parse_add(&mut self) -> Node {
        let mut node = self.parse_num();
        while self.token.0 == TokenType::Add {
            self.consume();
            let right = self.parse_num();
            node = Node::Add(Box::new(node), Box::new(right))
        }
        node
    }

    fn parse_num(&mut self) -> Node {
        self.expect(TokenType::Num);
        let node = Node::Num(self.token.1.parse().unwrap());
        self.consume();
        node
    }
}

fn evaluate(node: Node) -> i32 {
    match node {
        Node::Num(value) => value,
        Node::Add(left, right) => evaluate(*left) + evaluate(*right),
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn next_eof() {
        let source = String::new();
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Eof, String::new()), token);
    }

    #[test]
    fn next_num_0() {
        let source = String::from("0");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("0")), token);
    }

    #[test]
    fn next_num_12() {
        let source = String::from("12");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("12")), token);
    }

    #[test]
    fn next_num_345() {
        let source = String::from("345");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("345")), token);
    }

    #[test]
    fn next_num_6789() {
        let source = String::from("6789");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Num, String::from("6789")), token);
    }

    #[test]
    fn next_add() {
        let source = String::from("+");
        let mut sut = Lexer::new(&source);
        let token = sut.next();
        assert_eq!(Token(TokenType::Add, String::from("+")), token);
    }

    #[test]
    #[should_panic]
    fn next_illegal_char() {
        let source = String::from("abc");
        let mut sut = Lexer::new(&source);
        sut.next();
    }

    #[test]
    fn next_combination() {
        let source = String::from("1234 + 567890");
        let mut sut = Lexer::new(&source);
        assert_eq!(Token(TokenType::Num, String::from("1234")), sut.next());
        assert_eq!(Token(TokenType::Add, String::from("+")), sut.next());
        assert_eq!(Token(TokenType::Num, String::from("567890")), sut.next());
        assert_eq!(Token(TokenType::Eof, String::from("")), sut.next());
    }

    #[test]
    fn parse_num() {
        let source = String::from("12345");
        let mut sut = Parser::new(&source);
        assert_eq!(Node::Num(12345), sut.parse());
    }

    #[test]
    fn parse_num_add_num() {
        let source = String::from("678 + 90");
        let mut sut = Parser::new(&source);
        assert_eq!(Node::Add(Box::new(Node::Num(678)), Box::new(Node::Num(90))), sut.parse());
    }

    #[test]
    fn parse_num_add_num_repeat() {
        let source = String::from("1 + 23 + 456 + 7890");
        let mut sut = Parser::new(&source);
        let a = Box::new(Node::Num(1));
        let b = Box::new(Node::Num(23));
        let c = Box::new(Node::Num(456));
        let d = Box::new(Node::Num(7890));
        let e = Box::new(Node::Add(a, b));
        let f = Box::new(Node::Add(e, c));
        let g = Node::Add(f, d);
        assert_eq!(g, sut.parse());
    }

    #[test]
    fn evaluate_num() {
        let source = String::from("12345");
        let node = Parser::new(&source).parse();
        assert_eq!(12345, evaluate(node));
    }

    #[test]
    fn evaluate_num_add_num() {
        let source = String::from("678 + 90");
        let node = Parser::new(&source).parse();
        assert_eq!(678 + 90, evaluate(node));
    }

    #[test]
    fn evaluate_num_add_num_repeat() {
        let source = String::from("1 + 23 + 456 + 7890");
        let node = Parser::new(&source).parse();
        assert_eq!(1 + 23 + 456 + 7890, evaluate(node));
    }
}

<|endoftext|>