<commit_before>use nom::{Err as NomErr, ErrorKind, IResult};
use nom::IResult::*;
use syntax::*;

/// Check if the given byte is valid in an identifier.
fn is_identifier(c: u8) -> bool {
    let ch = char::from(c);
    ch.is_alphanumeric() || ch == '_'
}

named!(identifier_raw <&[u8], &[u8]>, take_while1!(is_identifier));
named!(identifier <&[u8], Identifier>, map!(identifier_raw, |bytes: &[u8]| String::from_utf8(bytes.to_vec()).unwrap()));

/// Match an `identifier` against a built-in type specifier, returning
/// an error if there is no match.
pub fn type_specifier<T: TypeSpecifier>(i: &[u8]) -> IResult<&[u8], T> {
    let (remaining, identifier) = try_parse!(i, identifier);
    let type_specifier = T::from(identifier.as_ref());

    if type_specifier.is_none() {
        return Error(NomErr::Code(ErrorKind::AlphaNumeric));
    }

    Done(remaining, type_specifier.unwrap())
}

named!(pub variable<&[u8], Expr>, map!(identifier, Expr::Variable));

/// Parse a declaration as a statement.
named!(pub statement<&[u8], Statement>,
  alt!(
    map!(declaration, Statement::Declaration) | macro_call
  )
);

// Parse a list of 0 or more statements.
named!(pub statement_list<&[u8], Vec<Statement>>, many0!(statement));

/// Parse either a block or symbol declaration.
named!(pub declaration<&[u8], Declaration>,
  alt!(
    block_declaration
    | macro_declaration
    | symbol_declaration
  )
);

/// Parse a single named `Symbol` declaration.
named!(pub symbol_declaration<&[u8], Declaration>,
  ws!(do_parse!(
    qualifier: type_specifier >>
    name: identifier >>
    initializer: opt!(preceded!(tag!("="), expr)) >>
    char!(';') >>

    (Declaration::Symbol {qualifier, name, initializer})
  ))
);

/// Parse a `block` or `optional` container, named by an `Identifer` and containing
/// a list of 0 or more `Statement`s.
named!(pub block_declaration<&[u8], Declaration>,
  ws!(do_parse!(
    is_abstract: opt!(tag!("abstract")) >>
    qualifier: type_specifier >>
    name: identifier >>
    char!('{') >>
    statements: many0!(statement) >>
    char!('}') >>

    (Declaration::Block {
      is_abstract: is_abstract.is_some(),
      qualifier,
      name,
      statements
    })
  ))
);

named!(pub macro_declaration<&[u8], Declaration>,
    ws!(do_parse!(
        tag!("macro") >>
        name: identifier >>
        parameters: delimited!(tag!("("), macro_param_list, tag!(")")) >>
        tag!("{") >>
        statements: statement_list >>
        tag!("}") >>

        (Declaration::Macro {
            name,
            parameters,
            statements
        })
    ))
);

named!(pub macro_param_list<&[u8], Vec<MacroParameter>>,
    ws!(do_parse!(
        first_param: macro_param >>
        rest_params: many0!(ws!(do_parse!(char!(',') >> param: macro_param >> (param)))) >>

        ({
            let mut params = rest_params.clone();
            params.insert(0, first_param);

            params
        })
    ))
);

named!(pub macro_param<&[u8], MacroParameter>,
    ws!(do_parse!(
        qualifier: type_specifier >>
        name: identifier >>

        (MacroParameter {
            qualifier, name
        })
    ))
);

named!(pub macro_call<&[u8], Statement>,
    ws!(do_parse!(
        name: identifier >>
        arguments: delimited!(tag!("("), macro_argument_list, tag!(")")) >>
        tag!(";") >>

        (Statement::MacroCall(name, arguments))
    ))
);

named!(pub macro_argument_list<&[u8], Vec<Expr>>,
    ws!(do_parse!(
        first_param: expr >>
        rest_params: many0!(ws!(do_parse!(char!(',') >> param: expr >> (param)))) >>

        ({
            let mut params = rest_params.clone();
            params.insert(0, first_param);

            params
        })
    ))
);

named!(pub expr<&[u8], Expr>,
  alt!(
    context
    | level_range
    | category_range
    | variable
  )
);

named!(pub level<&[u8], Expr>,
  alt_complete!(
    do_parse!(
        sensitivity: identifier >>
        categories: category_range >>

        (Expr::Level(LevelExpr {
            sensitivity,
            categories: Box::from(categories)
        }))
    )
    | variable
  )
);

named!(pub level_range<&[u8], Expr>,
    ws!(do_parse!(
        range: separated_pair!(level, eat_separator!(&b"-"[..]), level) >>

        (Expr::LevelRange(
            Box::from(range.0), Box::from(range.1)
        ))
    ))
);

named!(pub category_range<&[u8], Expr>,
  ws!(do_parse!(
        range: separated_pair!(identifier, eat_separator!(&b"."[..]), identifier) >>

        (Expr::CategoryRange(
            range.0, range.1
        ))
    ))
);

named!(pub context<&[u8], Expr>,
  ws!(do_parse!(
      user_id: identifier >>
      char!(':') >>
      role_id: identifier >>
      char!(':') >>
      type_id: identifier >>
      level_range: opt!(complete!(preceded!(char!(':'), level_range))) >>

      (Expr::Context {
        user_id,
        role_id,
        type_id,
        level_range: level_range.map(|v| Box::from(v))
      })
  ))
);

#[cfg(test)]
mod tests {

    use super::*;

    fn parse<O, P>(input: &str, parser: P) -> O
    where
        P: Fn(&[u8]) -> IResult<&[u8], O>,
    {
        let bytes = input.as_bytes();
        let result = parser(bytes);

        if result.is_err() {
            panic!("Parse error: {}", result.unwrap_err());
        }

        let (remaining, output) = result.unwrap();

        output
    }

    #[test]
    pub fn parse_type_specifier() {
        assert_eq!(
            parse::<SymbolType, _>("type", type_specifier),
            SymbolType::Type
        );
    }

    #[test]
    pub fn parse_context_expr() {
        let result = parse::<Expr, _>("user:role:type", context);

        match result {
            Expr::Context {
                user_id,
                role_id,
                type_id,
                level_range,
            } => {
                assert_eq!("user", user_id);
                assert_eq!("role", role_id);
                assert_eq!("type", type_id);
                assert_eq!(true, level_range.is_none());
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_levelrange_expr() {
        let result = parse::<Expr, _>("s0-s1", level_range);

        if let Expr::LevelRange(low, high) = result {
            assert_eq!(Expr::var("s0"), *low);
            assert_eq!(Expr::var("s1"), *high);
        } else {
            panic!("Invalid value parsed");
        }
    }

    #[test]
    pub fn parse_context_expr_with_levelrange() {
        let result = parse::<Expr, _>("user:role:type:s0 - s1", context);

        match result {
            Expr::Context {
                user_id,
                role_id,
                type_id,
                level_range,
            } => {
                if let &Expr::LevelRange(ref low, ref high) = level_range.unwrap().as_ref() {
                    assert_eq!(Expr::var("s0"), **low);
                    assert_eq!(Expr::var("s1"), **high);
                } else {
                    panic!("No level range found");
                }
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_block_decl() {
        let result = parse::<Declaration, _>("abstract block abc {}", block_declaration);

        match result {
            Declaration::Block {
                is_abstract,
                qualifier,
                statements,
                name,
            } => {
                assert_eq!(true, is_abstract);
                assert_eq!("abc", name);
                assert_eq!(BlockType::Block, qualifier);
            }
            _ => panic!("Invalid value"),
        }
    }

    #[test]
    pub fn parse_abstract_block_decl() {
        let result = parse::<Declaration, _>("abstract block abc {}", block_declaration);

        match result {
            Declaration::Block {
                is_abstract,
                qualifier,
                statements,
                name,
            } => assert_eq!(true, is_abstract),
            _ => panic!("Invalid value"),
        }
    }

    #[test]
    pub fn parse_symbol_decl() {
        let result = parse::<Declaration, _>("type_attribute my_type;", symbol_declaration);

        match result {
            Declaration::Symbol {
                qualifier,
                name,
                initializer,
            } => {
                assert_eq!(SymbolType::TypeAttribute, qualifier);
                assert_eq!("my_type", name);
                assert_eq!(None, initializer)
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_symbol_decl_with_initializer() {
        let result = parse::<Declaration, _>(
            "context my_context = user:role:type:s0-s1;",
            symbol_declaration,
        );

        match result {
            Declaration::Symbol {
                qualifier,
                name,
                initializer,
            } => {
                assert_eq!(SymbolType::Context, qualifier);
                assert_eq!("my_context", name);

                match initializer {
                    Some(Expr::Context {
                             user_id,
                             role_id,
                             type_id,
                             level_range,
                         }) => {}
                    _ => panic!("No initializer found"),
                }
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_macro_decl() {
        let result = parse::<Declaration, _>(
            "macro my_macro(type v, type v1) {

            }",
            macro_declaration,
        );

        match result {
            Declaration::Macro {
                name,
                parameters,
                statements,
            } => {
                assert_eq!("my_macro", name);
                assert_eq!("v", parameters[0].name);
                assert_eq!("v1", parameters[1].name);
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_macro_call() {
        let result = parse::<Statement, _>("my_macro(type_name);", macro_call);

        if let Statement::MacroCall(ref name, ref params) = result {
            assert_eq!("my_macro", name);
            assert_eq!(Expr::var("type_name"), params[0])
        } else {
            panic!("Invalid value parsed");
        }
    }
}<commit_msg>Fix level expression parsing<commit_after>use nom::{Err as NomErr, ErrorKind, IResult};
use nom::IResult::*;
use syntax::*;

/// Check if the given byte is valid in an identifier.
fn is_identifier(c: u8) -> bool {
    let ch = char::from(c);
    ch.is_alphanumeric() || ch == '_'
}

named!(identifier_raw <&[u8], &[u8]>, take_while1!(is_identifier));
named!(identifier <&[u8], Identifier>, map!(identifier_raw, |bytes: &[u8]| String::from_utf8(bytes.to_vec()).unwrap()));

/// Match an `identifier` against a built-in type specifier, returning
/// an error if there is no match.
pub fn type_specifier<T: TypeSpecifier>(i: &[u8]) -> IResult<&[u8], T> {
    let (remaining, identifier) = try_parse!(i, identifier);
    let type_specifier = T::from(identifier.as_ref());

    if type_specifier.is_none() {
        return Error(NomErr::Code(ErrorKind::AlphaNumeric));
    }

    Done(remaining, type_specifier.unwrap())
}

named!(pub variable<&[u8], Expr>, map!(identifier, Expr::Variable));

/// Parse a declaration as a statement.
named!(pub statement<&[u8], Statement>,
  alt!(
    map!(declaration, Statement::Declaration) | macro_call
  )
);

// Parse a list of 0 or more statements.
named!(pub statement_list<&[u8], Vec<Statement>>, many0!(statement));

/// Parse either a block or symbol declaration.
named!(pub declaration<&[u8], Declaration>,
  alt!(
    block_declaration
    | macro_declaration
    | symbol_declaration
  )
);

/// Parse a single named `Symbol` declaration.
named!(pub symbol_declaration<&[u8], Declaration>,
  ws!(do_parse!(
    qualifier: type_specifier >>
    name: identifier >>
    initializer: opt!(preceded!(tag!("="), expr)) >>
    char!(';') >>

    (Declaration::Symbol {qualifier, name, initializer})
  ))
);

/// Parse a `block` or `optional` container, named by an `Identifer` and containing
/// a list of 0 or more `Statement`s.
named!(pub block_declaration<&[u8], Declaration>,
  ws!(do_parse!(
    is_abstract: opt!(tag!("abstract")) >>
    qualifier: type_specifier >>
    name: identifier >>
    char!('{') >>
    statements: many0!(statement) >>
    char!('}') >>

    (Declaration::Block {
      is_abstract: is_abstract.is_some(),
      qualifier,
      name,
      statements
    })
  ))
);

named!(pub macro_declaration<&[u8], Declaration>,
    ws!(do_parse!(
        tag!("macro") >>
        name: identifier >>
        parameters: delimited!(tag!("("), macro_param_list, tag!(")")) >>
        tag!("{") >>
        statements: statement_list >>
        tag!("}") >>

        (Declaration::Macro {
            name,
            parameters,
            statements
        })
    ))
);

named!(pub macro_param_list<&[u8], Vec<MacroParameter>>,
    ws!(do_parse!(
        first_param: macro_param >>
        rest_params: many0!(ws!(do_parse!(char!(',') >> param: macro_param >> (param)))) >>

        ({
            let mut params = rest_params.clone();
            params.insert(0, first_param);

            params
        })
    ))
);

named!(pub macro_param<&[u8], MacroParameter>,
    ws!(do_parse!(
        qualifier: type_specifier >>
        name: identifier >>

        (MacroParameter {
            qualifier, name
        })
    ))
);

named!(pub macro_call<&[u8], Statement>,
    ws!(do_parse!(
        name: identifier >>
        arguments: delimited!(tag!("("), macro_argument_list, tag!(")")) >>
        tag!(";") >>

        (Statement::MacroCall(name, arguments))
    ))
);

named!(pub macro_argument_list<&[u8], Vec<Expr>>,
    ws!(do_parse!(
        first_param: expr >>
        rest_params: many0!(ws!(do_parse!(char!(',') >> param: expr >> (param)))) >>

        ({
            let mut params = rest_params.clone();
            params.insert(0, first_param);

            params
        })
    ))
);

named!(pub expr<&[u8], Expr>,
  alt!(
    context
    | level_range
    | category_range
    | variable
  )
);

named!(pub level<&[u8], Expr>,
    do_parse!(
        sensitivity: identifier >>
        tag!(":") >>
        categories: category_range_or_id >>

        (Expr::Level(LevelExpr {
            sensitivity,
            categories: Box::from(categories)
        }))
    )
);

named!(level_or_id<&[u8], Expr>, alt_complete!(level | variable));

named!(pub level_range<&[u8], Expr>,
    ws!(do_parse!(
        range: separated_pair!(level_or_id, eat_separator!(&b"-"[..]), level_or_id) >>

        (Expr::LevelRange(
            Box::from(range.0), Box::from(range.1)
        ))
    ))
);

named!(category_range_or_id<&[u8], Expr>, alt_complete!(category_range | variable));

named!(pub category_range<&[u8], Expr>,
  ws!(do_parse!(
        range: separated_pair!(identifier, eat_separator!(&b"."[..]), identifier) >>

        (Expr::CategoryRange(
            range.0, range.1
        ))
    ))
);

named!(pub context<&[u8], Expr>,
  ws!(do_parse!(
      user_id: identifier >>
      char!(':') >>
      role_id: identifier >>
      char!(':') >>
      type_id: identifier >>
      level_range: opt!(complete!(preceded!(char!(':'), level_range))) >>

      (Expr::Context {
        user_id,
        role_id,
        type_id,
        level_range: level_range.map(|v| Box::from(v))
      })
  ))
);

#[cfg(test)]
mod tests {

    use super::*;

    fn parse<O, P>(input: &str, parser: P) -> O
    where
        P: Fn(&[u8]) -> IResult<&[u8], O>,
    {
        let bytes = input.as_bytes();
        let result = parser(bytes);

        if result.is_err() {
            panic!("Parse error: {}", result.unwrap_err());
        }

        let (remaining, output) = result.unwrap();

        output
    }

    #[test]
    pub fn parse_type_specifier() {
        assert_eq!(
            parse::<SymbolType, _>("type", type_specifier),
            SymbolType::Type
        );
    }

    #[test]
    pub fn parse_context_expr() {
        let result = parse::<Expr, _>("user:role:type", context);

        match result {
            Expr::Context {
                user_id,
                role_id,
                type_id,
                level_range,
            } => {
                assert_eq!("user", user_id);
                assert_eq!("role", role_id);
                assert_eq!("type", type_id);
                assert_eq!(true, level_range.is_none());
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_levelrange_expr() {
        let result = parse::<Expr, _>("s0-s1", level_range);

        if let Expr::LevelRange(low, high) = result {
            assert_eq!(Expr::var("s0"), *low);
            assert_eq!(Expr::var("s1"), *high);
        } else {
            panic!("Invalid value parsed");
        }
    }

    #[test]
    pub fn parse_context_expr_with_levelrange() {
        let result = parse::<Expr, _>("user:role:type:s0 - s1", context);

        match result {
            Expr::Context {
                user_id,
                role_id,
                type_id,
                level_range,
            } => {
                if let &Expr::LevelRange(ref low, ref high) = level_range.unwrap().as_ref() {
                    assert_eq!(Expr::var("s0"), **low);
                    assert_eq!(Expr::var("s1"), **high);
                } else {
                    panic!("No level range found");
                }
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_block_decl() {
        let result = parse::<Declaration, _>("abstract block abc {}", block_declaration);

        match result {
            Declaration::Block {
                is_abstract,
                qualifier,
                statements,
                name,
            } => {
                assert_eq!(true, is_abstract);
                assert_eq!("abc", name);
                assert_eq!(BlockType::Block, qualifier);
            }
            _ => panic!("Invalid value"),
        }
    }

    #[test]
    pub fn parse_abstract_block_decl() {
        let result = parse::<Declaration, _>("abstract block abc {}", block_declaration);

        match result {
            Declaration::Block {
                is_abstract,
                qualifier,
                statements,
                name,
            } => assert_eq!(true, is_abstract),
            _ => panic!("Invalid value"),
        }
    }

    #[test]
    pub fn parse_symbol_decl() {
        let result = parse::<Declaration, _>("type_attribute my_type;", symbol_declaration);

        match result {
            Declaration::Symbol {
                qualifier,
                name,
                initializer,
            } => {
                assert_eq!(SymbolType::TypeAttribute, qualifier);
                assert_eq!("my_type", name);
                assert_eq!(None, initializer)
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_symbol_decl_with_initializer() {
        let result = parse::<Declaration, _>(
            "context my_context = user:role:type:s0-s1;",
            symbol_declaration,
        );

        match result {
            Declaration::Symbol {
                qualifier,
                name,
                initializer,
            } => {
                assert_eq!(SymbolType::Context, qualifier);
                assert_eq!("my_context", name);

                match initializer {
                    Some(Expr::Context {
                             user_id,
                             role_id,
                             type_id,
                             level_range,
                         }) => {}
                    _ => panic!("No initializer found"),
                }
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_macro_decl() {
        let result = parse::<Declaration, _>(
            "macro my_macro(type v, type v1) {

            }",
            macro_declaration,
        );

        match result {
            Declaration::Macro {
                name,
                parameters,
                statements,
            } => {
                assert_eq!("my_macro", name);
                assert_eq!("v", parameters[0].name);
                assert_eq!("v1", parameters[1].name);
            }
            _ => panic!("Invalid value parsed"),
        }
    }

    #[test]
    pub fn parse_macro_call() {
        let result = parse::<Statement, _>("my_macro(type_name);", macro_call);

        if let Statement::MacroCall(ref name, ref params) = result {
            assert_eq!("my_macro", name);
            assert_eq!(Expr::var("type_name"), params[0])
        } else {
            panic!("Invalid value parsed");
        }
    }
}<|endoftext|>


<commit_before>use rand::{Rng, thread_rng};
use app::GameState;
use ship::{Ship, ShipDirection};
use space::{Space, SpaceState};

pub struct Player {
    pub is_cpu: bool,
    pub spaces: Vec<Space>,
    pub ships: Vec<Ship>,
    grid_cursor: [u8; 2],
}

impl Player {
    pub fn new(is_cpu: bool) -> Player {
        let mut spaces = vec![];
        for col in 0..10 {
            for row in 0..10 {
                spaces.push(Space::new([col, row]));
            }
        }

        Player {
            is_cpu: is_cpu,
            spaces: spaces,
            ships: vec![],
            grid_cursor: [0, 0],
        }
    }

    /// Selects a space and checks the status of ships if there's a hit.
    pub fn select_space(&mut self, pos: &[u8; 2]) -> GameState {
        let mut game_state = GameState::Active;
        let mut space_state = SpaceState::Checked(false);
        let mut hit_ship = None;
        for (i, ship) in self.ships.iter().enumerate() {
            if ship.position.contains(pos) {
                space_state = SpaceState::Checked(true);
                hit_ship = Some(i);
            }
        }

        let space = self.spaces.iter()
            .position(|space| &space.position == pos)
            .unwrap();
        self.spaces[space].state = space_state;

        if space_state == SpaceState::Checked(true) {
            // Check if this ship has sunk.
            let hit_ship = hit_ship.unwrap();
            let mut ship_state = false;
            for ship_pos in &self.ships[hit_ship].position {
                if self.space_is_unchecked(&ship_pos) {
                    ship_state = true;
                }
            }

            if !ship_state {
                self.ships[hit_ship].state = ship_state;
            }

            // Check if any ships are left.
            let mut all_sunk = true;
            for ship in &self.ships {
                if ship.state {
                    all_sunk = false;
                    break;
                }
            }

            if all_sunk {
                game_state = GameState::Over;
            }
        }

        game_state
    }

    /// Determines the next space a CPU player will select.
    pub fn cpu_select_space(&mut self) -> [u8; 2] {
        let mut rng = thread_rng();
        let mut first_hit = None;
        let mut select = vec![];

        // Determines the order of priority of directions to check if there are
        // any hit spaces found.
        let mut directions: [[i32; 2]; 4] = [
            [-1, 0],
            [1, 0],
            [0, -1],
            [0, 1]
        ];
        rng.shuffle(&mut directions);

        for space in self.spaces.iter().filter(|s| s.state == SpaceState::Checked(true)) {

            // Get the hit ship.
            let mut ship: Option<&Ship> = None;
            for s in &self.ships {
                if s.position.contains(&space.position) {
                    ship = Some(s);
                    break;
                }
            }

            // Make sure the hit ship hasn't been sunk.
            if ship.unwrap().state {
                if first_hit.is_none() {
                    first_hit = Some(space.position);
                }

                // Check if this space forms part of a line of hit spaces.  If
                // it does, and the space at the end hasn't been selected yet,
                // it's a candidate for selection this turn.
                for check in &directions {
                    let mut xc = (space.position[0] as i32 + check[0]) as u8;
                    let mut yc = (space.position[1] as i32 + check[1]) as u8;

                    while self.space_is_hit(&[xc, yc]) {
                        xc = (xc as i32 + check[0]) as u8;
                        yc = (yc as i32 + check[1]) as u8;
                    }

                    if self.space_is_unchecked(&[xc, yc]) && ((xc as i32 - check[0]) as u8 != space.position[0] || (yc as i32 - check[1]) as u8 != space.position[1]) {
                        select.push([xc, yc]);
                        break;
                    }
                }
            }
        }

        // If a hit space was found, but no hit spaces next to it, select a
        // non-selected space next to it.
        if first_hit.is_some() && select.len() == 0 {
            let first_hit = first_hit.unwrap();
            let first_hit_i32 = [first_hit[0] as i32, first_hit[1] as i32];
            for check in &directions {
                let pos = [
                    (first_hit_i32[0] + check[0]) as u8,
                    (first_hit_i32[1] + check[1]) as u8
                ];
                if self.space_is_unchecked(&pos) {
                    select.push(pos);
                    break;
                }
            }
        }

        // If no spaces were selected to check, just check any available space.
        if select.len() == 0 {
            let mut pos: Option<[u8; 2]> = None;
            while pos.is_none() {
                let space = [
                    rng.gen_range(0, 10),
                    rng.gen_range(0, 10)
                ];
                if self.space_is_unchecked(&space) {
                    pos = Some(space);
                }
            }

            select.push(pos.unwrap());
        }

        // The way the potential selections are chosen, empty spaces to the
        // right or bottom of a line of hit spaces will always be chosen first,
        // so the list of selections should be shuffled.
        if select.len() > 1 {
            select.dedup();
            rng.shuffle(&mut select);
        }

        select[0]
    }

    pub fn cpu_place_ships(&mut self) {
        for length in 2..6 {
            let ship_pos = self.cpu_place_ship(length);
            self.ships.push(Ship::new(ship_pos));
        }
    }

    /// RNGs ship locations for CPU players.
    fn cpu_place_ship(&self, length: u8) -> Vec<[u8; 2]> {
        let mut ship = vec![];
        let mut valid = false;
        let mut x: u8;
        let mut y: u8;
        let mut direction: ShipDirection;
        let mut rng = thread_rng();

        // RNG a position and direction, then make sure it's valid.
        while !valid {
            x = rng.gen_range(0, 10);
            y = rng.gen_range(0, 10);
            direction = match rng.gen_range(0, 2) {
                0 => ShipDirection::Horizontal,
                1 => ShipDirection::Vertical,
                _ => unreachable!()
            };
            ship = self.get_ship_position([x, y], direction, length);
            valid = self.valid_ship_position(&ship);
        }

        ship
    }

    /// Returns a ship's grid positions, given its head position, direction and
    /// length.
    pub fn get_ship_position(
        &self,
        head: [u8; 2],
        direction: ShipDirection,
        length: u8
    ) -> Vec<[u8; 2]> {
        let mut ship = vec![head];
        for pos in 1..length {
            match direction {
                ShipDirection::Horizontal => ship.push([head[0] + pos as u8, head[1]]),
                ShipDirection::Vertical => ship.push([head[0], head[1] + pos as u8])
            }
        }

        ship
    }

    /// Checks that the selected ship position is valid before placing it.
    pub fn valid_ship_position(&self, new_ship: &Vec<[u8; 2]>) -> bool {
        let mut valid = true;

        for space in new_ship {
            // Make sure all ship spaces are within the grid.
            if space[0] > 9 || space[1] > 9 {
                valid = false;
            }

            // Make sure a ship isn't already in this space.
            if valid {
                valid = !self.ship_is_in_space(&space);
            }

            // CPU players are disallowed from placing ships together, because
            // it's just bad strategy.  Human players should still be allowed
            // to do what they want, though.
            if valid && self.is_cpu {
                valid = !self.ship_is_next_to(&space);
            }
        }

        valid
    }

    /// Checks whether a ship occupies the specified grid coordinates.
    pub fn ship_is_in_space(&self, pos: &[u8; 2]) -> bool {
        let mut result = false;
        for ship in &self.ships {
            if ship.position.contains(pos) {
                result = true;
            }
        }

        result
    }

    /// Checks whether there is a ship next to the specified grid coordinates.
    fn ship_is_next_to(&self, pos: &[u8; 2]) -> bool {
        let mut result = false;
        let x = pos[0];
        let y = pos[1];
        // Left
        if x > 0 {
            result = self.ship_is_in_space(&[x - 1, y]);
        }
        // Right
        if x < 9 && !result {
            result = self.ship_is_in_space(&[x + 1, y]);
        }
        // Above
        if y > 0 && !result {
            result = self.ship_is_in_space(&[x, y - 1]);
        }
        // Below
        if y < 9 && !result {
            result = self.ship_is_in_space(&[x, y + 1]);
        }

        result
    }

    /// Returns the current state of a space, if that space exists.
    fn space_state(&self, pos: &[u8; 2]) -> Option<SpaceState> {
        match self.spaces.iter().find(|s| &s.position == pos) {
            Some(space) => Some(space.state),
            None => None
        }
    }

    pub fn space_is_unchecked(&self, pos: &[u8; 2]) -> bool {
        self.space_state(&pos) == Some(SpaceState::Unchecked)
    }

    pub fn space_is_hit(&self, pos: &[u8; 2]) -> bool {
        self.space_state(&pos) == Some(SpaceState::Checked(true))
    }

    /// Returns the coordinates of the player's grid cursor.
    pub fn get_grid_cursor(&self) -> [u8; 2] {
        self.grid_cursor.clone()
    }

    /// Moves the player's grid cursor in a `direction` relative to the current
    /// grid cursor coordinates.
    pub fn move_grid_cursor(&mut self, direction: [i32; 2]) {
        let new_cursor = [
            self.grid_cursor[0] as i32 + direction[0],
            self.grid_cursor[1] as i32 + direction[1]
        ];

        if new_cursor[0] >= 0 && new_cursor[0] < 10
            && new_cursor[1] >= 0 && new_cursor[1] < 10 {
            self.set_grid_cursor(&[
                new_cursor[0] as u8,
                new_cursor[1] as u8
            ]);
        }
    }

    /// Sets the player's grid cursor coordinates.
    pub fn set_grid_cursor(&mut self, new_cursor: &[u8; 2]) {
        self.grid_cursor = *new_cursor;
    }
}

<commit_msg>Partial cleanup of player.rs<commit_after>use rand::{Rng, thread_rng};
use app::GameState;
use ship::{Ship, ShipDirection};
use space::{Space, SpaceState};

pub struct Player {
    pub is_cpu: bool,
    pub spaces: Vec<Space>,
    pub ships: Vec<Ship>,
    grid_cursor: [u8; 2],
}

impl Player {
    pub fn new(is_cpu: bool) -> Player {
        let mut spaces = vec![];
        for col in 0..10 {
            for row in 0..10 {
                spaces.push(Space::new([col, row]));
            }
        }

        Player {
            is_cpu: is_cpu,
            spaces: spaces,
            ships: vec![],
            grid_cursor: [0, 0],
        }
    }

    /// Selects a space and checks the status of ships if there's a hit.
    pub fn select_space(&mut self, pos: &[u8; 2]) -> GameState {
        let mut game_state = GameState::Active;
        let ship_hit = self.ships.iter().position(|s| s.position.contains(pos));
        let space_state = SpaceState::Checked(ship_hit.is_some());

        let space = self.spaces.iter()
            .position(|space| &space.position == pos)
            .unwrap();
        self.spaces[space].state = space_state;

        if let Some(ship) = ship_hit {
            let ship_sunk = self.ships[ship].position.iter()
                .all(|p| self.space_is_hit(p));

            if ship_sunk {
                self.ships[ship].state = false;
            }

            let all_sunk = self.ships.iter().all(|s| !s.state);
            if all_sunk {
                game_state = GameState::Over;
            }
        }

        game_state
    }

    /// Determines the next space a CPU player will select.
    pub fn cpu_select_space(&mut self) -> [u8; 2] {
        let mut rng = thread_rng();
        let mut first_hit = None;
        let mut select = vec![];

        // Determines the order of priority of directions to check if there are
        // any hit spaces found.
        let mut directions: [[i32; 2]; 4] = [
            [-1, 0],
            [1, 0],
            [0, -1],
            [0, 1]
        ];
        rng.shuffle(&mut directions);

        for space in self.spaces.iter().filter(|s| s.state == SpaceState::Checked(true)) {
            let hit_ship = self.ships.iter()
                .find(|s| s.position.contains(&space.position))
                .unwrap();

            if hit_ship.state {
                if first_hit.is_none() {
                    first_hit = Some(space.position);
                }

                // Check if this space forms part of a line of hit spaces.  If
                // it does, and the space at the end hasn't been selected yet,
                // it's a candidate for selection this turn.
                for check in &directions {
                    let mut xc = (space.position[0] as i32 + check[0]) as u8;
                    let mut yc = (space.position[1] as i32 + check[1]) as u8;

                    while self.space_is_hit(&[xc, yc]) {
                        xc = (xc as i32 + check[0]) as u8;
                        yc = (yc as i32 + check[1]) as u8;
                    }

                    if self.space_is_unchecked(&[xc, yc]) && ((xc as i32 - check[0]) as u8 != space.position[0] || (yc as i32 - check[1]) as u8 != space.position[1]) {
                        select.push([xc, yc]);
                        break;
                    }
                }
            }
        }

        // If a hit space was found, but no hit spaces next to it, select a
        // non-selected space next to it.
        if first_hit.is_some() && select.len() == 0 {
            let first_hit = first_hit.unwrap();
            let first_hit_i32 = [first_hit[0] as i32, first_hit[1] as i32];
            for check in &directions {
                let pos = [
                    (first_hit_i32[0] + check[0]) as u8,
                    (first_hit_i32[1] + check[1]) as u8
                ];
                if self.space_is_unchecked(&pos) {
                    select.push(pos);
                    break;
                }
            }
        }

        // If no spaces were selected to check, just check any available space.
        if select.len() == 0 {
            let mut pos: Option<[u8; 2]> = None;
            while pos.is_none() {
                let space = [
                    rng.gen_range(0, 10),
                    rng.gen_range(0, 10)
                ];
                if self.space_is_unchecked(&space) {
                    pos = Some(space);
                }
            }

            select.push(pos.unwrap());
        }

        // The way the potential selections are chosen, empty spaces to the
        // right or bottom of a line of hit spaces will always be chosen first,
        // so the list of selections should be shuffled.
        if select.len() > 1 {
            select.dedup();
            rng.shuffle(&mut select);
        }

        select[0]
    }

    pub fn cpu_place_ships(&mut self) {
        for length in 2..6 {
            let ship_pos = self.cpu_place_ship(length);
            self.ships.push(Ship::new(ship_pos));
        }
    }

    /// RNGs ship locations for CPU players.
    fn cpu_place_ship(&self, length: u8) -> Vec<[u8; 2]> {
        let mut ship = vec![];
        let mut valid = false;
        let mut x: u8;
        let mut y: u8;
        let mut direction: ShipDirection;
        let mut rng = thread_rng();

        // RNG a position and direction, then make sure it's valid.
        while !valid {
            x = rng.gen_range(0, 10);
            y = rng.gen_range(0, 10);
            direction = match rng.gen_range(0, 2) {
                0 => ShipDirection::Horizontal,
                1 => ShipDirection::Vertical,
                _ => unreachable!()
            };
            ship = self.get_ship_position([x, y], direction, length);
            valid = self.valid_ship_position(&ship);
        }

        ship
    }

    /// Returns a ship's grid positions, given its head position, direction and
    /// length.
    pub fn get_ship_position(
        &self,
        head: [u8; 2],
        direction: ShipDirection,
        length: u8
    ) -> Vec<[u8; 2]> {
        let mut ship = vec![head];
        for pos in 1..length {
            match direction {
                ShipDirection::Horizontal => ship.push([head[0] + pos as u8, head[1]]),
                ShipDirection::Vertical => ship.push([head[0], head[1] + pos as u8])
            }
        }

        ship
    }

    /// Checks that the given ship position is valid.
    ///
    /// If the player is CPU-controlled, a ship in a space next to another ship
    /// will be considered invalid.
    pub fn valid_ship_position(&self, new_ship: &Vec<[u8; 2]>) -> bool {
        new_ship.iter()
            .all(|s| self.valid_space(s) && !self.ship_is_in_space(s)
                 && !(self.ship_is_next_to(s) && self.is_cpu))
    }

    /// Checks whether a ship occupies the specified grid coordinates.
    pub fn ship_is_in_space(&self, pos: &[u8; 2]) -> bool {
        self.ships.iter().any(|s| s.position.contains(pos))
    }

    /// Checks whether there is a ship next to the specified grid coordinates.
    fn ship_is_next_to(&self, pos: &[u8; 2]) -> bool {
        let mut result = false;
        let x = pos[0];
        let y = pos[1];
        // Left
        if x > 0 {
            result = self.ship_is_in_space(&[x - 1, y]);
        }
        // Right
        if x < 9 && !result {
            result = self.ship_is_in_space(&[x + 1, y]);
        }
        // Above
        if y > 0 && !result {
            result = self.ship_is_in_space(&[x, y - 1]);
        }
        // Below
        if y < 9 && !result {
            result = self.ship_is_in_space(&[x, y + 1]);
        }

        result
    }

    fn valid_space(&self, pos: &[u8; 2]) -> bool {
        pos[0] < 10 && pos[1] < 10
    }

    /// Returns the current state of a space, if that space exists.
    fn space_state(&self, pos: &[u8; 2]) -> Option<SpaceState> {
        match self.spaces.iter().find(|s| &s.position == pos) {
            Some(space) => Some(space.state),
            None => None
        }
    }

    pub fn space_is_unchecked(&self, pos: &[u8; 2]) -> bool {
        self.space_state(&pos) == Some(SpaceState::Unchecked)
    }

    pub fn space_is_hit(&self, pos: &[u8; 2]) -> bool {
        self.space_state(&pos) == Some(SpaceState::Checked(true))
    }

    /// Returns the coordinates of the player's grid cursor.
    pub fn get_grid_cursor(&self) -> [u8; 2] {
        self.grid_cursor.clone()
    }

    /// Moves the player's grid cursor in a `direction` relative to the current
    /// grid cursor coordinates.
    pub fn move_grid_cursor(&mut self, direction: [i32; 2]) {
        let new_cursor = [
            self.grid_cursor[0] as i32 + direction[0],
            self.grid_cursor[1] as i32 + direction[1]
        ];

        if new_cursor[0] >= 0 && new_cursor[0] < 10
            && new_cursor[1] >= 0 && new_cursor[1] < 10 {
            self.set_grid_cursor(&[
                new_cursor[0] as u8,
                new_cursor[1] as u8
            ]);
        }
    }

    /// Sets the player's grid cursor coordinates.
    pub fn set_grid_cursor(&mut self, new_cursor: &[u8; 2]) {
        self.grid_cursor = *new_cursor;
    }
}

<|endoftext|>


<commit_before>#[crate_id(name="cat", vers="1.0.0", author="Seldaek")];
#[feature(managed_boxes)];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

extern crate getopts;

use std::os;
use std::io::{print, File};
use std::io::stdio::{stdout_raw, stdin_raw};

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("A", "show-all", "equivalent to -vET"),
        getopts::optflag("b", "number-nonblank", "number nonempty output lines, overrides -n"),
        getopts::optflag("e", "", "equivalent to -vE"),
        getopts::optflag("E", "show-ends", "display $ at end of each line"),
        getopts::optflag("n", "number", "number all output lines"),
        getopts::optflag("s", "squeeze-blank", "suppress repeated empty output lines"),
        getopts::optflag("t", "", "equivalent to -vT"),
        getopts::optflag("T", "show-tabs", "display TAB characters as ^I"),
        getopts::optflag("v", "show-nonprinting", "use ^ and M- notation, except for LF (\\n) and TAB (\\t)"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => fail!("Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("help") {
        println!("cat 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println!("");
        print(getopts::usage("Concatenate FILE(s), or standard input, to standard output.", opts));
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return;
    }
    if matches.opt_present("version") {
        println!("cat 1.0.0");
        return;
    }

    let mut number_mode = NumberNone;
    if matches.opt_present("number") {
        number_mode = NumberAll;
    }
    if matches.opt_present("number-nonblank") {
        number_mode = NumberNonEmpty;
    }
    let show_nonprint = matches.opts_present([~"show-nonprinting", ~"show-all", ~"t", ~"e"]);
    let show_ends = matches.opts_present([~"show-ends", ~"show-all", ~"e"]);
    let show_tabs = matches.opts_present([~"show-tabs",  ~"show-all", ~"t"]);
    let squeeze_blank = matches.opt_present("squeeze-blank");
    let mut files = matches.free;
    if files.is_empty() {
        files = ~[~"-"];
    }

    exec(files, number_mode, show_nonprint, show_ends, show_tabs, squeeze_blank);
}

#[deriving(Eq)]
pub enum NumberingMode {
    NumberNone,
    NumberNonEmpty,
    NumberAll,
}

static TAB: u8 = '\t' as u8;
#[allow(dead_code)]
static CR: u8 = '\r' as u8;
static LF: u8 = '\n' as u8;

#[cfg(windows)]
fn is_newline_char(byte: u8) -> bool {
    byte == LF || byte == CR
}

#[cfg(unix)]
fn is_newline_char(byte: u8) -> bool {
    byte == LF
}

pub fn exec(files: ~[~str], number: NumberingMode, show_nonprint: bool, show_ends: bool, show_tabs: bool, squeeze_blank: bool) {
    let mut writer = stdout_raw();

    if NumberNone != number || show_nonprint || show_ends || show_tabs || squeeze_blank {
        let mut counter: uint = 1;
        let is_numbering = number == NumberAll || number == NumberNonEmpty;

        for path in files.iter() {
            let mut reader = match open(path.to_owned()) {
                Some(f) => f,
                None => { continue }
            };

            let mut at_line_start = true;
            let mut buf = [0, .. 2];
            loop {
                // reading from a TTY seems to raise a condition on
                // EOF, rather than return Some(0) like a file.
                match reader.read(buf) {
                    Ok(n) if n != 0 => {
                        for byte in buf.slice_to(n).iter() {
                            if at_line_start && (number == NumberAll || (number == NumberNonEmpty && !is_newline_char(*byte))) {
                                match write!(&mut writer as &mut Writer, "{0:6u}\t", counter) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                                counter += 1;
                                at_line_start = false;
                            }
                            if is_numbering && *byte == LF {
                                at_line_start = true;
                            }
                            if show_tabs && *byte == TAB {
                                match writer.write(bytes!("^I")) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                            } else if show_ends && *byte == LF {
                                match writer.write(bytes!("$\n")) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                            } else if show_nonprint && (*byte < 32 || *byte >= 127) && !is_newline_char(*byte) {
                                let mut byte = *byte;
                                if byte >= 128 {
                                    match writer.write(bytes!("M-")) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                    byte = byte - 128;
                                }
                                if byte < 32 {
                                    match writer.write(['^' as u8, byte + 64]) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                } else if byte == 127 {
                                    match writer.write(['^' as u8, byte - 64]) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                } else {
                                    match writer.write([byte]) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                }
                            } else {
                                match writer.write([*byte]) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                            }
                        }
                    },
                    _ => break
                }
            }
        }
        return;
    }

    let mut buf = [0, .. 100000];
    // passthru mode
    for path in files.iter() {
        let mut reader = match open(path.to_owned()) {
            Some(f) => f,
            None => { continue }
        };

        loop {
            // reading from a TTY seems to raise a condition on EOF,
            // rather than return Some(0) like a file.
            match reader.read(buf) {
                Ok(n) if n != 0 => {
                    match writer.write(buf.slice_to(n)) {
                        Ok(_) => (), Err(err) => fail!("{}", err)
                    }
                }, _ => break
            }
        }
    }
}

fn open(path: ~str) -> Option<~Reader> {
    if "-" == path {
        return Some(~stdin_raw() as ~Reader);
    }

    match File::open(&std::path::Path::new(path.as_slice())) {
        Ok(fd) => return Some(~fd as ~Reader),
        Err(e) => fail!("cat: {0:s}: {1:s}", path, e.to_str())
    }
}
/* vim: set ai ts=4 sw=4 sts=4 et : */
<commit_msg>Use Buffered input/output where it makes sense.<commit_after>#[crate_id(name="cat", vers="1.0.0", author="Seldaek")];
#[feature(managed_boxes)];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

extern crate getopts;

use std::os;
use std::io::{print, File};
use std::io::stdio::{stdout_raw, stdin_raw};
use std::io::{BufferedReader, BufferedWriter};

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        getopts::optflag("A", "show-all", "equivalent to -vET"),
        getopts::optflag("b", "number-nonblank", "number nonempty output lines, overrides -n"),
        getopts::optflag("e", "", "equivalent to -vE"),
        getopts::optflag("E", "show-ends", "display $ at end of each line"),
        getopts::optflag("n", "number", "number all output lines"),
        getopts::optflag("s", "squeeze-blank", "suppress repeated empty output lines"),
        getopts::optflag("t", "", "equivalent to -vT"),
        getopts::optflag("T", "show-tabs", "display TAB characters as ^I"),
        getopts::optflag("v", "show-nonprinting", "use ^ and M- notation, except for LF (\\n) and TAB (\\t)"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => fail!("Invalid options\n{}", f.to_err_msg())
    };
    if matches.opt_present("help") {
        println!("cat 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println!("");
        print(getopts::usage("Concatenate FILE(s), or standard input, to standard output.", opts));
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return;
    }
    if matches.opt_present("version") {
        println!("cat 1.0.0");
        return;
    }

    let mut number_mode = NumberNone;
    if matches.opt_present("number") {
        number_mode = NumberAll;
    }
    if matches.opt_present("number-nonblank") {
        number_mode = NumberNonEmpty;
    }
    let show_nonprint = matches.opts_present([~"show-nonprinting", ~"show-all", ~"t", ~"e"]);
    let show_ends = matches.opts_present([~"show-ends", ~"show-all", ~"e"]);
    let show_tabs = matches.opts_present([~"show-tabs",  ~"show-all", ~"t"]);
    let squeeze_blank = matches.opt_present("squeeze-blank");
    let mut files = matches.free;
    if files.is_empty() {
        files = ~[~"-"];
    }

    exec(files, number_mode, show_nonprint, show_ends, show_tabs, squeeze_blank);
}

#[deriving(Eq)]
pub enum NumberingMode {
    NumberNone,
    NumberNonEmpty,
    NumberAll,
}

static TAB: u8 = '\t' as u8;
#[allow(dead_code)]
static CR: u8 = '\r' as u8;
static LF: u8 = '\n' as u8;

#[cfg(windows)]
fn is_newline_char(byte: u8) -> bool {
    byte == LF || byte == CR
}

#[cfg(unix)]
fn is_newline_char(byte: u8) -> bool {
    byte == LF
}

pub fn exec(files: ~[~str], number: NumberingMode, show_nonprint: bool, show_ends: bool, show_tabs: bool, squeeze_blank: bool) {

    if NumberNone != number || show_nonprint || show_ends || show_tabs || squeeze_blank {
        let mut counter: uint = 1;
        let is_numbering = number == NumberAll || number == NumberNonEmpty;

        for path in files.iter() {
            let mut reader = match open(path.to_owned()) {
                Some(f) => f,
                None => { continue }
            };

            let mut writer = BufferedWriter::with_capacity(1024 * 8, stdout_raw());
            let mut at_line_start = true;
            let mut buf = [0, .. 2];
            loop {
                // reading from a TTY seems to raise a condition on
                // EOF, rather than return Some(0) like a file.
                match reader.read(buf) {
                    Ok(n) if n != 0 => {
                        for byte in buf.slice_to(n).iter() {
                            if at_line_start && (number == NumberAll || (number == NumberNonEmpty && !is_newline_char(*byte))) {
                                match write!(&mut writer as &mut Writer, "{0:6u}\t", counter) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                                counter += 1;
                                at_line_start = false;
                            }
                            if is_numbering && *byte == LF {
                                at_line_start = true;
                            }
                            if show_tabs && *byte == TAB {
                                match writer.write(bytes!("^I")) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                            } else if show_ends && *byte == LF {
                                match writer.write(bytes!("$\n")) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                            } else if show_nonprint && (*byte < 32 || *byte >= 127) && !is_newline_char(*byte) {
                                let mut byte = *byte;
                                if byte >= 128 {
                                    match writer.write(bytes!("M-")) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                    byte = byte - 128;
                                }
                                if byte < 32 {
                                    match writer.write(['^' as u8, byte + 64]) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                } else if byte == 127 {
                                    match writer.write(['^' as u8, byte - 64]) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                } else {
                                    match writer.write([byte]) {
                                        Ok(_) => (), Err(err) => fail!("{}", err)
                                    };
                                }
                            } else {
                                match writer.write([*byte]) {
                                    Ok(_) => (), Err(err) => fail!("{}", err)
                                };
                            }
                        }
                    },
                    _ => break
                }
            }
        }
        return;
    }

    let mut buf = [0, .. 100000];
    let mut writer = stdout_raw();
    // passthru mode
    for path in files.iter() {
        let mut reader = match open(path.to_owned()) {
            Some(f) => f,
            None => { continue }
        };

        loop {
            // reading from a TTY seems to raise a condition on EOF,
            // rather than return Some(0) like a file.
            match reader.read(buf) {
                Ok(n) if n != 0 => {
                    match writer.write(buf.slice_to(n)) {
                        Ok(_) => (), Err(err) => fail!("{}", err)
                    }
                }, _ => break
            }
        }
    }
}

fn open(path: ~str) -> Option<~Reader> {
    if "-" == path {
        return Some(~stdin_raw() as ~Reader);
    }

    match File::open(&std::path::Path::new(path.as_slice())) {
        Ok(fd) => return Some(~fd as ~Reader),
        Err(e) => fail!("cat: {0:s}: {1:s}", path, e.to_str())
    }
}
/* vim: set ai ts=4 sw=4 sts=4 et : */
<|endoftext|>


<commit_before>pub use super::*;

use crate::dataflow::generic::{Results, ResultsRefCursor};
use crate::dataflow::BitDenotation;
use crate::dataflow::MaybeBorrowedLocals;
use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc::mir::*;
use std::cell::RefCell;

#[derive(Copy, Clone)]
pub struct MaybeStorageLive<'a, 'tcx> {
    body: &'a Body<'tcx>,
}

impl<'a, 'tcx> MaybeStorageLive<'a, 'tcx> {
    pub fn new(body: &'a Body<'tcx>) -> Self {
        MaybeStorageLive { body }
    }

    pub fn body(&self) -> &Body<'tcx> {
        self.body
    }
}

impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
    type Idx = Local;
    fn name() -> &'static str {
        "maybe_storage_live"
    }
    fn bits_per_block(&self) -> usize {
        self.body.local_decls.len()
    }

    fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
        // The resume argument is live on function entry (we don't care about
        // the `self` argument)
        for arg in self.body.args_iter().skip(1) {
            on_entry.insert(arg);
        }
    }

    fn statement_effect(&self, trans: &mut GenKillSet<Local>, loc: Location) {
        let stmt = &self.body[loc.block].statements[loc.statement_index];

        match stmt.kind {
            StatementKind::StorageLive(l) => trans.gen(l),
            StatementKind::StorageDead(l) => trans.kill(l),
            _ => (),
        }
    }

    fn terminator_effect(&self, _trans: &mut GenKillSet<Local>, _loc: Location) {
        // Terminators have no effect
    }

    fn propagate_call_return(
        &self,
        _in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        _dest_place: &mir::Place<'tcx>,
    ) {
        // Nothing to do when a call returns successfully
    }
}

impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
    /// bottom = dead
    const BOTTOM_VALUE: bool = false;
}

type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;

/// Dataflow analysis that determines whether each local requires storage at a
/// given location; i.e. whether its storage can go away without being observed.
pub struct RequiresStorage<'mir, 'tcx> {
    body: ReadOnlyBodyAndCache<'mir, 'tcx>,
    borrowed_locals: RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
}

impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
    pub fn new(
        body: ReadOnlyBodyAndCache<'mir, 'tcx>,
        borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>,
    ) -> Self {
        RequiresStorage {
            body,
            borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)),
        }
    }

    pub fn body(&self) -> &Body<'tcx> {
        &self.body
    }
}

impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
    type Idx = Local;
    fn name() -> &'static str {
        "requires_storage"
    }
    fn bits_per_block(&self) -> usize {
        self.body.local_decls.len()
    }

    fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
        // The resume argument is live on function entry (we don't care about
        // the `self` argument)
        for arg in self.body.args_iter().skip(1) {
            on_entry.insert(arg);
        }
    }

    fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {
        let stmt = &self.body[loc.block].statements[loc.statement_index];

        // If a place is borrowed in a statement, it needs storage for that statement.
        self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc);

        // If a place is assigned to in a statement, it needs storage for that statement.
        match &stmt.kind {
            StatementKind::StorageDead(l) => sets.kill(*l),
            StatementKind::Assign(box (place, _))
            | StatementKind::SetDiscriminant { box place, .. } => {
                sets.gen(place.local);
            }
            StatementKind::InlineAsm(box InlineAsm { outputs, .. }) => {
                for place in &**outputs {
                    sets.gen(place.local);
                }
            }

            // Nothing to do for these. Match exhaustively so this fails to compile when new
            // variants are added.
            StatementKind::AscribeUserType(..)
            | StatementKind::FakeRead(..)
            | StatementKind::Nop
            | StatementKind::Retag(..)
            | StatementKind::StorageLive(..) => {}
        }
    }

    fn statement_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        // If we move from a place then only stops needing storage *after*
        // that statement.
        self.check_for_move(sets, loc);
    }

    fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        let terminator = self.body[loc.block].terminator();

        // If a place is borrowed in a terminator, it needs storage for that terminator.
        self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc);

        if let TerminatorKind::Call { destination: Some((place, _)), .. } = terminator.kind {
            sets.gen(place.local);
        }
    }

    fn terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        // For call terminators the destination requires storage for the call
        // and after the call returns successfully, but not after a panic.
        // Since `propagate_call_unwind` doesn't exist, we have to kill the
        // destination here, and then gen it again in `propagate_call_return`.
        if let TerminatorKind::Call { destination: Some((ref place, _)), .. } =
            self.body[loc.block].terminator().kind
        {
            if let Some(local) = place.as_local() {
                sets.kill(local);
            }
        }
        self.check_for_move(sets, loc);
    }

    fn propagate_call_return(
        &self,
        in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        dest_place: &mir::Place<'tcx>,
    ) {
        in_out.insert(dest_place.local);
    }
}

impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
    /// Kill locals that are fully moved and have not been borrowed.
    fn check_for_move(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals };
        visitor.visit_location(self.body, loc);
    }
}

impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
    /// bottom = dead
    const BOTTOM_VALUE: bool = false;
}

struct MoveVisitor<'a, 'mir, 'tcx> {
    borrowed_locals: &'a RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
    sets: &'a mut GenKillSet<Local>,
}

impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
    fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
        if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
            let mut borrowed_locals = self.borrowed_locals.borrow_mut();
            borrowed_locals.seek_before(loc);
            if !borrowed_locals.contains(*local) {
                self.sets.kill(*local);
            }
        }
    }
}
<commit_msg>Handle resume args in `RequiresStorage` analysis<commit_after>pub use super::*;

use crate::dataflow::generic::{Results, ResultsRefCursor};
use crate::dataflow::BitDenotation;
use crate::dataflow::MaybeBorrowedLocals;
use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc::mir::*;
use std::cell::RefCell;

#[derive(Copy, Clone)]
pub struct MaybeStorageLive<'a, 'tcx> {
    body: &'a Body<'tcx>,
}

impl<'a, 'tcx> MaybeStorageLive<'a, 'tcx> {
    pub fn new(body: &'a Body<'tcx>) -> Self {
        MaybeStorageLive { body }
    }

    pub fn body(&self) -> &Body<'tcx> {
        self.body
    }
}

impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
    type Idx = Local;
    fn name() -> &'static str {
        "maybe_storage_live"
    }
    fn bits_per_block(&self) -> usize {
        self.body.local_decls.len()
    }

    fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
        // The resume argument is live on function entry (we don't care about
        // the `self` argument)
        for arg in self.body.args_iter().skip(1) {
            on_entry.insert(arg);
        }
    }

    fn statement_effect(&self, trans: &mut GenKillSet<Local>, loc: Location) {
        let stmt = &self.body[loc.block].statements[loc.statement_index];

        match stmt.kind {
            StatementKind::StorageLive(l) => trans.gen(l),
            StatementKind::StorageDead(l) => trans.kill(l),
            _ => (),
        }
    }

    fn terminator_effect(&self, _trans: &mut GenKillSet<Local>, _loc: Location) {
        // Terminators have no effect
    }

    fn propagate_call_return(
        &self,
        _in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        _dest_place: &mir::Place<'tcx>,
    ) {
        // Nothing to do when a call returns successfully
    }
}

impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
    /// bottom = dead
    const BOTTOM_VALUE: bool = false;
}

type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;

/// Dataflow analysis that determines whether each local requires storage at a
/// given location; i.e. whether its storage can go away without being observed.
pub struct RequiresStorage<'mir, 'tcx> {
    body: ReadOnlyBodyAndCache<'mir, 'tcx>,
    borrowed_locals: RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
}

impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
    pub fn new(
        body: ReadOnlyBodyAndCache<'mir, 'tcx>,
        borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>,
    ) -> Self {
        RequiresStorage {
            body,
            borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)),
        }
    }

    pub fn body(&self) -> &Body<'tcx> {
        &self.body
    }
}

impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
    type Idx = Local;
    fn name() -> &'static str {
        "requires_storage"
    }
    fn bits_per_block(&self) -> usize {
        self.body.local_decls.len()
    }

    fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
        // The resume argument is live on function entry (we don't care about
        // the `self` argument)
        for arg in self.body.args_iter().skip(1) {
            on_entry.insert(arg);
        }
    }

    fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {
        let stmt = &self.body[loc.block].statements[loc.statement_index];

        // If a place is borrowed in a statement, it needs storage for that statement.
        self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc);

        // If a place is assigned to in a statement, it needs storage for that statement.
        match &stmt.kind {
            StatementKind::StorageDead(l) => sets.kill(*l),
            StatementKind::Assign(box (place, _))
            | StatementKind::SetDiscriminant { box place, .. } => {
                sets.gen(place.local);
            }
            StatementKind::InlineAsm(box InlineAsm { outputs, .. }) => {
                for place in &**outputs {
                    sets.gen(place.local);
                }
            }

            // Nothing to do for these. Match exhaustively so this fails to compile when new
            // variants are added.
            StatementKind::AscribeUserType(..)
            | StatementKind::FakeRead(..)
            | StatementKind::Nop
            | StatementKind::Retag(..)
            | StatementKind::StorageLive(..) => {}
        }
    }

    fn statement_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        // If we move from a place then only stops needing storage *after*
        // that statement.
        self.check_for_move(sets, loc);
    }

    fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        let terminator = self.body[loc.block].terminator();

        // If a place is borrowed in a terminator, it needs storage for that terminator.
        self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc);

        match &terminator.kind {
            TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. }
            | TerminatorKind::Yield { resume_arg: Place { local, .. }, .. } => {
                sets.gen(*local);
            }

            // Nothing to do for these. Match exhaustively so this fails to compile when new
            // variants are added.
            TerminatorKind::Call { destination: None, .. }
            | TerminatorKind::Abort
            | TerminatorKind::Assert { .. }
            | TerminatorKind::Drop { .. }
            | TerminatorKind::DropAndReplace { .. }
            | TerminatorKind::FalseEdges { .. }
            | TerminatorKind::FalseUnwind { .. }
            | TerminatorKind::GeneratorDrop
            | TerminatorKind::Goto { .. }
            | TerminatorKind::Resume
            | TerminatorKind::Return
            | TerminatorKind::SwitchInt { .. }
            | TerminatorKind::Unreachable => {}
        }
    }

    fn terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        match &self.body[loc.block].terminator().kind {
            // For call terminators the destination requires storage for the call
            // and after the call returns successfully, but not after a panic.
            // Since `propagate_call_unwind` doesn't exist, we have to kill the
            // destination here, and then gen it again in `propagate_call_return`.
            TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } => {
                sets.kill(*local);
            }

            // Nothing to do for these. Match exhaustively so this fails to compile when new
            // variants are added.
            TerminatorKind::Call { destination: None, .. }
            | TerminatorKind::Yield { .. }
            | TerminatorKind::Abort
            | TerminatorKind::Assert { .. }
            | TerminatorKind::Drop { .. }
            | TerminatorKind::DropAndReplace { .. }
            | TerminatorKind::FalseEdges { .. }
            | TerminatorKind::FalseUnwind { .. }
            | TerminatorKind::GeneratorDrop
            | TerminatorKind::Goto { .. }
            | TerminatorKind::Resume
            | TerminatorKind::Return
            | TerminatorKind::SwitchInt { .. }
            | TerminatorKind::Unreachable => {}
        }

        self.check_for_move(sets, loc);
    }

    fn propagate_call_return(
        &self,
        in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        dest_place: &mir::Place<'tcx>,
    ) {
        in_out.insert(dest_place.local);
    }
}

impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
    /// Kill locals that are fully moved and have not been borrowed.
    fn check_for_move(&self, sets: &mut GenKillSet<Local>, loc: Location) {
        let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals };
        visitor.visit_location(self.body, loc);
    }
}

impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
    /// bottom = dead
    const BOTTOM_VALUE: bool = false;
}

struct MoveVisitor<'a, 'mir, 'tcx> {
    borrowed_locals: &'a RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
    sets: &'a mut GenKillSet<Local>,
}

impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
    fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
        if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
            let mut borrowed_locals = self.borrowed_locals.borrow_mut();
            borrowed_locals.seek_before(loc);
            if !borrowed_locals.contains(*local) {
                self.sets.kill(*local);
            }
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core,no_std)]

extern crate core;
extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;

use core::prelude::*;
use hil::Controller;
use sam4l::*;

pub static mut FIRESTORM : Option<Firestorm> = None;

#[allow(dead_code)]
pub struct Firestorm {
    chip: &'static mut chip::Sam4l,
    console: drivers::console::Console<sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static mut hil::gpio::GPIOPin; 14]>,
    tmp006: drivers::tmp006::TMP006<sam4l::i2c::I2CDevice>,
    timer: hil::timer::TimerMux,
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn with_driver<F, R>(&mut self, driver_num: usize, mut f: F) -> R where
            F: FnMut(Option<&mut hil::Driver>) -> R {

        f(match driver_num {
            0 => Some(&mut self.console),
            1 => Some(&mut self.gpio),
            2 => Some(&mut self.tmp006),
            _ => None
        })
    }
}

pub unsafe fn init() -> &'static mut Firestorm {
    chip::CHIP = Some(chip::Sam4l::new());
    let chip = chip::CHIP.as_mut().unwrap();
    chip.ast.select_clock(sam4l::ast::Clock::ClockRCSys);
    chip.ast.set_prescalar(0);
    chip.ast.clear_alarm();

    FIRESTORM = Some(Firestorm {
        chip: chip,
        console: drivers::console::Console::new(&mut chip.usarts[3]),
        gpio: drivers::gpio::GPIO::new(
            [ &mut chip.pc10, &mut chip.pc19, &mut chip.pc13
            , &mut chip.pa09, &mut chip.pa17, &mut chip.pc20
            , &mut chip.pa19, &mut chip.pa14, &mut chip.pa16
            , &mut chip.pa13, &mut chip.pa11, &mut chip.pa10
            , &mut chip.pa12, &mut chip.pc09]),
        tmp006: drivers::tmp006::TMP006::new(&mut chip.i2c[2]),
        timer: hil::timer::TimerMux::new(&mut chip.ast)
    });

    let firestorm : &'static mut Firestorm = FIRESTORM.as_mut().unwrap();

    chip.usarts[3].configure(sam4l::usart::USARTParams {
        client: &mut firestorm.console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    chip.pb09.configure(Some(sam4l::gpio::PeripheralFunction::A));
    chip.pb10.configure(Some(sam4l::gpio::PeripheralFunction::A));

    chip.pa21.configure(Some(sam4l::gpio::PeripheralFunction::E));
    chip.pa22.configure(Some(sam4l::gpio::PeripheralFunction::E));

    firestorm.console.initialize();
    firestorm
}

<commit_msg>Add LED on Firestorm.<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core,no_std)]

extern crate core;
extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;

use core::prelude::*;
use hil::Controller;
use sam4l::*;

pub static mut FIRESTORM : Option<Firestorm> = None;

#[allow(dead_code)]
pub struct Firestorm {
    chip: &'static mut chip::Sam4l,
    console: drivers::console::Console<sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static mut hil::gpio::GPIOPin; 14]>,
    tmp006: drivers::tmp006::TMP006<sam4l::i2c::I2CDevice>,
    timer: hil::timer::TimerMux,
    led: hil::led::LedHigh
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn with_driver<F, R>(&mut self, driver_num: usize, mut f: F) -> R where
            F: FnMut(Option<&mut hil::Driver>) -> R {

        f(match driver_num {
            0 => Some(&mut self.console),
            1 => Some(&mut self.gpio),
            2 => Some(&mut self.tmp006),
            _ => None
        })
    }
}

pub unsafe fn init() -> &'static mut Firestorm {
    chip::CHIP = Some(chip::Sam4l::new());
    let chip = chip::CHIP.as_mut().unwrap();
    chip.ast.select_clock(sam4l::ast::Clock::ClockRCSys);
    chip.ast.set_prescalar(0);
    chip.ast.clear_alarm();

    FIRESTORM = Some(Firestorm {
        chip: chip,
        console: drivers::console::Console::new(&mut chip.usarts[3]),
        gpio: drivers::gpio::GPIO::new(
            [ &mut chip.pc10, &mut chip.pc19, &mut chip.pc13
            , &mut chip.pa09, &mut chip.pa17, &mut chip.pc20
            , &mut chip.pa19, &mut chip.pa14, &mut chip.pa16
            , &mut chip.pa13, &mut chip.pa11, &mut chip.pa10
            , &mut chip.pa12, &mut chip.pc09]),
        tmp006: drivers::tmp006::TMP006::new(&mut chip.i2c[2]),
        timer: hil::timer::TimerMux::new(&mut chip.ast),
        led: hil::led::LedHigh::new(&mut chip.pc10)
    });

    let firestorm : &'static mut Firestorm = FIRESTORM.as_mut().unwrap();

    chip.usarts[3].configure(sam4l::usart::USARTParams {
        client: &mut firestorm.console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    chip.pb09.configure(Some(sam4l::gpio::PeripheralFunction::A));
    chip.pb10.configure(Some(sam4l::gpio::PeripheralFunction::A));

    chip.pa21.configure(Some(sam4l::gpio::PeripheralFunction::E));
    chip.pa22.configure(Some(sam4l::gpio::PeripheralFunction::E));

    firestorm.console.initialize();
    firestorm
}

<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core_intrinsics,lang_items)]

extern crate hotel;
extern crate hil;
extern crate support;

pub struct Firestorm;

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            use core::mem::transmute;
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

const LED : u32 = 0;
const LED_GPIO : u16 = 1;

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use core::intrinsics::{volatile_load,volatile_store};
    use hotel::pmu::*;
    use hotel::gpio;

    let uart_clock =
            Clock::new(PeripheralClock::Bank1(PeripheralClock1::Uart0Timer));
    let gpio_clock =
            Clock::new(PeripheralClock::Bank0(PeripheralClock0::Gpio0));

    // Drive DIOA0 from TX
    let pinmux_dioa0_sel : *mut u16 = 0x40060028 as *mut u16;
    volatile_store(pinmux_dioa0_sel, 70);

    // Drive DIOM4 from GPIO0_0
    let pinmux_diom4_sel : *mut u16 = 0x40060020 as *mut u16;
    volatile_store(pinmux_diom4_sel, LED_GPIO);

    /* ********************
     * UART
     * ********************/

    // Turn on UART0 clock
    uart_clock.enable();

    // Setup baud rate
    let nco = 5300; // 2^20 * 115200 / 24000000
    let uart_nco : *mut u16 = 0x40600008 as *mut u16;
    volatile_store(uart_nco, nco);

    // Enable TX
    let uart_ctrl : *mut u16 = 0x4060000C as *mut u16;
    volatile_store(uart_ctrl, 1);

    unsafe fn write_char(c : char) {
        let uart_state : *mut u32 = 0x40600014 as *mut u32;
        let uart_wdata : *mut u8 = 0x40600004 as *mut u8;

        while volatile_load(uart_state) & 1 != 0 {}

        volatile_store(uart_wdata, c as u8);
    }

    unsafe fn write_str(s : &str) {
        for c in s.chars() {
            write_char(c);
        }
    }

    write_str("Hello from Rust!\n");

    /* ********************
     * Blink
     * ********************/

    // Turn on GPIO clocks
    gpio_clock.enable();

    let led = &gpio::GPIOPin::new(gpio::GPIO0_BASE, gpio::Pin::P0);

    led.enable_output();

    loop {
        for _ in 0..3000000 {
            support::nop();
        }
        led.toggle();
    }

    static_init!(firestorm : Firestorm = Firestorm);
    firestorm
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        // FIXME: The wfi call from main() blocks forever if no interrupts are generated. For now,
        // pretend we have interrupts to avoid blocking.
        true
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {
        match driver_num {
            //1 => f(Some(self.gpio)),
            _ => f(None)
        }
    }
}

use core::fmt::Arguments;
#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    loop {}
}
<commit_msg>Tango: update to use uart and pinmux modules<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(lang_items)]

extern crate hotel;
extern crate hil;
extern crate support;

pub struct Firestorm;

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            use core::mem::transmute;
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use hotel::pmu::*;
    use hotel::gpio;

    let uart_clock =
            Clock::new(PeripheralClock::Bank1(PeripheralClock1::Uart0Timer));
    let gpio_clock =
            Clock::new(PeripheralClock::Bank0(PeripheralClock0::Gpio0));

    let pinmux = &mut *hotel::pinmux::PINMUX;

    // Drive DIOA0 from TX
    pinmux.dioa0.select.set(hotel::pinmux::Function::Uart0Tx);

    // Drive DIOM4 from GPIO0_0
    pinmux.diom4.select.set(hotel::pinmux::Function::Gpio0Gpio0);

    /* ********************
     * UART
     * ********************/

    // Turn on UART0 clock
    uart_clock.enable();

    let uart = &mut *hotel::uart::UART0;

    // Setup baud rate
    uart.nco.set(5300); // 2^20 * 115200 / 24000000

    // Enable TX
    uart.control.set(1);

    for c in "Hello from Rust!\n".chars() {
        while uart.state.get() & 1 != 0 {}
        uart.write_data.set(c as u32);
    }

    /* ********************
     * Blink
     * ********************/

    // Turn on GPIO clocks
    gpio_clock.enable();

    let led = &gpio::GPIOPin::new(gpio::GPIO0_BASE, gpio::Pin::P0);

    led.enable_output();

    loop {
        for _ in 0..3000000 {
            support::nop();
        }
        led.toggle();
    }

    static_init!(firestorm : Firestorm = Firestorm);
    firestorm
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        // FIXME: The wfi call from main() blocks forever if no interrupts are generated. For now,
        // pretend we have interrupts to avoid blocking.
        true
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {
        match driver_num {
            //1 => f(Some(self.gpio)),
            _ => f(None)
        }
    }
}

use core::fmt::Arguments;
#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    loop {}
}

<|endoftext|>


<commit_before>use clock::{GameTime, GameClock};
use framerate::counter::FrameCount;

#[derive(Debug)]
pub struct FrameRunner<C: FrameCount> {
    clock: GameClock,
    counter: C,
}

impl<C> FrameRunner<C>
    where C: FrameCount
{
    pub fn new(clock: GameClock, counter: C) -> FrameRunner<C> {
        FrameRunner {
            clock: clock,
            counter: counter,
        }
    }

    pub fn clock(&self) -> &GameClock {
        &self.clock
    }
    pub fn clock_mut(&mut self) -> &mut GameClock {
        &mut self.clock
    }
    pub fn counter(&self) -> &C {
        &self.counter
    }
    pub fn counter_mut(&mut self) -> &mut C {
        &mut self.counter
    }
    pub fn tick(&mut self) -> GameTime {
        let time = self.clock.tick(&mut self.counter);
        time
    }
}
<commit_msg>Added `do_frame` method to FrameRunner.<commit_after>use clock::{GameTime, GameClock};
use framerate::counter::FrameCount;

#[derive(Debug)]
pub struct FrameRunner<C: FrameCount> {
    clock: GameClock,
    counter: C,
}

impl<C> FrameRunner<C>
    where C: FrameCount
{
    pub fn new(clock: GameClock, counter: C) -> FrameRunner<C> {
        FrameRunner {
            clock: clock,
            counter: counter,
        }
    }

    pub fn clock(&self) -> &GameClock {
        &self.clock
    }
    pub fn clock_mut(&mut self) -> &mut GameClock {
        &mut self.clock
    }
    pub fn counter(&self) -> &C {
        &self.counter
    }
    pub fn counter_mut(&mut self) -> &mut C {
        &mut self.counter
    }
    pub fn tick(&mut self) -> GameTime {
        let time = self.clock.tick(&mut self.counter);
        time
    }

    pub fn do_frame<F>(&mut self, frame_fn: F)
        where F: FnOnce(GameTime)
    {
        let time = self.tick();
        frame_fn(time);
        self.clock.sleep_remaining(&self.counter);
    }
}
<|endoftext|>