<commit_before>
use serde::de::Error;

use std::marker::PhantomData;

use prelude::*;

use EdgeType;
use graph::Node;
use graph::{IndexType, Edge};
use serde_utils::MappedSequenceVisitor;
use serde_utils::CollectSeqWithLength;
use serde_utils::{IntoSerializable, FromDeserialized};

use super::{NodeIndex, EdgeIndex};
use serde::{Serialize, Serializer, Deserialize, Deserializer};

// Serialization representation for Graph
// Keep in sync with deserialization and StableGraph
#[derive(Serialize)]
#[serde(rename = "Graph")]
#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))]
pub struct SerGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> {
    #[serde(serialize_with="ser_graph_nodes")]
    nodes: &'a [Node<N, Ix>],
    node_holes: &'a [NodeIndex<Ix>],
    edge_property: EdgeProperty,
    #[serde(serialize_with="ser_graph_edges")]
    edges: &'a [Edge<E, Ix>],
}

// Deserialization representation for Graph
// Keep in sync with serialization and StableGraph
#[derive(Deserialize)]
#[serde(rename = "Graph")]
#[serde(bound(deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>"))]
pub struct DeserGraph<N, E, Ix> {
    #[serde(deserialize_with="deser_graph_nodes")]
    nodes: Vec<Node<N, Ix>>,
    #[serde(deserialize_with="deser_graph_node_holes")]
    #[allow(unused)]
    #[serde(default="Vec::new")]
    node_holes: Vec<NodeIndex<Ix>>,
    edge_property: EdgeProperty,
    #[serde(deserialize_with="deser_graph_edges")]
    edges: Vec<Edge<E, Ix>>,
}

impl<Ix> Serialize for NodeIndex<Ix>
    where Ix: IndexType + Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.0.serialize(serializer)
    }
}

impl<'de, Ix> Deserialize<'de> for NodeIndex<Ix>
    where Ix: IndexType + Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Ok(NodeIndex(Ix::deserialize(deserializer)?))
    }
}

impl<Ix> Serialize for EdgeIndex<Ix>
    where Ix: IndexType + Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.0.serialize(serializer)
    }
}

impl<'de, Ix> Deserialize<'de> for EdgeIndex<Ix>
    where Ix: IndexType + Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Ok(EdgeIndex(Ix::deserialize(deserializer)?))
    }
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all="lowercase")]
#[derive(Debug)]
pub enum EdgeProperty {
    Undirected,
    Directed,
}

impl EdgeProperty {
    pub fn is_directed(&self) -> bool {
        match *self {
            EdgeProperty::Directed => true,
            EdgeProperty::Undirected => false,
        }
    }
}

impl<Ty> From<PhantomData<Ty>> for EdgeProperty where Ty: EdgeType {
    fn from(_: PhantomData<Ty>) -> Self {
        if Ty::is_directed() {
            EdgeProperty::Directed
        } else {
            EdgeProperty::Undirected
        }
    }
}

impl<Ty> FromDeserialized for PhantomData<Ty> where Ty: EdgeType
{
    type Input = EdgeProperty;
    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
        where E2: Error
    {
        if input.is_directed() != Ty::is_directed() {
            Err(E2::custom(format_args!("graph edge property mismatch, \
                                        expected {:?}, found {:?}",
                                        EdgeProperty::from(PhantomData::<Ty>),
                                        input)))
        } else {
            Ok(PhantomData)
        }
    }
}

fn ser_graph_nodes<S, N, Ix>(nodes: &&[Node<N, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          N: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_exact(
        nodes.iter()
             .map(|node| &node.weight))
}

fn ser_graph_edges<S, E, Ix>(edges: &&[Edge<E, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          E: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_exact(
        edges.iter()
            .map(|edge| Some((
               edge.source(),
               edge.target(),
               &edge.weight,
            ))))
}

fn deser_graph_nodes<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Node<N, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::new(|n|
        Ok(Node {
            weight: n,
            next: [EdgeIndex::end(); 2],
        })
    ))
}

fn deser_graph_node_holes<'de, D, Ix>(deserializer: D) -> Result<Vec<NodeIndex<Ix>>, D::Error>
    where D: Deserializer<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::<NodeIndex<Ix>, NodeIndex<Ix>, _>::new(|_| {
        Err("Graph can not have holes in the node set, found non-empty node_holes")
    }))
}

fn deser_graph_edges<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Edge<N, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::<Option<(NodeIndex<Ix>, NodeIndex<Ix>, N)>, _, _>::new(|x|
        if let Some((i, j, w)) = x {
            Ok(Edge {
                weight: w,
                node: [i, j],
                next: [EdgeIndex::end(); 2],
            })
        } else {
            Err("Graph can not have holes in the edge set, found None, expected edge")
        }
    ))
}

impl<'a, N, E, Ty, Ix> IntoSerializable for &'a Graph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Output = SerGraph<'a, N, E, Ix>;
    fn into_serializable(self) -> Self::Output {
        SerGraph {
            nodes: &self.nodes,
            node_holes: &[],
            edges: &self.edges,
            edge_property: EdgeProperty::from(PhantomData::<Ty>),
        }
    }
}

impl<N, E, Ty, Ix> Serialize for Graph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Serialize,
          N: Serialize,
          E: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.into_serializable().serialize(serializer)
    }
}

pub fn invalid_node_err<E>(node_index: usize, len: usize) -> E where E: Error {
    E::custom(format_args!("invalid value: node index `{}` does not exist in graph \
                           with node bound {}",
                           node_index, len))
}

pub fn invalid_length_err<Ix, E>(node_or_edge: &str, len: usize) -> E
    where E: Error, Ix: IndexType
{
    E::custom(format_args!("invalid size: graph {} count {} exceeds index type maximum {}",
                           node_or_edge, len, <Ix as IndexType>::max().index()))
}

impl<'a, N, E, Ty, Ix> FromDeserialized for Graph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Input = DeserGraph<N, E, Ix>;
    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
        where E2: Error
    {
        let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
        let nodes = input.nodes;
        let edges = input.edges;
        if nodes.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
        }

        if edges.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("edge", edges.len()))?
        }

        let mut gr = Graph {
            nodes: nodes,
            edges: edges,
            ty: ty,
        };
        let nc = gr.node_count();
        gr.link_edges().map_err(|i| invalid_node_err(i.index(), nc))?;
        Ok(gr)
    }
}

impl<'de, N, E, Ty, Ix> Deserialize<'de> for Graph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Deserialize<'de>,
          N: Deserialize<'de>,
          E: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Self::from_deserialized(DeserGraph::deserialize(deserializer)?)
    }
}

<commit_msg>DOC: Add brief description of the graph serialization format<commit_after>
use serde::de::Error;

use std::marker::PhantomData;

use prelude::*;

use EdgeType;
use graph::Node;
use graph::{IndexType, Edge};
use serde_utils::MappedSequenceVisitor;
use serde_utils::CollectSeqWithLength;
use serde_utils::{IntoSerializable, FromDeserialized};

use super::{NodeIndex, EdgeIndex};
use serde::{Serialize, Serializer, Deserialize, Deserializer};

/// Serialization representation for Graph
/// Keep in sync with deserialization and StableGraph
///
/// The serialization format is as follows, in Pseudorust:
///
/// Graph {
///     nodes: [N],
///     node_holes: [NodeIndex<Ix>],
///     edge_property: EdgeProperty,
///     edges: [Option<(NodeIndex<Ix>, NodeIndex<Ix>, E)>]
/// }
///
/// The same format is used by both Graph and StableGraph.
///
/// For graph there are restrictions:
/// node_holes is always empty and edges are always Some
///
/// A stable graph serialization that obeys these restrictions
/// (effectively, it has no interior vacancies) can de deserialized
/// as a graph.
///
/// Node indices are serialized as integers and are fixed size for
/// binary formats, so the Ix parameter matters there.
#[derive(Serialize)]
#[serde(rename = "Graph")]
#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))]
pub struct SerGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> {
    #[serde(serialize_with="ser_graph_nodes")]
    nodes: &'a [Node<N, Ix>],
    node_holes: &'a [NodeIndex<Ix>],
    edge_property: EdgeProperty,
    #[serde(serialize_with="ser_graph_edges")]
    edges: &'a [Edge<E, Ix>],
}

// Deserialization representation for Graph
// Keep in sync with serialization and StableGraph
#[derive(Deserialize)]
#[serde(rename = "Graph")]
#[serde(bound(deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>"))]
pub struct DeserGraph<N, E, Ix> {
    #[serde(deserialize_with="deser_graph_nodes")]
    nodes: Vec<Node<N, Ix>>,
    #[serde(deserialize_with="deser_graph_node_holes")]
    #[allow(unused)]
    #[serde(default="Vec::new")]
    node_holes: Vec<NodeIndex<Ix>>,
    edge_property: EdgeProperty,
    #[serde(deserialize_with="deser_graph_edges")]
    edges: Vec<Edge<E, Ix>>,
}

impl<Ix> Serialize for NodeIndex<Ix>
    where Ix: IndexType + Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.0.serialize(serializer)
    }
}

impl<'de, Ix> Deserialize<'de> for NodeIndex<Ix>
    where Ix: IndexType + Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Ok(NodeIndex(Ix::deserialize(deserializer)?))
    }
}

impl<Ix> Serialize for EdgeIndex<Ix>
    where Ix: IndexType + Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.0.serialize(serializer)
    }
}

impl<'de, Ix> Deserialize<'de> for EdgeIndex<Ix>
    where Ix: IndexType + Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Ok(EdgeIndex(Ix::deserialize(deserializer)?))
    }
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all="lowercase")]
#[derive(Debug)]
pub enum EdgeProperty {
    Undirected,
    Directed,
}

impl EdgeProperty {
    pub fn is_directed(&self) -> bool {
        match *self {
            EdgeProperty::Directed => true,
            EdgeProperty::Undirected => false,
        }
    }
}

impl<Ty> From<PhantomData<Ty>> for EdgeProperty where Ty: EdgeType {
    fn from(_: PhantomData<Ty>) -> Self {
        if Ty::is_directed() {
            EdgeProperty::Directed
        } else {
            EdgeProperty::Undirected
        }
    }
}

impl<Ty> FromDeserialized for PhantomData<Ty> where Ty: EdgeType
{
    type Input = EdgeProperty;
    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
        where E2: Error
    {
        if input.is_directed() != Ty::is_directed() {
            Err(E2::custom(format_args!("graph edge property mismatch, \
                                        expected {:?}, found {:?}",
                                        EdgeProperty::from(PhantomData::<Ty>),
                                        input)))
        } else {
            Ok(PhantomData)
        }
    }
}

fn ser_graph_nodes<S, N, Ix>(nodes: &&[Node<N, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          N: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_exact(
        nodes.iter()
             .map(|node| &node.weight))
}

fn ser_graph_edges<S, E, Ix>(edges: &&[Edge<E, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          E: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_exact(
        edges.iter()
            .map(|edge| Some((
               edge.source(),
               edge.target(),
               &edge.weight,
            ))))
}

fn deser_graph_nodes<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Node<N, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::new(|n|
        Ok(Node {
            weight: n,
            next: [EdgeIndex::end(); 2],
        })
    ))
}

fn deser_graph_node_holes<'de, D, Ix>(deserializer: D) -> Result<Vec<NodeIndex<Ix>>, D::Error>
    where D: Deserializer<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::<NodeIndex<Ix>, NodeIndex<Ix>, _>::new(|_| {
        Err("Graph can not have holes in the node set, found non-empty node_holes")
    }))
}

fn deser_graph_edges<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Edge<N, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::<Option<(NodeIndex<Ix>, NodeIndex<Ix>, N)>, _, _>::new(|x|
        if let Some((i, j, w)) = x {
            Ok(Edge {
                weight: w,
                node: [i, j],
                next: [EdgeIndex::end(); 2],
            })
        } else {
            Err("Graph can not have holes in the edge set, found None, expected edge")
        }
    ))
}

impl<'a, N, E, Ty, Ix> IntoSerializable for &'a Graph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Output = SerGraph<'a, N, E, Ix>;
    fn into_serializable(self) -> Self::Output {
        SerGraph {
            nodes: &self.nodes,
            node_holes: &[],
            edges: &self.edges,
            edge_property: EdgeProperty::from(PhantomData::<Ty>),
        }
    }
}

impl<N, E, Ty, Ix> Serialize for Graph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Serialize,
          N: Serialize,
          E: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.into_serializable().serialize(serializer)
    }
}

pub fn invalid_node_err<E>(node_index: usize, len: usize) -> E where E: Error {
    E::custom(format_args!("invalid value: node index `{}` does not exist in graph \
                           with node bound {}",
                           node_index, len))
}

pub fn invalid_length_err<Ix, E>(node_or_edge: &str, len: usize) -> E
    where E: Error, Ix: IndexType
{
    E::custom(format_args!("invalid size: graph {} count {} exceeds index type maximum {}",
                           node_or_edge, len, <Ix as IndexType>::max().index()))
}

impl<'a, N, E, Ty, Ix> FromDeserialized for Graph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Input = DeserGraph<N, E, Ix>;
    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
        where E2: Error
    {
        let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
        let nodes = input.nodes;
        let edges = input.edges;
        if nodes.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
        }

        if edges.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("edge", edges.len()))?
        }

        let mut gr = Graph {
            nodes: nodes,
            edges: edges,
            ty: ty,
        };
        let nc = gr.node_count();
        gr.link_edges().map_err(|i| invalid_node_err(i.index(), nc))?;
        Ok(gr)
    }
}

impl<'de, N, E, Ty, Ix> Deserialize<'de> for Graph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Deserialize<'de>,
          N: Deserialize<'de>,
          E: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Self::from_deserialized(DeserGraph::deserialize(deserializer)?)
    }
}

<|endoftext|>


<commit_before>use collections::hashmap::HashMap;
use core::*;
use scoped_map::ScopedMap;
use typecheck::function_type_;

pub type TypeAndStr = (~[Constraint], Type, ~str);

pub fn do_lambda_lift(module: Module<TypeAndStr>) -> Module<Id> {
    lift_lambdas(rename_module(abstract_module(module)))
}

//Walks through an expression and notes all the free variables and for each lambda, adds the
//free variables to its arguments and performs an immediate application
//@variables All the local variables in scope, values are how many of the name there exists
//@free_vars The free variables for the returned expression
fn free_variables(variables: &mut HashMap<~str, int>, free_vars: &mut HashMap<~str, TypeAndStr>, expr: Expr<TypeAndStr>) -> Expr<TypeAndStr> {
    match expr {
        Identifier(i) => {
            //If the identifier is a local, add it to the free variables
            if variables.find(i.ref2()).map(|x| *x > 0).unwrap_or(false) {
                free_vars.insert(i.ref2().clone(), i.clone());
            }
            Identifier(i)
        }
        Apply(func, arg) => {
            let f = ~free_variables(variables, free_vars, *func);
            let a = ~free_variables(variables, free_vars, *arg);
            Apply(f, a)
        }
        Lambda(arg, body) => {
            variables.insert_or_update_with(arg.ref2().clone(), 1, |_, v| *v += 1);
            let b = free_variables(variables, free_vars, *body);
            *variables.get_mut(arg.ref2()) -= 1;
            free_vars.remove(arg.ref2());//arg was not actually a free variable
            Lambda(arg, ~b)
        }
        Let(bindings, expr) => {
            for bind in bindings.iter() {
                variables.insert_or_update_with(bind.name.ref2().clone(), 1, |_, v| *v += 1);
            }
            let mut free_vars2 = HashMap::new();
            let new_bindings: ~[Binding<TypeAndStr>] = bindings.move_iter().map(
                |Binding { name: name, expression: bind_expr }| {
                free_vars2.clear();
                let e = free_variables(variables, &mut free_vars2, bind_expr);
                //free_vars2 is the free variables for this binding
                for (k, v) in free_vars2.iter() {
                    free_vars.insert(k.clone(), v.clone());
                }
                Binding{
                    name: name,
                    expression: abstract(&free_vars2, e)
                }
            }).collect();
            let e = ~free_variables(variables, free_vars, *expr);
            for bind in new_bindings.iter() {
                *variables.get_mut(bind.name.ref2()) -= 1;
                free_vars.remove(bind.name.ref2());
            }
            Let(new_bindings, e)
        }
        Case(expr, alts) => {
            Case(expr, alts)
        }
        e => e
    }
}

fn abstract(free_vars: &HashMap<~str, TypeAndStr>, input_expr: Expr<TypeAndStr>) -> Expr<TypeAndStr> {
    let mut e = {
        let mut rhs = input_expr;
        let mut typ = rhs.get_type().clone();
        for (_, var) in free_vars.iter() {
            debug!("xxxxxxxxxxxxxxxx {}", var);
            rhs = Lambda(var.clone(), ~rhs);
            typ = function_type_(var.ref1().clone(), typ);
        }
        let bind = Binding {
            name: (~[], typ.clone(), "sc".to_owned()),
            expression: rhs
        };
        Let(~[bind], ~Identifier((~[], typ.clone(), "sc".to_owned())))
    };
    for (_, var) in free_vars.iter() {
        e = Apply(~e, ~Identifier(var.clone()));
    }
    e
}

struct Renamer {
    uniques: ScopedMap<~str, Name>,
    unique_id: uint
}
impl Renamer {

    fn rename_bindings(&mut self, bindings: ~[Binding<TypeAndStr>]) -> ~[Binding<Id>] {
        //Add all bindings in the scope
        for bind in bindings.iter() {
            self.make_unique(bind.name.ref2().clone());
        }
        bindings.move_iter().map(|binding| {
            let Binding { name: (constraints, typ, name), expression: expression } = binding;
            let n = self.uniques.find(&name).map(|u| u.clone())
                .expect(format!("Error: lambda_lift: Undefined variable {}", name));
            Binding {
                name: Id::new(n, typ, constraints),
                expression: self.rename(expression)
            }
        }).collect()
    }

    fn rename(&mut self, expr: Expr<TypeAndStr>) -> Expr<Id> {
        match expr {
            Literal(l) => Literal(l),
            Identifier((constraints, typ, i)) => {
                let n = match self.uniques.find(&i).map(|u| u.clone()) {
                    Some(n) => n,
                    None => Name { name: i, uid: 0 }//If the variable is not found in variables it is a global variable
                };
                Identifier(Id::new(n, typ, constraints))
            }
            Apply(func, arg) => Apply(~self.rename(*func), ~self.rename(*arg)),
            Lambda((constraints, typ, arg), body) => {
                self.uniques.enter_scope();
                let l = Lambda(Id::new(self.make_unique(arg), typ, constraints), ~self.rename(*body));
                self.uniques.exit_scope();
                l
            }
            Let(bindings, expr) => {
                self.uniques.enter_scope();
                let bs = self.rename_bindings(bindings);
                let l = Let(bs, ~self.rename(*expr));
                self.uniques.exit_scope();
                l
            }
            Case(expr, alts) => {
                let a = alts.move_iter().map(|Alternative { pattern: pattern, expression: expression }| {
                    self.uniques.enter_scope();
                    let a = Alternative {
                        pattern: self.rename_pattern(pattern),
                        expression: self.rename(expression)
                    };
                    self.uniques.exit_scope();
                    a
                }).collect();
                Case(~self.rename(*expr), a)
            }
        }
    }

    fn rename_pattern(&mut self, pattern: Pattern<TypeAndStr>) -> Pattern<Id> {
        match pattern {
            NumberPattern(i) => NumberPattern(i),
            ConstructorPattern(s, ps) => {
                let ps2 = ps.move_iter().map(|p| self.rename_pattern(p)).collect();
                ConstructorPattern(s, ps2)
            }
            IdentifierPattern((constraints, typ, s)) => IdentifierPattern(Id::new(self.make_unique(s), typ, constraints))
        }
    }

    fn make_unique(&mut self, name: ~str) -> Name {
        self.unique_id += 1;
        let u = Name { name: name.clone(), uid: self.unique_id};
        self.uniques.insert(name, u.clone());
        u
    }
}

fn lift_lambdas_expr<T>(expr: Expr<T>, out_lambdas: &mut Vec<Binding<T>>) -> Expr<T> {
    match expr {
        Apply(func, arg) => Apply(~lift_lambdas_expr(*func, out_lambdas), ~lift_lambdas_expr(*arg, out_lambdas)),
        Lambda(arg, body) => Lambda(arg, ~lift_lambdas_expr(*body, out_lambdas)),
        Let(bindings, expr) => {
            let mut new_binds = Vec::new();
            for Binding { name: name, expression: expression } in bindings.move_iter() {
                let is_lambda = match &expression {
                    &Lambda(..) => true,
                    _ => false
                };
                let bind = Binding { name: name, expression: lift_lambdas_expr(expression, out_lambdas) };
                if is_lambda {
                    out_lambdas.push(bind);
                }
                else {
                    new_binds.push(bind);
                }
            }
            if new_binds.len() == 0 {
                lift_lambdas_expr(*expr, out_lambdas)
            }
            else {
                Let(new_binds.move_iter().collect(), ~lift_lambdas_expr(*expr, out_lambdas))
            }
        }
        Case(expr, alts) => {
            let a = alts.move_iter().map(|Alternative { pattern: pattern, expression: expression }| {
                Alternative { pattern: pattern, expression: lift_lambdas_expr(expression, out_lambdas) }
            }).collect();
            Case(~lift_lambdas_expr(*expr, out_lambdas), a)
        }
        _ => expr
    }
}
pub fn lift_lambdas<T: ::std::fmt::Show>(module: Module<T>) -> Module<T> {
    let Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings,
        instances: instances
    } = module;

    let mut new_bindings : Vec<Binding<T>> = Vec::new();
    let bindings2 : ~[Binding<T>] = bindings.move_iter().map(|Binding { name: name, expression: expression }| {
        Binding { name: name, expression: lift_lambdas_expr(expression, &mut new_bindings) }
    }).collect();

    Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings2.move_iter().chain(new_bindings.move_iter()).collect(),
        instances: instances
    }
}

pub fn rename_module(module: Module<TypeAndStr>) -> Module<Id> {
    let mut renamer = Renamer { uniques: ScopedMap::new(), unique_id: 1 };
    let Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings,
        instances: instances
    } = module;

    let bindings2 = bindings.move_iter().map(|binding| {
        let Binding { name: (constraints, typ, name), expression: expression } = binding;
        Binding {
            name: Id::new(Name { name: name, uid: 0 }, typ, constraints),
            expression: renamer.rename(expression)
        }
    }).collect();

    Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings2,
        instances: instances
    }
}
pub fn abstract_module(module: Module<TypeAndStr>) -> Module<TypeAndStr> {
    each_binding(module,
        |name| name,
        |bind| {
            let Binding { name: name, expression: bind_expr } = bind;
            let mut variables = HashMap::new();
            let mut free_vars = HashMap::new();
            let e = free_variables(&mut variables, &mut free_vars, bind_expr);
            Binding { name: name, expression: e }
        })
}

pub fn each_binding<Ident, Ident2>(module: Module<Ident>, _trans: |Ident| -> Ident2, bind_f: |Binding<Ident>| -> Binding<Ident2>) -> Module<Ident2> {
    let Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings,
        instances: instances
    } = module;

    let bindings2 = bindings.move_iter().map(|x| bind_f(x)).collect();

    Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings2,
        instances: instances
    }
}

#[cfg(test)]
mod tests {
    use lambda_lift::*;
    use collections::hashmap::HashSet;
    use parser::Parser;
    use core::*;
    use core::translate::translate_module;

    struct CheckUniques {
        found: HashSet<Id>
    }

    impl Visitor<Id> for CheckUniques {
        fn visit_binding(&mut self, bind: &Binding<Id>) {
            assert!(self.found.insert(bind.name.clone()));
            self.visit_expr(&bind.expression);
        }
        fn visit_expr(&mut self, expr: &Expr<Id>) {
            match expr {
                &Lambda(ref i, _) => {
                    assert!(self.found.insert(i.clone()));
                }
                _ => ()
            }
            walk_expr(self, expr)
        }
    }

    #[test]
    fn all_uniques() {
        let mut visitor = CheckUniques { found: HashSet::new() };
        let mut parser = Parser::new(
r"add x y = 2
test = 3.14
test2 x =
    let
        test = 2
        f x =
            let g y = add x (f y)
            in add x test
    in f x".chars());
        let m = translate_module(parser.module());
        let module = rename_module(m);
        (&mut visitor as &mut Visitor<Id>).visit_module(&module);
    }

    fn check_args(expr: &Expr<Id>, args: &[&str]) -> bool {
        match expr {
            &Lambda(ref arg, ref body) => arg.name.name.equiv(&args[0]) && check_args(*body, args.slice_from(1)),
            _ => args.len() == 0
        }
    }

    struct CheckAbstract {
        count: int
    }

    fn get_let<'a>(expr: &'a Expr<Id>, args: &mut Vec<&'a str>) -> &'a Expr<Id> {
        match expr {
            &Apply(ref f, ref arg) => {
                let a: &Expr<Id> = *arg;
                match a {
                    &Identifier(ref i) => args.push(i.name.name.as_slice()),
                    _ => fail!("Expected identifier as argument")
                }
                get_let(*f, args)
            }
            _ => expr
        }
    }

    impl Visitor<Id> for CheckAbstract {
        fn visit_binding(&mut self, bind: &Binding<Id>) {
            if "f" == bind.name.name.name {
                let mut args = Vec::new();
                match get_let(&bind.expression, &mut args) {
                    &Let(ref binds, ref body) => {
                        //Push the argument of the function itself
                        args.push("x");
                        assert!(check_args(&binds[0].expression, args.as_slice()));
                        assert_eq!(Identifier(binds[0].name.clone()), **body);
                    }
                    _ => assert!(false, "Expected Let, found {}", bind.expression)
                }
                self.count += 1;
            }
            else if "g" == bind.name.name.name {
                let mut args = Vec::new();
                match get_let(&bind.expression, &mut args) {
                    &Let(ref binds, ref body) => {
                        args.push("y");
                        assert!(check_args(&binds[0].expression, args.as_slice()));
                        assert_eq!(Identifier(binds[0].name.clone()), **body);
                    }
                    _ => assert!(false, "Expected Let")
                }
                self.count += 1;
            }
            self.visit_expr(&bind.expression);
        }
    }

    #[test]
    fn all_free_vars() {
        let mut visitor = CheckAbstract { count: 0 };
        let mut parser = Parser::new(
r"add x y = 2
test = 3.14
test2 x =
    let
        test = 2
        f x =
            let g y = add x (f y)
            in add x test
    in f x".chars());
        let m = translate_module(parser.module());
        let module = rename_module(abstract_module(m));
        (&mut visitor as &mut Visitor<Id>).visit_module(&module);
        assert_eq!(visitor.count, 2);
    }

    struct NoLambdas;

    impl <T> Visitor<T> for NoLambdas {
        fn visit_expr(&mut self, expr: &Expr<T>) {
            match expr {
                &Lambda(..) => assert!(false, "Found lambda in expression"),
                _ => ()
            }
            walk_expr(self, expr);
        }
    }
    #[test]
    fn no_local_lambdas() {
        fn skip_lambdas<'a, T>(expr: &'a Expr<T>) -> &'a Expr<T> {
            match expr {
                &Lambda(_, ref body) => skip_lambdas(*body),
                _ => expr
            }
        }

        let mut visitor = NoLambdas;
        let mut parser = Parser::new(
r"add x y = 2
test = 3.14
test2 x =
    let
        test = 2
        f x =
            let g y = add x (f y)
            in add x test
    in f x".chars());
        let m = translate_module(parser.module());
        let module = lift_lambdas(m);
        for bind in module.bindings.iter() {
            (&mut visitor as &mut Visitor<TypeAndStr>).visit_expr(skip_lambdas(&bind.expression));
        }
    }
}
<commit_msg>Avoid generating unnecessary let's when abstracting<commit_after>use collections::hashmap::HashMap;
use core::*;
use scoped_map::ScopedMap;
use typecheck::function_type_;

pub type TypeAndStr = (~[Constraint], Type, ~str);

pub fn do_lambda_lift(module: Module<TypeAndStr>) -> Module<Id> {
    lift_lambdas(rename_module(abstract_module(module)))
}

//Walks through an expression and notes all the free variables and for each lambda, adds the
//free variables to its arguments and performs an immediate application
//@variables All the local variables in scope, values are how many of the name there exists
//@free_vars The free variables for the returned expression
fn free_variables(variables: &mut HashMap<~str, int>, free_vars: &mut HashMap<~str, TypeAndStr>, expr: Expr<TypeAndStr>) -> Expr<TypeAndStr> {
    match expr {
        Identifier(i) => {
            //If the identifier is a local, add it to the free variables
            if variables.find(i.ref2()).map(|x| *x > 0).unwrap_or(false) {
                free_vars.insert(i.ref2().clone(), i.clone());
            }
            Identifier(i)
        }
        Apply(func, arg) => {
            let f = ~free_variables(variables, free_vars, *func);
            let a = ~free_variables(variables, free_vars, *arg);
            Apply(f, a)
        }
        Lambda(arg, body) => {
            variables.insert_or_update_with(arg.ref2().clone(), 1, |_, v| *v += 1);
            let b = free_variables(variables, free_vars, *body);
            *variables.get_mut(arg.ref2()) -= 1;
            free_vars.remove(arg.ref2());//arg was not actually a free variable
            Lambda(arg, ~b)
        }
        Let(bindings, expr) => {
            for bind in bindings.iter() {
                variables.insert_or_update_with(bind.name.ref2().clone(), 1, |_, v| *v += 1);
            }
            let mut free_vars2 = HashMap::new();
            let new_bindings: ~[Binding<TypeAndStr>] = bindings.move_iter().map(
                |Binding { name: name, expression: bind_expr }| {
                free_vars2.clear();
                let e = free_variables(variables, &mut free_vars2, bind_expr);
                //free_vars2 is the free variables for this binding
                for (k, v) in free_vars2.iter() {
                    free_vars.insert(k.clone(), v.clone());
                }
                Binding{
                    name: name,
                    expression: abstract(&free_vars2, e)
                }
            }).collect();
            let e = ~free_variables(variables, free_vars, *expr);
            for bind in new_bindings.iter() {
                *variables.get_mut(bind.name.ref2()) -= 1;
                free_vars.remove(bind.name.ref2());
            }
            Let(new_bindings, e)
        }
        Case(expr, alts) => {
            Case(expr, alts)
        }
        e => e
    }
}

fn abstract(free_vars: &HashMap<~str, TypeAndStr>, input_expr: Expr<TypeAndStr>) -> Expr<TypeAndStr> {
    if free_vars.len() == 0 {
        input_expr
    }
    else {
        let mut e = {
            let mut rhs = input_expr;
            let mut typ = rhs.get_type().clone();
            for (_, var) in free_vars.iter() {
                rhs = Lambda(var.clone(), ~rhs);
                typ = function_type_(var.ref1().clone(), typ);
            }
            let bind = Binding {
                name: (~[], typ.clone(), "sc".to_owned()),
                expression: rhs
            };
            Let(~[bind], ~Identifier((~[], typ.clone(), "sc".to_owned())))
        };
        for (_, var) in free_vars.iter() {
            e = Apply(~e, ~Identifier(var.clone()));
        }
        e
    }
}

struct Renamer {
    uniques: ScopedMap<~str, Name>,
    unique_id: uint
}
impl Renamer {

    fn rename_bindings(&mut self, bindings: ~[Binding<TypeAndStr>]) -> ~[Binding<Id>] {
        //Add all bindings in the scope
        for bind in bindings.iter() {
            self.make_unique(bind.name.ref2().clone());
        }
        bindings.move_iter().map(|binding| {
            let Binding { name: (constraints, typ, name), expression: expression } = binding;
            let n = self.uniques.find(&name).map(|u| u.clone())
                .expect(format!("Error: lambda_lift: Undefined variable {}", name));
            Binding {
                name: Id::new(n, typ, constraints),
                expression: self.rename(expression)
            }
        }).collect()
    }

    fn rename(&mut self, expr: Expr<TypeAndStr>) -> Expr<Id> {
        match expr {
            Literal(l) => Literal(l),
            Identifier((constraints, typ, i)) => {
                let n = match self.uniques.find(&i).map(|u| u.clone()) {
                    Some(n) => n,
                    None => Name { name: i, uid: 0 }//If the variable is not found in variables it is a global variable
                };
                Identifier(Id::new(n, typ, constraints))
            }
            Apply(func, arg) => Apply(~self.rename(*func), ~self.rename(*arg)),
            Lambda((constraints, typ, arg), body) => {
                self.uniques.enter_scope();
                let l = Lambda(Id::new(self.make_unique(arg), typ, constraints), ~self.rename(*body));
                self.uniques.exit_scope();
                l
            }
            Let(bindings, expr) => {
                self.uniques.enter_scope();
                let bs = self.rename_bindings(bindings);
                let l = Let(bs, ~self.rename(*expr));
                self.uniques.exit_scope();
                l
            }
            Case(expr, alts) => {
                let a = alts.move_iter().map(|Alternative { pattern: pattern, expression: expression }| {
                    self.uniques.enter_scope();
                    let a = Alternative {
                        pattern: self.rename_pattern(pattern),
                        expression: self.rename(expression)
                    };
                    self.uniques.exit_scope();
                    a
                }).collect();
                Case(~self.rename(*expr), a)
            }
        }
    }

    fn rename_pattern(&mut self, pattern: Pattern<TypeAndStr>) -> Pattern<Id> {
        match pattern {
            NumberPattern(i) => NumberPattern(i),
            ConstructorPattern(s, ps) => {
                let ps2 = ps.move_iter().map(|p| self.rename_pattern(p)).collect();
                ConstructorPattern(s, ps2)
            }
            IdentifierPattern((constraints, typ, s)) => IdentifierPattern(Id::new(self.make_unique(s), typ, constraints))
        }
    }

    fn make_unique(&mut self, name: ~str) -> Name {
        self.unique_id += 1;
        let u = Name { name: name.clone(), uid: self.unique_id};
        self.uniques.insert(name, u.clone());
        u
    }
}

fn lift_lambdas_expr<T>(expr: Expr<T>, out_lambdas: &mut Vec<Binding<T>>) -> Expr<T> {
    match expr {
        Apply(func, arg) => Apply(~lift_lambdas_expr(*func, out_lambdas), ~lift_lambdas_expr(*arg, out_lambdas)),
        Lambda(arg, body) => Lambda(arg, ~lift_lambdas_expr(*body, out_lambdas)),
        Let(bindings, expr) => {
            let mut new_binds = Vec::new();
            for Binding { name: name, expression: expression } in bindings.move_iter() {
                let is_lambda = match &expression {
                    &Lambda(..) => true,
                    _ => false
                };
                let bind = Binding { name: name, expression: lift_lambdas_expr(expression, out_lambdas) };
                if is_lambda {
                    out_lambdas.push(bind);
                }
                else {
                    new_binds.push(bind);
                }
            }
            if new_binds.len() == 0 {
                lift_lambdas_expr(*expr, out_lambdas)
            }
            else {
                Let(new_binds.move_iter().collect(), ~lift_lambdas_expr(*expr, out_lambdas))
            }
        }
        Case(expr, alts) => {
            let a = alts.move_iter().map(|Alternative { pattern: pattern, expression: expression }| {
                Alternative { pattern: pattern, expression: lift_lambdas_expr(expression, out_lambdas) }
            }).collect();
            Case(~lift_lambdas_expr(*expr, out_lambdas), a)
        }
        _ => expr
    }
}
pub fn lift_lambdas<T: ::std::fmt::Show>(module: Module<T>) -> Module<T> {
    let Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings,
        instances: instances
    } = module;

    let mut new_bindings : Vec<Binding<T>> = Vec::new();
    let bindings2 : ~[Binding<T>] = bindings.move_iter().map(|Binding { name: name, expression: expression }| {
        Binding { name: name, expression: lift_lambdas_expr(expression, &mut new_bindings) }
    }).collect();

    Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings2.move_iter().chain(new_bindings.move_iter()).collect(),
        instances: instances
    }
}

pub fn rename_module(module: Module<TypeAndStr>) -> Module<Id> {
    let mut renamer = Renamer { uniques: ScopedMap::new(), unique_id: 1 };
    let Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings,
        instances: instances
    } = module;

    let bindings2 = bindings.move_iter().map(|binding| {
        let Binding { name: (constraints, typ, name), expression: expression } = binding;
        Binding {
            name: Id::new(Name { name: name, uid: 0 }, typ, constraints),
            expression: renamer.rename(expression)
        }
    }).collect();

    Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings2,
        instances: instances
    }
}
pub fn abstract_module(module: Module<TypeAndStr>) -> Module<TypeAndStr> {
    each_binding(module,
        |name| name,
        |bind| {
            let Binding { name: name, expression: bind_expr } = bind;
            let mut variables = HashMap::new();
            let mut free_vars = HashMap::new();
            let e = free_variables(&mut variables, &mut free_vars, bind_expr);
            Binding { name: name, expression: e }
        })
}

pub fn each_binding<Ident, Ident2>(module: Module<Ident>, _trans: |Ident| -> Ident2, bind_f: |Binding<Ident>| -> Binding<Ident2>) -> Module<Ident2> {
    let Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings,
        instances: instances
    } = module;

    let bindings2 = bindings.move_iter().map(|x| bind_f(x)).collect();

    Module {
        classes : classes,
        data_definitions: data_definitions,
        bindings : bindings2,
        instances: instances
    }
}

#[cfg(test)]
mod tests {
    use lambda_lift::*;
    use collections::hashmap::HashSet;
    use parser::Parser;
    use core::*;
    use core::translate::translate_module;

    struct CheckUniques {
        found: HashSet<Id>
    }

    impl Visitor<Id> for CheckUniques {
        fn visit_binding(&mut self, bind: &Binding<Id>) {
            assert!(self.found.insert(bind.name.clone()));
            self.visit_expr(&bind.expression);
        }
        fn visit_expr(&mut self, expr: &Expr<Id>) {
            match expr {
                &Lambda(ref i, _) => {
                    assert!(self.found.insert(i.clone()));
                }
                _ => ()
            }
            walk_expr(self, expr)
        }
    }

    #[test]
    fn all_uniques() {
        let mut visitor = CheckUniques { found: HashSet::new() };
        let mut parser = Parser::new(
r"add x y = 2
test = 3.14
test2 x =
    let
        test = 2
        f x =
            let g y = add x (f y)
            in add x test
    in f x".chars());
        let m = translate_module(parser.module());
        let module = rename_module(m);
        (&mut visitor as &mut Visitor<Id>).visit_module(&module);
    }

    fn check_args(expr: &Expr<Id>, args: &[&str]) -> bool {
        match expr {
            &Lambda(ref arg, ref body) => arg.name.name.equiv(&args[0]) && check_args(*body, args.slice_from(1)),
            _ => args.len() == 0
        }
    }

    struct CheckAbstract {
        count: int
    }

    fn get_let<'a>(expr: &'a Expr<Id>, args: &mut Vec<&'a str>) -> &'a Expr<Id> {
        match expr {
            &Apply(ref f, ref arg) => {
                let a: &Expr<Id> = *arg;
                match a {
                    &Identifier(ref i) => args.push(i.name.name.as_slice()),
                    _ => fail!("Expected identifier as argument")
                }
                get_let(*f, args)
            }
            _ => expr
        }
    }

    impl Visitor<Id> for CheckAbstract {
        fn visit_binding(&mut self, bind: &Binding<Id>) {
            if "f" == bind.name.name.name {
                let mut args = Vec::new();
                match get_let(&bind.expression, &mut args) {
                    &Let(ref binds, ref body) => {
                        //Push the argument of the function itself
                        args.push("x");
                        assert!(check_args(&binds[0].expression, args.as_slice()));
                        assert_eq!(Identifier(binds[0].name.clone()), **body);
                    }
                    _ => assert!(false, "Expected Let, found {}", bind.expression)
                }
                self.count += 1;
            }
            else if "g" == bind.name.name.name {
                let mut args = Vec::new();
                match get_let(&bind.expression, &mut args) {
                    &Let(ref binds, ref body) => {
                        args.push("y");
                        assert!(check_args(&binds[0].expression, args.as_slice()));
                        assert_eq!(Identifier(binds[0].name.clone()), **body);
                    }
                    _ => assert!(false, "Expected Let")
                }
                self.count += 1;
            }
            self.visit_expr(&bind.expression);
        }
    }

    #[test]
    fn all_free_vars() {
        let mut visitor = CheckAbstract { count: 0 };
        let mut parser = Parser::new(
r"add x y = 2
test = 3.14
test2 x =
    let
        test = 2
        f x =
            let g y = add x (f y)
            in add x test
    in f x".chars());
        let m = translate_module(parser.module());
        let module = rename_module(abstract_module(m));
        (&mut visitor as &mut Visitor<Id>).visit_module(&module);
        assert_eq!(visitor.count, 2);
    }

    struct NoLambdas;

    impl <T> Visitor<T> for NoLambdas {
        fn visit_expr(&mut self, expr: &Expr<T>) {
            match expr {
                &Lambda(..) => assert!(false, "Found lambda in expression"),
                _ => ()
            }
            walk_expr(self, expr);
        }
    }
    #[test]
    fn no_local_lambdas() {
        fn skip_lambdas<'a, T>(expr: &'a Expr<T>) -> &'a Expr<T> {
            match expr {
                &Lambda(_, ref body) => skip_lambdas(*body),
                _ => expr
            }
        }

        let mut visitor = NoLambdas;
        let mut parser = Parser::new(
r"add x y = 2
test = 3.14
test2 x =
    let
        test = 2
        f x =
            let g y = add x (f y)
            in add x test
    in f x".chars());
        let m = translate_module(parser.module());
        let module = lift_lambdas(m);
        for bind in module.bindings.iter() {
            (&mut visitor as &mut Visitor<TypeAndStr>).visit_expr(skip_lambdas(&bind.expression));
        }
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate arg_parser;
extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

use arg_parser::ArgParser;

#[cfg(target_os = "redox")]
fn df(path: &str, parser: &ArgParser) -> ::std::io::Result<()> {
    use coreutils::to_human_readable_string;
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64;
    let free = stat.f_bavail * stat.f_bsize as u64;
    let percent = (100.0 * used as f64 / size as f64) as u64;

    if parser.found("human-readable") {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 to_human_readable_string(size),
                 to_human_readable_string(used),
                 to_human_readable_string(free),
                 format!("{}%", percent));
    } else {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 (size + 1023)/1024,
                 (used + 1023)/1024,
                 (free + 1023)/1024,
                 format!("{}%", percent));
    }

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use arg_parser::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --human-readable
            human readable output
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "human-readable"])
        .add_flag(&["help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<10}{:>10}{:>10}{:>10}{:>5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)), &parser);
        }
    } else {
        for path in &parser.args {
            df(&path, &parser).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<commit_msg>Removed unused import.<commit_after>#![deny(warnings)]

extern crate arg_parser;
extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn df(path: &str, parser: &ArgParser) -> ::std::io::Result<()> {
    use coreutils::to_human_readable_string;
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64;
    let free = stat.f_bavail * stat.f_bsize as u64;
    let percent = (100.0 * used as f64 / size as f64) as u64;

    if parser.found("human-readable") {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 to_human_readable_string(size),
                 to_human_readable_string(used),
                 to_human_readable_string(free),
                 format!("{}%", percent));
    } else {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 (size + 1023)/1024,
                 (used + 1023)/1024,
                 (free + 1023)/1024,
                 format!("{}%", percent));
    }

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use arg_parser::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --human-readable
            human readable output
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "human-readable"])
        .add_flag(&["help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<10}{:>10}{:>10}{:>10}{:>5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)), &parser);
        }
    } else {
        for path in &parser.args {
            df(&path, &parser).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<|endoftext|>


<commit_before>// Copyright 2020 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::{
    sync::Arc,
    time::{Duration, Instant},
};
use sync::Mutex;

use super::{Event, EventReadResult, FakeClock, RawDescriptor, Result};
use crate::descriptor::{AsRawDescriptor, FromRawDescriptor, IntoRawDescriptor, SafeDescriptor};

pub struct Timer {
    pub(crate) handle: SafeDescriptor,
    pub(crate) interval: Option<Duration>,
}

impl Timer {
    /// Creates a new `Timer` instance that shares the same underlying `SafeDescriptor` as the
    /// existing `Timer` instance.
    pub fn try_clone(&self) -> std::result::Result<Timer, std::io::Error> {
        self.handle
            .try_clone()
            .map(|handle| Timer {
                handle,
                interval: self.interval,
            })
            .map_err(|err| std::io::Error::from_raw_os_error(err.errno()))
    }
}

// This enum represents those two different retrun values from a "wait" call. Either the
// timer will "expire", meaning it has reached it's duration, or the caller will time out
// waiting for the timer to expire. If no timeout option is provieded to the wait call
// then it can only return WaitResult::Expired or an error.
#[derive(PartialEq, Debug)]
pub enum WaitResult {
    Expired,
    Timeout,
}

impl AsRawDescriptor for Timer {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.handle.as_raw_descriptor()
    }
}

impl FromRawDescriptor for Timer {
    unsafe fn from_raw_descriptor(handle: RawDescriptor) -> Self {
        Timer {
            handle: SafeDescriptor::from_raw_descriptor(handle),
            interval: None,
        }
    }
}

impl IntoRawDescriptor for Timer {
    fn into_raw_descriptor(self) -> RawDescriptor {
        self.handle.into_raw_descriptor()
    }
}

/// FakeTimer: For use in tests.
pub struct FakeTimer {
    clock: Arc<Mutex<FakeClock>>,
    deadline_ns: Option<u64>,
    interval: Option<Duration>,
    event: Event,
}

impl FakeTimer {
    /// Creates a new fake Timer.  The timer is initally disarmed and must be armed by calling
    /// `reset`.
    pub fn new(clock: Arc<Mutex<FakeClock>>) -> Self {
        FakeTimer {
            clock,
            deadline_ns: None,
            interval: None,
            event: Event::new().unwrap(),
        }
    }

    /// Sets the timer to expire after `dur`.  If `interval` is not `None` it represents
    /// the period for repeated expirations after the initial expiration.  Otherwise
    /// the timer will expire just once.  Cancels any existing duration and repeating interval.
    pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()> {
        let mut guard = self.clock.lock();
        let deadline = guard.nanos() + dur.as_nanos() as u64;
        self.deadline_ns = Some(deadline);
        self.interval = interval;
        guard.add_event(deadline, self.event.try_clone()?);
        Ok(())
    }

    /// Waits until the timer expires, returning WaitResult::Expired when it expires.
    ///
    /// If timeout is not None, block for a maximum of the given `timeout` duration.
    /// If a timeout occurs, return WaitResult::Timeout.
    pub fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
        let wait_start = Instant::now();
        loop {
            if let Some(timeout) = timeout {
                let elapsed = Instant::now() - wait_start;
                if let Some(remaining) = elapsed.checked_sub(timeout) {
                    if let EventReadResult::Timeout = self.event.read_timeout(remaining)? {
                        return Ok(WaitResult::Timeout);
                    }
                } else {
                    return Ok(WaitResult::Timeout);
                }
            } else {
                self.event.read()?;
            }

            if let Some(deadline_ns) = &mut self.deadline_ns {
                let mut guard = self.clock.lock();
                let now = guard.nanos();
                if now >= *deadline_ns {
                    let mut expirys = 0;
                    if let Some(interval) = self.interval {
                        let interval_ns = interval.as_nanos() as u64;
                        if interval_ns > 0 {
                            expirys += (now - *deadline_ns) / interval_ns;
                            *deadline_ns += (expirys + 1) * interval_ns;
                            guard.add_event(*deadline_ns, self.event.try_clone()?);
                        }
                    }
                    return Ok(WaitResult::Expired);
                }
            }
        }
    }

    /// Block for a maximum of the given `timeout` duration.
    /// If a timeout occurs, return WaitResult::Timeout.
    pub fn wait(&mut self) -> Result<WaitResult> {
        self.wait_for(None)
    }

    /// After a timer is triggered from an EventContext, mark the timer as having been waited for.
    /// If a timer is not marked waited, it will immediately trigger the event context again. This
    /// does not need to be called after calling Timer::wait.
    ///
    /// Returns true if the timer has been adjusted since the EventContext was triggered by this
    /// timer.
    pub fn mark_waited(&mut self) -> Result<bool> {
        // Just do a self.wait with a timeout of 0. If it times out then the timer has been
        // adjusted.
        if let WaitResult::Timeout = self.wait_for(Some(Duration::from_secs(0)))? {
            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Disarms the timer.
    pub fn clear(&mut self) -> Result<()> {
        self.deadline_ns = None;
        self.interval = None;
        Ok(())
    }

    /// Returns the resolution of timers on the host.
    pub fn resolution() -> Result<Duration> {
        Ok(Duration::from_nanos(1))
    }
}

impl AsRawDescriptor for FakeTimer {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.event.as_raw_descriptor()
    }
}
impl IntoRawDescriptor for FakeTimer {
    fn into_raw_descriptor(self) -> RawDescriptor {
        self.event.into_raw_descriptor()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::time::{Duration, Instant};

    // clock error is 2*clock_resolution + 100 microseconds to handle
    // time change from calling now() to arming timer
    fn get_clock_error() -> Duration {
        Timer::resolution()
            .expect("expected to be able to read timer resolution")
            .checked_mul(2)
            .expect("timer resolution x 2 should not overflow")
            .checked_add(Duration::from_micros(100))
            .expect("timer resolution x 2 + 100 microsecond should not overflow")
    }

    #[test]
    #[ignore]
    fn one_shot() {
        // This test relies on the host having a reliable clock and not being
        // overloaded, so it's marked as "ignore".  You can run by running
        // cargo test -p win_sys_util timer -- --ignored

        let mut tfd = Timer::new().expect("failed to create Timer");

        let dur = Duration::from_millis(1000);
        let clock_error = get_clock_error();

        let now = Instant::now();
        tfd.reset(dur, None).expect("failed to arm timer");

        tfd.wait().expect("unable to wait for timer");
        let elapsed = now.elapsed();
        // elapsed is within +-clock_error from expected duration
        assert!(elapsed - clock_error <= dur);
        assert!(elapsed + clock_error >= dur);
    }

    /// Similar to one_shot, except this one waits for a clone of the timer.
    #[test]
    #[ignore]
    fn one_shot_cloned() {
        let mut tfd = Timer::new().expect("failed to create Timer");
        let dur = Duration::from_millis(1000);
        let mut cloned_tfd = tfd.try_clone().expect("failed to clone timer");

        // clock error is 2*clock_resolution + 100 microseconds to handle
        // time change from calling now() to arming timer
        let clock_error = get_clock_error();

        let now = Instant::now();
        tfd.reset(dur, None).expect("failed to arm timer");
        cloned_tfd.wait().expect("unable to wait for timer");
        let elapsed = now.elapsed();

        // elapsed is within +-clock_error from expected duration
        assert!(elapsed - clock_error <= dur);
        assert!(elapsed + clock_error >= dur);
    }

    #[test]
    #[ignore]
    fn repeating() {
        // This test relies on the host having a reliable clock and not being
        // overloaded, so it's marked as "ignore".  You can run by running
        // cargo test -p win_sys_util timer -- --ignored

        let mut tfd = Timer::new().expect("failed to create Timer");

        let dur = Duration::from_millis(200);
        // clock error is 2*clock_resolution + 100 microseconds to handle
        // time change from calling now() to arming timer
        let clock_error = Timer::resolution()
            .expect("expected to be able to read timer resolution")
            .checked_mul(2)
            .expect("timer resolution x 2 should not overflow")
            .checked_add(Duration::from_micros(100))
            .expect("timer resolution x 2 + 100 microsecond should not overflow");
        let interval = Duration::from_millis(100);
        let now = Instant::now();
        tfd.reset(dur, Some(interval)).expect("failed to arm timer");

        tfd.wait().expect("unable to wait for timer");
        // should take "dur" duration for the first wait
        assert!(now.elapsed() + clock_error >= dur);
        tfd.wait().expect("unable to wait for timer");
        // subsequent waits should take "interval" duration
        assert!(now.elapsed() + clock_error >= dur + interval);
        tfd.wait().expect("unable to wait for timer");
        assert!(now.elapsed() + clock_error >= dur + interval * 2);
    }

    #[test]
    fn fake_one_shot() {
        let clock = Arc::new(Mutex::new(FakeClock::new()));
        let mut tfd = FakeTimer::new(clock.clone());

        let dur = Duration::from_nanos(200);
        tfd.reset(dur, None).expect("failed to arm timer");

        clock.lock().add_ns(200);

        let result = tfd.wait().expect("unable to wait for timer");

        assert_eq!(result, WaitResult::Expired);
    }

    #[test]
    fn fake_one_shot_timeout() {
        let clock = Arc::new(Mutex::new(FakeClock::new()));
        let mut tfd = FakeTimer::new(clock.clone());

        let dur = Duration::from_nanos(200);
        tfd.reset(dur, None).expect("failed to arm timer");

        clock.lock().add_ns(100);
        let result = tfd
            .wait_for(Some(Duration::from_millis(0)))
            .expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Timeout);
        let result = tfd
            .wait_for(Some(Duration::from_millis(1)))
            .expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Timeout);

        clock.lock().add_ns(100);
        let result = tfd
            .wait_for(Some(Duration::from_millis(0)))
            .expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Expired);
    }

    #[test]
    fn fake_repeating() {
        let clock = Arc::new(Mutex::new(FakeClock::new()));
        let mut tfd = FakeTimer::new(clock.clone());

        let dur = Duration::from_nanos(200);
        let interval = Duration::from_nanos(100);
        tfd.reset(dur, Some(interval)).expect("failed to arm timer");

        clock.lock().add_ns(300);

        let mut result = tfd.wait().expect("unable to wait for timer");
        // An expiration from the initial expiry and from 1 repeat.
        assert_eq!(result, WaitResult::Expired);

        clock.lock().add_ns(300);
        result = tfd.wait().expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Expired);
    }

    #[test]
    #[ignore]
    fn zero_interval() {
        // This test relies on the host having a reliable clock and not being
        // overloaded, so it's marked as "ignore".  You can run by running
        // cargo test -p win_sys_util timer -- --ignored

        let mut tfd = Timer::new().expect("failed to create timer");

        let dur = Duration::from_nanos(200);
        // interval is 0, so should not repeat
        let interval = Duration::from_nanos(0);

        tfd.reset(dur, Some(interval)).expect("failed to arm timer");

        // should wait successfully the first time
        tfd.wait().expect("unable to wait for timer");

        // now this wait should timeout
        let wr = tfd
            .wait_for(Some(Duration::from_secs(1)))
            .expect("unable to wait on timer");

        assert_eq!(wr, WaitResult::Timeout);
    }
}
<commit_msg>base: timer: fix crate name in ignored tests<commit_after>// Copyright 2020 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::{
    sync::Arc,
    time::{Duration, Instant},
};
use sync::Mutex;

use super::{Event, EventReadResult, FakeClock, RawDescriptor, Result};
use crate::descriptor::{AsRawDescriptor, FromRawDescriptor, IntoRawDescriptor, SafeDescriptor};

pub struct Timer {
    pub(crate) handle: SafeDescriptor,
    pub(crate) interval: Option<Duration>,
}

impl Timer {
    /// Creates a new `Timer` instance that shares the same underlying `SafeDescriptor` as the
    /// existing `Timer` instance.
    pub fn try_clone(&self) -> std::result::Result<Timer, std::io::Error> {
        self.handle
            .try_clone()
            .map(|handle| Timer {
                handle,
                interval: self.interval,
            })
            .map_err(|err| std::io::Error::from_raw_os_error(err.errno()))
    }
}

// This enum represents those two different retrun values from a "wait" call. Either the
// timer will "expire", meaning it has reached it's duration, or the caller will time out
// waiting for the timer to expire. If no timeout option is provieded to the wait call
// then it can only return WaitResult::Expired or an error.
#[derive(PartialEq, Debug)]
pub enum WaitResult {
    Expired,
    Timeout,
}

impl AsRawDescriptor for Timer {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.handle.as_raw_descriptor()
    }
}

impl FromRawDescriptor for Timer {
    unsafe fn from_raw_descriptor(handle: RawDescriptor) -> Self {
        Timer {
            handle: SafeDescriptor::from_raw_descriptor(handle),
            interval: None,
        }
    }
}

impl IntoRawDescriptor for Timer {
    fn into_raw_descriptor(self) -> RawDescriptor {
        self.handle.into_raw_descriptor()
    }
}

/// FakeTimer: For use in tests.
pub struct FakeTimer {
    clock: Arc<Mutex<FakeClock>>,
    deadline_ns: Option<u64>,
    interval: Option<Duration>,
    event: Event,
}

impl FakeTimer {
    /// Creates a new fake Timer.  The timer is initally disarmed and must be armed by calling
    /// `reset`.
    pub fn new(clock: Arc<Mutex<FakeClock>>) -> Self {
        FakeTimer {
            clock,
            deadline_ns: None,
            interval: None,
            event: Event::new().unwrap(),
        }
    }

    /// Sets the timer to expire after `dur`.  If `interval` is not `None` it represents
    /// the period for repeated expirations after the initial expiration.  Otherwise
    /// the timer will expire just once.  Cancels any existing duration and repeating interval.
    pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()> {
        let mut guard = self.clock.lock();
        let deadline = guard.nanos() + dur.as_nanos() as u64;
        self.deadline_ns = Some(deadline);
        self.interval = interval;
        guard.add_event(deadline, self.event.try_clone()?);
        Ok(())
    }

    /// Waits until the timer expires, returning WaitResult::Expired when it expires.
    ///
    /// If timeout is not None, block for a maximum of the given `timeout` duration.
    /// If a timeout occurs, return WaitResult::Timeout.
    pub fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
        let wait_start = Instant::now();
        loop {
            if let Some(timeout) = timeout {
                let elapsed = Instant::now() - wait_start;
                if let Some(remaining) = elapsed.checked_sub(timeout) {
                    if let EventReadResult::Timeout = self.event.read_timeout(remaining)? {
                        return Ok(WaitResult::Timeout);
                    }
                } else {
                    return Ok(WaitResult::Timeout);
                }
            } else {
                self.event.read()?;
            }

            if let Some(deadline_ns) = &mut self.deadline_ns {
                let mut guard = self.clock.lock();
                let now = guard.nanos();
                if now >= *deadline_ns {
                    let mut expirys = 0;
                    if let Some(interval) = self.interval {
                        let interval_ns = interval.as_nanos() as u64;
                        if interval_ns > 0 {
                            expirys += (now - *deadline_ns) / interval_ns;
                            *deadline_ns += (expirys + 1) * interval_ns;
                            guard.add_event(*deadline_ns, self.event.try_clone()?);
                        }
                    }
                    return Ok(WaitResult::Expired);
                }
            }
        }
    }

    /// Block for a maximum of the given `timeout` duration.
    /// If a timeout occurs, return WaitResult::Timeout.
    pub fn wait(&mut self) -> Result<WaitResult> {
        self.wait_for(None)
    }

    /// After a timer is triggered from an EventContext, mark the timer as having been waited for.
    /// If a timer is not marked waited, it will immediately trigger the event context again. This
    /// does not need to be called after calling Timer::wait.
    ///
    /// Returns true if the timer has been adjusted since the EventContext was triggered by this
    /// timer.
    pub fn mark_waited(&mut self) -> Result<bool> {
        // Just do a self.wait with a timeout of 0. If it times out then the timer has been
        // adjusted.
        if let WaitResult::Timeout = self.wait_for(Some(Duration::from_secs(0)))? {
            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Disarms the timer.
    pub fn clear(&mut self) -> Result<()> {
        self.deadline_ns = None;
        self.interval = None;
        Ok(())
    }

    /// Returns the resolution of timers on the host.
    pub fn resolution() -> Result<Duration> {
        Ok(Duration::from_nanos(1))
    }
}

impl AsRawDescriptor for FakeTimer {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.event.as_raw_descriptor()
    }
}
impl IntoRawDescriptor for FakeTimer {
    fn into_raw_descriptor(self) -> RawDescriptor {
        self.event.into_raw_descriptor()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::time::{Duration, Instant};

    // clock error is 2*clock_resolution + 100 microseconds to handle
    // time change from calling now() to arming timer
    fn get_clock_error() -> Duration {
        Timer::resolution()
            .expect("expected to be able to read timer resolution")
            .checked_mul(2)
            .expect("timer resolution x 2 should not overflow")
            .checked_add(Duration::from_micros(100))
            .expect("timer resolution x 2 + 100 microsecond should not overflow")
    }

    #[test]
    #[ignore]
    fn one_shot() {
        // This test relies on the host having a reliable clock and not being
        // overloaded, so it's marked as "ignore".  You can run by running
        // cargo test -p base timer -- --ignored

        let mut tfd = Timer::new().expect("failed to create Timer");

        let dur = Duration::from_millis(1000);
        let clock_error = get_clock_error();

        let now = Instant::now();
        tfd.reset(dur, None).expect("failed to arm timer");

        tfd.wait().expect("unable to wait for timer");
        let elapsed = now.elapsed();
        // elapsed is within +-clock_error from expected duration
        assert!(elapsed - clock_error <= dur);
        assert!(elapsed + clock_error >= dur);
    }

    /// Similar to one_shot, except this one waits for a clone of the timer.
    #[test]
    #[ignore]
    fn one_shot_cloned() {
        let mut tfd = Timer::new().expect("failed to create Timer");
        let dur = Duration::from_millis(1000);
        let mut cloned_tfd = tfd.try_clone().expect("failed to clone timer");

        // clock error is 2*clock_resolution + 100 microseconds to handle
        // time change from calling now() to arming timer
        let clock_error = get_clock_error();

        let now = Instant::now();
        tfd.reset(dur, None).expect("failed to arm timer");
        cloned_tfd.wait().expect("unable to wait for timer");
        let elapsed = now.elapsed();

        // elapsed is within +-clock_error from expected duration
        assert!(elapsed - clock_error <= dur);
        assert!(elapsed + clock_error >= dur);
    }

    #[test]
    #[ignore]
    fn repeating() {
        // This test relies on the host having a reliable clock and not being
        // overloaded, so it's marked as "ignore".  You can run by running
        // cargo test -p base timer -- --ignored

        let mut tfd = Timer::new().expect("failed to create Timer");

        let dur = Duration::from_millis(200);
        // clock error is 2*clock_resolution + 100 microseconds to handle
        // time change from calling now() to arming timer
        let clock_error = Timer::resolution()
            .expect("expected to be able to read timer resolution")
            .checked_mul(2)
            .expect("timer resolution x 2 should not overflow")
            .checked_add(Duration::from_micros(100))
            .expect("timer resolution x 2 + 100 microsecond should not overflow");
        let interval = Duration::from_millis(100);
        let now = Instant::now();
        tfd.reset(dur, Some(interval)).expect("failed to arm timer");

        tfd.wait().expect("unable to wait for timer");
        // should take "dur" duration for the first wait
        assert!(now.elapsed() + clock_error >= dur);
        tfd.wait().expect("unable to wait for timer");
        // subsequent waits should take "interval" duration
        assert!(now.elapsed() + clock_error >= dur + interval);
        tfd.wait().expect("unable to wait for timer");
        assert!(now.elapsed() + clock_error >= dur + interval * 2);
    }

    #[test]
    fn fake_one_shot() {
        let clock = Arc::new(Mutex::new(FakeClock::new()));
        let mut tfd = FakeTimer::new(clock.clone());

        let dur = Duration::from_nanos(200);
        tfd.reset(dur, None).expect("failed to arm timer");

        clock.lock().add_ns(200);

        let result = tfd.wait().expect("unable to wait for timer");

        assert_eq!(result, WaitResult::Expired);
    }

    #[test]
    fn fake_one_shot_timeout() {
        let clock = Arc::new(Mutex::new(FakeClock::new()));
        let mut tfd = FakeTimer::new(clock.clone());

        let dur = Duration::from_nanos(200);
        tfd.reset(dur, None).expect("failed to arm timer");

        clock.lock().add_ns(100);
        let result = tfd
            .wait_for(Some(Duration::from_millis(0)))
            .expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Timeout);
        let result = tfd
            .wait_for(Some(Duration::from_millis(1)))
            .expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Timeout);

        clock.lock().add_ns(100);
        let result = tfd
            .wait_for(Some(Duration::from_millis(0)))
            .expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Expired);
    }

    #[test]
    fn fake_repeating() {
        let clock = Arc::new(Mutex::new(FakeClock::new()));
        let mut tfd = FakeTimer::new(clock.clone());

        let dur = Duration::from_nanos(200);
        let interval = Duration::from_nanos(100);
        tfd.reset(dur, Some(interval)).expect("failed to arm timer");

        clock.lock().add_ns(300);

        let mut result = tfd.wait().expect("unable to wait for timer");
        // An expiration from the initial expiry and from 1 repeat.
        assert_eq!(result, WaitResult::Expired);

        clock.lock().add_ns(300);
        result = tfd.wait().expect("unable to wait for timer");
        assert_eq!(result, WaitResult::Expired);
    }

    #[test]
    #[ignore]
    fn zero_interval() {
        // This test relies on the host having a reliable clock and not being
        // overloaded, so it's marked as "ignore".  You can run by running
        // cargo test -p base timer -- --ignored

        let mut tfd = Timer::new().expect("failed to create timer");

        let dur = Duration::from_nanos(200);
        // interval is 0, so should not repeat
        let interval = Duration::from_nanos(0);

        tfd.reset(dur, Some(interval)).expect("failed to arm timer");

        // should wait successfully the first time
        tfd.wait().expect("unable to wait for timer");

        // now this wait should timeout
        let wr = tfd
            .wait_for(Some(Duration::from_secs(1)))
            .expect("unable to wait on timer");

        assert_eq!(wr, WaitResult::Timeout);
    }
}
<|endoftext|>


<commit_before><commit_msg>Reword and fix typos in some error descriptions and docs<commit_after><|endoftext|>


<commit_before><commit_msg>Add #[inline] to cast methods<commit_after><|endoftext|>


<commit_before>extern crate glm;
extern crate sdl2;

use self::sdl2::rect;
use self::sdl2::render::{Renderer, Texture};

pub struct Meteor {
    texture: Texture,
    center: glm::Vector2<f64>,
    dims: glm::Vector2<u32>,
    max_coords: glm::Vector2<u32>,
    velocity: glm::Vector2<f64>,
    launched: bool,
}

impl Meteor {
    pub fn new(texture: Texture, max_coords: glm::Vector2<u32>) -> Self {
        let query = texture.query();
        let center = glm::dvec2(0., 0.);
        let dims = glm::uvec2(query.width, query.height);

        Meteor {
            texture: texture,
            center: center,
            dims: dims,
            max_coords: max_coords,
            velocity: glm::dvec2(0., 0.),
            launched: false,
        }
    }

    pub fn launch(&mut self, target: glm::Vector2<f64>) {
        const FACTOR: f64 = 85.;
        let offset = target - self.center;
        self.velocity = glm::dvec2(offset.x as f64 / FACTOR, offset.y as f64 / FACTOR);
        self.launched = true;
    }

    pub fn update(&mut self) {
        self.center.y += self.velocity.y;
        self.center.x += self.velocity.x;

        let max_height = self.max_coords.y as f64;
        let max_width = self.max_coords.x as f64;

        self.center.y = (self.center.y + max_height) % max_height;
        self.center.x = (self.center.x + max_width) % max_width;
    }

    pub fn is_launched(&self) -> bool {
        self.launched
    }

    pub fn draw(&self, renderer: &mut Renderer) -> Result<(), String> {
        self.drawing_rectangles()
            .iter()
            .filter(|r| r.is_some())
            .map(|&r| renderer.copy(&self.texture, None, r))
            .fold(Ok(()), |res, x| { if res.is_err() { res } else { x } })
    }

    fn drawing_rectangles(&self) -> [Option<rect::Rect>; 4] {
        let top = self.center.y as i32 - self.dims.y as i32 / 2;
        let bottom = self.center.y as i32 + self.dims.y as i32 / 2;
        let left = self.center.x as i32 - self.dims.x as i32 / 2;
        let right = self.center.x as i32 + self.dims.x as i32 / 2;

        let rect = rect::Rect::new(left, top, self.dims.x, self.dims.y);
        let mut rects: [Option<rect::Rect>; 4] = [Some(rect), None, None, None];
        let mut count = 1;

        let max_height = self.max_coords.y as i32;
        let max_width = self.max_coords.x as i32;

        if top < 0 {
            let mut rect = rect.clone();
            rect.set_y(top + max_height);
            rects[count] = Some(rect);
            count += 1;

            if left < 0 {
                rect.set_x(left + max_width);
                rects[count] = Some(rect);
                count += 1;
            } else if right > max_width {
                rect.set_right(right % max_width);
                rects[count] = Some(rect);
                count += 1;
            }
        } else if bottom > max_height {
            let mut rect = rect.clone();
            rect.set_bottom(bottom % max_height);
            rects[count] = Some(rect);
            count += 1;

            if left < 0 {
                rect.set_x(left + max_width);
                rects[count] = Some(rect);
                count += 1;
            } else if right > max_width {
                rect.set_right(right % max_width);
                rects[count] = Some(rect);
                count += 1;
            }
        }

        if left < 0 {
            let mut rect = rect.clone();
            rect.set_x(left + max_width);
            rects[count] = Some(rect);
        } else if right > max_width {
            let mut rect = rect.clone();
            rect.set_right(right % max_width);
            rects[count] = Some(rect);
        }

        rects
    }
}
<commit_msg>refactored drawing of meteor rectangles<commit_after>extern crate glm;
extern crate sdl2;

use self::sdl2::rect;
use self::sdl2::render::{Renderer, Texture};

pub struct Meteor {
    texture: Texture,
    center: glm::Vector2<f64>,
    dims: glm::Vector2<u32>,
    max_coords: glm::Vector2<u32>,
    velocity: glm::Vector2<f64>,
    launched: bool,
}

impl Meteor {
    pub fn new(texture: Texture, max_coords: glm::Vector2<u32>) -> Self {
        let query = texture.query();
        let center = glm::dvec2(0., 0.);
        let dims = glm::uvec2(query.width, query.height);

        Meteor {
            texture: texture,
            center: center,
            dims: dims,
            max_coords: max_coords,
            velocity: glm::dvec2(0., 0.),
            launched: false,
        }
    }

    pub fn launch(&mut self, target: glm::Vector2<f64>) {
        const FACTOR: f64 = 85.;
        let offset = target - self.center;
        self.velocity = glm::dvec2(offset.x as f64 / FACTOR, offset.y as f64 / FACTOR);
        self.launched = true;
    }

    pub fn update(&mut self) {
        self.center.y += self.velocity.y;
        self.center.x += self.velocity.x;

        let max_height = self.max_coords.y as f64;
        let max_width = self.max_coords.x as f64;

        self.center.y = (self.center.y + max_height) % max_height;
        self.center.x = (self.center.x + max_width) % max_width;
    }

    pub fn is_launched(&self) -> bool {
        self.launched
    }

    pub fn draw(&self, renderer: &mut Renderer) -> Result<(), String> {
        self.drawing_rectangles()
            .iter()
            .filter(|r| r.is_some())
            .map(|&r| renderer.copy(&self.texture, None, r))
            .fold(Ok(()), |res, x| { if res.is_err() { res } else { x } })
    }

    fn drawing_rectangles(&self) -> [Option<rect::Rect>; 4] {
        let left = self.center.x as i32 - self.dims.x as i32 / 2;
        let top = self.center.y as i32 - self.dims.y as i32 / 2;

        let rect = rect::Rect::new(left, top, self.dims.x, self.dims.y);
        let side_rect = self.side_rect(&rect);
        let vert_rect = self.vert_rect(&rect);

        let side_vert_rect = match vert_rect {
            Some(unwrapped) => self.side_rect(&unwrapped),
            None => None,
        };

        [Some(rect), vert_rect, side_rect, side_vert_rect]
    }

    fn vert_rect(&self, original: &rect::Rect) -> Option<rect::Rect> {
        let bottom = self.center.y as i32 + self.dims.y as i32 / 2;
        let top = self.center.y as i32 - self.dims.y as i32 / 2;
        let max_height = self.max_coords.y as i32;

        let mut copy = original.clone();

        if top < 0 {
            copy.set_y(top + max_height);
            Some(copy)
        } else if bottom > max_height {
            copy.set_bottom(bottom % max_height);
            Some(copy)
        } else {
            None
        }

    }

    fn side_rect(&self, original: &rect::Rect) -> Option<rect::Rect> {
        let left = self.center.x as i32 - self.dims.x as i32 / 2;
        let right = self.center.x as i32 + self.dims.x as i32 / 2;
        let max_width = self.max_coords.x as i32;

        let mut copy = original.clone();

        if left < 0 {
            copy.set_x(left + max_width);
            Some(copy)
        } else if right > max_width {
            copy.set_right(right % max_width);
            Some(copy)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>avoid materializing substituted $e hyps<commit_after><|endoftext|>


<commit_before>use proc_macro2::TokenStream;

use quote::ToTokens;

use shared::path;

use std::path::PathBuf;

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub source: Source,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<String>,
    pub parent: Option<&'a syn::Type>,
    pub path: PathBuf,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let mut meta = None;
        for attr in &ast.attrs {
            match attr.interpret_meta() {
                Some(m) => if m.name() == "template" {
                    meta = Some(m)
                },
                None => {
                    let mut tokens = TokenStream::new();
                    attr.to_tokens(&mut tokens);
                    panic!("unable to interpret attribute: {}", tokens)
                }
            }
        }

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

        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        for nm_item in meta_list.nested {
            if let syn::NestedMeta::Meta(ref item) = nm_item {
                if let syn::Meta::NameValue(ref pair) = item {
                    match pair.ident.to_string().as_ref() {
                        "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");
                        },
                        "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");
                        },
                        "print" => if let syn::Lit::Str(ref s) = pair.lit {
                            print = s.value().into();
                        } else {
                            panic!("print value must be string literal");
                        },
                        "escape" => if let syn::Lit::Str(ref s) = pair.lit {
                            escaping = Some(s.value().into());
                        } else {
                            panic!("escape value must be string literal");
                        },
                        "ext" => if let syn::Lit::Str(ref s) = pair.lit {
                            ext = Some(s.value());
                        } else {
                            panic!("ext value must be string literal");
                        },
                        attr => panic!("unsupported annotation key '{}' found", attr),
                    }
                }
            }
        }

        let source = source.expect("template path or source not found in attributes");
        let path = match (&source, ext.is_some()) {
            (&Source::Path(_), true) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            }
            (&Source::Source(_), false) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            }
            (&Source::Path(ref path), false) => path::find_template_from_path(path, None),
            (&Source::Source(_), true) => {
                PathBuf::from(format!("{}.{}", ast.ident, ext.as_ref().unwrap()))
            }
        };

        let parent = match ast.data {
            syn::Data::Struct(syn::DataStruct {
                fields: syn::Fields::Named(ref fields),
                ..
            }) => fields.named.iter().filter_map(|f| {
                f.ident
                    .as_ref()
                    .and_then(|name| if name == "_parent" { Some(&f.ty) } else { None })
            }),
            _ => panic!("derive(Template) only works for struct items"),
        }.next();

        TemplateInput {
            ast,
            source,
            print,
            escaping: escaping.unwrap_or_else(|| EscapeMode::from_path(&path)),
            ext,
            parent,
            path,
        }
    }
}

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

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl From<String> for EscapeMode {
    fn from(s: String) -> EscapeMode {
        use self::EscapeMode::*;
        match s.as_ref() {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

impl EscapeMode {
    fn from_path(path: &PathBuf) -> EscapeMode {
        let extension = path.extension().map(|s| s.to_str().unwrap()).unwrap_or("");
        if HTML_EXTENSIONS.contains(&extension) {
            EscapeMode::Html
        } else {
            EscapeMode::None
        }
    }
}

#[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),
        }
    }
}

const HTML_EXTENSIONS: [&str; 3] = ["html", "htm", "xml"];
<commit_msg>Improve field type determination<commit_after>use proc_macro2::TokenStream;

use quote::ToTokens;

use shared::path;

use std::path::PathBuf;

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub source: Source,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<String>,
    pub parent: Option<&'a syn::Type>,
    pub path: PathBuf,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let mut meta = None;
        for attr in &ast.attrs {
            match attr.interpret_meta() {
                Some(m) => if m.name() == "template" {
                    meta = Some(m)
                },
                None => {
                    let mut tokens = TokenStream::new();
                    attr.to_tokens(&mut tokens);
                    panic!("unable to interpret attribute: {}", tokens)
                }
            }
        }

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

        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        for nm_item in meta_list.nested {
            if let syn::NestedMeta::Meta(ref item) = nm_item {
                if let syn::Meta::NameValue(ref pair) = item {
                    match pair.ident.to_string().as_ref() {
                        "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");
                        },
                        "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");
                        },
                        "print" => if let syn::Lit::Str(ref s) = pair.lit {
                            print = s.value().into();
                        } else {
                            panic!("print value must be string literal");
                        },
                        "escape" => if let syn::Lit::Str(ref s) = pair.lit {
                            escaping = Some(s.value().into());
                        } else {
                            panic!("escape value must be string literal");
                        },
                        "ext" => if let syn::Lit::Str(ref s) = pair.lit {
                            ext = Some(s.value());
                        } else {
                            panic!("ext value must be string literal");
                        },
                        attr => panic!("unsupported annotation key '{}' found", attr),
                    }
                }
            }
        }

        let source = source.expect("template path or source not found in attributes");
        let path = match (&source, ext.is_some()) {
            (&Source::Path(_), true) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            }
            (&Source::Source(_), false) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            }
            (&Source::Path(ref path), false) => path::find_template_from_path(path, None),
            (&Source::Source(_), true) => {
                PathBuf::from(format!("{}.{}", ast.ident, ext.as_ref().unwrap()))
            }
        };

        let parent = match ast.data {
            syn::Data::Struct(syn::DataStruct {
                fields: syn::Fields::Named(ref fields),
                ..
            }) => fields.named.iter().find(|f| {
                if let Some(field_name) = f.ident.as_ref() {
                    field_name == "_parent"
                } else {
                    false
                }
            }),
            _ => panic!("derive(Template) only works for struct items"),
        };
        let parent = if let Some(parent) = parent {
            Some(&parent.ty)
        } else {
            None
        };

        TemplateInput {
            ast,
            source,
            print,
            escaping: escaping.unwrap_or_else(|| EscapeMode::from_path(&path)),
            ext,
            parent,
            path,
        }
    }
}

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

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl From<String> for EscapeMode {
    fn from(s: String) -> EscapeMode {
        use self::EscapeMode::*;
        match s.as_ref() {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

impl EscapeMode {
    fn from_path(path: &PathBuf) -> EscapeMode {
        let extension = path.extension().map(|s| s.to_str().unwrap()).unwrap_or("");
        if HTML_EXTENSIONS.contains(&extension) {
            EscapeMode::Html
        } else {
            EscapeMode::None
        }
    }
}

#[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),
        }
    }
}

const HTML_EXTENSIONS: [&str; 3] = ["html", "htm", "xml"];
<|endoftext|>