<commit_before>#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    OpenBracket,
    CloseBracket,
    Identifier(String), // Identifier, must be alphabetical
    Decimal(String), // Literal expression: 42
    Binary(String), // Literal expression: 0b101010
    // Octal(String), // Literal expression: 0o052
    Hexadecimal(String), // Literal expression: 0x2a
    Radix(String), // Non-{Bin, Hex, Dec, Oct}
    Operator(String),
    // Assignment(String),
    Unknown(char),
    // Placeholder/Don't care token. Every character is tokenized.
    Skip,
}

#[derive(PartialEq, Copy, Clone, Debug)]
enum State {
    General,
    Front,
    Bracket,
    Operator,
    Shift,
    // Assignment,
    Identifier,
    Radix,
}

pub type Tokens = Vec<(usize, Token)>;

pub struct Lexer {
    tokens: Tokens,
    curr_state: State,
    prev_state: State,
}

impl Lexer {
    pub fn new() -> Lexer {
        Lexer {
            tokens: Tokens::with_capacity(10),
            curr_state: State::Front,
            prev_state: State::General,
        }
    }

    pub fn analyze(&mut self, line: &str) -> &Tokens {
        self.reset_lexer();

        let mut radix = String::with_capacity(2);
        let mut shift = String::with_capacity(2);
        let mut start_position: usize = 0;
        let mut radix_position: usize = 0;
        let mut shift_position: usize = 0;

        for (position, character) in line.trim().chars().enumerate() {
            if character.is_whitespace() {
                continue;
            }

            let mut token = Token::Skip;
            self.prev_state = self.curr_state;
            match character {
                ')' => {
                    token = Token::CloseBracket;
                    start_position = position;
                    self.curr_state = State::Bracket;
                }
                '(' => {
                    token = Token::OpenBracket;
                    start_position = position;
                    self.curr_state = State::Bracket;
                }
                '^' | '&' | '|' | '~' | '-' => {
                    token = Token::Operator(character.to_string());
                    start_position = position;
                    self.curr_state = State::Operator;
                }
                '>' | '<' => {
                    if shift.is_empty() {
                        shift_position = position;
                    }
                    shift.push(character);
                    self.curr_state = State::Shift;
                }
                _ if character.is_alphabetic() => {
                    if radix.is_empty() {
                        radix_position = position;
                    }
                    radix.push(character);
                    if self.curr_state != State::Radix {
                        self.curr_state = State::Identifier;
                    }

                }
                _ if character.is_numeric() => {
                    if radix.is_empty() {
                        radix_position = position;
                    }
                    radix.push(character);
                    self.curr_state = State::Radix;
                }
                _ => {
                    token = Token::Unknown(character);
                    start_position = position;
                    self.curr_state = State::General;
                }
            }

            if self.prev_state == State::Radix && self.curr_state != State::Radix {
                self.identify_radix(radix_position, &mut radix);
            }

            if self.prev_state == State::Identifier && self.curr_state != State::Identifier {
                self.tokens.push((radix_position, Token::Identifier(radix.clone())));
                radix.clear();
            }

            if self.prev_state == State::Shift && self.curr_state != State::Shift {
                self.tokens.push((shift_position, Token::Operator(shift.clone())));
                shift.clear();
            }

            if token != Token::Skip {
                self.tokens.push((start_position, token.clone()));
            }

        }

        if !radix.is_empty() {
            if self.curr_state == State::Radix {
                self.identify_radix(radix_position, &mut radix);
            } else if self.curr_state == State::Identifier {
                self.tokens.push((radix_position, Token::Identifier(radix.clone())));
                radix.clear();
            }
        }

        if !shift.is_empty() {
            self.tokens.push((shift_position, Token::Operator(shift.clone())));
            shift.clear();
        }

        &self.tokens
    }

    fn identify_radix(&mut self, position: usize, radix: &mut String) {
        if !radix.parse::<i32>().is_err() {
            self.tokens.push((position, Token::Decimal(radix.clone())));
        } else {
            self.tokens.push((position, Token::Radix(radix.clone())));
        }
        radix.clear();
    }

    fn reset_lexer(&mut self) {
        self.curr_state = State::Front;
        self.prev_state = State::General;
        self.tokens.clear();
    }
}

// #[cfg(test)]
// mod tests {}
<commit_msg>Comment out unused Tokens in lexer<commit_after>#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    OpenBracket,
    CloseBracket,
    Identifier(String), // Identifier, must be alphabetical
    Decimal(String), // Literal expression: 42
    // Binary(String), // Literal expression: 0b101010
    // Octal(String), // Literal expression: 0o052
    // Hexadecimal(String), // Literal expression: 0x2a
    Radix(String), // Non-{Bin, Hex, Dec, Oct}
    Operator(String),
    // Assignment(String),
    Unknown(char),
    // Placeholder/Don't care token. Every character is tokenized.
    Skip,
}

#[derive(PartialEq, Copy, Clone, Debug)]
enum State {
    General,
    Front,
    Bracket,
    Operator,
    Shift,
    // Assignment,
    Identifier,
    Radix,
}

pub type Tokens = Vec<(usize, Token)>;

pub struct Lexer {
    tokens: Tokens,
    curr_state: State,
    prev_state: State,
}

impl Lexer {
    pub fn new() -> Lexer {
        Lexer {
            tokens: Tokens::with_capacity(10),
            curr_state: State::Front,
            prev_state: State::General,
        }
    }

    pub fn analyze(&mut self, line: &str) -> &Tokens {
        self.reset_lexer();

        let mut radix = String::with_capacity(2);
        let mut shift = String::with_capacity(2);
        let mut start_position: usize = 0;
        let mut radix_position: usize = 0;
        let mut shift_position: usize = 0;

        for (position, character) in line.trim().chars().enumerate() {
            if character.is_whitespace() {
                continue;
            }

            let mut token = Token::Skip;
            self.prev_state = self.curr_state;
            match character {
                ')' => {
                    token = Token::CloseBracket;
                    start_position = position;
                    self.curr_state = State::Bracket;
                }
                '(' => {
                    token = Token::OpenBracket;
                    start_position = position;
                    self.curr_state = State::Bracket;
                }
                '^' | '&' | '|' | '~' | '-' => {
                    token = Token::Operator(character.to_string());
                    start_position = position;
                    self.curr_state = State::Operator;
                }
                '>' | '<' => {
                    if shift.is_empty() {
                        shift_position = position;
                    }
                    shift.push(character);
                    self.curr_state = State::Shift;
                }
                _ if character.is_alphabetic() => {
                    if radix.is_empty() {
                        radix_position = position;
                    }
                    radix.push(character);
                    if self.curr_state != State::Radix {
                        self.curr_state = State::Identifier;
                    }

                }
                _ if character.is_numeric() => {
                    if radix.is_empty() {
                        radix_position = position;
                    }
                    radix.push(character);
                    self.curr_state = State::Radix;
                }
                _ => {
                    token = Token::Unknown(character);
                    start_position = position;
                    self.curr_state = State::General;
                }
            }

            if self.prev_state == State::Radix && self.curr_state != State::Radix {
                self.identify_radix(radix_position, &mut radix);
            }

            if self.prev_state == State::Identifier && self.curr_state != State::Identifier {
                self.tokens.push((radix_position, Token::Identifier(radix.clone())));
                radix.clear();
            }

            if self.prev_state == State::Shift && self.curr_state != State::Shift {
                self.tokens.push((shift_position, Token::Operator(shift.clone())));
                shift.clear();
            }

            if token != Token::Skip {
                self.tokens.push((start_position, token.clone()));
            }

        }

        if !radix.is_empty() {
            if self.curr_state == State::Radix {
                self.identify_radix(radix_position, &mut radix);
            } else if self.curr_state == State::Identifier {
                self.tokens.push((radix_position, Token::Identifier(radix.clone())));
                radix.clear();
            }
        }

        if !shift.is_empty() {
            self.tokens.push((shift_position, Token::Operator(shift.clone())));
            shift.clear();
        }

        &self.tokens
    }

    fn identify_radix(&mut self, position: usize, radix: &mut String) {
        if !radix.parse::<i32>().is_err() {
            self.tokens.push((position, Token::Decimal(radix.clone())));
        } else {
            self.tokens.push((position, Token::Radix(radix.clone())));
        }
        radix.clear();
    }

    fn reset_lexer(&mut self) {
        self.curr_state = State::Front;
        self.prev_state = State::General;
        self.tokens.clear();
    }
}

// #[cfg(test)]
// mod tests {}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq, Clone)]
pub enum Token<'input> {
    LParen,
    RParen,
    Symbol(&'input str),
    Number(i64),
    EOF,
}

pub struct Lexer<'input> {
    pub s: &'input str,
    pub pos: usize,
    pub col: usize,
    pub line_num: usize,
    pub tok_buf: Option<Token<'input>>,
}

fn is_valid_in_symbol(c: char) -> bool {
    c.is_alphabetic() ||
    match c {
        '+' | '-' | '*' | '/' | '#' | '<' | '>' | '=' => true,
        _ => false,
    }
}

impl<'input> Lexer<'input> {
    pub fn new(source: &'input str) -> Lexer<'input> {
        Lexer { s: source,
                pos: 0,
                col: 0,
                line_num: 1,
                tok_buf: None}
    }

    pub fn unread(&mut self, tok: Token<'input>) {
        match self.tok_buf {
            Some(_) => panic!("error: unread buffer full"),
            None => self.tok_buf = Some(tok),
        }
    }

    pub fn get_token(&mut self) -> Token<'input> {
        if let Some(tok) = self.tok_buf.clone() {
            self.tok_buf = None;
            return tok;
        }
        else {
            let mut iter = self.s[self.pos..].chars().peekable();
            while let Some(&c) = iter.peek() {
                if c.is_numeric() {
                    let mut n = c;
                    let start = self.pos;
                    while n.is_numeric() {
                        iter.next();
                        self.pos += 1;
                        self.col += 1;
                        n = match iter.peek() {
                            Some(&x) => x,
                            None => break,
                        };
                    }
                    return Token::Number(self.s[start..self.pos].parse().unwrap());
                }
                else if is_valid_in_symbol(c) {
                    let mut s = c;
                    let start = self.pos;
                    while s.is_alphanumeric() || is_valid_in_symbol(s) {
                        iter.next();
                        self.pos += 1;
                        self.col += 1;
                        s = match iter.peek() {
                            Some(&x) => x,
                            None => break,
                        };
                    }
                    return Token::Symbol(&self.s[start..self.pos]);
                }
                else {
                    match c {
                        '\n' => {
                            iter.next();
                            self.pos += 1;
                            self.col = 0;
                            self.line_num += 1;
                            continue;
                        },
                        ';' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            while let Some(c) = iter.next() {
                                self.pos += 1;
                                if c.clone() == '\n' {
                                    break;
                                }
                            }
                            self.line_num += 1;
                            self.col = 0;
                        },
                        ' ' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            continue
                        },
                        '(' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            return Token::LParen
                        },
                        ')' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            return Token::RParen
                        },

                        _ => panic!("line {}:{} unexpected char: {}", self.line_num, self.col, c),
                    }
                }
            }
            return Token::EOF;
        }
    }
}

impl<'input> Iterator for Lexer<'input> {
    type Item = Token<'input>;

    fn next(&mut self) -> Option<Token<'input>> {
        match self.get_token() {
            Token::EOF => None,
            t => Some(t),
        }
    }
}

fn main() {
    #[derive(Debug)]
    pub enum Ast<'input> {
        Symbol(&'input str),
        Number(i64),
        Bool(bool),
        List(Vec<Ast<'input>>),
        FuncName(&'input str),  // for closure-conversion

        Define(&'input str, Vec<&'input str>, Box<Ast<'input>>),
        If(Box<Ast<'input>>,     // cnd
           Box<Ast<'input>>,     // thn
           Box<Ast<'input>>),    // els
        Let(Vec<(&'input str, Ast<'input>)>, Box<Ast<'input>>),
    }

    pub struct Parser<'input> {
        lexer: Lexer<'input>
    }

    impl<'input> Parser<'input> {
        pub fn new(source: &'input str) -> Parser<'input> {
            Parser {
                lexer: Lexer::new(source)
            }
        }

        pub fn get_list(&mut self) -> Vec<Ast<'input>> {
            match self.get_expr() {
                Some(expr) => match self.lexer.next() {
                    None => vec![],
                    Some(Token::RParen) => vec![expr],
                    Some(tok) => {
                        self.lexer.unread(tok);
                        let mut seq = self.get_list();
                        seq.insert(0, expr);

                        return seq;
                    }
                },
                None => vec![],
            }
        }

        pub fn get_expr(&mut self) -> Option<Ast<'input>> {
            match self.lexer.next() {
                Some(Token::Symbol(s)) => Some(Ast::Symbol(s)),
                Some(Token::Number(n)) => Some(Ast::Number(n)),
                Some(Token::LParen) => Some(Ast::List(self.get_list())),
                Some(Token::RParen) => panic!("line {}: {} unmatched ')'",
                                              self.lexer.line_num,
                                              self.lexer.col),
                _ => None,
            }
        }

        pub fn get_ast(expr: &Ast<'input>) -> Ast<'input> {
            match expr {
                &Ast::Symbol(sym) =>
                    match &sym[..] {
                        "#f" => Ast::Bool(false),
                        "#t" => Ast::Bool(true),
                        _ => Ast::Symbol(sym)
                    },
                &Ast::List(ref elts) =>
                    match &elts[..] {
                        &[Ast::Symbol(k), Ast::List(ref defelts), ref body]
                            if k == "define" => {
                                let name = &defelts[0];
                                let args = &defelts[1..];

                                if let Ast::Symbol(name) = name {
                                    Ast::Define(name,
                                                vec![],
                                                Box::new(Parser::get_ast(&body)))
                                } else {
                                    panic!("invalid function prototype");
                                }
                            },
                        &[Ast::Symbol(k), ref cnd, ref thn, ref els]
                            if k == "if" => {
                                Ast::If(Box::new(Parser::get_ast(cnd)),
                                        Box::new(Parser::get_ast(thn)),
                                        Box::new(Parser::get_ast(els)))
                            },
                        &[Ast::Symbol(k), Ast::List(ref bindings), ref body]
                            if k == "let" => {
                                let mut astified_bindings = vec![];
                                for bind_pair in bindings {
                                    if let Ast::List(kv) = bind_pair {
                                        let (key, val) =
                                            if kv.len() == 2 {
                                                (kv[0], kv[1])
                                            } else {
                                                panic!("invalid let binding syntax");
                                            };

                                        let keyname =
                                            if let Ast::Symbol(k) = key {
                                                k
                                            } else {
                                                panic!("let binding key is not symbol");
                                            };

                                        astified_bindings.push((keyname, Parser::get_ast(&val)));
                                    }
                                }

                                Ast::Let(astified_bindings,
                                         Box::new(Parser::get_ast(&body)))
                            },
                        _ => Ast::Number(42),
                    },
                _ => Ast::Number(42),
            }
        }
    }

    let mut p = Parser::new("(if #t 42 (define (foo x y) (+ (* 1 2) 2)))");
    // println!("{:?}", p.get_expr());
    println!("{:?}", Parser::get_ast(&p.get_expr().unwrap()));
}
<commit_msg>Fix `let` and `define` parsing<commit_after>#[derive(Debug, PartialEq, Clone)]
pub enum Token<'input> {
    LParen,
    RParen,
    Symbol(&'input str),
    Number(i64),
    EOF,
}

pub struct Lexer<'input> {
    pub s: &'input str,
    pub pos: usize,
    pub col: usize,
    pub line_num: usize,
    pub tok_buf: Option<Token<'input>>,
}

fn is_valid_in_symbol(c: char) -> bool {
    c.is_alphabetic() ||
    match c {
        '+' | '-' | '*' | '/' | '#' | '<' | '>' | '=' => true,
        _ => false,
    }
}

impl<'input> Lexer<'input> {
    pub fn new(source: &'input str) -> Lexer<'input> {
        Lexer { s: source,
                pos: 0,
                col: 0,
                line_num: 1,
                tok_buf: None}
    }

    pub fn unread(&mut self, tok: Token<'input>) {
        match self.tok_buf {
            Some(_) => panic!("error: unread buffer full"),
            None => self.tok_buf = Some(tok),
        }
    }

    pub fn get_token(&mut self) -> Token<'input> {
        if let Some(tok) = self.tok_buf.clone() {
            self.tok_buf = None;
            return tok;
        }
        else {
            let mut iter = self.s[self.pos..].chars().peekable();
            while let Some(&c) = iter.peek() {
                if c.is_numeric() {
                    let mut n = c;
                    let start = self.pos;
                    while n.is_numeric() {
                        iter.next();
                        self.pos += 1;
                        self.col += 1;
                        n = match iter.peek() {
                            Some(&x) => x,
                            None => break,
                        };
                    }
                    return Token::Number(self.s[start..self.pos].parse().unwrap());
                }
                else if is_valid_in_symbol(c) {
                    let mut s = c;
                    let start = self.pos;
                    while s.is_alphanumeric() || is_valid_in_symbol(s) {
                        iter.next();
                        self.pos += 1;
                        self.col += 1;
                        s = match iter.peek() {
                            Some(&x) => x,
                            None => break,
                        };
                    }
                    return Token::Symbol(&self.s[start..self.pos]);
                }
                else {
                    match c {
                        '\n' => {
                            iter.next();
                            self.pos += 1;
                            self.col = 0;
                            self.line_num += 1;
                            continue;
                        },
                        ';' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            while let Some(c) = iter.next() {
                                self.pos += 1;
                                if c.clone() == '\n' {
                                    break;
                                }
                            }
                            self.line_num += 1;
                            self.col = 0;
                        },
                        ' ' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            continue
                        },
                        '(' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            return Token::LParen
                        },
                        ')' => {
                            iter.next();
                            self.pos += 1;
                            self.col += 1;
                            return Token::RParen
                        },

                        _ => panic!("line {}:{} unexpected char: {}", self.line_num, self.col, c),
                    }
                }
            }
            return Token::EOF;
        }
    }
}

impl<'input> Iterator for Lexer<'input> {
    type Item = Token<'input>;

    fn next(&mut self) -> Option<Token<'input>> {
        match self.get_token() {
            Token::EOF => None,
            t => Some(t),
        }
    }
}

fn main() {
    #[derive(Debug)]
    pub enum Ast<'input> {
        Symbol(&'input str),
        Number(i64),
        Bool(bool),
        List(Vec<Ast<'input>>),
        FuncName(&'input str),  // for closure-conversion

        Define(&'input str, Vec<&'input str>, Box<Ast<'input>>),
        If(Box<Ast<'input>>,     // cnd
           Box<Ast<'input>>,     // thn
           Box<Ast<'input>>),    // els
        Let(Vec<(&'input str, Ast<'input>)>, Box<Ast<'input>>),
    }

    pub struct Parser<'input> {
        lexer: Lexer<'input>
    }

    impl<'input> Parser<'input> {
        pub fn new(source: &'input str) -> Parser<'input> {
            Parser {
                lexer: Lexer::new(source)
            }
        }

        pub fn get_list(&mut self) -> Vec<Ast<'input>> {
            match self.get_expr() {
                Some(expr) => match self.lexer.next() {
                    None => vec![],
                    Some(Token::RParen) => vec![expr],
                    Some(tok) => {
                        self.lexer.unread(tok);
                        let mut seq = self.get_list();
                        seq.insert(0, expr);

                        return seq;
                    }
                },
                None => vec![],
            }
        }

        pub fn get_expr(&mut self) -> Option<Ast<'input>> {
            match self.lexer.next() {
                Some(Token::Symbol(s)) => Some(Ast::Symbol(s)),
                Some(Token::Number(n)) => Some(Ast::Number(n)),
                Some(Token::LParen) => Some(Ast::List(self.get_list())),
                Some(Token::RParen) => panic!("line {}: {} unmatched ')'",
                                              self.lexer.line_num,
                                              self.lexer.col),
                _ => None,
            }
        }

        pub fn get_arg_names(args: &[Ast<'input>]) -> Vec<&'input str> {
            let arg_names : Vec<&'input str> = args.iter().map(|arg| match arg {
                Ast::Symbol(name) => *name,
                _ => panic!("invalid arg"),
            }).collect();

            arg_names
        }

        pub fn get_ast(expr: &Ast<'input>) -> Ast<'input> {
            match expr {
                &Ast::Symbol(sym) =>
                    match &sym[..] {
                        "#f" => Ast::Bool(false),
                        "#t" => Ast::Bool(true),
                        _ => Ast::Symbol(sym)
                    },
                &Ast::List(ref elts) =>
                    match &elts[..] {
                        &[Ast::Symbol(k), Ast::List(ref defelts), ref body]
                            if k == "define" => {
                                let name = &defelts[0];
                                let args = &defelts[1..];

                                if let Ast::Symbol(name) = name {
                                    Ast::Define(name,
                                                Parser::get_arg_names(args),
                                                Box::new(Parser::get_ast(&body)))
                                } else {
                                    panic!("invalid function prototype");
                                }
                            },
                        &[Ast::Symbol(k), ref cnd, ref thn, ref els]
                            if k == "if" => {
                                Ast::If(Box::new(Parser::get_ast(cnd)),
                                        Box::new(Parser::get_ast(thn)),
                                        Box::new(Parser::get_ast(els)))
                            },
                        &[Ast::Symbol(k), Ast::List(ref bindings), ref body]
                            if k == "let" => {
                                let mut astified_bindings = vec![];
                                for bind_pair in bindings {
                                    if let Ast::List(kv) = bind_pair {
                                        let (key, val) =
                                            if kv.len() == 2 {
                                                let astified_val = Parser::get_ast(&kv[1]);
                                                let keyname =
                                                    if let Ast::Symbol(k) = kv[0] {
                                                        k
                                                    } else {
                                                        panic!("let binding key is not symbol");
                                                    };
                                                (keyname, astified_val)
                                            } else {
                                                panic!("invalid let binding syntax");
                                            };

                                        astified_bindings.push((key, val));
                                    }
                                }

                                Ast::Let(astified_bindings,
                                         Box::new(Parser::get_ast(&body)))
                            },
                        _ => Ast::Number(42),
                    },
                _ => Ast::Number(42),
            }
        }
    }

    let mut p = Parser::new("(if #t 42 (define (foo x y) (+ (* 1 2) 2)))");
    let mut p2 = Parser::new("(let ((x 10) (y 2)) (+ x y))");

    // println!("{:?}", p.get_expr());
    println!("{:?}", Parser::get_ast(&p.get_expr().unwrap()));
    println!("{:?}", Parser::get_ast(&p2.get_expr().unwrap()));
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::fmt;
use std::marker::PhantomData;
use raw_mutex::RawMutex;

/// A mutual exclusion primitive useful for protecting shared data
///
/// This mutex will block threads waiting for the lock to become available. The
/// mutex can also be statically initialized or created via a `new`
/// constructor. Each mutex has a type parameter which represents the data that
/// it is protecting. The data can only be accessed through the RAII guards
/// returned from `lock` and `try_lock`, which guarantees that the data is only
/// ever accessed when the mutex is locked.
///
/// # Differences from the standard library `Mutex`
///
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 byte of space, whereas the standard library boxes the
///   `Mutex` due to platform limitations.
/// - A `MutexGuard` can be sent to another thread and unlocked there.
/// - Can be statically constructed (requires the `const_fn` nightly feature).
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use parking_lot::Mutex;
/// use std::thread;
/// use std::sync::mpsc::channel;
///
/// const N: usize = 10;
///
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
/// //
/// // Here we're using an Arc to share memory among threads, and the data inside
/// // the Arc is protected with a mutex.
/// let data = Arc::new(Mutex::new(0));
///
/// let (tx, rx) = channel();
/// for _ in 0..10 {
///     let (data, tx) = (data.clone(), tx.clone());
///     thread::spawn(move || {
///         // The shared state can only be accessed once the lock is held.
///         // Our non-atomic increment is safe because we're the only thread
///         // which can access the shared state when the lock is held.
///         let mut data = data.lock();
///         *data += 1;
///         if *data == N {
///             tx.send(()).unwrap();
///         }
///         // the lock is unlocked here when `data` goes out of scope.
///     });
/// }
///
/// rx.recv().unwrap();
/// ```
pub struct Mutex<T: ?Sized> {
    raw: RawMutex,
    data: UnsafeCell<T>,
}

unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be access through this guard via its
/// `Deref` and `DerefMut` implementations
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
    mutex: &'a Mutex<T>,
    marker: PhantomData<&'a mut T>,
}

impl<T> Mutex<T> {
    /// Creates a new mutex in an unlocked state ready for use.
    #[cfg(feature = "nightly")]
    #[inline]
    pub const fn new(val: T) -> Mutex<T> {
        Mutex {
            data: UnsafeCell::new(val),
            raw: RawMutex::new(),
        }
    }

    /// Creates a new mutex in an unlocked state ready for use.
    #[cfg(not(feature = "nightly"))]
    #[inline]
    pub fn new(val: T) -> Mutex<T> {
        Mutex {
            data: UnsafeCell::new(val),
            raw: RawMutex::new(),
        }
    }

    /// Consumes this mutex, returning the underlying data.
    #[inline]
    pub fn into_inner(self) -> T {
        unsafe { self.data.into_inner() }
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Acquires a mutex, blocking the current thread until it is able to do so.
    ///
    /// This function will block the local thread until it is available to acquire
    /// the mutex. Upon returning, the thread is the only thread with the mutex
    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
    /// the guard goes out of scope, the mutex will be unlocked.
    ///
    /// Attempts to lock a mutex in the thread which already holds the lock will
    /// result is a deadlock.
    #[inline]
    pub fn lock(&self) -> MutexGuard<T> {
        self.raw.lock();
        MutexGuard {
            mutex: self,
            marker: PhantomData,
        }
    }

    /// Attempts to acquire this lock.
    ///
    /// If the lock could not be acquired at this time, then `Err` is returned.
    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
    /// guard is dropped.
    ///
    /// This function does not block.
    #[inline]
    pub fn try_lock(&self) -> Option<MutexGuard<T>> {
        if self.raw.try_lock() {
            Some(MutexGuard {
                mutex: self,
                marker: PhantomData,
            })
        } else {
            None
        }
    }

    /// Returns a mutable reference to the underlying data.
    ///
    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        unsafe { &mut *self.data.get() }
    }
}

impl<T: ?Sized + Default> Default for Mutex<T> {
    #[inline]
    fn default() -> Mutex<T> {
        Mutex::new(Default::default())
    }
}

impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.try_lock() {
            Some(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
            None => write!(f, "Mutex {{ <locked> }}"),
        }
    }
}

impl<'a, T: ?Sized + 'a> Deref for MutexGuard<'a, T> {
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
        unsafe { &*self.mutex.data.get() }
    }
}

impl<'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.mutex.data.get() }
    }
}

impl<'a, T: ?Sized + 'a> Drop for MutexGuard<'a, T> {
    #[inline]
    fn drop(&mut self) {
        self.mutex.raw.unlock();
    }
}

// Helper function used by Condvar, not publicly exported
#[inline]
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a RawMutex {
    &guard.mutex.raw
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc::channel;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;
    use {Mutex, Condvar};

    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    unsafe impl<T: Send> Send for Packet<T> {}
    unsafe impl<T> Sync for Packet<T> {}

    #[test]
    fn smoke() {
        let m = Mutex::new(());
        drop(m.lock());
        drop(m.lock());
    }

    #[test]
    fn lots_and_lots() {
        lazy_static! {
            static ref M: Mutex<()> = Mutex::new(());
        }
        static mut CNT: u32 = 0;
        const J: u32 = 1000;
        const K: u32 = 3;

        fn inc() {
            for _ in 0..J {
                unsafe {
                    let _g = M.lock();
                    CNT += 1;
                }
            }
        }

        let (tx, rx) = channel();
        for _ in 0..K {
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
        }

        drop(tx);
        for _ in 0..2 * K {
            rx.recv().unwrap();
        }
        assert_eq!(unsafe { CNT }, J * K * 2);
    }

    #[test]
    fn try_lock() {
        let m = Mutex::new(());
        *m.try_lock().unwrap() = ();
    }

    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut() = NonCopy(20);
        assert_eq!(m.into_inner(), NonCopy(20));
    }

    #[test]
    fn test_mutex_arc_condvar() {
        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
        let packet2 = Packet(packet.0.clone());
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            // wait until parent gets in
            rx.recv().unwrap();
            let &(ref lock, ref cvar) = &*packet2.0;
            let mut lock = lock.lock();
            *lock = true;
            cvar.notify_one();
        });

        let &(ref lock, ref cvar) = &*packet.0;
        let mut lock = lock.lock();
        tx.send(()).unwrap();
        assert!(!*lock);
        while !*lock {
            cvar.wait(&mut lock);
        }
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            let lock = arc2.lock();
            let lock2 = lock.lock();
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move || -> () {
                struct Unwinder {
                    i: Arc<Mutex<i32>>,
                }
                impl Drop for Unwinder {
                    fn drop(&mut self) {
                        *self.i.lock() += 1;
                    }
                }
                let _u = Unwinder { i: arc2 };
                panic!();
            })
            .join();
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_mutex_unsized() {
        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock(), comp);
    }

    #[test]
    fn test_mutexguard_send() {
        fn send<T: Send>(_: T) {}

        let mutex = Mutex::new(());
        send(mutex.lock());
    }
}
<commit_msg>Fix typo in docs<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::fmt;
use std::marker::PhantomData;
use raw_mutex::RawMutex;

/// A mutual exclusion primitive useful for protecting shared data
///
/// This mutex will block threads waiting for the lock to become available. The
/// mutex can also be statically initialized or created via a `new`
/// constructor. Each mutex has a type parameter which represents the data that
/// it is protecting. The data can only be accessed through the RAII guards
/// returned from `lock` and `try_lock`, which guarantees that the data is only
/// ever accessed when the mutex is locked.
///
/// # Differences from the standard library `Mutex`
///
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 byte of space, whereas the standard library boxes the
///   `Mutex` due to platform limitations.
/// - A `MutexGuard` can be sent to another thread and unlocked there.
/// - Can be statically constructed (requires the `const_fn` nightly feature).
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use parking_lot::Mutex;
/// use std::thread;
/// use std::sync::mpsc::channel;
///
/// const N: usize = 10;
///
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
/// //
/// // Here we're using an Arc to share memory among threads, and the data inside
/// // the Arc is protected with a mutex.
/// let data = Arc::new(Mutex::new(0));
///
/// let (tx, rx) = channel();
/// for _ in 0..10 {
///     let (data, tx) = (data.clone(), tx.clone());
///     thread::spawn(move || {
///         // The shared state can only be accessed once the lock is held.
///         // Our non-atomic increment is safe because we're the only thread
///         // which can access the shared state when the lock is held.
///         let mut data = data.lock();
///         *data += 1;
///         if *data == N {
///             tx.send(()).unwrap();
///         }
///         // the lock is unlocked here when `data` goes out of scope.
///     });
/// }
///
/// rx.recv().unwrap();
/// ```
pub struct Mutex<T: ?Sized> {
    raw: RawMutex,
    data: UnsafeCell<T>,
}

unsafe impl<T: Send> Send for Mutex<T> {}
unsafe impl<T: Send> Sync for Mutex<T> {}

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// `Deref` and `DerefMut` implementations.
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
    mutex: &'a Mutex<T>,
    marker: PhantomData<&'a mut T>,
}

impl<T> Mutex<T> {
    /// Creates a new mutex in an unlocked state ready for use.
    #[cfg(feature = "nightly")]
    #[inline]
    pub const fn new(val: T) -> Mutex<T> {
        Mutex {
            data: UnsafeCell::new(val),
            raw: RawMutex::new(),
        }
    }

    /// Creates a new mutex in an unlocked state ready for use.
    #[cfg(not(feature = "nightly"))]
    #[inline]
    pub fn new(val: T) -> Mutex<T> {
        Mutex {
            data: UnsafeCell::new(val),
            raw: RawMutex::new(),
        }
    }

    /// Consumes this mutex, returning the underlying data.
    #[inline]
    pub fn into_inner(self) -> T {
        unsafe { self.data.into_inner() }
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Acquires a mutex, blocking the current thread until it is able to do so.
    ///
    /// This function will block the local thread until it is available to acquire
    /// the mutex. Upon returning, the thread is the only thread with the mutex
    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
    /// the guard goes out of scope, the mutex will be unlocked.
    ///
    /// Attempts to lock a mutex in the thread which already holds the lock will
    /// result is a deadlock.
    #[inline]
    pub fn lock(&self) -> MutexGuard<T> {
        self.raw.lock();
        MutexGuard {
            mutex: self,
            marker: PhantomData,
        }
    }

    /// Attempts to acquire this lock.
    ///
    /// If the lock could not be acquired at this time, then `Err` is returned.
    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
    /// guard is dropped.
    ///
    /// This function does not block.
    #[inline]
    pub fn try_lock(&self) -> Option<MutexGuard<T>> {
        if self.raw.try_lock() {
            Some(MutexGuard {
                mutex: self,
                marker: PhantomData,
            })
        } else {
            None
        }
    }

    /// Returns a mutable reference to the underlying data.
    ///
    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        unsafe { &mut *self.data.get() }
    }
}

impl<T: ?Sized + Default> Default for Mutex<T> {
    #[inline]
    fn default() -> Mutex<T> {
        Mutex::new(Default::default())
    }
}

impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.try_lock() {
            Some(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
            None => write!(f, "Mutex {{ <locked> }}"),
        }
    }
}

impl<'a, T: ?Sized + 'a> Deref for MutexGuard<'a, T> {
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
        unsafe { &*self.mutex.data.get() }
    }
}

impl<'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.mutex.data.get() }
    }
}

impl<'a, T: ?Sized + 'a> Drop for MutexGuard<'a, T> {
    #[inline]
    fn drop(&mut self) {
        self.mutex.raw.unlock();
    }
}

// Helper function used by Condvar, not publicly exported
#[inline]
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a RawMutex {
    &guard.mutex.raw
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc::channel;
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;
    use {Mutex, Condvar};

    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    unsafe impl<T: Send> Send for Packet<T> {}
    unsafe impl<T> Sync for Packet<T> {}

    #[test]
    fn smoke() {
        let m = Mutex::new(());
        drop(m.lock());
        drop(m.lock());
    }

    #[test]
    fn lots_and_lots() {
        lazy_static! {
            static ref M: Mutex<()> = Mutex::new(());
        }
        static mut CNT: u32 = 0;
        const J: u32 = 1000;
        const K: u32 = 3;

        fn inc() {
            for _ in 0..J {
                unsafe {
                    let _g = M.lock();
                    CNT += 1;
                }
            }
        }

        let (tx, rx) = channel();
        for _ in 0..K {
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
        }

        drop(tx);
        for _ in 0..2 * K {
            rx.recv().unwrap();
        }
        assert_eq!(unsafe { CNT }, J * K * 2);
    }

    #[test]
    fn try_lock() {
        let m = Mutex::new(());
        *m.try_lock().unwrap() = ();
    }

    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut() = NonCopy(20);
        assert_eq!(m.into_inner(), NonCopy(20));
    }

    #[test]
    fn test_mutex_arc_condvar() {
        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
        let packet2 = Packet(packet.0.clone());
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            // wait until parent gets in
            rx.recv().unwrap();
            let &(ref lock, ref cvar) = &*packet2.0;
            let mut lock = lock.lock();
            *lock = true;
            cvar.notify_one();
        });

        let &(ref lock, ref cvar) = &*packet.0;
        let mut lock = lock.lock();
        tx.send(()).unwrap();
        assert!(!*lock);
        while !*lock {
            cvar.wait(&mut lock);
        }
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            let lock = arc2.lock();
            let lock2 = lock.lock();
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move || -> () {
                struct Unwinder {
                    i: Arc<Mutex<i32>>,
                }
                impl Drop for Unwinder {
                    fn drop(&mut self) {
                        *self.i.lock() += 1;
                    }
                }
                let _u = Unwinder { i: arc2 };
                panic!();
            })
            .join();
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_mutex_unsized() {
        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock(), comp);
    }

    #[test]
    fn test_mutexguard_send() {
        fn send<T: Send>(_: T) {}

        let mutex = Mutex::new(());
        send(mutex.lock());
    }
}
<|endoftext|>


<commit_before>use std;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io;

use tempdir::TempDir;

use pipeline::{CompileOptions, OutputType};
use ir;
use codegen;

fn get_writer(output_path: &Option<PathBuf>) -> io::Result<Box<std::io::Write>> {
    if let Some(ref output_path) = *output_path {
        Ok(Box::new(std::fs::File::create(output_path)?))
    } else {
        Ok(Box::new(std::io::stdout()))
    }
}

pub fn main_outer(tu: ir::TranslationUnit,
                  input_path: &str,
                  options: &CompileOptions)
                  -> io::Result<()> {
    match options.output_type {
        OutputType::Check => Ok(()),
        OutputType::LLVM => {
            let mut writer = get_writer(&options.output_path)?;
            codegen::llvm_gen::gen_translation_unit(&mut writer, tu)
        }
        OutputType::Run => {
            let tmp_dir = TempDir::new("elang-compiler")?;
            let exec_path = output_llvm(tu, input_path, tmp_dir.path(), options)?;
            if !run_command(exec_path, &[])?.success() {
                panic!("exec fail");
            }
            Ok(())
        }
        OutputType::Exec => {
            let tmp_dir = TempDir::new("elang-compiler")?;
            let exec_path = output_llvm(tu, input_path, tmp_dir.path(), options)?;
            let default_path = PathBuf::from("a.out");
            std::fs::copy(exec_path, options.output_path.as_ref().unwrap_or(&default_path))?;
            Ok(())
        }
    }
}

fn executable_name(path: &str) -> String {
    let file_name = Path::new(path).file_name().unwrap().to_str().unwrap();

    let mut name_parts: Vec<_> = file_name.split('.').collect();
    let parts_len = name_parts.len();
    if parts_len > 1 {
        name_parts.pop();
    }

    name_parts.join(".")
}

fn output_llvm(tu: ir::TranslationUnit,
               input_path: &str,
               tmp_dir_path: &Path,
               options: &CompileOptions)
               -> io::Result<PathBuf> {
    fn path_to_str(path: &PathBuf) -> &str {
        path.to_str().unwrap()
    }

    let exec_name = executable_name(input_path);

    let llvm_path = tmp_dir_path.join(format!("{}.ll", exec_name));
    let obj_path = tmp_dir_path.join(format!("{}.o", exec_name));
    let exec_path = tmp_dir_path.join(exec_name);

    let mut llvm_file = File::create(&llvm_path)?;
    codegen::llvm_gen::gen_translation_unit(&mut llvm_file, tu).expect("error llvm gen");

    if options.opt &&
       !run_command("opt",
                    &["-O3", "-S", path_to_str(&llvm_path), "-o", path_to_str(&llvm_path)])
                ?
                .success() {
        panic!("opt fail");
    }

    if !run_command("llc",
                    &["-filetype=obj", path_to_str(&llvm_path), "-o", path_to_str(&obj_path)])
                ?
                .success() {
        panic!("llc fail");
    }

    if !run_command("clang",
                    &[path_to_str(&obj_path), "-o", path_to_str(&exec_path)])
                ?
                .success() {
        panic!("clang fail");
    }

    Ok(exec_path)
}

fn run_command<S: AsRef<std::ffi::OsStr>>(ex: S,
                                          args: &[&str])
                                          -> io::Result<std::process::ExitStatus> {
    std::process::Command::new(ex).args(args).status()
}
<commit_msg>Rename output_llvm to output_exec<commit_after>use std;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io;

use tempdir::TempDir;

use pipeline::{CompileOptions, OutputType};
use ir;
use codegen;

fn get_writer(output_path: &Option<PathBuf>) -> io::Result<Box<std::io::Write>> {
    if let Some(ref output_path) = *output_path {
        Ok(Box::new(std::fs::File::create(output_path)?))
    } else {
        Ok(Box::new(std::io::stdout()))
    }
}

pub fn main_outer(tu: ir::TranslationUnit,
                  input_path: &str,
                  options: &CompileOptions)
                  -> io::Result<()> {
    match options.output_type {
        OutputType::Check => Ok(()),
        OutputType::LLVM => {
            let mut writer = get_writer(&options.output_path)?;
            codegen::llvm_gen::gen_translation_unit(&mut writer, tu)
        }
        OutputType::Run => {
            let tmp_dir = TempDir::new("elang-compiler")?;
            let exec_path = output_exec(tu, input_path, tmp_dir.path(), options)?;
            if !run_command(exec_path, &[])?.success() {
                panic!("exec fail");
            }
            Ok(())
        }
        OutputType::Exec => {
            let tmp_dir = TempDir::new("elang-compiler")?;
            let exec_path = output_exec(tu, input_path, tmp_dir.path(), options)?;
            let default_path = PathBuf::from("a.out");
            std::fs::copy(exec_path, options.output_path.as_ref().unwrap_or(&default_path))?;
            Ok(())
        }
    }
}

fn executable_name(path: &str) -> String {
    let file_name = Path::new(path).file_name().unwrap().to_str().unwrap();

    let mut name_parts: Vec<_> = file_name.split('.').collect();
    let parts_len = name_parts.len();
    if parts_len > 1 {
        name_parts.pop();
    }

    name_parts.join(".")
}

fn output_exec(tu: ir::TranslationUnit,
               input_path: &str,
               tmp_dir_path: &Path,
               options: &CompileOptions)
               -> io::Result<PathBuf> {
    fn path_to_str(path: &PathBuf) -> &str {
        path.to_str().unwrap()
    }

    let exec_name = executable_name(input_path);

    let llvm_path = tmp_dir_path.join(format!("{}.ll", exec_name));
    let obj_path = tmp_dir_path.join(format!("{}.o", exec_name));
    let exec_path = tmp_dir_path.join(exec_name);

    let mut llvm_file = File::create(&llvm_path)?;
    codegen::llvm_gen::gen_translation_unit(&mut llvm_file, tu).expect("error llvm gen");

    if options.opt &&
       !run_command("opt",
                    &["-O3", "-S", path_to_str(&llvm_path), "-o", path_to_str(&llvm_path)])
                ?
                .success() {
        panic!("opt fail");
    }

    if !run_command("llc",
                    &["-filetype=obj", path_to_str(&llvm_path), "-o", path_to_str(&obj_path)])
                ?
                .success() {
        panic!("llc fail");
    }

    if !run_command("clang",
                    &[path_to_str(&obj_path), "-o", path_to_str(&exec_path)])
                ?
                .success() {
        panic!("clang fail");
    }

    Ok(exec_path)
}

fn run_command<S: AsRef<std::ffi::OsStr>>(ex: S,
                                          args: &[&str])
                                          -> io::Result<std::process::ExitStatus> {
    std::process::Command::new(ex).args(args).status()
}
<|endoftext|>


<commit_before>//! The parse module is responsible for parsing events published by clients.

use regex::Regex;

use std::str::{self, FromStr};

use error::{Error, CapellaResult};

/// MetricType defines what kind of metric was parsed from a client.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum MetricType {
    Counter,
    Gauge,
    Histogram,
    Meter,
    Timer,
}

impl FromStr for MetricType {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "c" => Ok(MetricType::Counter),
            "g" => Ok(MetricType::Gauge),
            "h" => Ok(MetricType::Histogram),
            "m" => Ok(MetricType::Meter),
            "ms" => Ok(MetricType::Timer),
            _ => Err(Error::Parse),
        }
    }
}

/// A Metric defines a published client event.
#[derive(Debug, PartialEq)]
pub struct Metric {
    pub name: String,
    pub value: f64,
    pub metric_type: MetricType,
    pub sample_rate: Option<f64>,
}

impl Metric {
    pub fn new() -> Metric {
        Metric {
            name: String::new(),
            value: 0.0,
            metric_type: MetricType::Meter,
            sample_rate: None,
        }
    }
}

/// The parse_metric function trys to break down a single UDP packet into a single metric.
pub fn parse_metric(packet: &[u8]) -> CapellaResult<Metric> {
    lazy_static! {
        // TODO: Learn how to write this over multiple lines.
        static ref PATTERN: Regex = Regex::new(r"(?P<name>[\w\.]+):((?P<sign>\-|\+))?(?P<val>\d+)\|(?P<type>\w+)(\|@(?P<rate>\d+\.\d+))?").unwrap();
    }

    if let Ok(val) = str::from_utf8(packet) {
        if !PATTERN.is_match(val) {
            return Err(Error::Parse);
        }
    } else {
        return Err(Error::Parse);
    }

    // We know this matched before so it is safe to unwrap.
    let caps = PATTERN.captures(str::from_utf8(packet).unwrap()).unwrap();

    let mut metric = Metric::new();
    // These are required to match.
    let name = caps.name("name").unwrap().as_str();
    let value = caps.name("val").unwrap().as_str().parse::<f64>().map_err(Error::from)?;
    let metric_type = caps.name("type").unwrap().as_str();

    metric.name = String::from(name);
    metric.value = value;
    metric.metric_type = metric_type.parse::<MetricType>()?;

    // Now see if there were optional values added in.
    if let Some(sign) = caps.name("sign") {
        let s = sign.as_str();
        if s == "-" {
            metric.value *= -1.0;
        }
    }

    if let Some(rate) = caps.name("rate") {
        let r = rate.as_str().parse::<f64>().map_err(Error::from)?;
        metric.sample_rate = Some(r);
    }

    Ok(metric)
}

#[cfg(test)]
mod tests {
    use super::{Metric, MetricType, parse_metric};

    #[test]
    fn good_simple_meter() {
        let packet = b"test:1|m";
        let m1 = parse_metric(packet).unwrap();

        let mut m2 = Metric::new();
        m2.name = String::from("test");
        m2.value = 1.0;

        assert_eq!(m1, m2);
    }

    #[test]
    fn bad_parse_double_colon() {
        let packet = b"test::1|c";
        assert!(parse_metric(packet).is_err());
    }

    #[test]
    fn good_timing_with_rate() {
        let packet = b"test:1|ms|@0.1";
        let m1 = parse_metric(packet).unwrap();

        let mut m2 = Metric::new();
        m2.name = String::from("test");
        m2.value = 1.0;
        m2.metric_type = MetricType::Timer;
        m2.sample_rate = Some(0.1);

        assert_eq!(m1, m2);
    }

    #[test]
    fn bad_parse_float_value() {
        let packet = b"test:1.0|g";
        assert!(parse_metric(packet).is_err());
    }

    #[test]
    fn bad_parse_unknown_metric_type() {
        let packet = b"test:1|a";
        assert!(parse_metric(packet).is_err());
    }

    #[test]
    fn good_nested_metric_name() {
        let packet = b"test.nested.name:1|c";
        let m1 = parse_metric(packet).unwrap();

        let mut m2 = Metric::new();
        m2.name = String::from("test.nested.name");
        m2.value = 1.0;
        m2.metric_type = MetricType::Counter;

        assert_eq!(m1, m2);
    }
}
<commit_msg>update the pattern to allow for floats and make RE easier to grok<commit_after>//! The parse module is responsible for parsing events published by clients.

use regex::Regex;

use std::str::{self, FromStr};

use error::{Error, CapellaResult};

/// MetricType defines what kind of metric was parsed from a client.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum MetricType {
    Counter,
    Gauge,
    Histogram,
    Meter,
    Timer,
}

impl FromStr for MetricType {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "c" => Ok(MetricType::Counter),
            "g" => Ok(MetricType::Gauge),
            "h" => Ok(MetricType::Histogram),
            "m" => Ok(MetricType::Meter),
            "ms" => Ok(MetricType::Timer),
            _ => Err(Error::Parse),
        }
    }
}

/// A Metric defines a published client event.
#[derive(Debug, PartialEq)]
pub struct Metric {
    pub name: String,
    pub value: f64,
    pub metric_type: MetricType,
    pub sample_rate: Option<f64>,
}

impl Metric {
    pub fn new() -> Metric {
        Metric {
            name: String::new(),
            value: 0.0,
            metric_type: MetricType::Meter,
            sample_rate: None,
        }
    }
}

/// The parse_metric function trys to break down a single UDP packet into a single metric.
pub fn parse_metric(packet: &[u8]) -> CapellaResult<Metric> {
    lazy_static! {
        static ref PATTERN: Regex = Regex::new(r"(?x)
            (?P<name>[\w\.]+):
            ((?P<sign>\-|\+))?
            (?P<val>([0-9]*[.])?[0-9]+)
            \|(?P<type>\w+)
            (\|@(?P<rate>\d+\.\d+))?").unwrap();
    }

    if let Ok(val) = str::from_utf8(packet) {
        if !PATTERN.is_match(val) {
            return Err(Error::Parse);
        }
    } else {
        return Err(Error::Parse);
    }

    // We know this matched before so it is safe to unwrap.
    let caps = PATTERN.captures(str::from_utf8(packet).unwrap()).unwrap();

    let mut metric = Metric::new();
    // These are required to match.
    let name = caps.name("name").unwrap().as_str();
    let value = caps.name("val").unwrap().as_str().parse::<f64>().map_err(Error::from)?;
    let metric_type = caps.name("type").unwrap().as_str();

    metric.name = String::from(name);
    metric.value = value;
    metric.metric_type = metric_type.parse::<MetricType>()?;

    // Now see if there were optional values added in.
    if let Some(sign) = caps.name("sign") {
        let s = sign.as_str();
        if s == "-" {
            metric.value *= -1.0;
        }
    }

    if let Some(rate) = caps.name("rate") {
        let r = rate.as_str().parse::<f64>().map_err(Error::from)?;
        metric.sample_rate = Some(r);
    }

    Ok(metric)
}

#[cfg(test)]
mod tests {
    use super::{Metric, MetricType, parse_metric};

    #[test]
    fn good_simple_meter() {
        let packet = b"test:1|m";
        let m1 = parse_metric(packet).unwrap();

        let mut m2 = Metric::new();
        m2.name = String::from("test");
        m2.value = 1.0;

        assert_eq!(m1, m2);
    }

    #[test]
    fn bad_parse_double_colon() {
        let packet = b"test::1|c";
        assert!(parse_metric(packet).is_err());
    }

    #[test]
    fn good_timing_with_rate() {
        let packet = b"test:1|ms|@0.1";
        let m1 = parse_metric(packet).unwrap();

        let mut m2 = Metric::new();
        m2.name = String::from("test");
        m2.value = 1.0;
        m2.metric_type = MetricType::Timer;
        m2.sample_rate = Some(0.1);

        assert_eq!(m1, m2);
    }

    #[test]
    fn good_parse_float_value() {
        let packet = b"test:1.0|g";
        assert!(parse_metric(packet).is_ok());
    }

    #[test]
    fn bad_parse_unknown_metric_type() {
        let packet = b"test:1|a";
        assert!(parse_metric(packet).is_err());
    }

    #[test]
    fn good_nested_metric_name() {
        let packet = b"test.nested.name:1|c";
        let m1 = parse_metric(packet).unwrap();

        let mut m2 = Metric::new();
        m2.name = String::from("test.nested.name");
        m2.value = 1.0;
        m2.metric_type = MetricType::Counter;

        assert_eq!(m1, m2);
    }
}
<|endoftext|>


<commit_before>//! Las points.

#[derive(Debug, Default, PartialEq)]
pub struct Point {
    pub x: f64,
    pub y: f64,
    pub z: f64,
    pub intensity: u16,
    // TODO these aren't actually u8s
    pub return_number: u8,
    pub number_of_returns: u8,
    pub scan_direction: ScanDirection,
    pub edge_of_flight_line: bool,
    pub classification: Classification,
    pub scan_angle_rank: i8,
    pub user_data: u8,
    pub point_source_id: u16,
    pub gps_time: Option<f64>,
    pub red: Option<u16>,
    pub green: Option<u16>,
    pub blue: Option<u16>,
}

enum_from_primitive! {
#[derive(Debug, PartialEq)]
pub enum ScanDirection {
    Backward = 0,
    Forward = 1,
}
}

impl Default for ScanDirection {
    fn default() -> ScanDirection {
        ScanDirection::Forward
    }
}

enum_from_primitive! {
#[derive(Debug, PartialEq)]
pub enum Classification {
    CreatedNeverClassified = 0,
    Unclassified = 1,
    Ground = 2,
    LowVegetation = 3,
    MediumVegetation = 4,
    HighVegetation = 5,
    Building = 6,
    LowPoint = 7,
    ModelKeyPoint = 8,
    Water = 9,
    Reserved10 = 10,
    Reserved11 = 11,
    Overlap = 12,
    Reserved,
}
}

impl Default for Classification {
    fn default() -> Classification {
        Classification::CreatedNeverClassified
    }
}
<commit_msg>Document point<commit_after>//! Las points.

/// A las point.
///
/// As we do for the `Header` we encasulate different point formats by using `Option<T>`.
#[derive(Debug, Default, PartialEq)]
pub struct Point {
    /// The x value of the point.
    ///
    /// This value is assumed to not include a scaling and offset -- in other words, this is the
    /// "true" value, not the value stored in the lasfile.
    pub x: f64,
    /// The y value of the point.
    ///
    /// This value is assumed to not include a scaling and offset -- in other words, this is the
    /// "true" value, not the value stored in the lasfile.
    pub y: f64,
    /// The z value of the point.
    ///
    /// This value is assumed to not include a scaling and offset -- in other words, this is the
    /// "true" value, not the value stored in the lasfile.
    pub z: f64,
    /// The intensity of the point.
    pub intensity: u16,
    /// The return number of the point for its pulse.
    ///
    /// TODO these aren't actually u8s.
    pub return_number: u8,
    /// The number of returns in total for the pulse that produced this point.
    pub number_of_returns: u8,
    /// The `ScanDirection` of the point.
    pub scan_direction: ScanDirection,
    /// True if this point is on the edge of a flight line.
    pub edge_of_flight_line: bool,
    /// The `Classification` of this point.
    pub classification: Classification,
    /// The scan angle range -- basically, the integer value of the scan angle.
    pub scan_angle_rank: i8,
    /// Custom data that the user can provide.
    pub user_data: u8,
    /// The "file" from which this point originated.
    pub point_source_id: u16,
    /// The gps time of this point.
    pub gps_time: Option<f64>,
    /// The red channel for this point.
    pub red: Option<u16>,
    /// The green channel for this point.
    pub green: Option<u16>,
    /// The blue channel for this point.
    pub blue: Option<u16>,
}

enum_from_primitive! {
#[derive(Debug, PartialEq)]
pub enum ScanDirection {
    Backward = 0,
    Forward = 1,
}
}

impl Default for ScanDirection {
    fn default() -> ScanDirection {
        ScanDirection::Forward
    }
}

enum_from_primitive! {
#[derive(Debug, PartialEq)]
pub enum Classification {
    CreatedNeverClassified = 0,
    Unclassified = 1,
    Ground = 2,
    LowVegetation = 3,
    MediumVegetation = 4,
    HighVegetation = 5,
    Building = 6,
    LowPoint = 7,
    ModelKeyPoint = 8,
    Water = 9,
    Reserved10 = 10,
    Reserved11 = 11,
    Overlap = 12,
    Reserved,
}
}

impl Default for Classification {
    fn default() -> Classification {
        Classification::CreatedNeverClassified
    }
}
<|endoftext|>


<commit_before>use glutin_window::GlutinWindow;
use graphics::{DrawState, Transformed};
use graphics::text::Text;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event_loop::Events;
use piston::input::{Button, Event, Input, Key, RenderArgs, UpdateArgs};
use rand::Rng;
use std::cell::RefCell;
use std::borrow::BorrowMut;
use std::path::Path;
use std::iter::repeat;
use std::rc::Rc;

use actors::{Astroid, Bullet, Spaceship};

pub trait Scene {
    fn events(&mut self, &mut Rng, Rc<RefCell<GlutinWindow>>, &mut GlGraphics, (f64, f64)) -> Option<Box<Scene>>;
}

#[derive(Clone)]
pub struct MainScene {
    difficulty: usize,
    spaceship: Spaceship,
    bullets: Vec<Bullet>,
    astroids: Vec<Astroid>,
}

impl MainScene {
    pub fn new(difficulty: usize, rng: &mut Rng) -> MainScene {
        return MainScene{
            difficulty: difficulty,
            spaceship: Spaceship::new(),
            bullets: Vec::new(),
            astroids: repeat(0).take(difficulty).map(|_| Astroid::large_new(rng))
                .collect(),
        };
    }

    fn draw(&self, r: RenderArgs, ds: DrawState, gl: &mut GlGraphics) {
        use graphics::clear;
        gl.draw(r.viewport(), |c, gl| {
            clear(BLACK, gl);
            for astroid in self.astroids.iter() {
                astroid.draw(WHITE, &ds, c.transform, gl);
            }
            self.spaceship.draw(WHITE, &ds, c.transform, gl);
            for bullet in self.bullets.iter() {
                bullet.draw(WHITE, c.transform, gl);
            }
        })
    }

    fn update(&mut self, u: UpdateArgs, rng: &mut Rng, (width, height): (f64, f64)) -> Option<Box<Scene>> {
        self.spaceship.accelerate(u.dt);
        self.spaceship.turn(u.dt);
        self.spaceship.go(u.dt, width, height);
        self.spaceship.cooldown(u.dt);
        for ref mut astroid in self.astroids.iter_mut() {
            astroid.go(u.dt, width, height);
        }
        {
            let astroid_edges = self.astroids.iter()
                .flat_map(|astroid| astroid.edges());
            if self.spaceship.collides(astroid_edges) {
                return Some(Box::new(GameOverScene::new(self)));
            }
        }
        if self.spaceship.is_firing() && self.spaceship.ready_to_fire() {
            self.spaceship.fire(&mut self.bullets);
        }
        let mut new_bullets = Vec::with_capacity(self.bullets.len());
        for mut bullet in self.bullets.iter_mut() {
            bullet.go(u.dt, width, height);
            let mut collided = false;
            self.astroids = self.astroids.iter().flat_map(|a| {
                if bullet.collides(a) {
                    collided = true;
                    a.explode(rng)
                } else {
                    vec![a.clone()]
                }
            }).collect();
            if !collided {
                new_bullets.push(bullet.clone());
            }
        }
        new_bullets.retain(Bullet::is_alive);
        self.bullets = new_bullets;
        if self.astroids.len() == 0 {
            return Some(Box::new(MainScene::new(self.difficulty + 1, rng)));
        }
        return None;
    }
}

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

impl Scene for MainScene {
    fn events(&mut self, rng: &mut Rng, window: Rc<RefCell<GlutinWindow>>, gl: &mut GlGraphics, dimensions: (f64, f64)) -> Option<Box<Scene>> {

        let ds = DrawState::new();
        let ev = window.events();
        for e in ev {
            match e {
                Event::Update(u) => {
                    let scene_change = self.update(u, rng, dimensions);
                    if scene_change.is_some() {
                        return scene_change;
                    }
                },
                Event::Render(r) => self.draw(r, ds, gl),
                Event::Input(Input::Press(Button::Keyboard(k))) => {
                    self.spaceship.handle_press(k);
                    match k {
                        Key::R => self.spaceship = Spaceship::new(),
                        Key::Q => return None,
                        _ => (),
                    }
                },
                Event::Input(Input::Release(Button::Keyboard(k))) => {
                    self.spaceship.handle_release(k);
                },
                _ => (),
            }
        }
        return None;
    }
}

struct GameOverScene {
    end_game: MainScene
}

impl GameOverScene {
    fn new(end_game: &MainScene) -> GameOverScene {
        GameOverScene {
            end_game: end_game.clone(),
        }
    }
}

impl Scene for GameOverScene {
    fn events(&mut self, rng: &mut Rng, window: Rc<RefCell<GlutinWindow>>, gl: &mut GlGraphics, (x_max, y_max): (f64, f64)) -> Option<Box<Scene>> {
        let ds = DrawState::new();
        let game_over_text = Text::new_color(WHITE, 20);
        let mut character_cache: Box<GlyphCache> = Box::new(GlyphCache::new(Path::new("/usr/share/fonts/TTF/DejaVuSans.ttf")).unwrap());
        for e in window.events() {
            match e {
                Event::Render(r) => {
                    self.end_game.draw(r, ds, gl);
                    gl.draw(r.viewport(), |c, gl| {
                        game_over_text.draw("Game Over", character_cache.borrow_mut() as &mut GlyphCache, &ds, c.transform.trans(x_max/2.0, y_max/2.0), gl);
                    });
                },
                Event::Input(Input::Press(k)) => match k {
                    Button::Keyboard(Key::Space) => return Some(Box::new(MainScene::new(1, rng))),
                    Button::Keyboard(Key::Q) => return None,
                    _ => (),
                },
                _ => (),
            }
        }
        return None;
    }
}<commit_msg>Fixed restarting<commit_after>use glutin_window::GlutinWindow;
use graphics::{DrawState, Transformed};
use graphics::text::Text;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event_loop::Events;
use piston::input::{Button, Event, Input, Key, RenderArgs, UpdateArgs};
use rand::Rng;
use std::cell::RefCell;
use std::borrow::BorrowMut;
use std::path::Path;
use std::iter::repeat;
use std::rc::Rc;

use actors::{Astroid, Bullet, Spaceship};

pub trait Scene {
    fn events(&mut self, &mut Rng, Rc<RefCell<GlutinWindow>>, &mut GlGraphics, (f64, f64)) -> Option<Box<Scene>>;
}

#[derive(Clone)]
pub struct MainScene {
    difficulty: usize,
    spaceship: Spaceship,
    bullets: Vec<Bullet>,
    astroids: Vec<Astroid>,
}

impl MainScene {
    pub fn new(difficulty: usize, rng: &mut Rng) -> MainScene {
        return MainScene{
            difficulty: difficulty,
            spaceship: Spaceship::new(),
            bullets: Vec::new(),
            astroids: repeat(0).take(difficulty).map(|_| Astroid::large_new(rng))
                .collect(),
        };
    }

    fn draw(&self, r: RenderArgs, ds: DrawState, gl: &mut GlGraphics) {
        use graphics::clear;
        gl.draw(r.viewport(), |c, gl| {
            clear(BLACK, gl);
            for astroid in self.astroids.iter() {
                astroid.draw(WHITE, &ds, c.transform, gl);
            }
            self.spaceship.draw(WHITE, &ds, c.transform, gl);
            for bullet in self.bullets.iter() {
                bullet.draw(WHITE, c.transform, gl);
            }
        })
    }

    fn update(&mut self, u: UpdateArgs, rng: &mut Rng, (width, height): (f64, f64)) -> Option<Box<Scene>> {
        self.spaceship.accelerate(u.dt);
        self.spaceship.turn(u.dt);
        self.spaceship.go(u.dt, width, height);
        self.spaceship.cooldown(u.dt);
        for ref mut astroid in self.astroids.iter_mut() {
            astroid.go(u.dt, width, height);
        }
        {
            let astroid_edges = self.astroids.iter()
                .flat_map(|astroid| astroid.edges());
            if self.spaceship.collides(astroid_edges) {
                return Some(Box::new(GameOverScene::new(self)));
            }
        }
        if self.spaceship.is_firing() && self.spaceship.ready_to_fire() {
            self.spaceship.fire(&mut self.bullets);
        }
        let mut new_bullets = Vec::with_capacity(self.bullets.len());
        for mut bullet in self.bullets.iter_mut() {
            bullet.go(u.dt, width, height);
            let mut collided = false;
            self.astroids = self.astroids.iter().flat_map(|a| {
                if bullet.collides(a) {
                    collided = true;
                    a.explode(rng)
                } else {
                    vec![a.clone()]
                }
            }).collect();
            if !collided {
                new_bullets.push(bullet.clone());
            }
        }
        new_bullets.retain(Bullet::is_alive);
        self.bullets = new_bullets;
        if self.astroids.len() == 0 {
            return Some(Box::new(MainScene::new(self.difficulty + 1, rng)));
        }
        return None;
    }
}

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

impl Scene for MainScene {
    fn events(&mut self, mut rng: &mut Rng, window: Rc<RefCell<GlutinWindow>>, gl: &mut GlGraphics, dimensions: (f64, f64)) -> Option<Box<Scene>> {

        let ds = DrawState::new();
        let ev = window.events();
        for e in ev {
            match e {
                Event::Update(u) => {
                    let scene_change = self.update(u, rng, dimensions);
                    if scene_change.is_some() {
                        return scene_change;
                    }
                },
                Event::Render(r) => self.draw(r, ds, gl),
                Event::Input(Input::Press(Button::Keyboard(k))) => {
                    self.spaceship.handle_press(k);
                    match k {
                        Key::R => return Some(Box::new(MainScene::new(1, &mut rng))),
                        Key::Q => return None,
                        _ => (),
                    }
                },
                Event::Input(Input::Release(Button::Keyboard(k))) => {
                    self.spaceship.handle_release(k);
                },
                _ => (),
            }
        }
        return None;
    }
}

struct GameOverScene {
    end_game: MainScene
}

impl GameOverScene {
    fn new(end_game: &MainScene) -> GameOverScene {
        GameOverScene {
            end_game: end_game.clone(),
        }
    }
}

impl Scene for GameOverScene {
    fn events(&mut self, rng: &mut Rng, window: Rc<RefCell<GlutinWindow>>, gl: &mut GlGraphics, (x_max, y_max): (f64, f64)) -> Option<Box<Scene>> {
        let ds = DrawState::new();
        let game_over_text = Text::new_color(WHITE, 20);
        let mut character_cache: Box<GlyphCache> = Box::new(GlyphCache::new(Path::new("/usr/share/fonts/TTF/DejaVuSans.ttf")).unwrap());
        for e in window.events() {
            match e {
                Event::Render(r) => {
                    self.end_game.draw(r, ds, gl);
                    gl.draw(r.viewport(), |c, gl| {
                        game_over_text.draw("Game Over", character_cache.borrow_mut() as &mut GlyphCache, &ds, c.transform.trans(x_max/2.0, y_max/2.0), gl);
                    });
                },
                Event::Input(Input::Press(k)) => match k {
                    Button::Keyboard(Key::Space) => return Some(Box::new(MainScene::new(1, rng))),
                    Button::Keyboard(Key::Q) => return None,
                    _ => (),
                },
                _ => (),
            }
        }
        return None;
    }
}<|endoftext|>


<commit_before>
pub struct Sound {
	data: [u8,.. 0x16],
}

impl Sound {
	pub fn new() -> Sound {
		Sound { data: [0,.. 0x16] }
	}

	pub fn rb(&self, a: u16) -> u8 {
		self.data[a - 0xFF10]
	}

	pub fn wb(&mut self, a: u16, v: u8) {
		self.data[a - 0xFF10] = v;
	}
}

<commit_msg>Fixed bug in Sound<commit_after>
pub struct Sound {
	data: [u8,.. 0x17],
}

impl Sound {
	pub fn new() -> Sound {
		Sound { data: [0,.. 0x17] }
	}

	pub fn rb(&self, a: u16) -> u8 {
		self.data[a - 0xFF10]
	}

	pub fn wb(&mut self, a: u16, v: u8) {
		self.data[a - 0xFF10] = v;
	}
}

<|endoftext|>