<commit_before>//! Radiant exposure (base unit joule per square meter, kg · s⁻²).

quantity! {
    /// Radiant exposure (base unit joule per square meter, kg · s⁻²).
    quantity: RadiantExposure; "radiant exposure";
    /// Dimension of radiant exposure, MT⁻² (base unit joule per square meter, kg · s⁻²).
    dimension: ISQ<
        Z0,     // length
        P1,     // mass
        N2,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        // square meter denominator
        @yottajoule_per_square_meter: prefix!(yotta); "YJ/m²",
            "yottajoule per square meter", "yottajoules per square meter";
        @zettajoule_per_square_meter: prefix!(zetta); "ZJ/m²",
            "zettajoule per square meter", "zettajoules per square meter";
        @exajoule_per_square_meter: prefix!(exa); "EJ/m²",
            "exajoule per square meter", "exajoules per square meter";
        @petajoule_per_square_meter: prefix!(peta); "PJ/m²",
            "petajoule per square meter", "petajoules per square meter";
        @terajoule_per_square_meter: prefix!(tera); "TJ/m²",
            "terajoule per square meter", "terajoules per square meter";
        @gigajoule_per_square_meter: prefix!(giga); "GJ/m²",
            "gigajoule per square meter", "gigajoules per square meter";
        @megajoule_per_square_meter: prefix!(mega); "MJ/m²",
            "megajoule per square meter", "megajoules per square meter";
        @kilojoule_per_square_meter: prefix!(kilo); "kJ/m²",
            "kilojoule per square meter", "kilojoules per square meter";
        @hectojoule_per_square_meter: prefix!(hecto); "hJ/m²",
            "hectojoule per square meter", "hectojoules per square meter";
        @decajoule_per_square_meter: prefix!(deca); "daJ/m²",
            "decajoule per square meter", "decajoules per square meter";
        /// Derived unit of radiant exposure.
        @joule_per_square_meter: prefix!(none); "J/m²",
            "joule per square meter", "joules per square meter";
        @decijoule_per_square_meter: prefix!(deci); "dJ/m²",
            "decijoule per square meter", "decijoules per square meter";
        @centijoule_per_square_meter: prefix!(centi); "cJ/m²",
            "centijoule per square meter", "centijoules per square meter";
        @millijoule_per_square_meter: prefix!(milli); "mJ/m²",
            "millijoule per square meter", "millijoules per square meter";
        @microjoule_per_square_meter: prefix!(micro); "µJ/m²",
            "microjoule per square meter", "microjoules per square meter";
        @nanojoule_per_square_meter: prefix!(nano); "nJ/m²",
            "nanojoule per square meter", "nanojoules per square meter";
        @picojoule_per_square_meter: prefix!(pico); "pJ/m²",
            "picojoule per square meter", "picojoules per square meter";
        @femtojoule_per_square_meter: prefix!(femto); "fJ/m²",
            "femtojoule per square meter", "femtojoules per square meter";
        @attojoule_per_square_meter: prefix!(atto); "aJ/m²",
            "attojoule per square meter", "attojoules per square meter";
        @zeptojoule_per_square_meter: prefix!(zepto); "zJ/m²",
            "zeptojoule per square meter", "zeptojoules per square meter";
        @yoctojoule_per_square_meter: prefix!(yocto); "yJ/m²",
            "yoctojoule per square meter", "yoctojoules per square meter";

        // square centimeter denominator
        @gigajoule_per_square_centimeter: 1.0E13; "GJ/cm²",
            "gigajoule per square centimeter", "gigajoules per square centimeter";
        @megajoule_per_square_centimeter: 1.0E10; "MJ/cm²",
            "megajoule per square centimeter", "megajoules per square centimeter";
        @kilojoule_per_square_centimeter: 1.0E7; "kJ/cm²",
            "kilojoule per square centimeter", "kilojoules per square centimeter";
        @hectojoule_per_square_centimeter: 1.0E6; "hJ/cm²",
            "hectojoule per square centimeter", "hectojoules per square centimeter";
        @decajoule_per_square_centimeter: 1.0E5; "daJ/cm²",
            "decajoule per square centimeter", "decajoules per square centimeter";
        @joule_per_square_centimeter: 1.0E4; "J/cm²",
            "joule per square centimeter", "joules per square centimeter";
        @decijoule_per_square_centimeter: 1.0E3; "dJ/cm²",
            "decijoule per square centimeter", "decijoules per square centimeter";
        @centijoule_per_square_centimeter: 1.0E2; "cJ/cm²",
            "centijoule per square centimeter", "centijoules per square centimeter";
        @millijoule_per_square_centimeter: 1.0E1; "mJ/cm²",
            "millijoule per square centimeter", "millijoules per square centimeter";
        @microjoule_per_square_centimeter: 1.0E-2; "µJ/cm²",
            "microjoule per square centimeter", "microjoules per square centimeter";
        @nanojoule_per_square_centimeter: 1.0E-5; "nJ/cm²",
            "nanojoule per square centimeter", "nanojoules per square centimeter";

        // square millimeter denominator
        @gigajoule_per_square_millimeter: 1.0E15; "GJ/mm²",
            "gigajoule per square millimeter", "gigajoules per square millimeter";
        @megajoule_per_square_millimeter: 1.0E12; "MJ/mm²",
            "megajoule per square millimeter", "megajoules per square millimeter";
        @kilojoule_per_square_millimeter: 1.0E9; "kJ/mm²",
            "kilojoule per square millimeter", "kilojoules per square millimeter";
        @hectojoule_per_square_millimeter: 1.0E8; "hJ/mm²",
            "hectojoule per square millimeter", "hectojoules per square millimeter";
        @decajoule_per_square_millimeter: 1.0E7; "daJ/mm²",
            "decajoule per square millimeter", "decajoules per square millimeter";
        @joule_per_square_millimeter: 1.0E6; "J/mm²",
            "joule per square millimeter", "joules per square millimeter";
        @decijoule_per_square_millimeter: 1.0E5; "dJ/mm²",
            "decijoule per square millimeter", "decijoules per square millimeter";
        @centijoule_per_square_millimeter: 1.0E4; "cJ/mm²",
            "centijoule per square millimeter", "centijoules per square millimeter";
        @millijoule_per_square_millimeter: 1.0E3; "mJ/mm²",
            "millijoule per square millimeter", "millijoules per square millimeter";
        @microjoule_per_square_millimeter: 1.0E0; "µJ/mm²",
            "microjoule per square millimeter", "microjoules per square millimeter";
        @nanojoule_per_square_millimeter: 1.0E-3; "nJ/mm²",
            "nanojoule per square millimeter", "nanojoules per square millimeter";
    }
}

#[cfg(test)]
mod test {
    storage_types! {
        use num::One;
        use si::quantities::*;
        use si::energy as e;
        use si::length as l;
        use si::area as a;
        use si::radiant_exposure as re;
        use tests::Test;

        #[test]
        fn check_dimension() {
            let _: RadiantExposure<V> =
                Energy::new::<e::kilojoule>(V::one())
                / (Length::new::<l::meter>(V::one())
                   * Length::new::<l::meter>(V::one()));
        }

        #[test]
        fn check_units() {
            test::<e::yottajoule, a::square_meter, re::yottajoule_per_square_meter>();
            test::<e::zettajoule, a::square_meter, re::zettajoule_per_square_meter>();
            test::<e::exajoule, a::square_meter, re::exajoule_per_square_meter>();
            test::<e::petajoule, a::square_meter, re::petajoule_per_square_meter>();
            test::<e::terajoule, a::square_meter, re::terajoule_per_square_meter>();
            test::<e::gigajoule, a::square_meter, re::gigajoule_per_square_meter>();
            test::<e::megajoule, a::square_meter, re::megajoule_per_square_meter>();
            test::<e::kilojoule, a::square_meter, re::kilojoule_per_square_meter>();
            test::<e::hectojoule, a::square_meter, re::hectojoule_per_square_meter>();
            test::<e::decajoule, a::square_meter, re::decajoule_per_square_meter>();
            test::<e::joule, a::square_meter, re::joule_per_square_meter>();
            test::<e::decijoule, a::square_meter, re::decijoule_per_square_meter>();
            test::<e::centijoule, a::square_meter, re::centijoule_per_square_meter>();
            test::<e::millijoule, a::square_meter, re::millijoule_per_square_meter>();
            test::<e::microjoule, a::square_meter, re::microjoule_per_square_meter>();
            test::<e::nanojoule, a::square_meter, re::nanojoule_per_square_meter>();
            test::<e::picojoule, a::square_meter, re::picojoule_per_square_meter>();
            test::<e::femtojoule, a::square_meter, re::femtojoule_per_square_meter>();
            test::<e::attojoule, a::square_meter, re::attojoule_per_square_meter>();
            test::<e::zeptojoule, a::square_meter, re::zeptojoule_per_square_meter>();
            test::<e::yoctojoule, a::square_meter, re::yoctojoule_per_square_meter>();

            test::<e::gigajoule, a::square_centimeter, re::gigajoule_per_square_centimeter>();
            test::<e::megajoule, a::square_centimeter, re::megajoule_per_square_centimeter>();
            test::<e::kilojoule, a::square_centimeter, re::kilojoule_per_square_centimeter>();
            test::<e::hectojoule, a::square_centimeter, re::hectojoule_per_square_centimeter>();
            test::<e::decajoule, a::square_centimeter, re::decajoule_per_square_centimeter>();
            test::<e::joule, a::square_centimeter, re::joule_per_square_centimeter>();
            test::<e::decijoule, a::square_centimeter, re::decijoule_per_square_centimeter>();
            test::<e::centijoule, a::square_centimeter, re::centijoule_per_square_centimeter>();
            test::<e::millijoule, a::square_centimeter, re::millijoule_per_square_centimeter>();
            test::<e::microjoule, a::square_centimeter, re::microjoule_per_square_centimeter>();
            test::<e::nanojoule, a::square_centimeter, re::nanojoule_per_square_centimeter>();

            test::<e::gigajoule, a::square_millimeter, re::gigajoule_per_square_millimeter>();
            test::<e::megajoule, a::square_millimeter, re::megajoule_per_square_millimeter>();
            test::<e::kilojoule, a::square_millimeter, re::kilojoule_per_square_millimeter>();
            test::<e::hectojoule, a::square_millimeter, re::hectojoule_per_square_millimeter>();
            test::<e::decajoule, a::square_millimeter, re::decajoule_per_square_millimeter>();
            test::<e::joule, a::square_millimeter, re::joule_per_square_millimeter>();
            test::<e::decijoule, a::square_millimeter, re::decijoule_per_square_millimeter>();
            test::<e::centijoule, a::square_millimeter, re::centijoule_per_square_millimeter>();
            test::<e::millijoule, a::square_millimeter, re::millijoule_per_square_millimeter>();
            test::<e::microjoule, a::square_millimeter, re::microjoule_per_square_millimeter>();
            test::<e::nanojoule, a::square_millimeter, re::nanojoule_per_square_millimeter>();

            fn test<E: e::Conversion<V>, A: a::Conversion<V>, RE: re::Conversion<V>>() {
                Test::assert_approx_eq(
                    &RadiantExposure::new::<RE>(V::one()),
                    &(Energy::new::<E>(V::one()) / Area::new::<A>(V::one())));
            }
        }
    }
}
<commit_msg>Trailing whitespace<commit_after>//! Radiant exposure (base unit joule per square meter, kg · s⁻²).

quantity! {
    /// Radiant exposure (base unit joule per square meter, kg · s⁻²).
    quantity: RadiantExposure; "radiant exposure";
    /// Dimension of radiant exposure, MT⁻² (base unit joule per square meter, kg · s⁻²).
    dimension: ISQ<
        Z0,     // length
        P1,     // mass
        N2,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        // square meter denominator
        @yottajoule_per_square_meter: prefix!(yotta); "YJ/m²",
            "yottajoule per square meter", "yottajoules per square meter";
        @zettajoule_per_square_meter: prefix!(zetta); "ZJ/m²",
            "zettajoule per square meter", "zettajoules per square meter";
        @exajoule_per_square_meter: prefix!(exa); "EJ/m²",
            "exajoule per square meter", "exajoules per square meter";
        @petajoule_per_square_meter: prefix!(peta); "PJ/m²",
            "petajoule per square meter", "petajoules per square meter";
        @terajoule_per_square_meter: prefix!(tera); "TJ/m²",
            "terajoule per square meter", "terajoules per square meter";
        @gigajoule_per_square_meter: prefix!(giga); "GJ/m²",
            "gigajoule per square meter", "gigajoules per square meter";
        @megajoule_per_square_meter: prefix!(mega); "MJ/m²",
            "megajoule per square meter", "megajoules per square meter";
        @kilojoule_per_square_meter: prefix!(kilo); "kJ/m²",
            "kilojoule per square meter", "kilojoules per square meter";
        @hectojoule_per_square_meter: prefix!(hecto); "hJ/m²",
            "hectojoule per square meter", "hectojoules per square meter";
        @decajoule_per_square_meter: prefix!(deca); "daJ/m²",
            "decajoule per square meter", "decajoules per square meter";
        /// Derived unit of radiant exposure.
        @joule_per_square_meter: prefix!(none); "J/m²",
            "joule per square meter", "joules per square meter";
        @decijoule_per_square_meter: prefix!(deci); "dJ/m²",
            "decijoule per square meter", "decijoules per square meter";
        @centijoule_per_square_meter: prefix!(centi); "cJ/m²",
            "centijoule per square meter", "centijoules per square meter";
        @millijoule_per_square_meter: prefix!(milli); "mJ/m²",
            "millijoule per square meter", "millijoules per square meter";
        @microjoule_per_square_meter: prefix!(micro); "µJ/m²",
            "microjoule per square meter", "microjoules per square meter";
        @nanojoule_per_square_meter: prefix!(nano); "nJ/m²",
            "nanojoule per square meter", "nanojoules per square meter";
        @picojoule_per_square_meter: prefix!(pico); "pJ/m²",
            "picojoule per square meter", "picojoules per square meter";
        @femtojoule_per_square_meter: prefix!(femto); "fJ/m²",
            "femtojoule per square meter", "femtojoules per square meter";
        @attojoule_per_square_meter: prefix!(atto); "aJ/m²",
            "attojoule per square meter", "attojoules per square meter";
        @zeptojoule_per_square_meter: prefix!(zepto); "zJ/m²",
            "zeptojoule per square meter", "zeptojoules per square meter";
        @yoctojoule_per_square_meter: prefix!(yocto); "yJ/m²",
            "yoctojoule per square meter", "yoctojoules per square meter";

        // square centimeter denominator
        @gigajoule_per_square_centimeter: 1.0E13; "GJ/cm²",
            "gigajoule per square centimeter", "gigajoules per square centimeter";
        @megajoule_per_square_centimeter: 1.0E10; "MJ/cm²",
            "megajoule per square centimeter", "megajoules per square centimeter";
        @kilojoule_per_square_centimeter: 1.0E7; "kJ/cm²",
            "kilojoule per square centimeter", "kilojoules per square centimeter";
        @hectojoule_per_square_centimeter: 1.0E6; "hJ/cm²",
            "hectojoule per square centimeter", "hectojoules per square centimeter";
        @decajoule_per_square_centimeter: 1.0E5; "daJ/cm²",
            "decajoule per square centimeter", "decajoules per square centimeter";
        @joule_per_square_centimeter: 1.0E4; "J/cm²",
            "joule per square centimeter", "joules per square centimeter";
        @decijoule_per_square_centimeter: 1.0E3; "dJ/cm²",
            "decijoule per square centimeter", "decijoules per square centimeter";
        @centijoule_per_square_centimeter: 1.0E2; "cJ/cm²",
            "centijoule per square centimeter", "centijoules per square centimeter";
        @millijoule_per_square_centimeter: 1.0E1; "mJ/cm²",
            "millijoule per square centimeter", "millijoules per square centimeter";
        @microjoule_per_square_centimeter: 1.0E-2; "µJ/cm²",
            "microjoule per square centimeter", "microjoules per square centimeter";
        @nanojoule_per_square_centimeter: 1.0E-5; "nJ/cm²",
            "nanojoule per square centimeter", "nanojoules per square centimeter";

        // square millimeter denominator
        @gigajoule_per_square_millimeter: 1.0E15; "GJ/mm²",
            "gigajoule per square millimeter", "gigajoules per square millimeter";
        @megajoule_per_square_millimeter: 1.0E12; "MJ/mm²",
            "megajoule per square millimeter", "megajoules per square millimeter";
        @kilojoule_per_square_millimeter: 1.0E9; "kJ/mm²",
            "kilojoule per square millimeter", "kilojoules per square millimeter";
        @hectojoule_per_square_millimeter: 1.0E8; "hJ/mm²",
            "hectojoule per square millimeter", "hectojoules per square millimeter";
        @decajoule_per_square_millimeter: 1.0E7; "daJ/mm²",
            "decajoule per square millimeter", "decajoules per square millimeter";
        @joule_per_square_millimeter: 1.0E6; "J/mm²",
            "joule per square millimeter", "joules per square millimeter";
        @decijoule_per_square_millimeter: 1.0E5; "dJ/mm²",
            "decijoule per square millimeter", "decijoules per square millimeter";
        @centijoule_per_square_millimeter: 1.0E4; "cJ/mm²",
            "centijoule per square millimeter", "centijoules per square millimeter";
        @millijoule_per_square_millimeter: 1.0E3; "mJ/mm²",
            "millijoule per square millimeter", "millijoules per square millimeter";
        @microjoule_per_square_millimeter: 1.0E0; "µJ/mm²",
            "microjoule per square millimeter", "microjoules per square millimeter";
        @nanojoule_per_square_millimeter: 1.0E-3; "nJ/mm²",
            "nanojoule per square millimeter", "nanojoules per square millimeter";
    }
}

#[cfg(test)]
mod test {
    storage_types! {
        use num::One;
        use si::quantities::*;
        use si::energy as e;
        use si::length as l;
        use si::area as a;
        use si::radiant_exposure as re;
        use tests::Test;

        #[test]
        fn check_dimension() {
            let _: RadiantExposure<V> =
                Energy::new::<e::kilojoule>(V::one())
                / (Length::new::<l::meter>(V::one())
                   * Length::new::<l::meter>(V::one()));
        }

        #[test]
        fn check_units() {
            test::<e::yottajoule, a::square_meter, re::yottajoule_per_square_meter>();
            test::<e::zettajoule, a::square_meter, re::zettajoule_per_square_meter>();
            test::<e::exajoule, a::square_meter, re::exajoule_per_square_meter>();
            test::<e::petajoule, a::square_meter, re::petajoule_per_square_meter>();
            test::<e::terajoule, a::square_meter, re::terajoule_per_square_meter>();
            test::<e::gigajoule, a::square_meter, re::gigajoule_per_square_meter>();
            test::<e::megajoule, a::square_meter, re::megajoule_per_square_meter>();
            test::<e::kilojoule, a::square_meter, re::kilojoule_per_square_meter>();
            test::<e::hectojoule, a::square_meter, re::hectojoule_per_square_meter>();
            test::<e::decajoule, a::square_meter, re::decajoule_per_square_meter>();
            test::<e::joule, a::square_meter, re::joule_per_square_meter>();
            test::<e::decijoule, a::square_meter, re::decijoule_per_square_meter>();
            test::<e::centijoule, a::square_meter, re::centijoule_per_square_meter>();
            test::<e::millijoule, a::square_meter, re::millijoule_per_square_meter>();
            test::<e::microjoule, a::square_meter, re::microjoule_per_square_meter>();
            test::<e::nanojoule, a::square_meter, re::nanojoule_per_square_meter>();
            test::<e::picojoule, a::square_meter, re::picojoule_per_square_meter>();
            test::<e::femtojoule, a::square_meter, re::femtojoule_per_square_meter>();
            test::<e::attojoule, a::square_meter, re::attojoule_per_square_meter>();
            test::<e::zeptojoule, a::square_meter, re::zeptojoule_per_square_meter>();
            test::<e::yoctojoule, a::square_meter, re::yoctojoule_per_square_meter>();

            test::<e::gigajoule, a::square_centimeter, re::gigajoule_per_square_centimeter>();
            test::<e::megajoule, a::square_centimeter, re::megajoule_per_square_centimeter>();
            test::<e::kilojoule, a::square_centimeter, re::kilojoule_per_square_centimeter>();
            test::<e::hectojoule, a::square_centimeter, re::hectojoule_per_square_centimeter>();
            test::<e::decajoule, a::square_centimeter, re::decajoule_per_square_centimeter>();
            test::<e::joule, a::square_centimeter, re::joule_per_square_centimeter>();
            test::<e::decijoule, a::square_centimeter, re::decijoule_per_square_centimeter>();
            test::<e::centijoule, a::square_centimeter, re::centijoule_per_square_centimeter>();
            test::<e::millijoule, a::square_centimeter, re::millijoule_per_square_centimeter>();
            test::<e::microjoule, a::square_centimeter, re::microjoule_per_square_centimeter>();
            test::<e::nanojoule, a::square_centimeter, re::nanojoule_per_square_centimeter>();

            test::<e::gigajoule, a::square_millimeter, re::gigajoule_per_square_millimeter>();
            test::<e::megajoule, a::square_millimeter, re::megajoule_per_square_millimeter>();
            test::<e::kilojoule, a::square_millimeter, re::kilojoule_per_square_millimeter>();
            test::<e::hectojoule, a::square_millimeter, re::hectojoule_per_square_millimeter>();
            test::<e::decajoule, a::square_millimeter, re::decajoule_per_square_millimeter>();
            test::<e::joule, a::square_millimeter, re::joule_per_square_millimeter>();
            test::<e::decijoule, a::square_millimeter, re::decijoule_per_square_millimeter>();
            test::<e::centijoule, a::square_millimeter, re::centijoule_per_square_millimeter>();
            test::<e::millijoule, a::square_millimeter, re::millijoule_per_square_millimeter>();
            test::<e::microjoule, a::square_millimeter, re::microjoule_per_square_millimeter>();
            test::<e::nanojoule, a::square_millimeter, re::nanojoule_per_square_millimeter>();

            fn test<E: e::Conversion<V>, A: a::Conversion<V>, RE: re::Conversion<V>>() {
                Test::assert_approx_eq(
                    &RadiantExposure::new::<RE>(V::one()),
                    &(Energy::new::<E>(V::one()) / Area::new::<A>(V::one())));
            }
        }
    }
}
<|endoftext|>


<commit_before>use types::*;
use organism::Organism;
use event::EventType;

#[derive(Debug,Clone,Copy)]
pub enum Instruction {
    //pushing to data stack
    Num(Number),
    //controlflow
    Call,
    If,
    Ifelse,
    Loop,
    Condret,
    Ret,
    //stack operations
    Pop,
    Pop2,
    Dup,
    Dup2,
    Conddup,
    Swap,
    Swap2,
    Over,
    Over2,
    Rot,
    Tor,
    Nip,
    Tuck,
    //arithmetics
    //Unary
    Inc,
    Inc2,
    Dec,
    Dec2,
    Half,
    Double,
    Abs,
    Square,
    Sqrt,
    Signum,
    Negate,
    Not,
    Invert,
    Zero,
    //Binary
    Add,
    Sub,
    Mul,
    Div,
    Mod,

    Eq,
    Ne,
    Lt,
    Gt,
    Le,
    Ge,
    Or,
    And,
    Xor,
    Min,
    Max,
    Mov,
    //Eat,
    Spawn,
}

use self::Instruction::*;

impl Instruction {
    pub fn exec(self, org: &mut Organism) -> Option<EventType> {
        org.next_instr();
        match self {
            Num(n)  => instr_num(org, n),
            Call    => instr_call(org),
            If      => instr_if(org),
            Ifelse  => instr_ifelse(org),
            Loop    => instr_loop(org),
            Condret => instr_condret(org),
            Ret     => instr_ret(org),
            Pop     => instr_pop(org),
            Pop2    => instr_pop2(org),
            Dup     => instr_dup(org),
            Dup2    => instr_dup2(org),
            Conddup => instr_conddup(org),
            Swap    => instr_swap(org),
            Swap2   => instr_swap2(org),
            Over    => instr_over(org),
            Over2   => instr_over2(org),
            Rot     => instr_rot(org),
            Tor     => instr_tor(org),
            Nip     => instr_nip(org),
            Tuck    => instr_tuck(org),
            Inc     => instr_unary(org, |x| x + 1),
            Inc2    => instr_unary(org, |x| x + 2),
            Dec     => instr_unary(org, |x| x - 1),
            Dec2    => instr_unary(org, |x| x - 2),
            Half    => instr_unary(org, |x| x / 2),
            Double  => instr_unary(org, |x| x * 2),
            Abs     => instr_unary(org, |x| x.abs()),
            Square  => instr_unary(org, |x| x * x),
            Sqrt    => instr_unary_nonnegative(org, |x| (x as f64).sqrt() as Number),
            Signum  => instr_unary(org, |x| x.signum()),
            Negate  => instr_unary(org, |x| x.wrapping_neg()),
            Not     => instr_unary(org, |x| !x & 1),
            Invert  => instr_unary(org, |x| !x),
            Zero    => instr_unary(org, |x| bool_to_int(x == 0)),
            Add     => instr_binary(org, |x, y| x + y),
            Sub     => instr_binary(org, |x, y| x - y),
            Mul     => instr_binary(org, |x, y| x * y),
            Div     => instr_binary_notnull(org, |x, y| x / y),
            Mod     => instr_binary_notnull(org, |x, y| x % y),
            Eq      => instr_binary(org, |x, y| bool_to_int(x == y)),
            Ne      => instr_binary(org, |x, y| bool_to_int(x != y)),
            Lt      => instr_binary(org, |x, y| bool_to_int(x  < y)),
            Gt      => instr_binary(org, |x, y| bool_to_int(x  > y)),
            Le      => instr_binary(org, |x, y| bool_to_int(x <= y)),
            Ge      => instr_binary(org, |x, y| bool_to_int(x >= y)),
            Or      => instr_binary(org, |x, y| x | y),
            And     => instr_binary(org, |x, y| x & y),
            Xor     => instr_binary(org, |x, y| x ^ y),
            Min     => instr_binary(org, |x, y| if x > y {x} else {y}),
            Max     => instr_binary(org, |x, y| if x < y {x} else {y}),
            Mov     => instr_move(org),
            //Eat     => instr_eat(org),
            Spawn   => instr_spawn(org),
        }
    }
}

fn bool_to_int(b: bool) -> Number {
    if b {
        1
    } else {
        0
    }
}

fn instr_num(org: &mut Organism, n: Number) -> Option<EventType> {
    org.push(n);
    None
}

fn instr_call(org: &mut Organism) -> Option<EventType> {
    org.pop(1).and_then(|v| Some(org.call(v[0])));
    None
}

fn instr_if(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        if v[0] != 0 {
            org.call(v[1]);
        }
        None
    })
}

fn instr_ifelse(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|v| {
        if v[0] != 0 {
            org.call(v[1]);
        } else {
            org.call(v[2]);
        }
        None
    })
}

fn instr_loop(org: &mut Organism) -> Option<EventType> {
    org.pop(1).and_then(|v| {
        if v[0] != 0 {
            org.looop();
        }
        None
    })
}

fn instr_condret(org: &mut Organism) -> Option<EventType> {
    org.pop(1).and_then(|v| {
        if v[0] != 0 {
            org.ret();
        }
        None
    })
}
fn instr_ret(org: &mut Organism) -> Option<EventType> {
    org.ret();
    None
}

fn instr_pop(org: &mut Organism) -> Option<EventType> {
    org.pop(1);
    None
}

fn instr_pop2(org: &mut Organism) -> Option<EventType> {
    org.pop(2);
    None
}

fn instr_dup(org: &mut Organism) -> Option<EventType> {
    org.peek(1).and_then(|v| {
        org.push(v[0]);
        None
    })
}

fn instr_dup2(org: &mut Organism) -> Option<EventType> {
    org.peek(2).and_then(|v| {
        org.push_all(v);
        None
    })
}

fn instr_conddup(org: &mut Organism) -> Option<EventType> {
    org.peek(1).and_then(|v| {
        if v[0] != 0 {
            org.push(v[0]);
        }
        None
    })
}

fn instr_swap(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|mut v| {
        v.reverse();
        org.push_all(v);
        None
    })
}

fn instr_swap2(org: &mut Organism) -> Option<EventType> {
    org.pop(4).and_then(|mut v| {
        v.swap(0,1);
        v.swap(2,3);
        org.push_all(v);
        None
    })
}

fn instr_over(org: &mut Organism) -> Option<EventType> {
    org.peek(2).and_then(|v| {
        org.push(v[0]);
        None
    })
}

fn instr_over2(org: &mut Organism) -> Option<EventType> {
    org.peek(4).and_then(|mut v| {
        v.truncate(2);
        org.push_all(v);
        None
    })
}

fn instr_rot(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|mut v| {
        let tmp = v.remove(0);
        v.push(tmp);
        org.push_all(v);
        None
    })
}

fn instr_tor(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|mut v| {
        let tmp = v.pop().unwrap();
        v.insert(0, tmp);
        org.push_all(v);
        None
    })
}

fn instr_nip(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        org.push(v[1]);
        None
    })
}

fn instr_tuck(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        org.push(v[1]);
        org.push_all(v);
        None
    })
}

//change this to a wrapping semantic or some random runtime failures will show
fn instr_unary<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number) -> Number {
    org.pop(1).and_then(|v| {
        org.push(f(v[0]));
        None
    })
}

fn instr_unary_nonnegative<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number) -> Number {
    org.pop(1).and_then(|v| {
        if v[0] >= 0 {
            org.push(f(v[0]));
        }
        None
    })
}

fn instr_binary<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number, Number) -> Number {
    org.pop(2).and_then(|v| {
        org.push(f(v[0],v[1]));
        None
    })
}

fn instr_binary_notnull<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number, Number) -> Number {
    org.pop(2).and_then(|v| {
        if v[1] != 0 {
            org.push(f(v[0],v[1]));
        }
        None
    })
}

fn instr_move(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        Some(EventType::Mov{ dir: Direction::from_coords(v[0], v[1]) })
    })
}

/*
fn instr_eat(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        Some(EventType::Eat{ orgID: org.id, dir: Direction::from_coords(v[0], v[1]) })
    })
}*/

fn instr_spawn(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|v| {
        if v[2] >= 0 {
            Some(EventType::Spawn { dir: Direction::from_coords(v[0], v[1]), nrg: v[2] as u64 })
        } else {
            None
        }
    })
}
<commit_msg>casting instead of branching<commit_after>use types::*;
use organism::Organism;
use event::EventType;

#[derive(Debug,Clone,Copy)]
pub enum Instruction {
    //pushing to data stack
    Num(Number),
    //controlflow
    Call,
    If,
    Ifelse,
    Loop,
    Condret,
    Ret,
    //stack operations
    Pop,
    Pop2,
    Dup,
    Dup2,
    Conddup,
    Swap,
    Swap2,
    Over,
    Over2,
    Rot,
    Tor,
    Nip,
    Tuck,
    //arithmetics
    //Unary
    Inc,
    Inc2,
    Dec,
    Dec2,
    Half,
    Double,
    Abs,
    Square,
    Sqrt,
    Signum,
    Negate,
    Not,
    Invert,
    Zero,
    //Binary
    Add,
    Sub,
    Mul,
    Div,
    Mod,

    Eq,
    Ne,
    Lt,
    Gt,
    Le,
    Ge,
    Or,
    And,
    Xor,
    Min,
    Max,
    Mov,
    //Eat,
    Spawn,
}

use self::Instruction::*;

impl Instruction {
    pub fn exec(self, org: &mut Organism) -> Option<EventType> {
        org.next_instr();
        match self {
            Num(n)  => instr_num(org, n),
            Call    => instr_call(org),
            If      => instr_if(org),
            Ifelse  => instr_ifelse(org),
            Loop    => instr_loop(org),
            Condret => instr_condret(org),
            Ret     => instr_ret(org),
            Pop     => instr_pop(org),
            Pop2    => instr_pop2(org),
            Dup     => instr_dup(org),
            Dup2    => instr_dup2(org),
            Conddup => instr_conddup(org),
            Swap    => instr_swap(org),
            Swap2   => instr_swap2(org),
            Over    => instr_over(org),
            Over2   => instr_over2(org),
            Rot     => instr_rot(org),
            Tor     => instr_tor(org),
            Nip     => instr_nip(org),
            Tuck    => instr_tuck(org),
            Inc     => instr_unary(org, |x| x + 1),
            Inc2    => instr_unary(org, |x| x + 2),
            Dec     => instr_unary(org, |x| x - 1),
            Dec2    => instr_unary(org, |x| x - 2),
            Half    => instr_unary(org, |x| x / 2),
            Double  => instr_unary(org, |x| x * 2),
            Abs     => instr_unary(org, |x| x.abs()),
            Square  => instr_unary(org, |x| x * x),
            Sqrt    => instr_unary_nonnegative(org, |x| (x as f64).sqrt() as Number),
            Signum  => instr_unary(org, |x| x.signum()),
            Negate  => instr_unary(org, |x| x.wrapping_neg()),
            Not     => instr_unary(org, |x| !x & 1),
            Invert  => instr_unary(org, |x| !x),
            Zero    => instr_unary(org, |x| bool_to_int(x == 0)),
            Add     => instr_binary(org, |x, y| x + y),
            Sub     => instr_binary(org, |x, y| x - y),
            Mul     => instr_binary(org, |x, y| x * y),
            Div     => instr_binary_notnull(org, |x, y| x / y),
            Mod     => instr_binary_notnull(org, |x, y| x % y),
            Eq      => instr_binary(org, |x, y| (x == y) as Number),
            Ne      => instr_binary(org, |x, y| (x != y) as Number),
            Lt      => instr_binary(org, |x, y| (x  < y) as Number),
            Gt      => instr_binary(org, |x, y| (x  > y) as Number),
            Le      => instr_binary(org, |x, y| (x <= y) as Number),
            Ge      => instr_binary(org, |x, y| (x >= y) as Number),
            Or      => instr_binary(org, |x, y| x | y),
            And     => instr_binary(org, |x, y| x & y),
            Xor     => instr_binary(org, |x, y| x ^ y),
            Min     => instr_binary(org, |x, y| if x > y { x } else { y }),
            Max     => instr_binary(org, |x, y| if x < y { x } else { y }),
            Mov     => instr_move(org),
            //Eat     => instr_eat(org),
            Spawn   => instr_spawn(org),
        }
    }
}

fn instr_num(org: &mut Organism, n: Number) -> Option<EventType> {
    org.push(n);
    None
}

fn instr_call(org: &mut Organism) -> Option<EventType> {
    org.pop(1).and_then(|v| Some(org.call(v[0])));
    None
}

fn instr_if(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        if v[0] != 0 {
            org.call(v[1]);
        }
        None
    })
}

fn instr_ifelse(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|v| {
        if v[0] != 0 {
            org.call(v[1]);
        } else {
            org.call(v[2]);
        }
        None
    })
}

fn instr_loop(org: &mut Organism) -> Option<EventType> {
    org.pop(1).and_then(|v| {
        if v[0] != 0 {
            org.looop();
        }
        None
    })
}

fn instr_condret(org: &mut Organism) -> Option<EventType> {
    org.pop(1).and_then(|v| {
        if v[0] != 0 {
            org.ret();
        }
        None
    })
}
fn instr_ret(org: &mut Organism) -> Option<EventType> {
    org.ret();
    None
}

fn instr_pop(org: &mut Organism) -> Option<EventType> {
    org.pop(1);
    None
}

fn instr_pop2(org: &mut Organism) -> Option<EventType> {
    org.pop(2);
    None
}

fn instr_dup(org: &mut Organism) -> Option<EventType> {
    org.peek(1).and_then(|v| {
        org.push(v[0]);
        None
    })
}

fn instr_dup2(org: &mut Organism) -> Option<EventType> {
    org.peek(2).and_then(|v| {
        org.push_all(v);
        None
    })
}

fn instr_conddup(org: &mut Organism) -> Option<EventType> {
    org.peek(1).and_then(|v| {
        if v[0] != 0 {
            org.push(v[0]);
        }
        None
    })
}

fn instr_swap(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|mut v| {
        v.reverse();
        org.push_all(v);
        None
    })
}

fn instr_swap2(org: &mut Organism) -> Option<EventType> {
    org.pop(4).and_then(|mut v| {
        v.swap(0,1);
        v.swap(2,3);
        org.push_all(v);
        None
    })
}

fn instr_over(org: &mut Organism) -> Option<EventType> {
    org.peek(2).and_then(|v| {
        org.push(v[0]);
        None
    })
}

fn instr_over2(org: &mut Organism) -> Option<EventType> {
    org.peek(4).and_then(|mut v| {
        v.truncate(2);
        org.push_all(v);
        None
    })
}

fn instr_rot(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|mut v| {
        let tmp = v.remove(0);
        v.push(tmp);
        org.push_all(v);
        None
    })
}

fn instr_tor(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|mut v| {
        let tmp = v.pop().unwrap();
        v.insert(0, tmp);
        org.push_all(v);
        None
    })
}

fn instr_nip(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        org.push(v[1]);
        None
    })
}

fn instr_tuck(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        org.push(v[1]);
        org.push_all(v);
        None
    })
}

//change this to a wrapping semantic or some random runtime failures will show
fn instr_unary<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number) -> Number {
    org.pop(1).and_then(|v| {
        org.push(f(v[0]));
        None
    })
}

fn instr_unary_nonnegative<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number) -> Number {
    org.pop(1).and_then(|v| {
        if v[0] >= 0 {
            org.push(f(v[0]));
        }
        None
    })
}

fn instr_binary<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number, Number) -> Number {
    org.pop(2).and_then(|v| {
        org.push(f(v[0],v[1]));
        None
    })
}

fn instr_binary_notnull<F>(org: &mut Organism, f: F) -> Option<EventType>
    where F: Fn(Number, Number) -> Number {
    org.pop(2).and_then(|v| {
        if v[1] != 0 {
            org.push(f(v[0],v[1]));
        }
        None
    })
}

fn instr_move(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        Some(EventType::Mov{ dir: Direction::from_coords(v[0], v[1]) })
    })
}

/*
fn instr_eat(org: &mut Organism) -> Option<EventType> {
    org.pop(2).and_then(|v| {
        Some(EventType::Eat{ orgID: org.id, dir: Direction::from_coords(v[0], v[1]) })
    })
}*/

fn instr_spawn(org: &mut Organism) -> Option<EventType> {
    org.pop(3).and_then(|v| {
        if v[2] >= 0 {
            Some(EventType::Spawn { dir: Direction::from_coords(v[0], v[1]), nrg: v[2] as u64 })
        } else {
            None
        }
    })
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use error::StoreError as SE;
use error::StoreErrorKind as SEK;
use std::path::PathBuf;
use std::collections::HashMap;
use std::sync::Mutex;
use std::cell::RefCell;
use std::sync::Arc;

use libimagerror::into::IntoError;

use super::FileAbstraction;
use super::FileAbstractionInstance;
use store::Entry;
use storeid::StoreId;

type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Entry>>>>;

/// `FileAbstraction` type, this is the Test version!
///
/// A lazy file is either absent, but a path to it is available, or it is present.
#[derive(Debug)]
pub struct InMemoryFileAbstractionInstance {
    fs_abstraction: Backend,
    absent_path: PathBuf,
}

impl InMemoryFileAbstractionInstance {

    pub fn new(fs: Backend, pb: PathBuf) -> InMemoryFileAbstractionInstance {
        InMemoryFileAbstractionInstance {
            fs_abstraction: fs,
            absent_path: pb
        }
    }

}

impl FileAbstractionInstance for InMemoryFileAbstractionInstance {

    /**
     * Get the mutable file behind a InMemoryFileAbstraction object
     */
    fn get_file_content(&mut self, _: StoreId) -> Result<Entry, SE> {
        debug!("Getting lazy file: {:?}", self);

        let p = self.absent_path.clone();
        match self.fs_abstraction.lock() {
            Ok(mut mtx) => {
                mtx.get_mut()
                    .get(&p)
                    .cloned()
                    .ok_or(SEK::FileNotFound.into_error())
            }

            Err(_) => Err(SEK::LockError.into_error())
        }
    }

    fn write_file_content(&mut self, buf: &Entry) -> Result<(), SE> {
        match *self {
            InMemoryFileAbstractionInstance { ref absent_path, .. } => {
                let mut mtx = self.fs_abstraction.lock().expect("Locking Mutex failed");
                let mut backend = mtx.get_mut();
                let _ = backend.insert(absent_path.clone(), buf.clone());
                return Ok(());
            },
        };
    }
}

#[derive(Debug)]
pub struct InMemoryFileAbstraction {
    virtual_filesystem: Backend,
}

impl InMemoryFileAbstraction {

    pub fn new() -> InMemoryFileAbstraction {
        InMemoryFileAbstraction {
            virtual_filesystem: Arc::new(Mutex::new(RefCell::new(HashMap::new()))),
        }
    }

    pub fn backend(&self) -> &Backend {
        &self.virtual_filesystem
    }

}

impl FileAbstraction for InMemoryFileAbstraction {

    fn remove_file(&self, path: &PathBuf) -> Result<(), SE> {
        debug!("Removing: {:?}", path);
        self.backend()
            .lock()
            .expect("Locking Mutex failed")
            .get_mut()
            .remove(path)
            .map(|_| ())
            .ok_or(SEK::FileNotFound.into_error())
    }

    fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
        debug!("Copying : {:?} -> {:?}", from, to);
        let mut mtx = self.backend().lock().expect("Locking Mutex failed");
        let mut backend = mtx.get_mut();

        let a = try!(backend.get(from).cloned().ok_or(SEK::FileNotFound.into_error()));
        backend.insert(to.clone(), a);
        debug!("Copying: {:?} -> {:?} worked", from, to);
        Ok(())
    }

    fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
        debug!("Renaming: {:?} -> {:?}", from, to);
        let mut mtx = self.backend().lock().expect("Locking Mutex failed");
        let mut backend = mtx.get_mut();

        let a = try!(backend.get(from).cloned().ok_or(SEK::FileNotFound.into_error()));
        backend.insert(to.clone(), a);
        debug!("Renaming: {:?} -> {:?} worked", from, to);
        Ok(())
    }

    fn create_dir_all(&self, _: &PathBuf) -> Result<(), SE> {
        Ok(())
    }

    fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
        Box::new(InMemoryFileAbstractionInstance::new(self.backend().clone(), p))
    }
}

<commit_msg>Remove unnecessary clone() call<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use error::StoreError as SE;
use error::StoreErrorKind as SEK;
use std::path::PathBuf;
use std::collections::HashMap;
use std::sync::Mutex;
use std::cell::RefCell;
use std::sync::Arc;

use libimagerror::into::IntoError;

use super::FileAbstraction;
use super::FileAbstractionInstance;
use store::Entry;
use storeid::StoreId;

type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Entry>>>>;

/// `FileAbstraction` type, this is the Test version!
///
/// A lazy file is either absent, but a path to it is available, or it is present.
#[derive(Debug)]
pub struct InMemoryFileAbstractionInstance {
    fs_abstraction: Backend,
    absent_path: PathBuf,
}

impl InMemoryFileAbstractionInstance {

    pub fn new(fs: Backend, pb: PathBuf) -> InMemoryFileAbstractionInstance {
        InMemoryFileAbstractionInstance {
            fs_abstraction: fs,
            absent_path: pb
        }
    }

}

impl FileAbstractionInstance for InMemoryFileAbstractionInstance {

    /**
     * Get the mutable file behind a InMemoryFileAbstraction object
     */
    fn get_file_content(&mut self, _: StoreId) -> Result<Entry, SE> {
        debug!("Getting lazy file: {:?}", self);

        match self.fs_abstraction.lock() {
            Ok(mut mtx) => {
                mtx.get_mut()
                    .get(&self.absent_path)
                    .cloned()
                    .ok_or(SEK::FileNotFound.into_error())
            }

            Err(_) => Err(SEK::LockError.into_error())
        }
    }

    fn write_file_content(&mut self, buf: &Entry) -> Result<(), SE> {
        match *self {
            InMemoryFileAbstractionInstance { ref absent_path, .. } => {
                let mut mtx = self.fs_abstraction.lock().expect("Locking Mutex failed");
                let mut backend = mtx.get_mut();
                let _ = backend.insert(absent_path.clone(), buf.clone());
                return Ok(());
            },
        };
    }
}

#[derive(Debug)]
pub struct InMemoryFileAbstraction {
    virtual_filesystem: Backend,
}

impl InMemoryFileAbstraction {

    pub fn new() -> InMemoryFileAbstraction {
        InMemoryFileAbstraction {
            virtual_filesystem: Arc::new(Mutex::new(RefCell::new(HashMap::new()))),
        }
    }

    pub fn backend(&self) -> &Backend {
        &self.virtual_filesystem
    }

}

impl FileAbstraction for InMemoryFileAbstraction {

    fn remove_file(&self, path: &PathBuf) -> Result<(), SE> {
        debug!("Removing: {:?}", path);
        self.backend()
            .lock()
            .expect("Locking Mutex failed")
            .get_mut()
            .remove(path)
            .map(|_| ())
            .ok_or(SEK::FileNotFound.into_error())
    }

    fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
        debug!("Copying : {:?} -> {:?}", from, to);
        let mut mtx = self.backend().lock().expect("Locking Mutex failed");
        let mut backend = mtx.get_mut();

        let a = try!(backend.get(from).cloned().ok_or(SEK::FileNotFound.into_error()));
        backend.insert(to.clone(), a);
        debug!("Copying: {:?} -> {:?} worked", from, to);
        Ok(())
    }

    fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> {
        debug!("Renaming: {:?} -> {:?}", from, to);
        let mut mtx = self.backend().lock().expect("Locking Mutex failed");
        let mut backend = mtx.get_mut();

        let a = try!(backend.get(from).cloned().ok_or(SEK::FileNotFound.into_error()));
        backend.insert(to.clone(), a);
        debug!("Renaming: {:?} -> {:?} worked", from, to);
        Ok(())
    }

    fn create_dir_all(&self, _: &PathBuf) -> Result<(), SE> {
        Ok(())
    }

    fn new_instance(&self, p: PathBuf) -> Box<FileAbstractionInstance> {
        Box::new(InMemoryFileAbstractionInstance::new(self.backend().clone(), p))
    }
}

<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

pub use gfx::format::{Srgb8, Depth};

gfx_vertex_struct!( Vertex {
    pos: [f32; 2] = "a_Pos",
    uv: [f32; 2] = "a_Uv",
});

impl Vertex {
    fn new(p: [f32; 2], u: [f32; 2]) -> Vertex {
        Vertex {
            pos: p,
            uv: u,
        }
    }
}

gfx_pipeline!(pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    tex: gfx::TextureSampler<[f32; 3]> = "t_Tex",
    out: gfx::RenderTarget<Srgb8> = "o_Color",
});

// Larger red dots
const L0_DATA: [u8; 16] = [
    0x00, 0x00, 0x00, 0x00,
    0x00, 0xc0, 0xc0, 0x00,
    0x00, 0xc0, 0xc0, 0x00,
    0x00, 0x00, 0x00, 0x00,
];

// Uniform green
const L1_DATA: [u8; 4] = [
    0x10, 0x18,
    0x18, 0x18,
];

// Uniform blue
const L2_DATA: [u8; 1] = [ 0x02 ];

fn make_texture<R, F>(factory: &mut F) -> gfx::handle::ShaderResourceView<R, [f32; 3]>
        where R: gfx::Resources,
              F: gfx::Factory<R>
{
    let kind = gfx::tex::Kind::D2(4, 4, gfx::tex::AaMode::Single);
    let tex = factory.create_texture(kind, 3, gfx::SHADER_RESOURCE,
        Some(gfx::format::ChannelType::Unorm)).unwrap();

    type Rgb332 = (gfx::format::R3_G3_B2, gfx::format::Unorm);

    factory.update_texture::<Rgb332>(&tex, &tex.get_info().to_image_info(0),
        gfx::cast_slice(&L0_DATA), None).unwrap();
    factory.update_texture::<Rgb332>(&tex, &tex.get_info().to_image_info(1),
        gfx::cast_slice(&L1_DATA), None).unwrap();
    factory.update_texture::<Rgb332>(&tex, &tex.get_info().to_image_info(2),
        gfx::cast_slice(&L2_DATA), None).unwrap();

    factory.view_texture_as_shader_resource::<Rgb332>(
        &tex, (0, 2), gfx::format::Swizzle::new()).unwrap()
}

pub fn main() {
    use gfx::traits::{Device, Factory, FactoryExt};

    let builder = glutin::WindowBuilder::new()
        .with_title("Mipmap example".to_string())
        .with_dimensions(800, 600);
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<Srgb8, Depth>(builder);
    let mut encoder = factory.create_encoder();

    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/120.glslv"),
        include_bytes!("shader/120.glslf"),
        gfx::state::CullFace::Nothing,
        pipe::new()
        ).unwrap();

    let vertex_data = [
        Vertex::new([ 0.0,  0.0], [ 0.0,  0.0]),
        Vertex::new([ 1.0,  0.0], [50.0,  0.0]),
        Vertex::new([ 1.0,  1.1], [50.0, 50.0]),

        Vertex::new([ 0.0,  0.0], [  0.0,   0.0]),
        Vertex::new([-1.0,  0.0], [800.0,   0.0]),
        Vertex::new([-1.0, -1.0], [800.0, 800.0]),
    ];
    let (vbuf, slice) = factory.create_vertex_buffer(&vertex_data);

    let texture_view = make_texture(&mut factory);

    let sampler = factory.create_sampler(gfx::tex::SamplerInfo::new(
        gfx::tex::FilterMethod::Trilinear,
        gfx::tex::WrapMode::Tile,
    ));

    let data = pipe::Data {
        vbuf: vbuf,
        tex: (texture_view, sampler),
        out: main_color,
    };

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        encoder.reset();
        encoder.clear(&data.out, [0.1, 0.2, 0.3]);
        encoder.draw(&slice, &pso, &data);

        device.submit(encoder.as_buffer());
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>Use R8_G8_B8 format for textures.<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

pub use gfx::format::{Srgb8, Depth};

gfx_vertex_struct!( Vertex {
    pos: [f32; 2] = "a_Pos",
    uv: [f32; 2] = "a_Uv",
});

impl Vertex {
    fn new(p: [f32; 2], u: [f32; 2]) -> Vertex {
        Vertex {
            pos: p,
            uv: u,
        }
    }
}

gfx_pipeline!(pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    tex: gfx::TextureSampler<[f32; 3]> = "t_Tex",
    out: gfx::RenderTarget<Srgb8> = "o_Color",
});

// Larger red dots
const L0_DATA: [[u8; 3]; 16] = [
    [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0xc0, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
    [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ], [ 0x00, 0x00, 0x00 ],
];

// Uniform green
const L1_DATA: [[u8; 3]; 4] = [
    [ 0x00, 0xc0, 0x00 ], [ 0x00, 0xc0, 0x00 ],
    [ 0x00, 0xc0, 0x00 ], [ 0x00, 0xc0, 0x00 ],
];

// Uniform blue
const L2_DATA: [[u8; 3]; 1] = [ [ 0x00, 0x00, 0xc0 ] ];

fn make_texture<R, F>(factory: &mut F) -> gfx::handle::ShaderResourceView<R, [f32; 3]>
        where R: gfx::Resources,
              F: gfx::Factory<R>
{
    let kind = gfx::tex::Kind::D2(4, 4, gfx::tex::AaMode::Single);
    let tex = factory.create_texture(kind, 3, gfx::SHADER_RESOURCE,
        Some(gfx::format::ChannelType::Unorm)).unwrap();

    type Rgb8 = (gfx::format::R8_G8_B8, gfx::format::Unorm);

    factory.update_texture::<Rgb8>(&tex, &tex.get_info().to_image_info(0),
        gfx::cast_slice(&L0_DATA), None).unwrap();
    factory.update_texture::<Rgb8>(&tex, &tex.get_info().to_image_info(1),
        gfx::cast_slice(&L1_DATA), None).unwrap();
    factory.update_texture::<Rgb8>(&tex, &tex.get_info().to_image_info(2),
        gfx::cast_slice(&L2_DATA), None).unwrap();

    factory.view_texture_as_shader_resource::<Rgb8>(
        &tex, (0, 2), gfx::format::Swizzle::new()).unwrap()
}

pub fn main() {
    use gfx::traits::{Device, Factory, FactoryExt};

    let builder = glutin::WindowBuilder::new()
        .with_title("Mipmap example".to_string())
        .with_dimensions(800, 600);
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<Srgb8, Depth>(builder);
    let mut encoder = factory.create_encoder();

    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/120.glslv"),
        include_bytes!("shader/120.glslf"),
        gfx::state::CullFace::Nothing,
        pipe::new()
        ).unwrap();

    let vertex_data = [
        Vertex::new([ 0.0,  0.0], [ 0.0,  0.0]),
        Vertex::new([ 1.0,  0.0], [50.0,  0.0]),
        Vertex::new([ 1.0,  1.1], [50.0, 50.0]),

        Vertex::new([ 0.0,  0.0], [  0.0,   0.0]),
        Vertex::new([-1.0,  0.0], [800.0,   0.0]),
        Vertex::new([-1.0, -1.0], [800.0, 800.0]),
    ];
    let (vbuf, slice) = factory.create_vertex_buffer(&vertex_data);

    let texture_view = make_texture(&mut factory);

    let sampler = factory.create_sampler(gfx::tex::SamplerInfo::new(
        gfx::tex::FilterMethod::Trilinear,
        gfx::tex::WrapMode::Tile,
    ));

    let data = pipe::Data {
        vbuf: vbuf,
        tex: (texture_view, sampler),
        out: main_color,
    };

    'main: loop {
        // quit when Esc is pressed.
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        encoder.reset();
        encoder.clear(&data.out, [0.1, 0.2, 0.3]);
        encoder.draw(&slice, &pso, &data);

        device.submit(encoder.as_buffer());
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<|endoftext|>


<commit_before>use buffer::{Lexeme, Position, Token};
use syntect::parsing::{ParseState, Scope, ScopeStack, SyntaxDefinition};
use buffer::token::line_iterator::LineIterator;
use std::vec::IntoIter;

pub struct TokenIterator<'a> {
    scopes: ScopeStack,
    parser: ParseState,
    line_tokens: Option<IntoIter<Token<'a>>>,
    lines: LineIterator<'a>
}

impl<'a> TokenIterator<'a> {
    pub fn new(data: &'a str, def: &SyntaxDefinition) -> TokenIterator<'a> {
        TokenIterator{
            scopes: ScopeStack::new(),
            parser: ParseState::new(def),
            line_tokens: None,
            lines: LineIterator::new(data)
        }
    }

    fn next_token(&mut self) -> Option<Token<'a>> {
        // Try to fetch a token from the current line.
        if let Some(ref mut tokens) = self.line_tokens {
            if let Some(token) = tokens.next() {
                return Some(token)
            }
        }

        // We're done with this line; on to the next.
        self.parse_next_line();

        // If this returns none, we're done.
        if let Some(ref mut tokens) = self.line_tokens {
            tokens.next()
        } else {
            None
        }
    }

    fn parse_next_line(&mut self) {
        let mut tokens = Vec::new();
        let mut offset = 0;
        let mut last_scope: Option<Scope> = None;

        if let Some((line_number, line)) = self.lines.next() {
            if line_number > 0 {
                // We've found another line, so push a newline token.
                tokens.push(Token::Newline);
            }

            for (change_offset, scope_change) in self.parser.parse_line(line) {
                // We only want to capture the deepest scope for a given token,
                // so we apply all of them and only capture once we move on to
                // another token/offset.
                if change_offset > offset {
                    tokens.push(
                        Token::Lexeme(Lexeme{
                            value: &line[offset..change_offset],
                            scope: last_scope.clone(),
                            position: Position{
                                line: line_number,
                                offset: offset
                            }
                        })
                    );
                    offset = change_offset;
                }

                // Apply the scope and keep a reference to it, so
                // that we can pair it with a token later on.
                self.scopes.apply(&scope_change);
                last_scope = self.scopes.as_slice().last().map(|s| s.clone());

            }

            // We already have discrete variant for newlines,
            // so exclude them when considering content length.
            if let Some(end_of_line) = line.len().checked_sub(1) {
                if offset < end_of_line {
                    // The rest of the line hasn't triggered a scope
                    // change; categorize it with the last known scope.
                    tokens.push(
                        Token::Lexeme(Lexeme{
                            value: &line[offset..end_of_line],
                            scope: last_scope.clone(),
                            position: Position{
                                line: line_number,
                                offset: offset
                            }
                        })
                    );
                }
            };

            self.line_tokens = Some(tokens.into_iter());
        } else {
            self.line_tokens = None;
        }
    }
}

impl<'a> Iterator for TokenIterator<'a> {
    type Item = Token<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(token) = self.next_token() {
            return Some(token)
        }

        self.parse_next_line();
        self.next_token()
    }
}

#[cfg(test)]
mod tests {
    use super::TokenIterator;
    use buffer::{Lexeme, Position, Scope, Token};
    use syntect::parsing::SyntaxSet;

    #[test]
    fn token_iterator_returns_correct_tokens() {
        let syntax_set = SyntaxSet::load_defaults_newlines();
        let def = syntax_set.find_syntax_by_extension("rs");
        let iterator = TokenIterator::new("struct Buffer {\n// comment\n  data: String\n}garbage\n\n", def.unwrap());
        let expected_tokens = vec![
            Token::Lexeme(Lexeme{
                value: "struct",
                scope: Some(Scope::new("storage.type.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 0 }
            }),
            Token::Lexeme(Lexeme{
                value: " ",
                scope: Some(Scope::new("meta.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 6 }
            }),
            Token::Lexeme(Lexeme{
                value: "Buffer",
                scope: Some(Scope::new("entity.name.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 7 }
            }),
            Token::Lexeme(Lexeme{
                value: " ",
                scope: Some(Scope::new("meta.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 13 }
            }),
            Token::Lexeme(Lexeme{
                value: "{",
                scope: Some(Scope::new("punctuation.definition.block.begin.rust").unwrap()),
                position: Position{ line: 0, offset: 14 }
            }),
            Token::Newline,
            Token::Lexeme(Lexeme{
                value: "// comment",
                scope: Some(Scope::new("comment.line.double-slash.rust").unwrap()),
                position: Position{ line: 1, offset: 0 }
            }),
            Token::Newline,
            Token::Lexeme(Lexeme{
                value: "  ",
                scope: None,
                position: Position{ line: 2, offset: 0 }
            }),
            Token::Lexeme(Lexeme{
                value: "data",
                scope: Some(Scope::new("variable.other.property.rust").unwrap()),
                position: Position{ line: 2, offset: 2 }
            }),
            Token::Lexeme(Lexeme{
                value: ":",
                scope: Some(Scope::new("punctuation.separator.rust").unwrap()),
                position: Position{ line: 2, offset: 6 }
            }),
            Token::Lexeme(Lexeme{
                value: " String",
                scope: Some(Scope::new("meta.block.rust").unwrap()),
                position: Position{ line: 2, offset: 7 }
            }),
            Token::Newline,
            Token::Lexeme(Lexeme{
                value: "}",
                scope: Some(Scope::new("punctuation.definition.block.end.rust").unwrap()),
                position: Position{ line: 3, offset: 0 }
            }),
            Token::Lexeme(Lexeme{
                value: "garbage",
                scope: Some(Scope::new("source.rust").unwrap()),
                position: Position{ line: 3, offset: 1 }
            }),
            Token::Newline,
            Token::Newline
        ];
        let actual_tokens: Vec<Token> = iterator.collect();
        println!("{:?}", actual_tokens);
        for (index, token) in expected_tokens.into_iter().enumerate() {
            assert_eq!(token, actual_tokens[index]);
        }

        //assert_eq!(expected_tokens, actual_tokens);
    }

    #[test]
    fn token_iterator_handles_content_without_trailing_newline() {
        let syntax_set = SyntaxSet::load_defaults_newlines();
        let def = syntax_set.find_syntax_by_extension("rs");
        let iterator = TokenIterator::new("struct", def.unwrap());
        let expected_tokens = vec![
            Token::Lexeme(Lexeme{
                value: "struct",
                scope: Some(Scope::new("storage.type.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 0 }
            })
        ];
        let actual_tokens: Vec<Token> = iterator.collect();
        for (index, token) in expected_tokens.into_iter().enumerate() {
            assert_eq!(token, actual_tokens[index]);
        }

        //assert_eq!(expected_tokens, actual_tokens);
    }
}
<commit_msg>Build line tokens one at a time<commit_after>use buffer::{Lexeme, Position, Token};
use syntect::parsing::{ParseState, ScopeStack, ScopeStackOp, SyntaxDefinition};
use buffer::token::line_iterator::LineIterator;

pub struct TokenIterator<'a> {
    scopes: ScopeStack,
    parser: ParseState,
    lines: LineIterator<'a>,
    current_line: Option<&'a str>,
    current_line_number: usize,
    line_events: Vec<(usize, ScopeStackOp)>,
    last_event_offset: usize,
}

impl<'a> TokenIterator<'a> {
    pub fn new(data: &'a str, def: &SyntaxDefinition) -> TokenIterator<'a> {
        let mut token_iterator = TokenIterator{
            scopes: ScopeStack::new(),
            parser: ParseState::new(def),
            lines: LineIterator::new(data),
            current_line: None,
            current_line_number: 0,
            line_events: Vec::new(),
            last_event_offset: 0,
        };

        // Preload the first line
        token_iterator.parse_next_line();

        token_iterator
    }

    fn next_token(&mut self) -> Option<Token<'a>> {
        // Try to fetch a token from the current line.
        if let Some(token) = self.build_next_token() {
            return Some(token)
        }

        // We're done with this line; on to the next.
        self.parse_next_line();
        if self.current_line.is_some() {
            Some(Token::Newline)
        } else {
            None
        }
    }

    fn build_next_token(&mut self) -> Option<Token<'a>> {
        let mut lexeme = None;

        if let Some(line) = self.current_line {
            while let Some((event_offset, scope_change)) = self.line_events.pop() {
                // We only want to capture the deepest scope for a given token,
                // so we apply all of them and only capture once we move on to
                // another token/offset.
                if event_offset > self.last_event_offset {
                    lexeme = Some(
                        Token::Lexeme(Lexeme{
                            value: &line[self.last_event_offset..event_offset],
                            scope: self.scopes.as_slice().last().map(|s| s.clone()),
                            position: Position{
                                line: self.current_line_number,
                                offset: self.last_event_offset,
                            }
                        })
                    );
                    self.last_event_offset = event_offset;
                }

                // Apply the scope and keep a reference to it, so
                // that we can pair it with a token later on.
                self.scopes.apply(&scope_change);

                if lexeme.is_some() { return lexeme }
            }

            // We already have discrete variant for newlines,
            // so exclude them when considering content length.
            if let Some(end_of_line) = line.len().checked_sub(1) {
                if self.last_event_offset < end_of_line {
                    // The rest of the line hasn't triggered a scope
                    // change; categorize it with the last known scope.
                    lexeme = Some(
                        Token::Lexeme(Lexeme{
                            value: &line[self.last_event_offset..end_of_line],
                            scope: self.scopes.as_slice().last().map(|s| s.clone()),
                            position: Position{
                                line: self.current_line_number,
                                offset: self.last_event_offset
                            }
                        })
                    );
                }

            };
        }
        self.current_line = None;

        if lexeme.is_some() {
            lexeme
        } else {
            None
        }
    }

    fn parse_next_line(&mut self) {
        // Reset this, since we're starting a new line.
        self.last_event_offset = 0;

        if let Some((line_number, line)) = self.lines.next() {
            // We reverse the line elements so that we can pop them off one at a
            // time, handling each event while allowing us to stop at any point.
            let mut line_events = self.parser.parse_line(line);
            line_events.reverse();
            self.line_events = line_events;

            // Keep a reference to the line so that we can create slices of it.
            self.current_line = Some(line);
            self.current_line_number = line_number;
        } else {
            self.current_line = None;
        }
    }
}

impl<'a> Iterator for TokenIterator<'a> {
    type Item = Token<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        self.next_token()
    }
}

#[cfg(test)]
mod tests {
    use super::TokenIterator;
    use buffer::{Lexeme, Position, Scope, Token};
    use syntect::parsing::SyntaxSet;

    #[test]
    fn token_iterator_returns_correct_tokens() {
        let syntax_set = SyntaxSet::load_defaults_newlines();
        let def = syntax_set.find_syntax_by_extension("rs");
        let iterator = TokenIterator::new("struct Buffer {\n// comment\n  data: String\n}garbage\n\n", def.unwrap());
        let expected_tokens = vec![
            Token::Lexeme(Lexeme{
                value: "struct",
                scope: Some(Scope::new("storage.type.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 0 }
            }),
            Token::Lexeme(Lexeme{
                value: " ",
                scope: Some(Scope::new("meta.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 6 }
            }),
            Token::Lexeme(Lexeme{
                value: "Buffer",
                scope: Some(Scope::new("entity.name.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 7 }
            }),
            Token::Lexeme(Lexeme{
                value: " ",
                scope: Some(Scope::new("meta.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 13 }
            }),
            Token::Lexeme(Lexeme{
                value: "{",
                scope: Some(Scope::new("punctuation.definition.block.begin.rust").unwrap()),
                position: Position{ line: 0, offset: 14 }
            }),
            Token::Newline,
            Token::Lexeme(Lexeme{
                value: "// comment",
                scope: Some(Scope::new("comment.line.double-slash.rust").unwrap()),
                position: Position{ line: 1, offset: 0 }
            }),
            Token::Newline,
            Token::Lexeme(Lexeme{
                value: "  ",
                scope: Some(Scope::new("meta.block.rust").unwrap()),
                position: Position{ line: 2, offset: 0 }
            }),
            Token::Lexeme(Lexeme{
                value: "data",
                scope: Some(Scope::new("variable.other.property.rust").unwrap()),
                position: Position{ line: 2, offset: 2 }
            }),
            Token::Lexeme(Lexeme{
                value: ":",
                scope: Some(Scope::new("punctuation.separator.rust").unwrap()),
                position: Position{ line: 2, offset: 6 }
            }),
            Token::Lexeme(Lexeme{
                value: " String",
                scope: Some(Scope::new("meta.block.rust").unwrap()),
                position: Position{ line: 2, offset: 7 }
            }),
            Token::Newline,
            Token::Lexeme(Lexeme{
                value: "}",
                scope: Some(Scope::new("punctuation.definition.block.end.rust").unwrap()),
                position: Position{ line: 3, offset: 0 }
            }),
            Token::Lexeme(Lexeme{
                value: "garbage",
                scope: Some(Scope::new("source.rust").unwrap()),
                position: Position{ line: 3, offset: 1 }
            }),
            Token::Newline,
            Token::Newline
        ];
        let actual_tokens: Vec<Token> = iterator.collect();
        for (index, token) in expected_tokens.into_iter().enumerate() {
            assert_eq!(token, actual_tokens[index]);
        }

        //assert_eq!(expected_tokens, actual_tokens);
    }

    #[test]
    fn token_iterator_handles_content_without_trailing_newline() {
        let syntax_set = SyntaxSet::load_defaults_newlines();
        let def = syntax_set.find_syntax_by_extension("rs");
        let iterator = TokenIterator::new("struct", def.unwrap());
        let expected_tokens = vec![
            Token::Lexeme(Lexeme{
                value: "struct",
                scope: Some(Scope::new("storage.type.struct.rust").unwrap()),
                position: Position{ line: 0, offset: 0 }
            })
        ];
        let actual_tokens: Vec<Token> = iterator.collect();
        for (index, token) in expected_tokens.into_iter().enumerate() {
            assert_eq!(token, actual_tokens[index]);
        }

        //assert_eq!(expected_tokens, actual_tokens);
    }
}
<|endoftext|>


<commit_before>//! The base class
use std::os;
use std::cmp;

use term::color;

use self::lines::*;
use line::{PromptLineType, PromptLine, PromptLineBuilder, PromptBox};

/// Defines the speed at which to run the to_string method
pub enum PluginSpeed {
    /// Don't run plugin
    Ignored,

    /// Don't do anything that might be slow
    Fast,

    /// Do whatever you want (still try to be fast as possible)
    Slow
}

impl PluginSpeed {
    fn is_ignored(&self) -> bool {
        match *self {
            PluginSpeed::Ignored => true,
            _ => false
        }
    }
}

mod lines {
    pub const TOP       : i16 = 8;
    pub const BOTTOM    : i16 = 4;
    pub const LEFT      : i16 = 2;
    pub const RIGHT     : i16 = 1;
}

/// PromptBuffer
///
/// Used to contain a list of PromptLines
/// Knows how to format a serise of PromptLines in a pretty way
pub struct PromptBuffer {
    plugins: Vec<Box<PromptBufferPlugin+Send>>,
    path: Path
}

impl PromptBuffer {
    /// Creates a new PromptBuffer at the current path
    pub fn new() -> PromptBuffer {
        PromptBuffer {
            plugins: Vec::new(),
            path: os::make_absolute(&Path::new(".")).unwrap()
        }
    }

    fn get_line(flags: i16) -> char {
        return match flags {
            c if c == TOP | BOTTOM | LEFT | RIGHT => '┼',
            c if c == TOP | BOTTOM | LEFT         => '┤',
            c if c == TOP | BOTTOM        | RIGHT => '├',
            c if c == TOP | BOTTOM                => '│',
            c if c == TOP          | LEFT | RIGHT => '┴',
            c if c == TOP          | LEFT         => '┘',
            c if c == TOP                 | RIGHT => '└',
            c if c ==       BOTTOM | LEFT         => '┐',
            c if c ==       BOTTOM        | RIGHT => '┌',
            c if c ==       BOTTOM | LEFT | RIGHT => '┬',
            c if c ==                LEFT | RIGHT => '─',
            _      => panic!("Passed invalid value to get_line")
        }
    }

    fn trail_off() -> String {
        let mut retval = String::new();
        for _ in 0..10 {
            retval = format!("{}{}", retval, PromptBuffer::get_line(LEFT|RIGHT));
        }
        retval
    }

    fn start(&self, lines: &mut Vec<PromptLine>) {
        lines.push(PromptLineBuilder::new()
            .block(&"\\w")
            .block(&"\\H")
            .build());
    }

    /// Adds a plugin to the prompt buffer
    ///
    /// They will be executed in order
    pub fn add_plugin(&mut self, plugin: Box<PromptBufferPlugin+Send>) {
        self.plugins.push(plugin);
    }

    /// Store the new path for the PromptBuffer.
    ///
    /// This is sent in as context to PromptBufferPlugins
    pub fn set_path(&mut self, p: Path) {
        self.path = p;
    }

    /// Returns the result of the prompt
    ///
    /// Allows specifying wanted plugin speed
    pub fn to_string_ext(&mut self, speed: PluginSpeed) -> String {
        let mut retval = String::new();
        let mut lines = Vec::new();

        self.start(&mut lines);

        if !speed.is_ignored() {
            let mut pl = self.plugins.as_mut_slice();
            for i in 0 .. pl.len() {
                pl[i].run(&speed, &self.path, &mut lines);
            }
        }

        for ix in 0 .. lines.len() {
            let ref line = lines[ix];
            let current = line.level;
            let (after, start, end) = if ix + 1 < lines.len() {
                let a = lines[ix + 1].level;
                (a, cmp::min(current, a), cmp::max(current, a))
            } else {
                (0, 0, current)
            };

            let mut line_text = String::new();

            // FIXME: change when range syntax is fixed
            for _ in (0..start) {
                line_text = format!(" {}", line_text);
            }

            for i in start .. end + 1 {
                line_text = format!("{}{}", line_text,
                    PromptBuffer::get_line(
                        if i == current && ix > 0 { TOP } else { 0 } |
                        if i == after { BOTTOM } else { 0 } |
                        if i > start { LEFT } else { 0 } |
                        match line.line_type {
                            PromptLineType::Boxed => RIGHT,
                            PromptLineType::Free => if i == current {
                                0
                            } else {
                                RIGHT
                            }
                        }
                    )
                );
            }

            for b in line.parts.iter() {
                line_text = match line.line_type {
                    PromptLineType::Boxed => format!("{}{}{}{}{}",
                        line_text,
                        PromptBuffer::get_line(LEFT|RIGHT),
                        PromptBuffer::get_line(LEFT|TOP|BOTTOM),
                        b,
                        PromptBuffer::get_line(TOP|BOTTOM|RIGHT)),
                    PromptLineType::Free => format!("{} {}", line_text, b)
                };
            }

            match line.line_type {
                PromptLineType::Boxed => {
                    line_text = format!("{}{}", line_text, PromptBuffer::trail_off());
                },
                _ => {}
            }

            retval = format!("{}{}\n", retval, line_text);
        }

        format!("{}{}{}{} ",
            retval,
            PromptBuffer::get_line(TOP|RIGHT), PromptBuffer::get_line(LEFT|RIGHT),
            PromptBox::create("\\$".to_string(), color::RED, false))
    }

    /// Returns the prompt with plugins run
    pub fn to_string(&mut self) -> String {
        self.to_string_ext(PluginSpeed::Slow)
    }

    /// Print a result with the plugins
    pub fn print(&mut self) {
        println!("{}", self.to_string());
    }

    /// Print a result while skipping all plugins
    pub fn print_fast(&mut self) {
        println!("{}", self.to_string_ext(PluginSpeed::Fast));
    }
}

/// Implement this trait to allow extension of the PromptBuffer's result
pub trait PromptBufferPlugin {
    /// Should append as many PromptLines as it wants to the lines Vec
    ///
    /// The path can be used to provide context if necessary
    fn run(&mut self, speed: &PluginSpeed, path: &Path, lines: &mut Vec<PromptLine>);
}
<commit_msg>Derive Copy for PluginSpeed<commit_after>//! The base class
use std::os;
use std::cmp;

use term::color;

use self::lines::*;
use line::{PromptLineType, PromptLine, PromptLineBuilder, PromptBox};

/// Defines the speed at which to run the to_string method
#[derive(Copy)]
pub enum PluginSpeed {
    /// Don't run plugin
    Ignored,

    /// Don't do anything that might be slow
    Fast,

    /// Do whatever you want (still try to be fast as possible)
    Slow
}

impl PluginSpeed {
    fn is_ignored(&self) -> bool {
        match *self {
            PluginSpeed::Ignored => true,
            _ => false
        }
    }
}

mod lines {
    pub const TOP       : i16 = 8;
    pub const BOTTOM    : i16 = 4;
    pub const LEFT      : i16 = 2;
    pub const RIGHT     : i16 = 1;
}

/// PromptBuffer
///
/// Used to contain a list of PromptLines
/// Knows how to format a serise of PromptLines in a pretty way
pub struct PromptBuffer {
    plugins: Vec<Box<PromptBufferPlugin+Send>>,
    path: Path
}

impl PromptBuffer {
    /// Creates a new PromptBuffer at the current path
    pub fn new() -> PromptBuffer {
        PromptBuffer {
            plugins: Vec::new(),
            path: os::make_absolute(&Path::new(".")).unwrap()
        }
    }

    fn get_line(flags: i16) -> char {
        return match flags {
            c if c == TOP | BOTTOM | LEFT | RIGHT => '┼',
            c if c == TOP | BOTTOM | LEFT         => '┤',
            c if c == TOP | BOTTOM        | RIGHT => '├',
            c if c == TOP | BOTTOM                => '│',
            c if c == TOP          | LEFT | RIGHT => '┴',
            c if c == TOP          | LEFT         => '┘',
            c if c == TOP                 | RIGHT => '└',
            c if c ==       BOTTOM | LEFT         => '┐',
            c if c ==       BOTTOM        | RIGHT => '┌',
            c if c ==       BOTTOM | LEFT | RIGHT => '┬',
            c if c ==                LEFT | RIGHT => '─',
            _      => panic!("Passed invalid value to get_line")
        }
    }

    fn trail_off() -> String {
        let mut retval = String::new();
        for _ in 0..10 {
            retval = format!("{}{}", retval, PromptBuffer::get_line(LEFT|RIGHT));
        }
        retval
    }

    fn start(&self, lines: &mut Vec<PromptLine>) {
        lines.push(PromptLineBuilder::new()
            .block(&"\\w")
            .block(&"\\H")
            .build());
    }

    /// Adds a plugin to the prompt buffer
    ///
    /// They will be executed in order
    pub fn add_plugin(&mut self, plugin: Box<PromptBufferPlugin+Send>) {
        self.plugins.push(plugin);
    }

    /// Store the new path for the PromptBuffer.
    ///
    /// This is sent in as context to PromptBufferPlugins
    pub fn set_path(&mut self, p: Path) {
        self.path = p;
    }

    /// Returns the result of the prompt
    ///
    /// Allows specifying wanted plugin speed
    pub fn to_string_ext(&mut self, speed: PluginSpeed) -> String {
        let mut retval = String::new();
        let mut lines = Vec::new();

        self.start(&mut lines);

        if !speed.is_ignored() {
            let mut pl = self.plugins.as_mut_slice();
            for i in 0 .. pl.len() {
                pl[i].run(&speed, &self.path, &mut lines);
            }
        }

        for ix in 0 .. lines.len() {
            let ref line = lines[ix];
            let current = line.level;
            let (after, start, end) = if ix + 1 < lines.len() {
                let a = lines[ix + 1].level;
                (a, cmp::min(current, a), cmp::max(current, a))
            } else {
                (0, 0, current)
            };

            let mut line_text = String::new();

            // FIXME: change when range syntax is fixed
            for _ in (0..start) {
                line_text = format!(" {}", line_text);
            }

            for i in start .. end + 1 {
                line_text = format!("{}{}", line_text,
                    PromptBuffer::get_line(
                        if i == current && ix > 0 { TOP } else { 0 } |
                        if i == after { BOTTOM } else { 0 } |
                        if i > start { LEFT } else { 0 } |
                        match line.line_type {
                            PromptLineType::Boxed => RIGHT,
                            PromptLineType::Free => if i == current {
                                0
                            } else {
                                RIGHT
                            }
                        }
                    )
                );
            }

            for b in line.parts.iter() {
                line_text = match line.line_type {
                    PromptLineType::Boxed => format!("{}{}{}{}{}",
                        line_text,
                        PromptBuffer::get_line(LEFT|RIGHT),
                        PromptBuffer::get_line(LEFT|TOP|BOTTOM),
                        b,
                        PromptBuffer::get_line(TOP|BOTTOM|RIGHT)),
                    PromptLineType::Free => format!("{} {}", line_text, b)
                };
            }

            match line.line_type {
                PromptLineType::Boxed => {
                    line_text = format!("{}{}", line_text, PromptBuffer::trail_off());
                },
                _ => {}
            }

            retval = format!("{}{}\n", retval, line_text);
        }

        format!("{}{}{}{} ",
            retval,
            PromptBuffer::get_line(TOP|RIGHT), PromptBuffer::get_line(LEFT|RIGHT),
            PromptBox::create("\\$".to_string(), color::RED, false))
    }

    /// Returns the prompt with plugins run
    pub fn to_string(&mut self) -> String {
        self.to_string_ext(PluginSpeed::Slow)
    }

    /// Print a result with the plugins
    pub fn print(&mut self) {
        println!("{}", self.to_string());
    }

    /// Print a result while skipping all plugins
    pub fn print_fast(&mut self) {
        println!("{}", self.to_string_ext(PluginSpeed::Fast));
    }
}

/// Implement this trait to allow extension of the PromptBuffer's result
pub trait PromptBufferPlugin {
    /// Should append as many PromptLines as it wants to the lines Vec
    ///
    /// The path can be used to provide context if necessary
    fn run(&mut self, speed: &PluginSpeed, path: &Path, lines: &mut Vec<PromptLine>);
}
<|endoftext|>