<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use command::CommandResult;
use error::{Error, Result};
use regex::Regex;
use std::fs::File;
use std::io::Read;
use target::bin_resolver::BinResolver;
use target::default_base as default;

pub fn service_init(name: &str, action: &str) -> Result<Option<CommandResult>> {
    if action == "enable" || action == "disable" {
        let chkconfig = BinResolver::resolve("chkconfig")?;
        let result = default::command_exec(&format!("{} {}", chkconfig.to_str().unwrap(), name))?;

        match action {
            "enable" if result.exit_code != 0 => Ok(Some(try!(default::command_exec(&format!("{} {} on", chkconfig.to_str().unwrap(), name))))),
            "disable" if result.exit_code == 0 => Ok(Some(try!(default::command_exec(&format!("{} {} off", chkconfig.to_str().unwrap(), name))))),
            _ => Ok(None)
        }
    } else {
        default::service_action(name, action)
    }
}

pub fn version() -> Result<(String, u32, u32, u32)> {
    let mut fh = try!(File::open("/etc/redhat-release"));
    let mut fc = String::new();
    fh.read_to_string(&mut fc).unwrap();

    let regex = Regex::new(r"release ([0-9]+)\.([0-9]+)\.([0-9]+)").unwrap();
    if let Some(cap) = regex.captures(&fc) {
        let version_maj = cap.at(1).unwrap().parse()?;
        let version_min = cap.at(2).unwrap().parse()?;
        let version_patch = cap.at(3).unwrap().parse()?;
        let version_str = format!("{}.{}.{}", version_maj, version_min, version_patch);
        Ok((version_str, version_maj, version_min, version_patch))
    } else {
        Err(Error::Generic("Could not match OS version".into()))
    }
}
<commit_msg>Fix bug detecting RHEL family OS versions where MIN and PATCH may be missing<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use command::CommandResult;
use error::{Error, Result};
use regex::Regex;
use std::fs::File;
use std::io::Read;
use target::bin_resolver::BinResolver;
use target::default_base as default;

pub fn service_init(name: &str, action: &str) -> Result<Option<CommandResult>> {
    if action == "enable" || action == "disable" {
        let chkconfig = BinResolver::resolve("chkconfig")?;
        let result = default::command_exec(&format!("{} {}", chkconfig.to_str().unwrap(), name))?;

        match action {
            "enable" if result.exit_code != 0 => Ok(Some(try!(default::command_exec(&format!("{} {} on", chkconfig.to_str().unwrap(), name))))),
            "disable" if result.exit_code == 0 => Ok(Some(try!(default::command_exec(&format!("{} {} off", chkconfig.to_str().unwrap(), name))))),
            _ => Ok(None)
        }
    } else {
        default::service_action(name, action)
    }
}

pub fn version() -> Result<(String, u32, u32, u32)> {
    let mut fh = try!(File::open("/etc/redhat-release"));
    let mut fc = String::new();
    fh.read_to_string(&mut fc).unwrap();

    let regex = Regex::new(r"release ([0-9]+)(?:\.([0-9]+)(?:\.([0-9]+))?)?").unwrap();
    if let Some(cap) = regex.captures(&fc) {
        let version_maj = cap.at(1).unwrap().parse()?;
        let version_min = cap.at(2).unwrap_or("0").parse()?;
        let version_patch = cap.at(3).unwrap_or("0").parse()?;
        let version_str = format!("{}.{}.{}", version_maj, version_min, version_patch);
        Ok((version_str, version_maj, version_min, version_patch))
    } else {
        Err(Error::Generic("Could not match OS version".into()))
    }
}
<|endoftext|>


<commit_before>/* Cymbalum, Molecular Simulation in Rust - Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 */

//! [Chemfiles](https://github.com/chemfiles/chemfiles/) adaptators for Cymbalum.

extern crate chemfiles;
use universe::{Particle, Universe};
use universe::cells::{UnitCell, CellType};
use types::Vector3D;

use self::chemfiles::Error;

/// Convert chemfiles types to Cymbalum types
trait ToCymbalum {
    /// Output type
    type Output;
    /// Conversion function
    fn to_cymbalum(self) -> Result<Self::Output, Error>;
}

impl ToCymbalum for chemfiles::Atom {
    type Output = Particle;
    fn to_cymbalum(self) -> Result<Particle, Error> {
        let name = try!(self.name());
        let mut part = Particle::new(name);
        let mass = try!(self.mass());
        part.mass = mass as f64;
        Ok(part)
    }
}

impl ToCymbalum for chemfiles::UnitCell {
    type Output = UnitCell;
    fn to_cymbalum(self) -> Result<UnitCell, Error> {
        let cell_type = try!(self.cell_type());
        let cell = match cell_type {
            chemfiles::CellType::Infinite => UnitCell::new(),
            chemfiles::CellType::Orthorombic => {
                let (a, b, c) = try!(self.lengths());
                UnitCell::ortho(a, b, c)
            },
            chemfiles::CellType::Triclinic => {
                let (a, b, c) = try!(self.lengths());
                let (alpha, beta, gamma) = try!(self.angles());
                UnitCell::triclinic(a, b, c, alpha, beta, gamma)
            }
        };
        Ok(cell)
    }
}

impl ToCymbalum for chemfiles::Frame {
    type Output = Universe;
    fn to_cymbalum(self) -> Result<Universe, Error> {
        let cell = try!(self.cell());
        let cell = try!(cell.to_cymbalum());
        let mut universe = Universe::from_cell(cell);
        let topology = try!(self.topology());
        let positions = try!(self.positions());
        let natoms = try!(self.natoms());
        let step = try!(self.step());

        universe.set_step(step);

        for i in 0..natoms {
            let atom = try!(topology.atom(i as u64));
            let particle = try!(atom.to_cymbalum());

            universe.add_particle(particle);
            let position = Vector3D::new(
                positions[i][0] as f64,
                positions[i][1] as f64,
                positions[i][2] as f64
            );
            universe[i].position = position;
        }

        let mut bonds = try!(topology.bonds());
        while !bonds.is_empty() {
            let bond = bonds.pop().unwrap();
            if let Some(perms) = universe.add_bond(bond[0] as usize, bond[1] as usize) {
                apply_particle_permutation(&mut bonds, perms);
            }
        }
        Ok(universe)
    }
}

fn apply_particle_permutation(bonds: &mut Vec<[u64; 2]>, perms: Vec<(usize, usize)>) {
    'bonds: for bond in bonds {
        for perm in &perms {
            if bond[0] == (perm.0 as u64) {
                bond[0] = perm.1 as u64;
                continue 'bonds;
            } else if bond[1] == (perm.0 as u64) {
                bond[1] = perm.1 as u64;
                continue 'bonds;
            }
        }
    }
}

/// Convert a chemfiles `Frame` to an `Universe`
pub fn frame_to_universe(frame: chemfiles::Frame) -> Result<Universe, Error> {
    frame.to_cymbalum()
}

/******************************************************************************/

/// Convert Cymbalum types to chemfiles types
trait ToChemfiles {
    /// Output type
    type Output;
    /// Conversion function
    fn to_chemfiles(&self) -> Result<Self::Output, Error>;
}

impl ToChemfiles for Particle {
    type Output = chemfiles::Atom;
    fn to_chemfiles(&self) -> Result<chemfiles::Atom, Error> {
        let mut res = try!(chemfiles::Atom::new(self.name()));
        try!(res.set_mass(self.mass as f32));
        return Ok(res);
    }
}

impl ToChemfiles for UnitCell {
    type Output = chemfiles::UnitCell;
    fn to_chemfiles(&self) -> Result<chemfiles::UnitCell, Error> {
        let res = match self.celltype() {
            CellType::Infinite => {
                unimplemented!()
            }
            CellType::Orthorombic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                try!(chemfiles::UnitCell::new(a, b, c))
            },
            CellType::Triclinic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                let (alpha, beta, gamma) = (self.alpha(), self.beta(), self.gamma());
                try!(chemfiles::UnitCell::triclinic(a, b, c, alpha, beta, gamma))
            },
        };
        return Ok(res);
    }
}

impl ToChemfiles for Universe {
    type Output = chemfiles::Frame;
    fn to_chemfiles(&self) -> Result<chemfiles::Frame, Error> {

        let natoms = self.size();
        let mut frame = try!(chemfiles::Frame::new(natoms as u64));

        try!(frame.set_step(self.step()));

        let mut topology = try!(chemfiles::Topology::new());
        let mut positions = vec![[0.0f32; 3]; natoms];
        let mut velocities = vec![[0.0f32; 3]; natoms];

        for (i, p) in self.iter().enumerate() {
            let pos = p.position;
            positions[i][0] = pos.x as f32;
            positions[i][1] = pos.y as f32;
            positions[i][2] = pos.z as f32;

            let vel = p.velocity;
            velocities[i][0] = vel.x as f32;
            velocities[i][1] = vel.y as f32;
            velocities[i][2] = vel.z as f32;

            let atom = try!(p.to_chemfiles());
            try!(topology.push(&atom));
        }
        try!(frame.set_positions(positions));
        try!(frame.set_velocities(velocities));

        for molecule in self.molecules() {
            for bond in molecule.bonds() {
                try!(topology.add_bond(bond.i() as u64, bond.j() as u64));
            }
        }

        try!(frame.set_topology(&topology));
        // Guessing angles and dihedrals
        try!(frame.guess_topology(false));

        let cell = try!(self.cell().to_chemfiles());
        try!(frame.set_cell(&cell));
        Ok(frame)
    }
}

/// Convert an `Universe` to a chemfiles `Frame`
pub fn universe_to_frame(universe: &Universe) -> Result<chemfiles::Frame, Error> {
    universe.to_chemfiles()
}
<commit_msg>Update chemfiles interface<commit_after>/* Cymbalum, Molecular Simulation in Rust - Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 */

//! [Chemfiles](https://github.com/chemfiles/chemfiles/) adaptators for Cymbalum.

extern crate chemfiles;
use universe::{Particle, Universe};
use universe::cells::{UnitCell, CellType};
use types::Vector3D;

use self::chemfiles::Error;

/// Convert chemfiles types to Cymbalum types
trait ToCymbalum {
    /// Output type
    type Output;
    /// Conversion function
    fn to_cymbalum(self) -> Result<Self::Output, Error>;
}

impl ToCymbalum for chemfiles::Atom {
    type Output = Particle;
    fn to_cymbalum(self) -> Result<Particle, Error> {
        let name = try!(self.name());
        let mut part = Particle::new(name);
        let mass = try!(self.mass());
        part.mass = mass as f64;
        Ok(part)
    }
}

impl ToCymbalum for chemfiles::UnitCell {
    type Output = UnitCell;
    fn to_cymbalum(self) -> Result<UnitCell, Error> {
        let cell_type = try!(self.cell_type());
        let cell = match cell_type {
            chemfiles::CellType::Infinite => UnitCell::new(),
            chemfiles::CellType::Orthorombic => {
                let (a, b, c) = try!(self.lengths());
                UnitCell::ortho(a, b, c)
            },
            chemfiles::CellType::Triclinic => {
                let (a, b, c) = try!(self.lengths());
                let (alpha, beta, gamma) = try!(self.angles());
                UnitCell::triclinic(a, b, c, alpha, beta, gamma)
            }
        };
        Ok(cell)
    }
}

impl ToCymbalum for chemfiles::Frame {
    type Output = Universe;
    fn to_cymbalum(self) -> Result<Universe, Error> {
        let cell = try!(self.cell());
        let cell = try!(cell.to_cymbalum());
        let mut universe = Universe::from_cell(cell);
        let topology = try!(self.topology());
        let positions = try!(self.positions());
        let natoms = try!(self.natoms());
        let step = try!(self.step());

        universe.set_step(step as u64);

        for i in 0..natoms {
            let atom = try!(topology.atom(i));
            let particle = try!(atom.to_cymbalum());

            universe.add_particle(particle);
            let position = Vector3D::new(
                positions[i][0] as f64,
                positions[i][1] as f64,
                positions[i][2] as f64
            );
            universe[i].position = position;
        }

        let mut bonds = try!(topology.bonds());
        while !bonds.is_empty() {
            let bond = bonds.pop().unwrap();
            if let Some(perms) = universe.add_bond(bond[0] as usize, bond[1] as usize) {
                apply_particle_permutation(&mut bonds, perms);
            }
        }
        Ok(universe)
    }
}

fn apply_particle_permutation(bonds: &mut Vec<[usize; 2]>, perms: Vec<(usize, usize)>) {
    'bonds: for bond in bonds {
        for perm in &perms {
            if bond[0] == perm.0 {
                bond[0] = perm.1;
                continue 'bonds;
            } else if bond[1] == perm.0 {
                bond[1] = perm.1;
                continue 'bonds;
            }
        }
    }
}

/// Convert a chemfiles `Frame` to an `Universe`
pub fn frame_to_universe(frame: chemfiles::Frame) -> Result<Universe, Error> {
    frame.to_cymbalum()
}

/******************************************************************************/

/// Convert Cymbalum types to chemfiles types
trait ToChemfiles {
    /// Output type
    type Output;
    /// Conversion function
    fn to_chemfiles(&self) -> Result<Self::Output, Error>;
}

impl ToChemfiles for Particle {
    type Output = chemfiles::Atom;
    fn to_chemfiles(&self) -> Result<chemfiles::Atom, Error> {
        let mut res = try!(chemfiles::Atom::new(self.name()));
        try!(res.set_mass(self.mass as f32));
        return Ok(res);
    }
}

impl ToChemfiles for UnitCell {
    type Output = chemfiles::UnitCell;
    fn to_chemfiles(&self) -> Result<chemfiles::UnitCell, Error> {
        let res = match self.celltype() {
            CellType::Infinite => {
                unimplemented!()
            }
            CellType::Orthorombic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                try!(chemfiles::UnitCell::new(a, b, c))
            },
            CellType::Triclinic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                let (alpha, beta, gamma) = (self.alpha(), self.beta(), self.gamma());
                try!(chemfiles::UnitCell::triclinic(a, b, c, alpha, beta, gamma))
            },
        };
        return Ok(res);
    }
}

impl ToChemfiles for Universe {
    type Output = chemfiles::Frame;
    fn to_chemfiles(&self) -> Result<chemfiles::Frame, Error> {

        let natoms = self.size();
        let mut frame = try!(chemfiles::Frame::new(natoms));

        try!(frame.set_step(self.step() as usize));

        let mut topology = try!(chemfiles::Topology::new());
        let mut positions = vec![[0.0f32; 3]; natoms];
        let mut velocities = vec![[0.0f32; 3]; natoms];

        for (i, p) in self.iter().enumerate() {
            let pos = p.position;
            positions[i][0] = pos.x as f32;
            positions[i][1] = pos.y as f32;
            positions[i][2] = pos.z as f32;

            let vel = p.velocity;
            velocities[i][0] = vel.x as f32;
            velocities[i][1] = vel.y as f32;
            velocities[i][2] = vel.z as f32;

            let atom = try!(p.to_chemfiles());
            try!(topology.push(&atom));
        }
        try!(frame.set_positions(positions));
        try!(frame.set_velocities(velocities));

        for molecule in self.molecules() {
            for bond in molecule.bonds() {
                try!(topology.add_bond(bond.i(), bond.j()));
            }
        }

        try!(frame.set_topology(&topology));
        // Guessing angles and dihedrals
        try!(frame.guess_topology(false));

        let cell = try!(self.cell().to_chemfiles());
        try!(frame.set_cell(&cell));
        Ok(frame)
    }
}

/// Convert an `Universe` to a chemfiles `Frame`
pub fn universe_to_frame(universe: &Universe) -> Result<chemfiles::Frame, Error> {
    universe.to_chemfiles()
}
<|endoftext|>


<commit_before>use super::unsupported;
use crate::ffi::CStr;
use crate::io;
use crate::num::NonZeroUsize;
use crate::sys::unsupported;
use crate::time::Duration;

pub struct Thread(!);

pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;

impl Thread {
    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
        unsupported()
    }

    pub fn yield_now() {}

    pub fn set_name(_name: &CStr) {}

    pub fn sleep(dur: Duration) {
        use crate::arch::wasm32;
        use crate::cmp;

        // Use an atomic wait to block the current thread artificially with a
        // timeout listed. Note that we should never be notified (return value
        // of 0) or our comparison should never fail (return value of 1) so we
        // should always only resume execution through a timeout (return value
        // 2).
        let mut nanos = dur.as_nanos();
        while nanos > 0 {
            let amt = cmp::min(i64::MAX as u128, nanos);
            let mut x = 0;
            let val = unsafe { wasm32::memory_atomic_wait32(&mut x, 0, amt as i64) };
            debug_assert_eq!(val, 2);
            nanos -= amt;
        }
    }

    pub fn join(self) {}
}

pub fn available_concurrency() -> io::Result<NonZeroUsize> {
    unsupported()
}

pub mod guard {
    pub type Guard = !;
    pub unsafe fn current() -> Option<Guard> {
        None
    }
    pub unsafe fn init() -> Option<Guard> {
        None
    }
}

// We currently just use our own thread-local to store our
// current thread's ID, and then we lazily initialize it to something allocated
// from a global counter.
pub fn my_id() -> u32 {
    use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};

    static NEXT_ID: AtomicU32 = AtomicU32::new(0);

    #[thread_local]
    static mut MY_ID: u32 = 0;

    unsafe {
        // If our thread ID isn't set yet then we need to allocate one. Do so
        // with with a simple "atomically add to a global counter" strategy.
        // This strategy doesn't handled what happens when the counter
        // overflows, however, so just abort everything once the counter
        // overflows and eventually we could have some sort of recycling scheme
        // (or maybe this is all totally irrelevant by that point!). In any case
        // though we're using a CAS loop instead of a `fetch_add` to ensure that
        // the global counter never overflows.
        if MY_ID == 0 {
            let mut cur = NEXT_ID.load(SeqCst);
            MY_ID = loop {
                let next = cur.checked_add(1).unwrap_or_else(|| crate::process::abort());
                match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
                    Ok(_) => break next,
                    Err(i) => cur = i,
                }
            };
        }
        MY_ID
    }
}
<commit_msg>Rollup merge of #86807 - tversteeg:patch-1, r=bjorn3<commit_after>use crate::ffi::CStr;
use crate::io;
use crate::num::NonZeroUsize;
use crate::sys::unsupported;
use crate::time::Duration;

pub struct Thread(!);

pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;

impl Thread {
    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
        unsupported()
    }

    pub fn yield_now() {}

    pub fn set_name(_name: &CStr) {}

    pub fn sleep(dur: Duration) {
        use crate::arch::wasm32;
        use crate::cmp;

        // Use an atomic wait to block the current thread artificially with a
        // timeout listed. Note that we should never be notified (return value
        // of 0) or our comparison should never fail (return value of 1) so we
        // should always only resume execution through a timeout (return value
        // 2).
        let mut nanos = dur.as_nanos();
        while nanos > 0 {
            let amt = cmp::min(i64::MAX as u128, nanos);
            let mut x = 0;
            let val = unsafe { wasm32::memory_atomic_wait32(&mut x, 0, amt as i64) };
            debug_assert_eq!(val, 2);
            nanos -= amt;
        }
    }

    pub fn join(self) {}
}

pub fn available_concurrency() -> io::Result<NonZeroUsize> {
    unsupported()
}

pub mod guard {
    pub type Guard = !;
    pub unsafe fn current() -> Option<Guard> {
        None
    }
    pub unsafe fn init() -> Option<Guard> {
        None
    }
}

// We currently just use our own thread-local to store our
// current thread's ID, and then we lazily initialize it to something allocated
// from a global counter.
pub fn my_id() -> u32 {
    use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};

    static NEXT_ID: AtomicU32 = AtomicU32::new(0);

    #[thread_local]
    static mut MY_ID: u32 = 0;

    unsafe {
        // If our thread ID isn't set yet then we need to allocate one. Do so
        // with with a simple "atomically add to a global counter" strategy.
        // This strategy doesn't handled what happens when the counter
        // overflows, however, so just abort everything once the counter
        // overflows and eventually we could have some sort of recycling scheme
        // (or maybe this is all totally irrelevant by that point!). In any case
        // though we're using a CAS loop instead of a `fetch_add` to ensure that
        // the global counter never overflows.
        if MY_ID == 0 {
            let mut cur = NEXT_ID.load(SeqCst);
            MY_ID = loop {
                let next = cur.checked_add(1).unwrap_or_else(|| crate::process::abort());
                match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
                    Ok(_) => break next,
                    Err(i) => cur = i,
                }
            };
        }
        MY_ID
    }
}
<|endoftext|>


<commit_before>use crate::consts::{
    constant, Constant,
    Constant::{F32, F64},
};
use crate::utils::*;
use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability;
use rustc_hir::*;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::f32::consts as f32_consts;
use std::f64::consts as f64_consts;
use sugg::Sugg;
use syntax::ast;

declare_clippy_lint! {
    /// **What it does:** Looks for floating-point expressions that
    /// can be expressed using built-in methods to improve both
    /// accuracy and performance.
    ///
    /// **Why is this bad?** Negatively impacts accuracy and performance.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    ///
    /// ```rust
    /// use std::f32::consts::E;
    ///
    /// let a = 3f32;
    /// let _ = (2f32).powf(a);
    /// let _ = E.powf(a);
    /// let _ = a.powf(1.0 / 2.0);
    /// let _ = a.powf(1.0 / 3.0);
    /// let _ = a.log(2.0);
    /// let _ = a.log(10.0);
    /// let _ = a.log(E);
    /// let _ = (1.0 + a).ln();
    /// let _ = a.exp() - 1.0;
    /// let _ = a.powf(2.0);
    /// ```
    ///
    /// is better expressed as
    ///
    /// ```rust
    /// use std::f32::consts::E;
    ///
    /// let a = 3f32;
    /// let _ = a.exp2();
    /// let _ = a.exp();
    /// let _ = a.sqrt();
    /// let _ = a.cbrt();
    /// let _ = a.log2();
    /// let _ = a.log10();
    /// let _ = a.ln();
    /// let _ = a.ln_1p();
    /// let _ = a.exp_m1();
    /// let _ = a.powi(2);
    /// ```
    pub SUBOPTIMAL_FLOPS,
    nursery,
    "usage of sub-optimal floating point operations"
}

declare_lint_pass!(FloatingPointArithmetic => [SUBOPTIMAL_FLOPS]);

// Returns the specialized log method for a given base if base is constant
// and is one of 2, 10 and e
fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Option<&'static str> {
    if let Some((value, _)) = constant(cx, cx.tables, base) {
        if F32(2.0) == value || F64(2.0) == value {
            return Some("log2");
        } else if F32(10.0) == value || F64(10.0) == value {
            return Some("log10");
        } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
            return Some("ln");
        }
    }

    None
}

// Adds type suffixes and parenthesis to method receivers if necessary
fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) -> Sugg<'a> {
    let mut suggestion = Sugg::hir(cx, expr, "..");

    if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind {
        expr = &inner_expr;
    }

    if_chain! {
        // if the expression is a float literal and it is unsuffixed then
        // add a suffix so the suggestion is valid and unambiguous
        if let ty::Float(float_ty) = cx.tables.expr_ty(expr).kind;
        if let ExprKind::Lit(lit) = &expr.kind;
        if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
        then {
            let op = format!(
                "{}{}{}",
                suggestion,
                // Check for float literals without numbers following the decimal
                // separator such as `2.` and adds a trailing zero
                if sym.as_str().ends_with('.') {
                    "0"
                } else {
                    ""
                },
                float_ty.name_str()
            ).into();

            suggestion = match suggestion {
                Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
                _ => Sugg::NonParen(op)
            };
        }
    }

    suggestion.maybe_par()
}

fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
    if let Some(method) = get_specialized_log_method(cx, &args[1]) {
        span_lint_and_sugg(
            cx,
            SUBOPTIMAL_FLOPS,
            expr.span,
            "logarithm for bases 2, 10 and e can be computed more accurately",
            "consider using",
            format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method),
            Applicability::MachineApplicable,
        );
    }
}

// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
// suggest usage of `(x + (y - 1)).ln_1p()` instead
fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
    if_chain! {
        if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind;
        if op.node == BinOpKind::Add;
        then {
            let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) {
                (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
                (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
                _ => return,
            };

            span_lint_and_sugg(
                cx,
                SUBOPTIMAL_FLOPS,
                expr.span,
                "ln(1 + x) can be computed more accurately",
                "consider using",
                format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)),
                Applicability::MachineApplicable,
            );
        }
    }
}

// Returns an integer if the float constant is a whole number and it
// can be converted to an integer without loss
// TODO: Add a better check to determine whether the float can be
// casted without loss
#[allow(clippy::cast_possible_truncation)]
fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
    match value {
        F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => {
            if *num > -16_777_217.0 && *num < 16_777_217.0 {
                Some(num.round() as i64)
            } else {
                None
            }
        },
        F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => {
            if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 {
                Some(num.round() as i64)
            } else {
                None
            }
        },
        _ => None,
    }
}

fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
    // Check receiver
    if let Some((value, _)) = constant(cx, cx.tables, &args[0]) {
        let method;

        if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
            method = "exp";
        } else if F32(2.0) == value || F64(2.0) == value {
            method = "exp2";
        } else {
            return;
        }

        span_lint_and_sugg(
            cx,
            SUBOPTIMAL_FLOPS,
            expr.span,
            "exponent for bases 2 and e can be computed more accurately",
            "consider using",
            format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method),
            Applicability::MachineApplicable,
        );
    }

    // Check argument
    if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
        let help;
        let method;

        if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
            help = "square-root of a number can be computed more efficiently and accurately";
            method = "sqrt";
        } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
            help = "cube-root of a number can be computed more accurately";
            method = "cbrt";
        } else if let Some(exponent) = get_integer_from_float_constant(&value) {
            span_lint_and_sugg(
                cx,
                SUBOPTIMAL_FLOPS,
                expr.span,
                "exponentiation with integer powers can be computed more efficiently",
                "consider using",
                format!("{}.powi({})", Sugg::hir(cx, &args[0], ".."), exponent),
                Applicability::MachineApplicable,
            );

            return;
        } else {
            return;
        }

        span_lint_and_sugg(
            cx,
            SUBOPTIMAL_FLOPS,
            expr.span,
            help,
            "consider using",
            format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method),
            Applicability::MachineApplicable,
        );
    }
}

// TODO: Lint expressions of the form `x.exp() - y` where y > 1
// and suggest usage of `x.exp_m1() - (y - 1)` instead
fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    if_chain! {
        if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind;
        if op.node == BinOpKind::Sub;
        if cx.tables.expr_ty(lhs).is_floating_point();
        if let Some((value, _)) = constant(cx, cx.tables, rhs);
        if F32(1.0) == value || F64(1.0) == value;
        if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind;
        if cx.tables.expr_ty(&method_args[0]).is_floating_point();
        if path.ident.name.as_str() == "exp";
        then {
            span_lint_and_sugg(
                cx,
                SUBOPTIMAL_FLOPS,
                expr.span,
                "(e.pow(x) - 1) can be computed more accurately",
                "consider using",
                format!(
                    "{}.exp_m1()",
                    Sugg::hir(cx, &method_args[0], "..")
                ),
                Applicability::MachineApplicable,
            );
        }
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
            let recv_ty = cx.tables.expr_ty(&args[0]);

            if recv_ty.is_floating_point() {
                match &*path.ident.name.as_str() {
                    "ln" => check_ln1p(cx, expr, args),
                    "log" => check_log_base(cx, expr, args),
                    "powf" => check_powf(cx, expr, args),
                    _ => {},
                }
            }
        } else {
            check_expm1(cx, expr);
        }
    }
}
<commit_msg>Fix `powi` suggestion and add general improvements<commit_after>use crate::consts::{
    constant, Constant,
    Constant::{F32, F64},
};
use crate::utils::*;
use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability;
use rustc_hir::*;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::f32::consts as f32_consts;
use std::f64::consts as f64_consts;
use sugg::{format_numeric_literal, Sugg};
use syntax::ast;

declare_clippy_lint! {
    /// **What it does:** Looks for floating-point expressions that
    /// can be expressed using built-in methods to improve both
    /// accuracy and performance.
    ///
    /// **Why is this bad?** Negatively impacts accuracy and performance.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    ///
    /// ```rust
    /// use std::f32::consts::E;
    ///
    /// let a = 3f32;
    /// let _ = (2f32).powf(a);
    /// let _ = E.powf(a);
    /// let _ = a.powf(1.0 / 2.0);
    /// let _ = a.powf(1.0 / 3.0);
    /// let _ = a.log(2.0);
    /// let _ = a.log(10.0);
    /// let _ = a.log(E);
    /// let _ = (1.0 + a).ln();
    /// let _ = a.exp() - 1.0;
    /// let _ = a.powf(2.0);
    /// ```
    ///
    /// is better expressed as
    ///
    /// ```rust
    /// use std::f32::consts::E;
    ///
    /// let a = 3f32;
    /// let _ = a.exp2();
    /// let _ = a.exp();
    /// let _ = a.sqrt();
    /// let _ = a.cbrt();
    /// let _ = a.log2();
    /// let _ = a.log10();
    /// let _ = a.ln();
    /// let _ = a.ln_1p();
    /// let _ = a.exp_m1();
    /// let _ = a.powi(2);
    /// ```
    pub SUBOPTIMAL_FLOPS,
    nursery,
    "usage of sub-optimal floating point operations"
}

declare_lint_pass!(FloatingPointArithmetic => [SUBOPTIMAL_FLOPS]);

// Returns the specialized log method for a given base if base is constant
// and is one of 2, 10 and e
fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Option<&'static str> {
    if let Some((value, _)) = constant(cx, cx.tables, base) {
        if F32(2.0) == value || F64(2.0) == value {
            return Some("log2");
        } else if F32(10.0) == value || F64(10.0) == value {
            return Some("log10");
        } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
            return Some("ln");
        }
    }

    None
}

// Adds type suffixes and parenthesis to method receivers if necessary
fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) -> Sugg<'a> {
    let mut suggestion = Sugg::hir(cx, expr, "..");

    if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind {
        expr = &inner_expr;
    }

    if_chain! {
        // if the expression is a float literal and it is unsuffixed then
        // add a suffix so the suggestion is valid and unambiguous
        if let ty::Float(float_ty) = cx.tables.expr_ty(expr).kind;
        if let ExprKind::Lit(lit) = &expr.kind;
        if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
        then {
            let op = format!(
                "{}{}{}",
                suggestion,
                // Check for float literals without numbers following the decimal
                // separator such as `2.` and adds a trailing zero
                if sym.as_str().ends_with('.') {
                    "0"
                } else {
                    ""
                },
                float_ty.name_str()
            ).into();

            suggestion = match suggestion {
                Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
                _ => Sugg::NonParen(op)
            };
        }
    }

    suggestion.maybe_par()
}

fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
    if let Some(method) = get_specialized_log_method(cx, &args[1]) {
        span_lint_and_sugg(
            cx,
            SUBOPTIMAL_FLOPS,
            expr.span,
            "logarithm for bases 2, 10 and e can be computed more accurately",
            "consider using",
            format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method),
            Applicability::MachineApplicable,
        );
    }
}

// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
// suggest usage of `(x + (y - 1)).ln_1p()` instead
fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
    if_chain! {
        if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind;
        if op.node == BinOpKind::Add;
        then {
            let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) {
                (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
                (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
                _ => return,
            };

            span_lint_and_sugg(
                cx,
                SUBOPTIMAL_FLOPS,
                expr.span,
                "ln(1 + x) can be computed more accurately",
                "consider using",
                format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)),
                Applicability::MachineApplicable,
            );
        }
    }
}

// Returns an integer if the float constant is a whole number and it can be
// converted to an integer without loss of precision. For now we only check
// ranges [-16777215, 16777216) for type f32 as whole number floats outside
// this range are lossy and ambiguous.
#[allow(clippy::cast_possible_truncation)]
fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
    match value {
        F32(num) if num.fract() == 0.0 => {
            if (-16_777_215.0..16_777_216.0).contains(num) {
                Some(num.round() as i32)
            } else {
                None
            }
        },
        F64(num) if num.fract() == 0.0 => {
            if (-2_147_483_648.0..2_147_483_648.0).contains(num) {
                Some(num.round() as i32)
            } else {
                None
            }
        },
        _ => None,
    }
}

fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
    // Check receiver
    if let Some((value, _)) = constant(cx, cx.tables, &args[0]) {
        let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
            "exp"
        } else if F32(2.0) == value || F64(2.0) == value {
            "exp2"
        } else {
            return;
        };

        span_lint_and_sugg(
            cx,
            SUBOPTIMAL_FLOPS,
            expr.span,
            "exponent for bases 2 and e can be computed more accurately",
            "consider using",
            format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method),
            Applicability::MachineApplicable,
        );
    }

    // Check argument
    if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
        let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
            (
                "square-root of a number can be computed more efficiently and accurately",
                format!("{}.sqrt()", Sugg::hir(cx, &args[0], ".."))
            )
        } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
            (
                "cube-root of a number can be computed more accurately",
                format!("{}.cbrt()", Sugg::hir(cx, &args[0], ".."))
            )
        } else if let Some(exponent) = get_integer_from_float_constant(&value) {
            (
                "exponentiation with integer powers can be computed more efficiently",
                format!(
                    "{}.powi({})",
                    Sugg::hir(cx, &args[0], ".."),
                    format_numeric_literal(&exponent.to_string(), None, false)
                )
            )
        } else {
            return;
        };

        span_lint_and_sugg(
            cx,
            SUBOPTIMAL_FLOPS,
            expr.span,
            help,
            "consider using",
            suggestion,
            Applicability::MachineApplicable,
        );
    }
}

// TODO: Lint expressions of the form `x.exp() - y` where y > 1
// and suggest usage of `x.exp_m1() - (y - 1)` instead
fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
    if_chain! {
        if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind;
        if op.node == BinOpKind::Sub;
        if cx.tables.expr_ty(lhs).is_floating_point();
        if let Some((value, _)) = constant(cx, cx.tables, rhs);
        if F32(1.0) == value || F64(1.0) == value;
        if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind;
        if cx.tables.expr_ty(&method_args[0]).is_floating_point();
        if path.ident.name.as_str() == "exp";
        then {
            span_lint_and_sugg(
                cx,
                SUBOPTIMAL_FLOPS,
                expr.span,
                "(e.pow(x) - 1) can be computed more accurately",
                "consider using",
                format!(
                    "{}.exp_m1()",
                    Sugg::hir(cx, &method_args[0], "..")
                ),
                Applicability::MachineApplicable,
            );
        }
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
            let recv_ty = cx.tables.expr_ty(&args[0]);

            if recv_ty.is_floating_point() {
                match &*path.ident.name.as_str() {
                    "ln" => check_ln1p(cx, expr, args),
                    "log" => check_log_base(cx, expr, args),
                    "powf" => check_powf(cx, expr, args),
                    _ => {},
                }
            }
        } else {
            check_expm1(cx, expr);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fmt::{self, Debug};
use std::sync::{Condvar as StdCondvar, MutexGuard, WaitTimeoutResult};
use std::time::Duration;

static CONDVAR_POISONED: &str = "condvar is poisoned";

/// A Condition Variable.
#[derive(Default)]
pub struct Condvar {
    std: StdCondvar,
}

impl Condvar {
    /// Creates a new condvar that is ready to be waited on.
    pub fn new() -> Condvar {
        Condvar {
            std: StdCondvar::new(),
        }
    }

    /// Waits on a condvar, blocking the current thread until it is notified.
    pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
        self.std.wait(guard).expect(CONDVAR_POISONED)
    }

    /// Blocks the current thread until this condition variable receives a notification and the
    /// provided condition is false.
    pub fn wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T>
    where
        F: FnMut(&mut T) -> bool,
    {
        self.std
            .wait_while(guard, condition)
            .expect(CONDVAR_POISONED)
    }

    /// Waits on a condvar, blocking the current thread until it is notified
    /// or the specified duration has elapsed.
    pub fn wait_timeout<'a, T>(
        &self,
        guard: MutexGuard<'a, T>,
        dur: Duration,
    ) -> (MutexGuard<'a, T>, WaitTimeoutResult) {
        self.std.wait_timeout(guard, dur).expect(CONDVAR_POISONED)
    }

    /// Waits on this condition variable for a notification, timing out after a specified duration.
    pub fn wait_timeout_while<'a, T, F>(
        &self,
        guard: MutexGuard<'a, T>,
        dur: Duration,
        condition: F,
    ) -> (MutexGuard<'a, T>, WaitTimeoutResult)
    where
        F: FnMut(&mut T) -> bool,
    {
        self.std
            .wait_timeout_while(guard, dur, condition)
            .expect(CONDVAR_POISONED)
    }

    /// Waits on a condvar, blocking the current thread until it is notified and
    /// the provided condition is false.
    pub fn wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T>
    where
        F: FnMut(&mut T) -> bool,
    {
        match self.std.wait_while(guard, condition) {
            Ok(result) => result,
            Err(_) => panic!("condvar is poisoned"),
        }
    }

    /// Waits on a condvar, blocking the current thread until it is notified and
    /// the provided condition is false, or until the specified duration has elapsed.
    pub fn wait_timeout_while<'a, T, F>(
        &self,
        guard: MutexGuard<'a, T>,
        dur: Duration,
        condition: F,
    ) -> (MutexGuard<'a, T>, WaitTimeoutResult)
    where
        F: FnMut(&mut T) -> bool,
    {
        match self.std.wait_timeout_while(guard, dur, condition) {
            Ok(result) => result,
            Err(_) => panic!("condvar is poisoned"),
        }
    }

    /// Notifies one thread blocked by this condvar.
    pub fn notify_one(&self) {
        self.std.notify_one();
    }

    /// Notifies all threads blocked by this condvar.
    pub fn notify_all(&self) {
        self.std.notify_all();
    }
}

impl Debug for Condvar {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.std, formatter)
    }
}
<commit_msg>Revert "sync: Add wait_while variants to condvar wrapper"<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fmt::{self, Debug};
use std::sync::{Condvar as StdCondvar, MutexGuard, WaitTimeoutResult};
use std::time::Duration;

static CONDVAR_POISONED: &str = "condvar is poisoned";

/// A Condition Variable.
#[derive(Default)]
pub struct Condvar {
    std: StdCondvar,
}

impl Condvar {
    /// Creates a new condvar that is ready to be waited on.
    pub fn new() -> Condvar {
        Condvar {
            std: StdCondvar::new(),
        }
    }

    /// Waits on a condvar, blocking the current thread until it is notified.
    pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
        self.std.wait(guard).expect(CONDVAR_POISONED)
    }

    /// Blocks the current thread until this condition variable receives a notification and the
    /// provided condition is false.
    pub fn wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T>
    where
        F: FnMut(&mut T) -> bool,
    {
        self.std
            .wait_while(guard, condition)
            .expect(CONDVAR_POISONED)
    }

    /// Waits on a condvar, blocking the current thread until it is notified
    /// or the specified duration has elapsed.
    pub fn wait_timeout<'a, T>(
        &self,
        guard: MutexGuard<'a, T>,
        dur: Duration,
    ) -> (MutexGuard<'a, T>, WaitTimeoutResult) {
        self.std.wait_timeout(guard, dur).expect(CONDVAR_POISONED)
    }

    /// Waits on this condition variable for a notification, timing out after a specified duration.
    pub fn wait_timeout_while<'a, T, F>(
        &self,
        guard: MutexGuard<'a, T>,
        dur: Duration,
        condition: F,
    ) -> (MutexGuard<'a, T>, WaitTimeoutResult)
    where
        F: FnMut(&mut T) -> bool,
    {
        self.std
            .wait_timeout_while(guard, dur, condition)
            .expect(CONDVAR_POISONED)
    }

    /// Notifies one thread blocked by this condvar.
    pub fn notify_one(&self) {
        self.std.notify_one();
    }

    /// Notifies all threads blocked by this condvar.
    pub fn notify_all(&self) {
        self.std.notify_all();
    }
}

impl Debug for Condvar {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.std, formatter)
    }
}
<|endoftext|>


<commit_before>use askama_shared::{Config, Syntax};

use std::path::PathBuf;

use quote::ToTokens;
use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub config: &'a Config<'a>,
    pub syntax: &'a Syntax<'a>,
    pub source: Source,
    pub print: Print,
    pub escaper: &'a str,
    pub ext: Option<String>,
    pub parent: Option<&'a syn::Type>,
    pub path: PathBuf,
}

impl<'a> TemplateInput<'a> {
    /// Extract the template metadata from the `DeriveInput` structure. This
    /// mostly recovers the data for the `TemplateInput` fields from the
    /// `template()` attribute list fields; it also finds the of the `_parent`
    /// field, if any.
    pub fn new<'n>(ast: &'n syn::DeriveInput, config: &'n Config) -> TemplateInput<'n> {
        // Check that an attribute called `template()` exists and that it is
        // the proper type (list).
        let meta = ast
            .attrs
            .iter()
            .find_map(|attr| match attr.parse_meta() {
                Ok(m) => {
                    if m.path().is_ident("template") {
                        Some(m)
                    } else {
                        None
                    }
                }
                Err(e) => panic!("unable to parse attribute: {}", e),
            })
            .expect("no attribute 'template' found");

        let meta_list = match meta {
            syn::Meta::List(inner) => inner,
            _ => panic!("attribute 'template' has incorrect type"),
        };

        // Loop over the meta attributes and find everything that we
        // understand. Raise panics if something is not right.
        // `source` contains an enum that can represent `path` or `source`.
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        let mut syntax = None;
        for item in meta_list.nested {
            if let syn::NestedMeta::Meta(syn::Meta::NameValue(ref pair)) = item {
                if pair.path.is_ident("path") {
                    if let syn::Lit::Str(ref s) = pair.lit {
                        if source.is_some() {
                            panic!("must specify 'source' or 'path', not both");
                        }
                        source = Some(Source::Path(s.value()));
                    } else {
                        panic!("template path must be string literal");
                    }
                } else if pair.path.is_ident("source") {
                    if let syn::Lit::Str(ref s) = pair.lit {
                        if source.is_some() {
                            panic!("must specify 'source' or 'path', not both");
                        }
                        source = Some(Source::Source(s.value()));
                    } else {
                        panic!("template source must be string literal");
                    }
                } else if pair.path.is_ident("print") {
                    if let syn::Lit::Str(ref s) = pair.lit {
                        print = s.value().into();
                    } else {
                        panic!("print value must be string literal");
                    }
                } else if pair.path.is_ident("escape") {
                    if let syn::Lit::Str(ref s) = pair.lit {
                        escaping = Some(s.value());
                    } else {
                        panic!("escape value must be string literal");
                    }
                } else if pair.path.is_ident("ext") {
                    if let syn::Lit::Str(ref s) = pair.lit {
                        ext = Some(s.value());
                    } else {
                        panic!("ext value must be string literal");
                    }
                } else if pair.path.is_ident("syntax") {
                    if let syn::Lit::Str(ref s) = pair.lit {
                        syntax = Some(s.value())
                    } else {
                        panic!("syntax value must be string literal");
                    }
                } else {
                    panic!("unsupported attribute key '{}' found", pair.path.to_token_stream())
                }
            }
        }

        // Validate the `source` and `ext` value together, since they are
        // related. In case `source` was used instead of `path`, the value
        // of `ext` is merged into a synthetic `path` value here.
        let source = source.expect("template path or source not found in attributes");
        let path = match (&source, &ext) {
            (&Source::Path(ref path), None) => config.find_template(path, None),
            (&Source::Source(_), Some(ext)) => PathBuf::from(format!("{}.{}", ast.ident, ext)),
            (&Source::Path(_), Some(_)) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            }
            (&Source::Source(_), None) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            }
        };

        // Check to see if a `_parent` field was defined on the context
        // struct, and store the type for it for use in the code generator.
        let parent = match ast.data {
            syn::Data::Struct(syn::DataStruct {
                fields: syn::Fields::Named(ref fields),
                ..
            }) => fields
                .named
                .iter()
                .find(|f| f.ident.as_ref().filter(|name| *name == "_parent").is_some())
                .map(|f| &f.ty),
            _ => None,
        };

        if parent.is_some() {
            eprint!(
                "   --> in struct {}\n   = use of deprecated field '_parent'\n",
                ast.ident
            );
        }

        // Validate syntax
        let syntax = syntax.map_or_else(
            || config.syntaxes.get(config.default_syntax).unwrap(),
            |s| {
                config
                    .syntaxes
                    .get(&s)
                    .expect(&format!("attribute syntax {} not exist", s))
            },
        );

        // Match extension against defined output formats

        let extension = escaping.unwrap_or_else(|| {
            path.extension()
                .map(|s| s.to_str().unwrap())
                .unwrap_or("")
                .to_string()
        });

        let mut escaper = None;
        for (extensions, path) in &config.escapers {
            if extensions.contains(&extension) {
                escaper = Some(path);
                break;
            }
        }

        let escaper = escaper.unwrap_or_else(|| {
            panic!("no escaper defined for extension '{}'", extension);
        });

        TemplateInput {
            ast,
            config,
            source,
            print,
            escaper,
            ext,
            parent,
            path,
            syntax,
        }
    }
}

pub enum Source {
    Path(String),
    Source(String),
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl From<String> for Print {
    fn from(s: String) -> Print {
        use self::Print::*;
        match s.as_ref() {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}
<commit_msg>Prevent rightward drift in attribute interpretation code<commit_after>use askama_shared::{Config, Syntax};

use std::path::PathBuf;

use quote::ToTokens;
use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub config: &'a Config<'a>,
    pub syntax: &'a Syntax<'a>,
    pub source: Source,
    pub print: Print,
    pub escaper: &'a str,
    pub ext: Option<String>,
    pub parent: Option<&'a syn::Type>,
    pub path: PathBuf,
}

impl<'a> TemplateInput<'a> {
    /// Extract the template metadata from the `DeriveInput` structure. This
    /// mostly recovers the data for the `TemplateInput` fields from the
    /// `template()` attribute list fields; it also finds the of the `_parent`
    /// field, if any.
    pub fn new<'n>(ast: &'n syn::DeriveInput, config: &'n Config) -> TemplateInput<'n> {
        // Check that an attribute called `template()` exists and that it is
        // the proper type (list).
        let meta = ast
            .attrs
            .iter()
            .find_map(|attr| match attr.parse_meta() {
                Ok(m) => {
                    if m.path().is_ident("template") {
                        Some(m)
                    } else {
                        None
                    }
                }
                Err(e) => panic!("unable to parse attribute: {}", e),
            })
            .expect("no attribute 'template' found");

        let meta_list = match meta {
            syn::Meta::List(inner) => inner,
            _ => panic!("attribute 'template' has incorrect type"),
        };

        // Loop over the meta attributes and find everything that we
        // understand. Raise panics if something is not right.
        // `source` contains an enum that can represent `path` or `source`.
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        let mut syntax = None;
        for item in meta_list.nested {
            let pair = match item {
                syn::NestedMeta::Meta(syn::Meta::NameValue(ref pair)) => pair,
                _ => panic!(
                    "unsupported attribute argument {:?}",
                    item.to_token_stream()
                ),
            };

            if pair.path.is_ident("path") {
                if let syn::Lit::Str(ref s) = pair.lit {
                    if source.is_some() {
                        panic!("must specify 'source' or 'path', not both");
                    }
                    source = Some(Source::Path(s.value()));
                } else {
                    panic!("template path must be string literal");
                }
            } else if pair.path.is_ident("source") {
                if let syn::Lit::Str(ref s) = pair.lit {
                    if source.is_some() {
                        panic!("must specify 'source' or 'path', not both");
                    }
                    source = Some(Source::Source(s.value()));
                } else {
                    panic!("template source must be string literal");
                }
            } else if pair.path.is_ident("print") {
                if let syn::Lit::Str(ref s) = pair.lit {
                    print = s.value().into();
                } else {
                    panic!("print value must be string literal");
                }
            } else if pair.path.is_ident("escape") {
                if let syn::Lit::Str(ref s) = pair.lit {
                    escaping = Some(s.value());
                } else {
                    panic!("escape value must be string literal");
                }
            } else if pair.path.is_ident("ext") {
                if let syn::Lit::Str(ref s) = pair.lit {
                    ext = Some(s.value());
                } else {
                    panic!("ext value must be string literal");
                }
            } else if pair.path.is_ident("syntax") {
                if let syn::Lit::Str(ref s) = pair.lit {
                    syntax = Some(s.value())
                } else {
                    panic!("syntax value must be string literal");
                }
            } else {
                panic!(
                    "unsupported attribute key '{}' found",
                    pair.path.to_token_stream()
                )
            }
        }

        // Validate the `source` and `ext` value together, since they are
        // related. In case `source` was used instead of `path`, the value
        // of `ext` is merged into a synthetic `path` value here.
        let source = source.expect("template path or source not found in attributes");
        let path = match (&source, &ext) {
            (&Source::Path(ref path), None) => config.find_template(path, None),
            (&Source::Source(_), Some(ext)) => PathBuf::from(format!("{}.{}", ast.ident, ext)),
            (&Source::Path(_), Some(_)) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            }
            (&Source::Source(_), None) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            }
        };

        // Check to see if a `_parent` field was defined on the context
        // struct, and store the type for it for use in the code generator.
        let parent = match ast.data {
            syn::Data::Struct(syn::DataStruct {
                fields: syn::Fields::Named(ref fields),
                ..
            }) => fields
                .named
                .iter()
                .find(|f| f.ident.as_ref().filter(|name| *name == "_parent").is_some())
                .map(|f| &f.ty),
            _ => None,
        };

        if parent.is_some() {
            eprint!(
                "   --> in struct {}\n   = use of deprecated field '_parent'\n",
                ast.ident
            );
        }

        // Validate syntax
        let syntax = syntax.map_or_else(
            || config.syntaxes.get(config.default_syntax).unwrap(),
            |s| {
                config
                    .syntaxes
                    .get(&s)
                    .expect(&format!("attribute syntax {} not exist", s))
            },
        );

        // Match extension against defined output formats

        let extension = escaping.unwrap_or_else(|| {
            path.extension()
                .map(|s| s.to_str().unwrap())
                .unwrap_or("")
                .to_string()
        });

        let mut escaper = None;
        for (extensions, path) in &config.escapers {
            if extensions.contains(&extension) {
                escaper = Some(path);
                break;
            }
        }

        let escaper = escaper.unwrap_or_else(|| {
            panic!("no escaper defined for extension '{}'", extension);
        });

        TemplateInput {
            ast,
            config,
            source,
            print,
            escaper,
            ext,
            parent,
            path,
            syntax,
        }
    }
}

pub enum Source {
    Path(String),
    Source(String),
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl From<String> for Print {
    fn from(s: String) -> Print {
        use self::Print::*;
        match s.as_ref() {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use core::clock::*;
use backend::world;
use core::geometry::*;
use cgmath::Vector;

pub struct GameSystem {
	hourglass: Hourglass<SystemStopwatch>,
	to_spawn: usize,
	spawned: usize,
}

impl Updateable for GameSystem {
	fn update(&mut self, _: &world::WorldState, _: f32) {
		if self.hourglass.is_expired() {
			self.hourglass.flip();
			self.to_spawn += 1;
		}
	}
}

impl System for GameSystem {
	fn from_world(&mut self, _: &world::World) {
		self.spawned = self.to_spawn;
	}
	fn to_world(&self, world: &mut world::World) {
		for i in self.spawned..self.to_spawn {
			let r = 0.2 * i as f32;
			world.new_resource(Position::zero(),
			                   Some(Motion {
				                   velocity: Velocity::new(r.cos(), r.sin()),
				                   spin: 0.16,
			                   }));
		}
	}
}

impl Default for GameSystem {
	fn default() -> Self {
		GameSystem {
			hourglass: Hourglass::new(0.5),
			to_spawn: 0,
			spawned: 0,
		}
	}
}

impl GameSystem {}
<commit_msg>Initial speed, magic number!<commit_after>use super::*;
use core::clock::*;
use backend::world;
use core::geometry::*;
use cgmath::Vector;

pub struct GameSystem {
	hourglass: Hourglass<SystemStopwatch>,
	to_spawn: usize,
	spawned: usize,
}

impl Updateable for GameSystem {
	fn update(&mut self, _: &world::WorldState, _: f32) {
		if self.hourglass.is_expired() {
			self.hourglass.flip();
			self.to_spawn += 1;
		}
	}
}

impl System for GameSystem {
	fn from_world(&mut self, _: &world::World) {
		self.spawned = self.to_spawn;
	}
	fn to_world(&self, world: &mut world::World) {
		for i in self.spawned..self.to_spawn {
			let r = 0.2 * i as f32;
			world.new_resource(Position::zero(),
			                   Some(Motion {
				                   velocity: Velocity::new(r.cos(), r.sin()) * 5.,
				                   spin: 0.16,
			                   }));
		}
	}
}

impl Default for GameSystem {
	fn default() -> Self {
		GameSystem {
			hourglass: Hourglass::new(0.5),
			to_spawn: 0,
			spawned: 0,
		}
	}
}

impl GameSystem {}
<|endoftext|>


<commit_before>import std::{str, option, int, map};
import codemap::span;
import ast::*;

fn respan<copy T>(sp: span, t: T) -> spanned<T> {
    ret {node: t, span: sp};
}

fn new_node_hash<copy V>() -> map::hashmap<node_id, V> {
    fn node_id_hash(&&i: node_id) -> uint { ret int::hash(i as int); }
    fn node_id_eq(&&a: node_id, &&b: node_id) -> bool
        { ret int::eq(a as int, b as int); }
    ret map::mk_hashmap(node_id_hash, node_id_eq);
}

/* assuming that we're not in macro expansion */
fn mk_sp(lo: uint, hi: uint) -> span {
    ret {lo: lo, hi: hi, expanded_from: codemap::os_none};
}

// make this a const, once the compiler supports it
fn dummy_sp() -> span { ret mk_sp(0u, 0u); }

fn path_name(p: @path) -> str { path_name_i(p.node.idents) }

fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }

fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }

fn variant_def_ids(d: def) -> {tg: def_id, var: def_id} {
    alt d { def_variant(tag_id, var_id) { ret {tg: tag_id, var: var_id}; } }
}

fn def_id_of_def(d: def) -> def_id {
    alt d {
      def_fn(id, _) { ret id; }
      def_obj_field(id, _) { ret id; }
      def_mod(id) { ret id; }
      def_native_mod(id) { ret id; }
      def_const(id) { ret id; }
      def_arg(id, _) { ret id; }
      def_local(id, _) { ret id; }
      def_variant(_, id) { ret id; }
      def_ty(id) { ret id; }
      def_ty_param(_, _) { fail; }
      def_binding(id) { ret id; }
      def_use(id) { ret id; }
      def_native_ty(id) { ret id; }
      def_native_fn(id, _) { ret id; }
      def_upvar(id, _, _) { ret id; }
    }
}

type pat_id_map = std::map::hashmap<str, node_id>;

// This is used because same-named variables in alternative patterns need to
// use the node_id of their namesake in the first pattern.
fn pat_id_map(pat: @pat) -> pat_id_map {
    let map = std::map::new_str_hash::<node_id>();
    pat_bindings(pat) {|bound|
        let name = alt bound.node { pat_bind(n) { n } };
        map.insert(name, bound.id);
    };
    ret map;
}

// FIXME: could return a constrained type
fn pat_bindings(pat: @pat, it: block(@pat)) {
    alt pat.node {
      pat_bind(_) { it(pat); }
      pat_tag(_, sub) { for p in sub { pat_bindings(p, it); } }
      pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
      pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
      pat_box(sub) { pat_bindings(sub, it); }
      pat_uniq(sub) { pat_bindings(sub, it); }
      pat_wild. | pat_lit(_) | pat_range(_, _) { }
    }
}

fn pat_binding_ids(pat: @pat) -> [node_id] {
    let found = [];
    pat_bindings(pat) {|b| found += [b.id]; };
    ret found;
}

fn binop_to_str(op: binop) -> str {
    alt op {
      add. { ret "+"; }
      sub. { ret "-"; }
      mul. { ret "*"; }
      div. { ret "/"; }
      rem. { ret "%"; }
      and. { ret "&&"; }
      or. { ret "||"; }
      bitxor. { ret "^"; }
      bitand. { ret "&"; }
      bitor. { ret "|"; }
      lsl. { ret "<<"; }
      lsr. { ret ">>"; }
      asr. { ret ">>>"; }
      eq. { ret "=="; }
      lt. { ret "<"; }
      le. { ret "<="; }
      ne. { ret "!="; }
      ge. { ret ">="; }
      gt. { ret ">"; }
    }
}

pure fn lazy_binop(b: binop) -> bool {
    alt b { and. { true } or. { true } _ { false } }
}

fn unop_to_str(op: unop) -> str {
    alt op {
      box(mt) { if mt == mut { ret "@mutable "; } ret "@"; }
      uniq(mt) { if mt == mut { ret "~mutable "; } ret "~"; }
      deref. { ret "*"; }
      not. { ret "!"; }
      neg. { ret "-"; }
    }
}

fn is_path(e: @expr) -> bool {
    ret alt e.node { expr_path(_) { true } _ { false } };
}

fn ty_mach_to_str(tm: ty_mach) -> str {
    alt tm {
      ty_u8. { ret "u8"; }
      ty_u16. { ret "u16"; }
      ty_u32. { ret "u32"; }
      ty_u64. { ret "u64"; }
      ty_i8. { ret "i8"; }
      ty_i16. { ret "i16"; }
      ty_i32. { ret "i32"; }
      ty_i64. { ret "i64"; }
      ty_f32. { ret "f32"; }
      ty_f64. { ret "f64"; }
    }
}

fn is_exported(i: ident, m: _mod) -> bool {
    let nonlocal = true;
    for it: @item in m.items {
        if it.ident == i { nonlocal = false; }
        alt it.node {
          item_tag(variants, _) {
            for v: variant in variants {
                if v.node.name == i { nonlocal = false; }
            }
          }
          _ { }
        }
        if !nonlocal { break; }
    }
    let count = 0u;
    for vi: @view_item in m.view_items {
        alt vi.node {
          view_item_export(ids, _) {
            for id in ids { if str::eq(i, id) { ret true; } }
            count += 1u;
          }
          _ {/* fall through */ }
        }
    }
    // If there are no declared exports then
    // everything not imported is exported
    // even if it's nonlocal (since it's explicit)
    ret count == 0u && !nonlocal;
}

pure fn is_call_expr(e: @expr) -> bool {
    alt e.node { expr_call(_, _, _) { true } _ { false } }
}

pure fn is_tail_call_expr(e: @expr) -> bool {
    alt e.node {
      expr_call(_, _, _) { true }
      expr_cast(inner_e, _) { is_call_expr(inner_e) }
      _ { false }
    }
}

fn is_constraint_arg(e: @expr) -> bool {
    alt e.node {
      expr_lit(_) { ret true; }
      expr_path(_) { ret true; }
      _ { ret false; }
    }
}

fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); }

fn hash_ty(&&t: @ty) -> uint { ret t.span.lo << 16u + t.span.hi; }

fn hash_def_id(&&id: def_id) -> uint {
    id.crate as uint << 16u + (id.node as uint)
}

fn eq_def_id(&&a: def_id, &&b: def_id) -> bool {
    a == b
}

fn new_def_id_hash<copy T>() -> std::map::hashmap<def_id, T> {
    std::map::mk_hashmap(hash_def_id, eq_def_id)
}

fn block_from_expr(e: @expr) -> blk {
    let blk_ = default_block([], option::some::<@expr>(e), e.id);
    ret {node: blk_, span: e.span};
}

fn default_block(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) ->
   blk_ {
    {view_items: [], stmts: stmts1, expr: expr1, id: id1, rules: default_blk}
}

fn obj_field_from_anon_obj_field(f: anon_obj_field) -> obj_field {
    ret {mut: f.mut, ty: f.ty, ident: f.ident, id: f.id};
}

// This is a convenience function to transfor ternary expressions to if
// expressions so that they can be treated the same
fn ternary_to_if(e: @expr) -> @expr {
    alt e.node {
      expr_ternary(cond, then, els) {
        let then_blk = block_from_expr(then);
        let els_blk = block_from_expr(els);
        let els_expr =
            @{id: els.id, node: expr_block(els_blk), span: els.span};
        ret @{id: e.id,
              node: expr_if(cond, then_blk, option::some(els_expr)),
              span: e.span};
      }
      _ { fail; }
    }
}

fn ty_param_kind(tp: ty_param) -> kind { tp.kind }

// FIXME this doesn't handle big integer/float literals correctly (nor does
// the rest of our literal handling)
tag const_val { const_float(float); const_int(i64); const_str(str); }

fn eval_const_expr(e: @expr) -> const_val {
    fn fromb(b: bool) -> const_val { const_int(b as i64) }
    alt e.node {
      expr_unary(neg., inner) {
        alt eval_const_expr(inner) {
          const_float(f) { const_float(-f) }
          const_int(i) { const_int(-i) }
        }
      }
      expr_unary(not., inner) {
        alt eval_const_expr(inner) {
          const_int(i) { const_int(!i) }
        }
      }
      expr_binary(op, a, b) {
        alt (eval_const_expr(a), eval_const_expr(b)) {
          (const_float(a), const_float(b)) {
            alt op {
              add. { const_float(a + b) } sub. { const_float(a - b) }
              mul. { const_float(a * b) } div. { const_float(a / b) }
              rem. { const_float(a % b) } eq. { fromb(a == b) }
              lt. { fromb(a < b) } le. { fromb(a <= b) } ne. { fromb(a != b) }
              ge. { fromb(a >= b) } gt. { fromb(a > b) }
            }
          }
          (const_int(a), const_int(b)) {
            alt op {
              add. { const_int(a + b) } sub. { const_int(a - b) }
              mul. { const_int(a * b) } div. { const_int(a / b) }
              rem. { const_int(a % b) } and. | bitand. { const_int(a & b) }
              or. | bitor. { const_int(a | b) } bitxor. { const_int(a ^ b) }
              eq. { fromb(a == b) } lt. { fromb(a < b) }
              le. { fromb(a <= b) } ne. { fromb(a != b) }
              ge. { fromb(a >= b) } gt. { fromb(a > b) }
            }
          }
        }
      }
      expr_lit(lit) { lit_to_const(lit) }
    }
}

fn lit_to_const(lit: @lit) -> const_val {
    alt lit.node {
      lit_str(s) { const_str(s) }
      lit_char(ch) { const_int(ch as i64) }
      lit_int(i) | lit_mach_int(_, i) { const_int(i as i64) }
      lit_uint(ui) { const_int(ui as i64) }
      lit_float(s) | lit_mach_float(_, s) {
        const_float(std::float::from_str(s))
      }
      lit_nil. { const_int(0i64) }
      lit_bool(b) { const_int(b as i64) }
    }
}

fn compare_const_vals(a: const_val, b: const_val) -> int {
  alt (a, b) {
    (const_int(a), const_int(b)) { a == b ? 0 : a < b ? -1 : 1 }
    (const_float(a), const_float(b)) { a == b ? 0 : a < b ? -1 : 1 }
    (const_str(a), const_str(b)) { a == b ? 0 : a < b ? -1 : 1 }
  }
}

fn compare_lit_exprs(a: @expr, b: @expr) -> int {
  compare_const_vals(eval_const_expr(a), eval_const_expr(b))
}

fn lit_expr_eq(a: @expr, b: @expr) -> bool { compare_lit_exprs(a, b) == 0 }

fn lit_eq(a: @lit, b: @lit) -> bool {
    compare_const_vals(lit_to_const(a), lit_to_const(b)) == 0
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>fix hash function: + binds tighter than <<<commit_after>import std::{str, option, int, map};
import codemap::span;
import ast::*;

fn respan<copy T>(sp: span, t: T) -> spanned<T> {
    ret {node: t, span: sp};
}

fn new_node_hash<copy V>() -> map::hashmap<node_id, V> {
    fn node_id_hash(&&i: node_id) -> uint { ret int::hash(i as int); }
    fn node_id_eq(&&a: node_id, &&b: node_id) -> bool
        { ret int::eq(a as int, b as int); }
    ret map::mk_hashmap(node_id_hash, node_id_eq);
}

/* assuming that we're not in macro expansion */
fn mk_sp(lo: uint, hi: uint) -> span {
    ret {lo: lo, hi: hi, expanded_from: codemap::os_none};
}

// make this a const, once the compiler supports it
fn dummy_sp() -> span { ret mk_sp(0u, 0u); }

fn path_name(p: @path) -> str { path_name_i(p.node.idents) }

fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }

fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }

fn variant_def_ids(d: def) -> {tg: def_id, var: def_id} {
    alt d { def_variant(tag_id, var_id) { ret {tg: tag_id, var: var_id}; } }
}

fn def_id_of_def(d: def) -> def_id {
    alt d {
      def_fn(id, _) { ret id; }
      def_obj_field(id, _) { ret id; }
      def_mod(id) { ret id; }
      def_native_mod(id) { ret id; }
      def_const(id) { ret id; }
      def_arg(id, _) { ret id; }
      def_local(id, _) { ret id; }
      def_variant(_, id) { ret id; }
      def_ty(id) { ret id; }
      def_ty_param(_, _) { fail; }
      def_binding(id) { ret id; }
      def_use(id) { ret id; }
      def_native_ty(id) { ret id; }
      def_native_fn(id, _) { ret id; }
      def_upvar(id, _, _) { ret id; }
    }
}

type pat_id_map = std::map::hashmap<str, node_id>;

// This is used because same-named variables in alternative patterns need to
// use the node_id of their namesake in the first pattern.
fn pat_id_map(pat: @pat) -> pat_id_map {
    let map = std::map::new_str_hash::<node_id>();
    pat_bindings(pat) {|bound|
        let name = alt bound.node { pat_bind(n) { n } };
        map.insert(name, bound.id);
    };
    ret map;
}

// FIXME: could return a constrained type
fn pat_bindings(pat: @pat, it: block(@pat)) {
    alt pat.node {
      pat_bind(_) { it(pat); }
      pat_tag(_, sub) { for p in sub { pat_bindings(p, it); } }
      pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
      pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
      pat_box(sub) { pat_bindings(sub, it); }
      pat_uniq(sub) { pat_bindings(sub, it); }
      pat_wild. | pat_lit(_) | pat_range(_, _) { }
    }
}

fn pat_binding_ids(pat: @pat) -> [node_id] {
    let found = [];
    pat_bindings(pat) {|b| found += [b.id]; };
    ret found;
}

fn binop_to_str(op: binop) -> str {
    alt op {
      add. { ret "+"; }
      sub. { ret "-"; }
      mul. { ret "*"; }
      div. { ret "/"; }
      rem. { ret "%"; }
      and. { ret "&&"; }
      or. { ret "||"; }
      bitxor. { ret "^"; }
      bitand. { ret "&"; }
      bitor. { ret "|"; }
      lsl. { ret "<<"; }
      lsr. { ret ">>"; }
      asr. { ret ">>>"; }
      eq. { ret "=="; }
      lt. { ret "<"; }
      le. { ret "<="; }
      ne. { ret "!="; }
      ge. { ret ">="; }
      gt. { ret ">"; }
    }
}

pure fn lazy_binop(b: binop) -> bool {
    alt b { and. { true } or. { true } _ { false } }
}

fn unop_to_str(op: unop) -> str {
    alt op {
      box(mt) { if mt == mut { ret "@mutable "; } ret "@"; }
      uniq(mt) { if mt == mut { ret "~mutable "; } ret "~"; }
      deref. { ret "*"; }
      not. { ret "!"; }
      neg. { ret "-"; }
    }
}

fn is_path(e: @expr) -> bool {
    ret alt e.node { expr_path(_) { true } _ { false } };
}

fn ty_mach_to_str(tm: ty_mach) -> str {
    alt tm {
      ty_u8. { ret "u8"; }
      ty_u16. { ret "u16"; }
      ty_u32. { ret "u32"; }
      ty_u64. { ret "u64"; }
      ty_i8. { ret "i8"; }
      ty_i16. { ret "i16"; }
      ty_i32. { ret "i32"; }
      ty_i64. { ret "i64"; }
      ty_f32. { ret "f32"; }
      ty_f64. { ret "f64"; }
    }
}

fn is_exported(i: ident, m: _mod) -> bool {
    let nonlocal = true;
    for it: @item in m.items {
        if it.ident == i { nonlocal = false; }
        alt it.node {
          item_tag(variants, _) {
            for v: variant in variants {
                if v.node.name == i { nonlocal = false; }
            }
          }
          _ { }
        }
        if !nonlocal { break; }
    }
    let count = 0u;
    for vi: @view_item in m.view_items {
        alt vi.node {
          view_item_export(ids, _) {
            for id in ids { if str::eq(i, id) { ret true; } }
            count += 1u;
          }
          _ {/* fall through */ }
        }
    }
    // If there are no declared exports then
    // everything not imported is exported
    // even if it's nonlocal (since it's explicit)
    ret count == 0u && !nonlocal;
}

pure fn is_call_expr(e: @expr) -> bool {
    alt e.node { expr_call(_, _, _) { true } _ { false } }
}

pure fn is_tail_call_expr(e: @expr) -> bool {
    alt e.node {
      expr_call(_, _, _) { true }
      expr_cast(inner_e, _) { is_call_expr(inner_e) }
      _ { false }
    }
}

fn is_constraint_arg(e: @expr) -> bool {
    alt e.node {
      expr_lit(_) { ret true; }
      expr_path(_) { ret true; }
      _ { ret false; }
    }
}

fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); }

fn hash_ty(&&t: @ty) -> uint {
    let res = (t.span.lo << 16u) + t.span.hi;
    ret res;
}

fn hash_def_id(&&id: def_id) -> uint {
    id.crate as uint << 16u + (id.node as uint)
}

fn eq_def_id(&&a: def_id, &&b: def_id) -> bool {
    a == b
}

fn new_def_id_hash<copy T>() -> std::map::hashmap<def_id, T> {
    std::map::mk_hashmap(hash_def_id, eq_def_id)
}

fn block_from_expr(e: @expr) -> blk {
    let blk_ = default_block([], option::some::<@expr>(e), e.id);
    ret {node: blk_, span: e.span};
}

fn default_block(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) ->
   blk_ {
    {view_items: [], stmts: stmts1, expr: expr1, id: id1, rules: default_blk}
}

fn obj_field_from_anon_obj_field(f: anon_obj_field) -> obj_field {
    ret {mut: f.mut, ty: f.ty, ident: f.ident, id: f.id};
}

// This is a convenience function to transfor ternary expressions to if
// expressions so that they can be treated the same
fn ternary_to_if(e: @expr) -> @expr {
    alt e.node {
      expr_ternary(cond, then, els) {
        let then_blk = block_from_expr(then);
        let els_blk = block_from_expr(els);
        let els_expr =
            @{id: els.id, node: expr_block(els_blk), span: els.span};
        ret @{id: e.id,
              node: expr_if(cond, then_blk, option::some(els_expr)),
              span: e.span};
      }
      _ { fail; }
    }
}

fn ty_param_kind(tp: ty_param) -> kind { tp.kind }

// FIXME this doesn't handle big integer/float literals correctly (nor does
// the rest of our literal handling)
tag const_val { const_float(float); const_int(i64); const_str(str); }

fn eval_const_expr(e: @expr) -> const_val {
    fn fromb(b: bool) -> const_val { const_int(b as i64) }
    alt e.node {
      expr_unary(neg., inner) {
        alt eval_const_expr(inner) {
          const_float(f) { const_float(-f) }
          const_int(i) { const_int(-i) }
        }
      }
      expr_unary(not., inner) {
        alt eval_const_expr(inner) {
          const_int(i) { const_int(!i) }
        }
      }
      expr_binary(op, a, b) {
        alt (eval_const_expr(a), eval_const_expr(b)) {
          (const_float(a), const_float(b)) {
            alt op {
              add. { const_float(a + b) } sub. { const_float(a - b) }
              mul. { const_float(a * b) } div. { const_float(a / b) }
              rem. { const_float(a % b) } eq. { fromb(a == b) }
              lt. { fromb(a < b) } le. { fromb(a <= b) } ne. { fromb(a != b) }
              ge. { fromb(a >= b) } gt. { fromb(a > b) }
            }
          }
          (const_int(a), const_int(b)) {
            alt op {
              add. { const_int(a + b) } sub. { const_int(a - b) }
              mul. { const_int(a * b) } div. { const_int(a / b) }
              rem. { const_int(a % b) } and. | bitand. { const_int(a & b) }
              or. | bitor. { const_int(a | b) } bitxor. { const_int(a ^ b) }
              eq. { fromb(a == b) } lt. { fromb(a < b) }
              le. { fromb(a <= b) } ne. { fromb(a != b) }
              ge. { fromb(a >= b) } gt. { fromb(a > b) }
            }
          }
        }
      }
      expr_lit(lit) { lit_to_const(lit) }
    }
}

fn lit_to_const(lit: @lit) -> const_val {
    alt lit.node {
      lit_str(s) { const_str(s) }
      lit_char(ch) { const_int(ch as i64) }
      lit_int(i) | lit_mach_int(_, i) { const_int(i as i64) }
      lit_uint(ui) { const_int(ui as i64) }
      lit_float(s) | lit_mach_float(_, s) {
        const_float(std::float::from_str(s))
      }
      lit_nil. { const_int(0i64) }
      lit_bool(b) { const_int(b as i64) }
    }
}

fn compare_const_vals(a: const_val, b: const_val) -> int {
  alt (a, b) {
    (const_int(a), const_int(b)) { a == b ? 0 : a < b ? -1 : 1 }
    (const_float(a), const_float(b)) { a == b ? 0 : a < b ? -1 : 1 }
    (const_str(a), const_str(b)) { a == b ? 0 : a < b ? -1 : 1 }
  }
}

fn compare_lit_exprs(a: @expr, b: @expr) -> int {
  compare_const_vals(eval_const_expr(a), eval_const_expr(b))
}

fn lit_expr_eq(a: @expr, b: @expr) -> bool { compare_lit_exprs(a, b) == 0 }

fn lit_eq(a: @lit, b: @lit) -> bool {
    compare_const_vals(lit_to_const(a), lit_to_const(b)) == 0
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>// Copyright 2018 The Grin 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.

//! Definition of the genesis block. Placeholder for now.

use time;

use core;
use consensus;
use core::target::Difficulty;
use global;

/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 1997 - 1900,
				tm_mon: 7,
				tm_mday: 4,
				..time::empty_tm()
			},
			nonce: global::get_genesis_nonce(),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2017 - 1900,
				tm_mon: 10,
				tm_mday: 16,
				tm_hour: 20,
				..time::empty_tm()
			},
			nonce: 28205,
			pow: core::Proof::new(vec![
				0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74,
				0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af,
				0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb,
				0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8,
				0x7f29, 0x7ff8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Second testnet genesis block (cuckoo30). TBD and don't start getting excited
/// just because you see this reference here... this is for testing mining
/// at cuckoo 30
pub fn genesis_testnet2() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 3,
				tm_mday: 26,
				tm_hour: 16,
				..time::empty_tm()
			},
			//TODO: Check this is over-estimated at T2 launch
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: 5100,
			pow: core::Proof::new(vec![
				0xc959ec, 0x16c10da, 0x186c549, 0x3045401, 0x38226e3, 0x42d041b, 0x49bf309,
				0x5295ae9, 0x6ae4490, 0x763ba88, 0x78e711e, 0x8459fc9, 0x8579418, 0x8fbfc38,
				0xbf735f0, 0xc30a750, 0xcf1df67, 0xea54fb7, 0xec30a7e, 0xf285691, 0x115b6000,
				0x11a68288, 0x11a6a1be, 0x1257f383, 0x12ec0836, 0x14357351, 0x14b25747,
				0x14d9e57c, 0x14f6755c, 0x14f99326, 0x17fe205f, 0x19523912, 0x1973f000,
				0x19a433b1, 0x19ff0f3a, 0x1bc050d1, 0x1da8c0cb, 0x1de11b30, 0x1eded1f7,
				0x1f10dc08, 0x1f9a491c, 0x1fa004f8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 7,
				tm_mday: 14,
				..time::empty_tm()
			},
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: global::get_genesis_nonce(),
			pow: core::Proof::zero(consensus::PROOFSIZE),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}
<commit_msg>Genesis update with 172 difficulty<commit_after>// Copyright 2018 The Grin 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.

//! Definition of the genesis block. Placeholder for now.

use time;

use core;
use consensus;
use core::target::Difficulty;
use global;

/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 1997 - 1900,
				tm_mon: 7,
				tm_mday: 4,
				..time::empty_tm()
			},
			nonce: global::get_genesis_nonce(),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2017 - 1900,
				tm_mon: 10,
				tm_mday: 16,
				tm_hour: 20,
				..time::empty_tm()
			},
			nonce: 28205,
			pow: core::Proof::new(vec![
				0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74,
				0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af,
				0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb,
				0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8,
				0x7f29, 0x7ff8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Second testnet genesis block (cuckoo30). TBD and don't start getting excited
/// just because you see this reference here... this is for testing mining
/// at cuckoo 30
pub fn genesis_testnet2() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 3,
				tm_mday: 26,
				tm_hour: 16,
				..time::empty_tm()
			},
			//TODO: Check this is over-estimated at T2 launch
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: 42365,
			pow: core::Proof::new(vec![
				0xa3163, 0x9f42bf, 0x243ea6f, 0x34acaa4, 0x3552efa, 0x4315a83, 0x4f5f496,
				0x541ba37, 0x717ce71, 0x7be44aa, 0x9ac0a9e, 0xa1d9984, 0xb75f60e, 0xe184928,
				0xe44c7f6, 0x11a4dba8, 0x12981f4d, 0x12c0ab3b, 0x131bbaca, 0x14b4bbb5,
				0x14dda829, 0x15968500, 0x168cc6e2, 0x177f2f26, 0x179a2836, 0x17b12d39,
				0x17b786cd, 0x183def3b, 0x18873d9b, 0x188abb3f, 0x18be6db8, 0x1914cea1,
				0x1992c0c9, 0x1a18f935, 0x1aa2f6c0, 0x1aad6430, 0x1ab216d7, 0x1b08c5b4,
				0x1c3f7184, 0x1c6a820a, 0x1cfbf6a0, 0x1de9a55d
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 7,
				tm_mday: 14,
				..time::empty_tm()
			},
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: global::get_genesis_nonce(),
			pow: core::Proof::zero(consensus::PROOFSIZE),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}
<|endoftext|>


<commit_before>// xfail-test

// Create a task that is supervised by another task,
// join the supervised task from the supervising task,
// then fail the supervised task. The supervised task
// will kill the supervising task, waking it up. The
// supervising task no longer needs to be wakened when
// the supervised task exits.

use std;
import std::task;

fn supervised() {
    // Yield to make sure the supervisor joins before we
    // fail. This is currently not needed because the supervisor
    // runs first, but I can imagine that changing.
    task::yield();
    fail;
}

fn supervisor() {
    // Unsupervise this task so the process doesn't return a failure status as
    // a result of the main task being killed.
    task::unsupervise();
    let f = supervised;
    let t = task::_spawn(supervised);
    task::join_id(t);
}

fn main() {
    let f = supervisor;
    let dom2 = task::_spawn(f);
    task::join_id(dom2);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Rehabilitate run-pass/task-killjoin.rs<commit_after>// xfail-win32
// Create a task that is supervised by another task,
// join the supervised task from the supervising task,
// then fail the supervised task. The supervised task
// will kill the supervising task, waking it up. The
// supervising task no longer needs to be wakened when
// the supervised task exits.

use std;
import std::task;

fn supervised(&&_args: ()) {
    // Yield to make sure the supervisor joins before we
    // fail. This is currently not needed because the supervisor
    // runs first, but I can imagine that changing.
    task::yield();
    fail;
}

fn supervisor(&&_args: ()) {
    // Unsupervise this task so the process doesn't return a failure status as
    // a result of the main task being killed.
    task::unsupervise();
    let f = supervised;
    let t = task::spawn_joinable((), supervised);
    task::join(t);
}

fn main() {
    let dom2 = task::spawn_joinable((), supervisor);
    task::join(dom2);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>